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
#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);
}
Previous article:How to solve the heating problem of atmega8
Next article:How to define variables in flash space in AVRGCC (big data storage)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- Are ADC accuracy and resolution the same thing?
- Won't boot!!! How wrong is this schematic?
- EEWORLD University ---- RISC-V Processor Design Series
- [NUCLEO-L552ZE Review] +RT-Thread Porting
- Single source shortest path - Dijkstara algorithm
- Why can't the external interrupt 0 of the STC15W204S microcontroller be entered? Can the serial port interrupt send data?
- Synopsys' latest IP resource recommendations - artificial intelligence, automotive, and high-performance computing
- AD PCB ad cannot be selected after copper coating, it is not a problem of which layer
- About fatalerror in Modelsim simulation
- Several concepts about switching power supply