AVR MCU serial port multi-machine communication program

Publisher:qiuxubiaoLatest update time:2017-12-15 Source: eefocus Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

In the process of multi-machine communication, the RS232 interfaces of all devices are connected to the communication line, and only one device can be the host, and the others are slaves. The communication is initiated by the host. The data frame generally uses 1 start bit and 9 data bits, of which the 9th bit (RXB8) is used to indicate whether the frame is an address frame or a data frame. When the frame type characterization bit is "1", it indicates that the frame data is an address frame; when the frame type characterization bit is "0", it indicates that the frame is a data frame. 
  In AVR, by setting the flag bit MPCM in the UCSRA register of the slave, the function of filtering the received data frame of the USART receiver can be enabled. If the filtering function is enabled, the slave receiver will filter the received data frames that are not address information frames and will not put them into the receiving buffer. This effectively facilitates the writing of the slave MCU data frame processing program in multi-machine communication (compared with the standard 51 structure). The transmitter is not affected by the MPCM bit setting. 


  The multi-machine communication mode allows multiple slaves to receive data sent by a master on the communication line. By decoding the address in the received address frame, it is determined which slave is addressed by the master. If a slave is addressed by the master, it will receive the next data frame sent by the master, while other slaves will ignore the data frame until an address frame is received again. (The slave address is determined by the software of each slave). 
  For the host MCU in the multi-machine communication system, a 9-bit data frame structure can be set (UCSZ=7). When sending an address frame, set the 9th bit to "1"; when sending a data frame, set the 9th bit to "0". In this case, the slave must also be set to receive a 9-bit data frame structure. The 
  data exchange process of the multi-machine communication mode is as follows: 
    1) Set all slaves to work in the multi-machine communication mode (MPCM=1).  
    2) The communication starts with the master sending an address frame first, such as 8-bit data is 0X01 (slave address No. 1), the 9th bit = "1", calling slave No. 1. 
    3) All slaves receive and read the address frame sent by the master. In all slave MCUs, the RXC flag is set, indicating that the address frame is received. 
    4) Each slave MCU reads the UDR register and determines whether it is addressed by the host. If it is addressed, clear the MPCM bit in the UCSAR register and wait for data to be received; otherwise, keep MPCM as "1" and wait for the next address frame to be received (this step should be processed and implemented by the user software): 
      A) The processing process of the MCU as slave No. 1 is: after receiving the address frame, it determines that the read UDR data 0X01 is its own address, sets the MPCM bit to "0", and receives all subsequent data frames sent by the host until the next address frame.  
      B) The processing process of other slave MCUs: after receiving the address frame, it determines that the read UDR data 0X01 is not its own address, sets the MPCM bit to "1", so that they will ignore the data frames subsequently sent by the host until the host sends the address frame again. 
    5) When the addressed slave MCU receives the last data frame, it sets the MPCM bit to 1 and waits for the next address frame to appear (this step should also be processed and implemented by the user software), and then repeats from step 2.  



[Transfer] Example; 

  Communication rules:  
   1: Clock 7.3728 MHz / Baud rate 9600 / 9 data bits / Odd parity / 1 stop bit / Hardware multi-machine communication function /  
   2: Communication connection uses hardware MAX485, bidirectional simplex  
   3: The number of bytes of each upstream/downstream data packet is the same (communication data volume)  
   4: Each upstream/downstream data packet uses CRC8 check  
   5: Data reception uses interrupt + query method  
   6: The host always sends a data packet to the slave, and the slave replies a data packet to the host after receiving the data packet  
   7: Regardless of whether it is the host or the slave, if there is any error in the received data packet, the data packet will be discarded, which is equivalent to not receiving it  
   8: Slaves cannot communicate with each other, and data can only be exchanged through the host  
   9: Invalid address is 0, host address is 1, slave address is 2.3.4... Broadcast address is 255  
*/  
#include   
#include   
#include   
#include //CRC check function is in this file    

#define amount 10 //Set the communication data amount (including 1 address frame, n data frames, 1 check frame)  

unsigned char send[amount]; //Sending box  
unsigned char inbox[amount]; //Incoming box  
unsigned char n=0; //Memory interrupt times  

//--------------------------------------------------------------------  
interrupt[12] Rxd_isr(void) //Receive interrupt  
{    
   unsigned char ERROR=0;  
   if( UCSRA&4 || UCSRA&16 ) ERROR=1; //Parity check error or frame error is recorded     
   inbox[n]=UDR; //Save to inbox  
   n++; //Memory interrupt times  
   if(ERROR) inbox[0]=0; //If there is a communication error, the address frame of the inbox is marked as invalid address 0  
}  

