8051单片机串口复杂命令接收与解析

发布者:cheng1984最新更新时间:2021-08-11 来源: eefocus关键字:单片机  串口 手机看文章 扫描二维码
随时随地手机看文章

下面程序是为了实现二自由度自动进样检测器的控制而编写的. 在程序执行过程中, 我发现, 在发送Start.E再发送Stop.E后, 串口助手接收缓存区并未显示一连串"00": 这说明在输入Start.E后, 虽然又收到Stop.E时执行了"en = 0"这个表达式, 但是回到第一层中断处理程序后, 这里的en还是"1"(并未变为我们希望的"0"). 这说明, 以串口中断实现对二自由度自动进样检测仪的控制, 还是有一定难度的. 接下来我将致力于解决这一难题.


#include <STC89C5xRC.H>


char buf[30];//存放串口传来的数据


int i = 0;


int en;


void UART_INT() interrupt 4//串行通信中断处理程序

{

    int len = 0;

    int j = 0;

    if(RI == 1)//如果收到数据

    {

        if(i == 30)

        {

            i = 0;//防止越界访问

        }

        RI = 0;

        buf[i++] = SBUF;//将数据接收下来

        if(buf[i - 1] == 'E')//到达结尾

        {

            len = i - 1;//记录数据长度

            i = 0;

            if(len == 6)

            {

                if(buf[0] == 'S' && buf[1] == 't' && buf[2] == 'a' && buf[3] == 'r' && buf[4] == 't' && buf[5] == '.')

                {

                    //Start命令(开机)

                    en = 1;

                    while(1)

                    {

                        SBUF = 1;

                        while(TI == 0);

                        TI = 0;

                        while(en == 0)

                        {

                            SBUF = 0;

                            while(TI == 0);

                            TI = 0;

                        }

                    }

                }

                else if(buf[0] == 'R' && buf[1] == 'e' && buf[2] == 's' && buf[3] == 'e' && buf[4] == 't' && buf[5] == '.')//主转盘回到原始位置,针臂抬到最高位置

                {

                    //Reset命令(复位命令)

                    while(j < len)

                    {

                        SBUF = buf[j];

                        while(TI == 0);//等待数据发送

                        TI = 0;

                        j++;

                    }

                    j = 0;

                    en = 0;

                }

            }

            else if(len == 5)//停机命令

            {

                if(buf[0] == 'S' && buf[1] == 't' && buf[2] == 'o' && buf[3] == 'p' && buf[4] == '.')

                {

                    //Stop命令(停机命令)

                    en = 0;

                }

            }

            else if(len == 18)//要求主转盘转动相应格数

            {

                if(buf[0] == 'M' && buf[1] == 'a' && buf[2] == 'i' && buf[3] == 'n' && buf[4] == ' ' && buf[5] == 'm' && buf[6] == 'o' && buf[7] == 't' && buf[8] == 'o' && buf[9] == 'r' && buf[10] == ' ' && buf[11] == 'r' && buf[12] == 'u' && buf[13] == 'n' && buf[14] == ' ')

                {

                    //Main motor run命令,比如Main motor run 22.

                    if(buf[15] >= '1' && buf[15] <= '9' && buf[16] >= '1' && buf[16] <= '9')//确定发来的步数是数字

                    {

                        while(j < len)

                        {

                            SBUF = buf[j];

                            while(TI == 0);//等待数据发送

                            TI = 0;

                            j++;

                        }

                        j = 0;

                    }

                }

            }

        }

    }

}


int main()

{

    RI = 0;

    TI = 0;

    TMOD = 0x21;

    SCON = 0x50;

    TH1 = 0xe6;

    TL1 = 0xe6;

    TR1 = 1;

    IE = 0x90;

    while(1)

    {

        ;//采用前后台系统架构

    }

}

 


我将上述程序中的轮询部分去除, 并分别以D8/D7/D6/D5的点亮对应Start./Reset./Stop.E/Main motor run steps.命令.


在运行后发现, 四种命令完美对应四盏灯的亮灭.


#include


char buf[30];//存放串口传来的数据


