51单片机串口通信接收多字节判断

用51单片机实现串口通信,并对接收到的6个十六进制数与初定十六进制数55 00 03 11 00 ec作比较

这是一个基本的 51 单片机串口接收程序,用于接收六个十六进制数,并将其存储到一个数组中。程序然后与给定的六个十六进制数进行比较,如果匹配,它将向串口发送一个“O”消息,否则发送“E"

#include <reg51.h>

#define BUFFER_SIZE 6

unsigned char buffer[BUFFER_SIZE];
unsigned char expected[] = {0x55, 0x00, 0x03, 0x11, 0x00, 0xec};

void main() {
    unsigned char i;

    // 初始化串口和时钟,参考上面的,不多写了
    // ...

    // 循环接收 6 个字节的数据
    for (i = 0; i < BUFFER_SIZE; i++) {
        while (!RI); // 等待接收到数据
        buffer[i] = SBUF; // 读取接收到的数据
        RI = 0; // 清除接收中断标志
    }

    // 比较接收到的数据与预期的数据
    for (i = 0; i < BUFFER_SIZE; i++) {
        if (buffer[i] != expected[i]) {
            // 如果不匹配,向串口发送一个错误消息并退出程序
            SBUF = 'E';
            while (!TI); // 等待发送完成
            TI = 0; // 清除发送中断标志
            return;
        }
    }

    // 如果匹配,向串口发送一个成功消息
    SBUF = 'O';
    while (!TI); // 等待发送完成
    TI = 0; // 清除发送中断标志
}

注意,这是一个基本的示例程序。在实际的应用中,你需要根据你的具体需求对其进行修改和优化。例如添加超时机制来避免无限等待串口数据。

参考GPT和自己的思路,可以使用以下代码实现串口通信,并判断接收到的数据是否与目标数据相同:

#include <reg51.h>
#include <stdio.h>

// 串口初始化
void UartInit()
{
    SCON = 0x50;    // 8位数据位,可变波特率
    TMOD &= 0x0F;   // 设置定时器1为模式2
    TMOD |= 0x20;
    TH1 = 0xFD;     // 波特率9600
    TL1 = 0xFD;
    TR1 = 1;        // 启动定时器1
    ES = 1;         // 允许串口中断
    EA = 1;         // 开启总中断
}

// 串口中断服务函数
void Uart() interrupt 4
{
    if (RI) // 接收中断
    {
        RI = 0; // 清除接收标志位
        // 处理接收到的数据
        unsigned char data = SBUF; // 读取接收缓冲区
        // 比较接收到的数据是否与目标数据相同
        if (data == 0x55)
        {
            // 接收到第一个字节,开始比较后续的5个字节
            unsigned char recvData[6];
            recvData[0] = data;
            int i;
            for (i = 1; i < 6; i++)
            {
                while (!RI); // 等待接收完成
                RI = 0; // 清除接收标志位
                recvData[i] = SBUF; // 读取接收缓冲区
            }
            // 比较接收到的数据是否与目标数据相同
            if (recvData[1] == 0x00 && recvData[2] == 0x03 && recvData[3] == 0x11 && recvData[4] == 0x00 && recvData[5] == 0xec)
            {
                // 接收到目标数据,执行相应操作
            }
        }
    }
}

int main()
{
    UartInit();
    while (1);
    return 0;
}

以上代码中,UartInit()函数用于初始化串口,Uart()函数是串口中断服务函数,每当接收到一个字符时,中断服务函数就会被触发。在中断服务函数中,我们通过判断接收到的数据是否为目标数据的第一个字节(0x55),来启动接收并比较后续的5个字节。如果接收到的数据与目标数据相同,则执行相应的操作。在main()函数中,我们仅仅启动了串口,然后进入一个死循环,保证程序不会退出。

  • 关于该问题,我找了一篇非常好的博客,你可以看看是否有帮助,链接:51单片机串口通信发送乱码
  • 除此之外, 这篇博客: 51单片机—串口通信中的 - 实现51单片机串口通信的知识储备 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 目的:用异步通信实现单片机与计算机之间的数据交流
    1.波特率
    波特率可以衡量数字信号传输的速率,其大小为每秒传输二进制数的位数,单位为:bps。比如:每秒传输300帧数据,一帧数据是十个二进制数,则传输速率就是300x10=3000(bps)。单片机和计算机的传输速率要一致。
    2.波特率的设置
    计算机的波特率可以在界面上直接调整,那单片机的波特率要怎么设置呢?
    我们一般是把T1(定时中断1)作为波特率的发生器,而且利用的是T1的工作方式2。
    此时波特率的计算公式为:在这里插入图片描述
    解释一下公式内容:
    一.SMOD
    SMOD属于PCON寄存器,不可位寻址,大家可以把其理解为波特率加倍标志,置0的时候不加倍,置1的时候波特率加倍。
    在这里插入图片描述
    二. fosc
    fosc就是单片机的晶振频率,一般是11.0529MHz(还有一种情况是12MHz,但其误差相对较大,一般不予采用)1M=1000,000
    三.(256-T初)
    T1的工作方式2是八位数据自动装填(八位二进制数的范围是0~255,共256个数),初始值在开始时装入TH1和TL1,工作时只有TH1计数,当TH1溢出时把TL1中的初始值重新赋值给TH1,这样就实现了自动装填。
    (256-T初)代表着每次定时器计数的次数。
    3.如何设置波特率(假如设置波特率为9600bps)
    首先-设置定时器T1的工作方式:编辑TMOD寄存器为TMOD=0X20;使定时器T1处于工作方式2;
    然后-计算T1的初始值并装载TH1和TL1,波特率为9600bps时TH1=0XFD、TL1=0XFD;
    最后-启动T1:编辑TCON寄存器中的TR1,使TR1=1(打开T1定时器)。通过设置PCON寄存器PCON=0X00设置SMOD=0。
    4.如何确定串行口控制
    通过编辑SCON寄存器控制串行口
    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述在这里插入图片描述
    其实主要是控制串行口的工作方式:SM0=0、SM1=1,和打开串行口的允许接收位:REN=1。
    5.打开中断
    打开总中断和串口通信中断:EA=1、ES=1。
    6.SBUF寄存器
    前面讲了一大堆铺垫,相信大家都有一个疑问:单片机是怎么发送数据呢?它又是如何接收数据呢? 如果要细讲这其中的传输原理,那会是复杂难懂的,好在单片机的内部硬件自带发送和接收数据的功能,它是通过SBUF寄存器实现的。
    SBUF寄存器有俩个,一个是发送寄存器,另一个是接收寄存器(名字都一样),但在逻辑上SBUF只有一个(地址都为99H),物理结构上,这是俩个完全独立的寄存器。如果CPU写SBUF,数据就会被送入发送寄存器准备发送;如果CPU读SBUF,则读入的数据一定来自接收寄存器。
    简单来讲:a=SBUF,代表单片机从计算机接收到了数据(接收到的数据自动存在接收寄存器SBUF中)并且从接收寄存器SBUF读取数据并赋给a。SBUF=a,代表单片机要给计算机发送a数据,只需将a赋给发送寄存器SBUF就行,发送寄存器SBUF会自动给计算机发送SBUF中的数据。
    下面是其工作图:
    在这里插入图片描述(RXD是接收引脚,TXD是发送引脚)
    7.TI与RI
    TI和RI都在SCON寄存器中。
    TI是发送中断标志位,当数据发送完成后,TI由硬件置1,TI置1后向CPU提出中断申请,进入中断函数后需要软件置0(TI=0;)
    RI是接收中断标志位,当数据接收完成后,RI由硬件置1,RI置1后向CPU提出中断申请,进入中断函数后需要软件置0(RI=0;)
    8.串口中断
    串口中断函数是

    void (函数名无所谓) interrupt 4
    {
    	中断程序;
    }
    

    一旦TI或者RI为1就执行中断函数,并且需要在中断函数中将TI、RI重新置0。

1、定义一个足够大的数组作为缓存区,进行接收串口数据(使用串口通信接收函数进行接收数据);
2、在循环中取出接收的数组每一位与需要的内容进行比较,如果符合则在串口助手打印提示内容即可(使用串口通信发送函数)。