//---------------------------------------------------------------------  
void main(void)  
{  
   usart_init(); //Serial port initialization  
   UCSRA=0; //Host turns off the address filtering function (multi-machine communication function)  
   #asm("sei") //Turn on global interrupt  
   while(1)  
   {  
     //-------------Talk to slave 2. Talk to other slaves is similar to the following program-------------------  
     n=0; //Clear interrupt count to 0  
     inbox[0]=0; //Clear inbox address to 0  
     //Please update the data to be sent  
     //send[1]=?    
     //......  
     //send[n]=?  
     send[0]=2; //Change this address to communicate with a slave  
     send[amount-1]=crc8(send,amount-1); //Calculate the crc8 checksum of the outbox  
     usart_out(send,amount); //Send the data in the outbox send[];  
      
     //Wait, the slave will reply after receiving the data. If the data volume is 10 bytes, it must not be less than 13ms!!!  
     //This time is calculated manually, and the possibility of the slave extending the reply time due to various interruptions must be considered  
      
     delay_ms(15);  
      
     //if(n<3) If the received data is less than 3, then the communication line is faulty  
      
     //If the inbox has received amount of data and the crc8 check succeeds, then...  
     if(n==amount && inbox[amount-1]==crc8(inbox,amount-1))  
       {  
         if(inbox[0]==1) //If the inbox address frame belongs to this machine, run the following test code  
           {  
             DDRD.3=1;  
             PORTD.3=1; delay_ms(10);  
             PORTD.3=0; delay_ms(990);  
           }  
            
         if(inbox[0]==255)  
           {  
             //Please add the processing procedure for receiving broadcast data here  
           }  
       }                
   }  
} //end  


------------------------------------------------------------  
Slave  
----------------------------------------------------------------------------  
#include   
#include   
#include   

#define amount 10 //Set the communication data amount (including 1 address frame, n data frames, 1 check frame)    
#define address 2 //Please set the local address here  

unsigned char send[amount]; //Sending box  
unsigned char inbox[amount]; //Incoming box  
unsigned char n=0; //Memory interrupt count  

interrupt[12] Rxd_isr(void) //Receive interrupt  
{    
   unsigned char ERROR=0;  
   if( UCSRA&4 || UCSRA&16 ) ERROR=1; //Record parity error or frame error  
   inbox[n]=UDR; //Save received data to the inbox  
   n++; //Remember the number of receptions  
   if(ERROR) //If the communication is wrong....  
     {  
       n=0; //Reset the reception count to 0  
       inbox[0]=0; //Change the address to invalid address 0  
       UCSRA|=0x01; //Reopen the address frame filtering function of the receiver  
     }  
    
   //If the address matches the local or broadcast address, turn off the address filtering (multi-machine communication) function    
   if(inbox[0]==address ||inbox[0]==255) UCSRA&=254;  
    
   if(n==amount) //After receiving amount data...  
     {    
       n=0; //Reset the reception count to 0  
       UCSRA|=0x01; //Reopen the address frame filtering function of the receiver  
       if(inbox[amount-1]==crc8(inbox,amount-1)) //If the crc8 check is correct...  
         {     
           if(inbox[0]==address) //If the address matches the local machine, reply data  
             {    
               send[0]=1; //The outbox address points to the host  
               send[amount-1]=crc8(send,amount-1);//Generate CRC8 checksum for the outbox  
               usart_out(send,amount); //Send the data packet of the outbox send[]  
               //Please back up your inbox information here  
             }  
           if(inbox[0]==255) //If it is a broadcast address...  
             {  
               //Please add your code here  
               //Please do not reply after receiving broadcast data  
             }  
         }  
     }  
}  

void main(void)  
{  
   usart_init();  
   #asm("sei")  

   while (1)  
         {  
           //send[1]=?  
           //......  
           //send[n]=?  
         };  
}  


---------------------------------------------------------------------------------  
usart.h file  
---------------------------------------------------------------------------------  
//Baud rate 9600/9 data bits/1 stop bit/odd parity/transmit and receive enabled/receive interrupt  
void usart_init(void)  
      {    
        UCSRA=0x01;  
        UCSRB=0x9C;  
        UC SRC =http://www.p IC avr.com/0xB6;  
        UBRRH=0x00;  
        UBRRL=47;  

        PORTD.4=0; //MAX485 usually works in the receiving state  
        DDRD.4=1;  
      }  

//-----------------------------------------------------------  
//Start sending amount data from the first address of the array datas[], where the 0th data is the address frame and the others are data frames  
void usart_out(unsigned char *datas,unsigned char n)  
      {  
        unsigned char i=0;    
        PORTD.4=1; //Make MAX485 in the sending state  
        while(i             {    
               if(i==0) UCSRB|=1; else UCSRB&=254;     
               UDR=*(datas+i); //Load data and start sending  
               while((UCSRA&64)==0); //Wait for the end of sending  
               UCSRA|=64; //Clear the sending end flag  
               i++; //Sending times statistics  
             }  
        PORTD.4=0; //Put MAX485 in receiving state  
      }     

---------------------------------------------------------------------------------  
crc8 verification program  
---------------------------------------------------------------------------------  
unsigned char crc8(unsigned char *ptr, unsigned char len)    
{  
   unsigned char i;  
   unsigned char crc=0;  
   while(len--!=0)    
    {  
      for(i=1; i!=0; i*=2)  
       {  
         if((crc&1)!=0) {crc/=2; crc^=0x8C;}  
         else crc/=2;  
         if((*ptr&i)!=0) crc^=0x8C;       
        }    
      ptr++;  
     }  
return(crc);  


Reference address:AVR MCU serial port multi-machine communication program

Previous article:AD sampling program of ATMege8
Next article:ICC AVR LCD1602 display program

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号