int i = 0;


int en = 0;


void UART_INT() interrupt 4//串行通信中断处理程序

{

    int len = 0;

    int j = 0;

    if(RI == 1)//如果收到数据

    {

        if(i == 30)

        {

            i = 0;//防止越界访问

        }

        RI = 0;

        buf[i++] = SBUF;//将数据接收下来

        if(buf[i - 1] == 'E')//到达结尾

        {

            len = i - 1;//记录数据长度

            i = 0;

            if(len == 6)

            {

                if(buf[0] == 'S' && buf[1] == 't' && buf[2] == 'a' && buf[3] == 'r' && buf[4] == 't' && buf[5] == '.')

                {

                    //Start命令(开机)

                    en = 1;

                    P27 = 0;//D8亮

                    P26 = 1;

                    P25 = 1;

                    P24 = 1;

                }

                else if(buf[0] == 'R' && buf[1] == 'e' && buf[2] == 's' && buf[3] == 'e' && buf[4] == 't' && buf[5] == '.')//主转盘回到原始位置,针臂抬到最高位置

                {

                    //Reset命令(复位命令)

                    en = 0;

                    P27 = 1;

                    P26 = 0;//D7亮

                    P25 = 1;

                    P24 = 1;

                }

            }

            else if(len == 5)//停机命令

            {

                if(buf[0] == 'S' && buf[1] == 't' && buf[2] == 'o' && buf[3] == 'p' && buf[4] == '.')

                {

                    //Stop命令(停机命令)

[1] [2]
关键字:单片机  串口 引用地址:8051单片机串口复杂命令接收与解析

上一篇:8051单片机(STC89C52)稳定显示某两位数字
下一篇:51单片机——八段数码管

推荐阅读最新更新时间:2024-11-11 04:13

AVR单片机内部RC振荡器和能隙电压基准的稳定性研究
曾经在反复研究 MEGA 48 的内部 RC 振荡器 和 能隙 电压 基准的稳定性后,选择了 MEGA 48, 用内部 RC 来驱动 做串口通信.一直都比较成功! 突然前些天, 发现上次能正常通信的软件, 通信不了了! 反复检查后, 很仔细才发现 mega48 的振荡 频率 在示波器上,略有些偏大了! 为此,我对 OS CC AL 直接加大 3 后, 通信完全正常! 于是,就该芯片我对 振荡的温度漂移做了简单的试验.希望能给大家一些参考.由于条件简陋, 我唯一改变温度的办法是 热风枪. 为了便于对比,我使用了外部的稳定的频率作参考,然后应用自己编写的自动校准软件对 片内 RC 振荡器频率进行测量 该芯片的 出厂校正参数为 A3
[单片机]
HT1621LCD驱动 PIC单片机
STATUS EQU 3H FSR EQU 4H RB EQU 6H RC EQU 7H OPTIONA EQU 81H TRISB EQU 86H TRISC EQU 87H GENR0 EQU 053H GENR1 EQU 054H WD_RG EQU 055H DA_AG0 EQU 056H ;SEG0 SEG1 DA_AG8 EQU 05EH ;SEG16 SEG17 ;............................. C EQU 0 Z EQU 2 RP0 EQU 5 RP1 EQU 6 CS
[单片机]
51单片机 串口通信 中断
从一段程序开始 实现电脑向单片机发送一些数据,单片机返回Iget +数据 #include #define uchar unsigned char #define uint unsigned int unsigned char flag,a,i;//声明标志位 flag uchar code table = I get void init() { TMOD=0x20;//设置T1定时器工作方式为2 8位初值自动重装的8位定时器 这里设置了两个计数器的工作方式 TH1=0xfd; / /T1定时器装初值(高八位) 控制串口通信的波特率(由定时器1的溢出率控制) TL1=0xfd; //T1定时器装入初值(低八位)
[单片机]
程序的思考(从单片机到PC)
关于程序的执行,以前想的不多,没有意识到一个程序在运行时,从哪里读指令,数据又写在哪里。 从单片机上知道,在上电的那一刻,MCU的程序指针PC会被初始化为上电复位时的地址,从哪个地址处读取将要执行的指令,由此程序在MCU上开始执行(当然在调用程序的 main之前,还有一系列其他的的初始化要做,如堆栈的初始化,不过这些我们很少回去修改)。PC在上电时,和MCU差不多,不过读取的是BIOS,有它完成了很多初始化操作,最后,调用系统的初始化函数,将控制权交给了操作系统,于是我们看到了Windows,Linux系统启动了。如果将操作系统看作是在处理器上跑的一个很大的裸机程序(就是直接在硬件上跑的程序,因为操作系统就是直接跑在CPU上的,这样
[单片机]
学51单片机-按键的扫描检测与消抖
触发按键,简称按键,是电路设计中常用的器件之一。种类很多,有贴片式的,有直插式的,有四条腿的,也有两条腿的。一般根据需求,进行高低、大小的选择。 如上图所示,样式非常多。记得我第一次去中发买按键的时候,老板问我要什么样的,我也不知道,就说常用的就行。老板嘿嘿一笑,知道我是新人,就拿了几款常见的给我选。 现在自然不会这么笨,一般来说,选择的参数也就这么几项,尺寸、高度、封装方式。例如我想买一种按键,我就直接问老板:6*6*5,四脚贴片的按键有木有? 6*6是什么意思?占地面积,单位是毫米,就是说长和宽都是6mm的。 5是高度,按键整体高度,单位是毫米。要求精细的,会说明按键座的高度和按键头的高度。
[单片机]
学51<font color='red'>单片机</font>-按键的扫描检测与消抖
单片机LED灯计数
电路图: 代码如下: #include reg51.h sbit P1_7 = P1 ^ 7; sbit P1_6 = P1 ^ 6; sbit P1_5 = P1 ^ 5; sbit P1_4 = P1 ^ 4; void delay(unsigned char i) { unsigned int j = 0,k = 0; for(k = 0; k i; k++) for(j = 0; j 255; j++); } void main(void) { char i = 0; while (1) { P1_7 = 0; delay(200); P1_6 = 0; de
[单片机]
<font color='red'>单片机</font>LED灯计数
关Atmega16单片机进入“编程模式失败”问题的解决办法之一
最近在搞ATmega16单片机,自己做了一个PCB板子,一开始还能下程序,可是下了几次后,就突然间下不进去了,每次都提示“进入编程模式失败”,如下图 又有如下的提示,大致是说下载速率过快,下载频率应该小于单片机晶振的四分之一 网上查了好多资料,但是一直不知道怎么弄,怀疑自己的单片机熔丝位被改了,或者被锁了,或者自己画的电路板有问题,为此换了好几块单片机都是这样的,搞得自己焦头烂额。搞了一个多星期,被自己无意间操作了如下步骤,就是如下图 再找到如下区域 就是这个ISP一项。我用的是STK500 下载器, USBISP下载方式下载的。一开始这个图中的“ISP”右边的下拉框是没有数据的,我点开它,给它设定为57.6kHz
[单片机]
关Atmega16<font color='red'>单片机</font>进入“编程模式失败”问题的解决办法之一
你了解你的GD32 MCU系统主频是多少吗 ?
系统时钟是GD32 MCU的时基,可以理解为系统的心跳,片上所有的外设以及CPU最原始的时钟都来自于系统时钟,因而明确当前系统时钟是多少非常重要,只有明确了系统时钟,才能够实现准确的定时、准确的采样间隔以及准确的通信速率等。 以GD32F303为例,其系统时钟配置在system_gd32f30x.c中,如下图所示,可以通过打开或者关闭相关的宏定义进行时钟配置,GD32以及提供了一些时钟配置的函数,可以通过宏定义开关进行选择。 确认当前系统时钟有以下两个方法: 1、软件方式确认 使用void SystemCoreClockUpdate(void)函数进行更新当前系统时钟SystemCoreClock,该函数为根据当前RCU
[单片机]
你了解你的GD32 <font color='red'>MCU</font>系统主频是多少吗 ?
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved