AVR microcontroller serial port multi-machine communication and examples

Publisher:温暖微笑Latest update time:2016-10-07 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 indication bit is "1", it means that the frame data is an address frame; when the frame type indication bit is "0", it means that the frame is a data frame.

  In AVR, by setting the flag bit MPCM in the slave's UCSRA register, the USART receiver can be enabled to filter the received data frames. 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 host on the communication line. By decoding the address in the received address frame, it is determined which slave is addressed by the host. If a slave is addressed by the host, it will receive the next data frame sent by the host, 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 multi-machine communication mode is as follows:
    1) Set all slaves to work in multi-machine communication mode (MPCM=1). 
    2) The communication starts with the host sending an address frame, such as 8-bit data 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 host. In the MCU of all slaves, the RXC flag is set, indicating that the address frame has been 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 "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, determine that the read UDR data 0X01 is its own address, set the MPCM bit to "0", and receive all subsequent data frames sent by the host until the next address frame. 
      B) Processing of other slave MCUs: After receiving the address frame, they determine that the UDR data 0X01 is not their own address, and set the MPCM bit to "1". In this way, they will ignore the data frame sent by the host until the host sends the address frame again.
    5) After the addressed slave MCU receives the last data frame, it sets the MPCM bit 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 volume (including 1 address frame, n data frames, and 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 error or frame error is recorded    
   inbox[n]=UDR; //Save to inbox 
   n++; //Memory interrupt timesif 
   (ERROR) inbox[0]=0; //If the communication is wrong, 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 address filtering function (multi-machine communication function) 
   #asm("sei") //Open global interruptswhile 
   (1) 
   { 
     //-------------Talk to slave 2. Talk to other slaves is similar to the following program------------------- 
     n=0; //Clear interrupt times 
     inbox[0]=0; //Clear inbox address 
     //Please update the data to be sent 
     //send[1]=?   
     //...... 
     //send[n]=? 
     send[0]=2; //Change this address to talk to a slavesend 
     [amount-1]=crc8(send,amount-1); //Calculate the CRC8 checksum of the outboxusart_out 
     (send,amount); //Send the data in the outboxsend[]; 
     
     //Wait, the slave will reply after receiving the data. If the data is 10 bytes, it cannot be less than 13ms!!! 
     //This time is calculated manually. It is necessary to consider the possibility that the slave may extend the reply time due to various interruptsdelay_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 data and the crc8 check succeeds... 
     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 program 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 the received data to inbox 
   n++; //Memory 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 machine or the 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 the crc8 checksum of 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 the 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; 
        UCSRC=0xB6; 
        UBRRH=0x00; 
        UBRRL=47; 

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

//----------------------------------------------------------- 
//Send 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; //Put MAX485 in the sending state 
        while(i              {   
               if(i==0) UCSRB|=1; else UCSRB&=254;    
               UDR=*(datas+i); //Load data and start sendingwhile 
               ((UCSRA&64)==0); //Wait for the end of sending 
               UCSRA|=64; //Clear the send end flag 
               i++; //Send 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 microcontroller serial port multi-machine communication and examples

Previous article:How to solve the heating problem of atmega8
Next article:How to define variables in flash space in AVRGCC (big data storage)

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号