Section 39: Determine the data header to receive a serial port general program framework

Publisher:WhisperingSoulLatest update time:2016-03-15 Source: eefocus Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
Opening remarks:

The previous section talked about the program framework for judging the data tail, but in most projects, data is received by judging the data header. This section will teach you two knowledge points:

The first one is how to parse the data header protocol and extract valid data from a string of data that has been received.

Second: Whether judging the data header or the data tail, whether it is a single-chip microcomputer or a host computer, it is best to send an extra padding invalid byte 0x00 before the fixed protocol, because due to hardware reasons, the first byte is often easily lost.

For details, please see the source code.

(1) Hardware platform:

Based on Zhu Zhaoqi 51 single-chip microcomputer learning board.

(2) Functions to be implemented:

The baud rate is: 9600.

Communication protocol: EB 00 55 XX YY

After adding invalid padding bytes, the host computer should actually send: 00 EB 00 55 XX YY

The first bit 00 is an invalid fill byte to prevent the first byte from being lost due to hardware reasons.

The 2nd, 3rd and 4th digits EB 00 55 are the data header.

The last two digits XX YY are valid data.

At any time, in a string of data received by the MCU from the computer "Serial Port Debug Assistant" host computer, as long as the data contains the keyword EB 00 55, and the two bytes of data XX YY after this keyword are 01 02 respectively, the buzzer will beep once to indicate that the received data header and valid data are correct.

(3) The source code is explained as follows:

#include "REG52.H"

#define const_voice_short 40 //Duration of the buzzer short call

#define const_rc_size 10 //Buffer array size for receiving serial port interrupt data

#define const_receive_time 5 //If no serial data comes in after this time, it is considered that a string of data has been received. This time can be adjusted according to the actual situation

void initial_myself(void);

void initial_peripheral(void);

void delay_long(unsigned int uiDelaylong);

void T0_time(void); //Timer interrupt function

void usart_receive(void); //Serial port receive interrupt function

void usart_service(void); //Serial port service program, in the main function

sbit beep_dr=P2^7; //Buzzer driver IO port

unsigned int uiSendCnt=0; //Timer used to identify whether the serial port has received a string of data

unsigned char ucSendLock=1; //Self-locking variable of the serial port service program. Each time a string of data is received, it is processed only once.

unsigned int uiRcregTotal=0; // represents how much data the current buffer has received

unsigned char ucRcregBuf[const_rc_size]; //Buffer array for receiving serial port interrupt data

unsigned int uiRcMoveIndex=0; //Intermediate variable used to parse data protocol

unsigned int uiVoiceCnt=0; //Buzzer beeping duration counter

void main()

{

initial_myself();

delay_long(100);

initial_peripheral();

while(1)

{

usart_service(); //Serial port service program

}

}

void usart_service(void) //Serial port service program, in the main function

{

/* Note 1:

* The principle of identifying whether a string of data has been completely received:

* If no byte of data is received within the specified time, it is considered that a string of data has been received, and then the data protocol is entered.

* Parsing and processing stage. The implementation of this function should be read together with the timing interrupt and serial port interrupt programs to understand the relationship between them.

*/

if(uiSendCnt>=const_receive_time&&ucSendLock==1) //Indicates that no new data is coming from the serial port after a certain period of time.

{

ucSendLock=0; //Lock after processing once, no need to come in every time unless there is new data to be received

//The following code enters the stage of data protocol parsing and data processing

uiRcMoveIndex=0; //Since it is to judge the data head, the subscript movement variable starts from 0 of the array and moves to the end

/* Note 2:

* To judge the data header and enter the loop to parse the data protocol, two conditions must be met:

* First: The maximum receive buffer data must be greater than the length of a string of data (here is 5. Including 2 valid data and 3 data headers)

* Second: The cursor uiRcMoveIndex must be less than or equal to the maximum receive buffer data minus the length of a string of data (here is 5. Including 2 valid data and 3 data headers)

*/

while(uiRcregTotal>=5&&uiRcMoveIndex<=(uiRcregTotal-5))

{

if(ucRcregBuf[uiRcMoveIndex+0]==0xeb&&ucRcregBuf[uiRcMoveIndex+1]==0x00&&ucRcregBuf[uiRcMoveIndex+2]==0x55) //judgment of data header eb 00 55

{

if(ucRcregBuf[uiRcMoveIndex+3]==0x01&&ucRcregBuf[uiRcMoveIndex+4]==0x02) //Judgement of valid data 01 02

{

uiVoiceCnt=const_voice_short; //The buzzer makes a sound, indicating that the data header and valid data are received correctly

}

break; //Exit the loop

}

uiRcMoveIndex++; //Because it is to judge the data head, the cursor moves towards the end of the array

}

uiRcregTotal=0; // Clear the buffer index to facilitate receiving new data from index 0 next time

}

}

void T0_time(void) interrupt 1 //Timer interrupt

{

TF0=0; //Clear interrupt flag

TR0=0; //Disable interrupt

if(uiSendCnt

{

uiSendCnt++; //On the surface, the data is continuously accumulated, but in the serial port interrupt, it will be cleared every time a byte is received, unless there is no serial port data in the middle

ucSendLock=1; //Open the self-locking flag

}

if(uiVoiceCnt!=0)

{

uiVoiceCnt--; //Every time the timer interrupt is entered, it will be decremented by 1 until it is equal to zero. Then the beeping will stop.

beep_dr=0; //The buzzer is controlled by a PNP transistor and starts beeping when the voltage level is low.

}

else

{

; //Add an extra empty instruction here to maintain symmetry with the number of if bracket statements, both are two instructions. It is also OK not to add it.

beep_dr=1; //The buzzer is controlled by a PNP transistor, and it stops beeping when the level is high.

}

TH0=0xfe; //Reinstall initial value (65535-500)=65035=0xfe0b

TL0=0x0b;

TR0=1; //Open interrupt

}

void usart_receive(void) interrupt 4 //Serial port receiving data interrupt

{

if(RI==1)

{

RI = 0;

++uiRcregTotal;

if(uiRcregTotal>const_rc_size) //Exceeds the buffer

{

uiRcregTotal=const_rc_size;

}

ucRcregBuf[uiRcregTotal-1]=SBUF; //Cache the data received by the serial port into the receiving buffer

uiSendCnt=0; // Feed the dog in time. Although the main function keeps accumulating, it will never grow as long as the serial port data has not been sent out, because each interrupt is cleared.

}

else //I don't use this code on other MCUs. Maybe adding "TI = 0;" on 51 MCU will improve stability.

{

TI = 0;

}

}

void delay_long(unsigned int uiDelayLong)

{

unsigned int i;

unsigned int j;

for(i=0;i

{

for(j=0;j<500;j++) //Number of empty instructions in the embedded loop

{

; //A semicolon is equivalent to executing an empty statement

}

}

}

void initial_myself(void) //Initialize the MCU in the first zone

{

beep_dr=1; //Use PNP transistor to control the buzzer, it will not sound when the output is high level.

//Configure the timer

TMOD=0x01; //Set timer 0 to working mode 1

TH0=0xfe; //Reinstall initial value (65535-500)=65035=0xfe0b

TL0=0x0b;

//Configure the serial port

SCON=0x50;

TMOD=0X21;

TH1=TL1=-(11059200L/12/32/9600); //I am not sure what this configuration code means, but it is related to the baud rate of the serial port.

TR1=1;

}

void initial_peripheral(void) // Initialize the periphery of the second zone

{

EA=1; //Open the general interrupt

ES=1; //Enable serial port interrupt

ET0=1; //Enable timer interrupt

TR0=1; //Start timing interrupt

}

Closing remarks:

This section describes the commonly used program framework for judging the data header to receive a string of data. However, in many projects, it is not enough to just judge the data header. A more detailed communication protocol is required, such as a communication protocol that can include data type, valid data length, valid data, and data verification. How to write such a program? For details, please listen to the next analysis - commonly used custom serial port communication protocols.

Reference address:Section 39: Determine the data header to receive a serial port general program framework

Previous article:Section 38: Determine the end of the data to receive a string of data serial port general program framework
Next article:Section 40: Commonly used custom serial communication protocols

Latest Microcontroller Articles
  • 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)
    Since development under LINUX is still quite troublesome, is there a more convenient and simple development method under WINDOWS? The answer is yes. Of course, it is not a development tool like ADS, because it ...
  • Learn ARM development(15)
    When using GCC to develop ARM, you will definitely encounter compiler problems. For example, you will encounter various warnings and errors when compiling C code. For example, I encountered several warnings yesterday, so let's take a look at what these warnings are ...
  • Learn ARM development(16)
  • Learn ARM development(17)
  • Learn ARM development(18)
  • Embedded system debugging simulation tool
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号