??? 08/17/10 06:57 Modified: 08/17/10 06:58 Read: times |
#178052 - Multiprocessor Communication 8052 |
I am using P89C52X2 controllers in our project, and the hardware is designed to support master-slave communication. There are 13 slave cards, which are identified by their addresses 0000b~1100b. The RxD's of all slaves are hardwired to TxD of master, and the TxD's are hardwired to the RxD of master.
Crystal in master is 12Mhz, and of slaves are 6Mhz. We are using serial communication Mode 3 with variable Baud rate of 31,250. We are using Timer 0 with 20 milliseconds interrupt. /* Initialize 8052 UART for multi-processor comms */ /* Mode 3: 9-bit uart, VARIABLE 31250 baud rate */ PCON = 0X80; SCON = 0xD0; /* Setup serial port control register */ TH1 = 0xFE; SM2 = 0; TB8 = 1; REN = 1; RB8 = 0; Information to be sent to slaves is differentiated as Command Byte / Data Byte by making use of TB8. We tried to implement the Serial Communication procedure provided by Philips (P89C51X2/52X2/54X2/58X2 datasheet --- FULL-DUPLEX ENHANCED UART - Multiprocessor Communications topic - page 21) After the initial detection of the active slave cards, the master card starts accessing each slave in a sequence in the main superloop, so that the addressed slave sends its data bytes to the master and the master waits till the end of data. So, data sending from slave to master is done in a sequence, once for each slave in the superloop. Data sending from master to slave is done whenever required. All data bytes sent / received require acknowledges reception / transmission to confirm that the data is communicated properly. /*****************************************************************************/ // ************* MASTER CARD CODE ************* /*****************************************************************************/ #define SP_START_BIT 0xCE #define SP_END_BIT 0xCC #define END_OF_COMM 0xCB #define ACKNOWLEDGE 0xCA #define DATA_ACK 0xC8 unsigned char buf; unsigned char end_of_comm; unsigned char synch_flag; bit acknowledge; bit data_ack; bit transmit_ready; void SerialISR_Master(void) interrupt 4 using 3 { /*Data Reception*/ if(RI) { // RI = 1, means data received from addressed slave buf = SBUF; // Store The Character Sent From Slave In Buffer if((buf == ACKNOWLEDGE)) { //If Data Received Is Acknowledge Type... acknowledge = 1;// Set Acknowledge Received Flag } else if(buf == DATA_ACK)//If Data Received Is 'Data Acknowledge'... data_ack = 1;// Set Data Acknowledged Flag else if((buf & 0XF0) == 0XA0) { // Cross Check The End Of Comm Signal Is Received From The Proper Slave Or Not end_of_comm = 0XCC; // Set The End Of Communication Flag } else if(buf == SP_END_BIT) { //If Data Received Is Slave Portocol End Flag... /*Process the received data operations*/ transmit_ready = 0; // Block The Transmitter Ready Token TB8 = 0; // Clear Bit 8 Of Comm SBUF = DATA_ACK; // Send The Data Acknowledge to Slave } else if(buf == SP_START_BIT) { //If Data Received Is Slave Protocol Start Byte /*Prepare to receive the Data bytes from the next reception*/ transmit_ready = 0; // Block The Transmitter Ready Token TB8 = 0; // Clear Bit 8 Of Comm SBUF = DATA_ACK; // Send The Data Acknowledge to Slave } else { //If Data Bytes Are Being Received... /*Load the data bytes into the buffers*/ transmit_ready = 0; // Block The Transmitter Ready Token TB8 = 0; // Clear Bit 8 Of Comm SBUF = DATA_ACK; // Send The Data Ack On Every Data Received } RI = 0; // Clear Ri To Wait For Next Character buf = 0; // Clear The Received Byte Storing Buffer } /*Data Transmission*/ else if(TI) { // TI = 1, means ready to load new character in SBUF TB8 = 0;// clear bit 8, for general data transmission TI = 0; // clear TI flag since we are going to transmit again transmit_ready = 1; // release the transmitter ready token after transmission completed } } bit enableSlaveToTx(unsigned char sid) { transmit_ready = 0; // take transmitter ready token in order to transmit acknowledge = 0; TB8 = 1; // set bit 8, for address transmission SBUF = sid; /* General Broadcast address - all slaves receive this */ synch_flag = 75; // Load The Synchronisation Flag Count, which counts down in TISR every 20 ms while( (!acknowledge) && synch_flag){;} if(!acknowledge) { return 0; } acknowledge = 0; // If It Responds Go Further return 1; } void getDataFromSlaves(void) { unsigned char slave_card_id; for(slave_card_id=0;slave_card_id<13;slave_card_id++) { if(end_of_comm == 0X55) { // If Comm Port Is Free... end_of_comm = 0XAA;//MAKE IT BUSY if(enableSlaveToTx(slave_card_id)) { // If The Addressed Slave Is Enabled For Transmitting Mode... synch_flag = 75; // Load The Synchronisation Flag Count, which counts down in TISR every 20 ms while( (end_of_comm == 0XAA) && synch_flag){;} // Wait Until The Slave Transmits The Total Data Or Synch Count Comes To Zero thro Timer 0 ISR if(end_of_comm == 0XAA) { // If The Slave Card Lost The Communication /*Error Log storing code goes here*/ } end_of_comm = 0x55;// Make Comm Port Free... } else { // If The Addressed Slave Does Not Respond At All... /*We give 5 turns for the slave to respond. If it fails, we store the Error Log and send reset signal to restart the system. else, */ end_of_comm = 0x55;// Make Comm Port Free... } } } } void main(void) { /*Initialisations go here*/ while(1) { getDataFromSlaves(); /*Remaining code goes here*/ } } /*****************************************************************************/ // ************* SLAVE CARD CODE ************* /*****************************************************************************/ #define MP_START_BIT 0XCF #define MP_END_BIT 0xCD #define ACKNOWLEDGE 0xCA #define DATA_ACK 0xC8 #define RESET_SLAVE_SIGN 0XC7 unsigned char code END_OF_COMM_ARR[13]=/*Used for identifying unique End Of Comms at Master End*/ {0XA0,0XA1,0XA2,0XA3,0XA4,0XA5,0XA6,0XA7,0XA8,0XA9,0XAA,0XAB}; bit restart; bit give_ack; bit give_data_ack; bit transmit_enable; bit trans_r; bit restart; unsigned char hardware_id;/*0000 ~ 1100 */ unsigned char rec_data; void send_data(unsigned char i) { trans_r = 1; SBUF = i; // SEND THE DATA TO THE MASTER while(trans_r); } void sendProtocolToMaster(void) { /* Data bytes sending code goes here. Each byte requires acknowledge from master (DATA_ACK) */ send_data(END_OF_COMM_ARR[hardware_id]); transmit_enable = 0; SM2 = 1; } void main (void) { /*Initialisation code here*/ /*Card hardware ID generation code here*/ if(!SM2) //CHECKING WHETHER THE SLAVE IS PERMITED TO SEND THE DATA OR NOT { if(give_ack) //IF THERE IS A REQUEST FOR ACK { give_ack = 0; //CLEAR THE REQUEST send_data(ACKNOWLEDGE); } if(give_data_ack) //IF THERE IS A REQUEST FOR ACK { give_data_ack = 0; //CLEAR THE REQUEST send_data(DATA_ACK); } if(transmit_enable) sendProtocolToMaster();//IF THE SLAVE IS ENABLED IN TRANSMITING MODE SEND ALL PROTOCOLS PENDING TO THE MASTER } if(restart) { EA = 0; ((void(code*)(void))0x0000)();//Go to location 00 of code } } void SerialISR_Slave(void) interrupt 4 using 3 { // RECEIVER SECTION if(RI) { // if a character is received rec_data = SBUF;// read data character sent from master and store it in rec buf if(RB8) // if received general broadcast address, { // Global Message Reception if(hardware_id == rec_data) { // if received correct address, transmit_enable = 1; SM2 = 0; // prepare to read data give_ack = 1; // SEND ACK SIGNAL TO MASTER } else SM2 = 1;// reset serial port for address reception mode // This message is not acknowledged back to the Master // since all the slaves would be replying it at the same time // and the data would therefore be corrupted. else if(rec_data == RESET_SLAVE_SIGN)/*To restart the slave*/ restart = 1; else {// if the addressed slave is not this... SM2 = 1; // reset serial port for address reception mode } RB8 = 0; } else if(!SM2) // IF SLAVE IS IN RECEIVING MODE { //Private Message data Reception if(rec_data == DATA_ACK)//If Data Received Is 'Data Acknowledge'... data_ack = 1;// Set Data Acknowledged Flag else if(rec_data == MP_END_BIT) { //If Data Received Is Slave Portocol End Flag... /*Process the received data operations*/ give_data_ack = 1; } else if(rec_data == MP_START_BIT) { //If Data Received Is Slave Protocol Start Byte /*Prepare to receive the Data bytes from the next reception*/ give_data_ack = 1; } else { //If Data Bytes Are Being Received... /*Load the data bytes into the buffers*/ give_data_ack = 1; } } RI = 0; rec_data = 0; } // TRANSMITTER SECTION if(TI) { // TI = 1, means ready to load new character in SBUF TI = 0; // clear TI flag since we are goling to transmit again trans_r =0; } } Q1: Is it a better way to use 31250 baud for serial communication? While the system is running, once in a while, one of the slaves is not responding when it is being addressed. We are trying to trace it with the help of error log at the instance of card response failure. Once this happens, we are sending reset command to restart the whole system, as the system is not running properly, it happens 2-3 times in 24 hrs. Q2: What issues affect a slave from not responding to command Byte? what needs to be done to refresh the communication? Q3. Are we using the correct way to communicate in Master Slave Application (as described in Philips datasheet) or better options are available to implement? |