#C51串口通讯4-#一串数据#中断即时解析用户自定义协议(握手接收应答)

发布者:科技飞翔最新更新时间:2022-09-16 来源: csdn关键字:C51  串口通讯  中断 手机看文章 扫描二维码
随时随地手机看文章

前言

提示:

1.上一章测试一种方法:简单协议下利用串口中断实时接收数据并校验后进行解析。

2.实际项目开发时,主机下发命令后,从机首先进行握手确认,数据错误情况下要进行相应回应(如错误指令)。

3.本章继续丰富开发,增加主从应答机制


提示:以下是本篇文章正文内容,下面案例可供参考


一、场景

示例:

主机下发命令,从机中断解析并应答,主函数处理事件


二、编程实现

1.自定义协议

如:

image.png

##主机类型定义命令类型(查询,设置,器件控制等等)

以控制数码管显示0x01为例


##从机握手应答:

a.数据正确回复:BB66BB8000[SUM_CHECK][XOR_CHECK]

b.和校验错误回复:BB66BB8100[SUM_CHECK][XOR_CHECK]

c.异或校验错误回复:BB66BB8200[SUM_CHECK][XOR_CHECK]


数据区数值显示在数码管上,仅作最大2组显示为例


2.代码设计

第一步:基于已调试过的工程,确认一串数据正确被接收并返回


第二步:配置UART中断服务函数:

1.判断帧头2.数据长度确认3.数据缓存4.校验判断5.应答:正确或错误提示


void uart_ISR() interrupt 4

{

UC i;

if(RI)

{

RI = 0;

//超时接收处理方案

// timer_start = 1;

// recv_buf[recv_Cnt] = SBUF;

// recv_Cnt++;

// ctimer_Cnt = 0;


//中断即时解析处理方案

recv_data = SBUF;

switch(machine_step)

{

case 0:

if(0xAA == recv_data) //1.帧头符合,状态+1,下一次中断进入后继续检测,否则丢弃

{

machine_step = 1;

}

else

{

machine_step = 0;

}

break;

case 1:

if(0x66 == recv_data)

{

machine_step = 2;

}

else

{

machine_step = 0;

}

break;

case 2:

if(0xAA == recv_data)

{

machine_step = 3;

recv_Cnt = 0; //2.即将进入数据区,计数启动

}

else

{

machine_step = 0;

}

break;

case 3:

sum_check = recv_data;

xor_check = recv_data;

recv_buf[recv_Cnt] = recv_data; //3.数据类型,存第一个数

machine_step = 4;

break;

case 4:

data_length = recv_data; // 数据长度

sum_check += recv_data;

xor_check ^= recv_data;

recv_Cnt++;

recv_buf[recv_Cnt] = recv_data; 

machine_step = 5;

break;

case 5:

sum_check += recv_data;

xor_check ^= recv_data;

recv_Cnt++;

recv_buf[recv_Cnt] = recv_data;

if(data_length < recv_Cnt) //不满足时,依旧是状态5

{

machine_step = 6;

}

break;

case 6:

if(sum_check == recv_data) //5.校验判断 //recv_data已经是新的一个字节,

{

machine_step = 7;

}

else

{

machine_step = 0; //累加和错误,下次重新开始判断

sum_check = 0; //校验清0,否则下一串数据在状态3时出错

xor_check = 0;

//7.接收应答:和校验错误提示  

for(i = 0; i<7; i++)

{

sendByte(sum_check_error[i]);

}

}

break;

case 7:

if(xor_check == recv_data)

{

recv_flag = 1; //6.数据正确,标志置1

cRealLen = recv_Cnt + 1; //缓冲区长度(数据类型+数据长度+数据区)


//7.接收应答:接收正确

for(i = 0; i<7; i++)

{

sendByte(recv_correct[i]);

}

}

else

{

machine_step = 0; //异或校验错误,下次重新开始判断


//8.接收应答:异或校验错误提示

for(i = 0; i<7; i++)

{

sendByte(xor_check_error[i]);

}

}

sum_check = 0; //校验清0,否则下一串数据在状态3时出错

xor_check = 0;

machine_step = 0; //++的数都要记得在某个地方清0

recv_Cnt = 0; //不清也ok,养成习惯清除

break;

default:break;

}

}

}


其中,便于演示,应答提示提前分配ROM常量:


unsigned char code recv_correct[] = {0xBB,0x66,0xBB,0x80,0x00,0x80,0x80};

unsigned char code sum_check_error[] = {0xBB,0x66,0xBB,0x81,0x00,0x81,0x81};

unsigned char code xor_check_error[] = {0xBB,0x66,0xBB,0x82,0x00,0x82,0x82};


第3步:主函数处理:

缓冲区数据:数据类型+数据长度+数据区

功能:数据区数值显示在数码管上,16进制


if(recv_flag)

{

recv_flag = 0;

// timer_start = 0; //关掉定时器,防止T0一直在执行


for (i = 0; i < cRealLen; i++)

{

uart_Recv[i] = vbuf[i];

}

// sendString(vbuf); //test

sendString(uart_Recv);

Exchange_Func();

clr_recvbuffer(vbuf);

}


void Exchange_Func(void)

{

if(0x01 == uart_Recv[0]) //仅作演示,数据类型01控制数码管显示

{

switch(uart_Recv[1]) //数据长度代表显示的位数

{

case 1:

SEG_DisBuf[0] = 23;

SEG_DisBuf[1] = 23;

SEG_DisBuf[2] = uart_Recv[2] >> 4;

SEG_DisBuf[3] = uart_Recv[2] & 0x0F;

break;

case 2:

SEG_DisBuf[0] = uart_Recv[2] >> 4;

SEG_DisBuf[1] = uart_Recv[2] & 0x0F;

SEG_DisBuf[2] = uart_Recv[3] >> 4;

SEG_DisBuf[3] = uart_Recv[3] & 0x0F;

break;

case 3:

break;

default:break;

}

}


3.测试验证

实测ok

测试验证

总结

1.限制于无仿真器,故在UART中断服务函数中调试时,插入几处sendByte(),方便观察进行到哪一步。发现数据紊乱,原因在于一帧数据溢出进入服务函数时,调用的sendByte()又进入一次函数,数据被覆盖。

2.样例为方便演示。实际情况下,接收应答的处理可以设置标志位,在主函数中处理,中断服务函数中工作尽量少。

3.样例较上一章优点在于:不局限数据长度、接收应答机制

关键字:C51  串口通讯  中断 引用地址:#C51串口通讯4-#一串数据#中断即时解析用户自定义协议(握手接收应答)

上一篇:#C51串口通讯5-#一串数据#中断定时+超时接收+接收应答+CRC校验
下一篇:#C51串口通讯3-#一串数据#中断即时解析用户自定义协议

推荐阅读最新更新时间:2024-11-03 12:35

C51在程序设计中的内存分配问题
C中内存分为四个区 栈:用来存放函数的形参和函数内的局部变量。由编译器分配空间,在函数执行完后由编译器自动释放。 堆:用来存放由动态分配函数(如mal LOC )分配的空间。是由程序员自己手动分配的,并且必须由程序员使用free释放。如果忘记用free释放,会导致所分配的空间一直占着不放,导致内存泄露。 全局区:用来存放全局变量和静态变量。存在于程序的整个运行期间,是由编译器分配和释放的。 文字常量区:例如char *c = “123456”;则”123456”为文字常量,存放于文字常量区。也由编译器控制分配和释放。 程序代码区:用来存放程序的 二进制 代码。 例子(一) int a = 0; //全局区 void main()
[单片机]
STM32中按键中断分析
在按键学习中,我们有用到查询的方法来判断按键事件是否发生,这种查询按键事件适用于程序工作量较少的情况下,一旦程序中工作量较大较多,则势必影响程序运行的效率,为了简化程序中控制的功能模块的执行时间,引入中断控制就很有必要,,一旦有中断时间发生,则程序立马跳转到中断向量的执行程序中,执行完成后就恢复到正常的程序状态。 在STM32F中采用中断控制器NVIC来设定中断。按照中断初始化配置的结构体文件,我们需要在NVIC初始化结构体配置如下: void EXti_PB12_Config(void) { //定义结构体 GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeD
[单片机]
Keil C51下快速小数运算算法
0 引言 实时控制系统程序设计中,常涉及到小数运算问题.计算机系统中用二进制表示小数的方法有定点数表示法和浮点数表示法.采用浮点数表示法表示的小数范围大、精度高,但程序代码长,运算速度慢.定点数表示的小数范围小、精度低,但程序代码短,运算速度快. 使用C语言设计程序具有程序可读性强,编程方便等优点,但按常规方法设计程序时,实时性不如采用汇编语言设计的程序,这在涉及到小数运算时表现更为突出.这样就限制了C语言的应用.如果采用合适的计算方法,使用C语言编程可以获得与汇编语言编程同样的实时性. 实时控制系统中的前向通道采集的原始数据大多是定点整数,例如前向模拟通道的A/D转换器的转换结果,定时/计数器的计数结果等,都是定点整
[单片机]
Keil <font color='red'>C51</font>下快速小数运算算法
STM32-串口通讯协议开发02
STM32 USART 简介 STM32芯片具有多个USART外设用于串口通讯,USART(通用同步异步收发器)能够灵活地与外部设备进行全双工通讯。USART的全称“通用同步异步收发器”,也就是说他可以同步通信也可以异步通信。但是我们实现串口打印调试信息到电脑,其实只用到了他的异步通信的功能。 USART除了有串口功能,它满足外部设备对工业标准NRZ 异步串行数据格式的要求,并且使用了小数波特率发生器提供了多种波特率,使得它的应用更加广泛。它还支持同步单向通信和半双工单线通信;还支持 LIN(局域互连网络)、智能卡协议与 IrDA(红外线数据协会) SIR ENDEC 规范,以及调制解调器操作 (CTS/RTS)。而且,它还支
[单片机]
STM32-<font color='red'>串口通讯</font><font color='red'>协议</font>开发02
系统分析S3C2410的中断处理
S3C2410 中断 在介绍2410的中断处理之前,我们不得不先看看先把ARM的异常向量表(ExcepTIon Vectors),下面对异常向量表(ExcepTIon Vectors),做一个简单的介绍: ARM的异常向量表一般存放在0x00000000处,ARM920T能处理有7个异常,他们分别是:Reset,Undefined instrucTIon,Software Interrupt,Abort (prefetch),Abort (data),IRQ,FIQ 下面是系统源码片段: _start: b Handle_Reset b HandleUndef b HandleSWI b HandlePrefetchAbort
[单片机]
MPC860的中断处理技术研究
摘要:MPC860是网络通信设备中应用最广的一款RISC嵌入式处理器。本文介绍MPC860的中断体系结果及中断发生后服务程序的处理流程;以SMC1的接收中断为例,阐述在设计操作系统管理的条件下,中断初始化程序和中断服务程序的编写。 关键词:嵌入式处理器 MPC860 中断体系结构 中断处理技术 引言 Motorola公司推出的MPC860 PowerQUICC是目前在通信领域应用得非常广泛的一款嵌入式处理器,被誉为MC68360 PowerQUICC在网络和数据通信领域的新一代产品。与MC68360相比,MPC860 PowerQUICC在各方面的性能,包括器件的适应性、外部扩展能力和芯片集成度等都得到了提高。 MPC8
[嵌入式]
基于ARM中的IRQ的中断处理
Startup中断向量表 ;******************************************************************************* ; ExcepTIon vectors ;******************************************************************************* LDR PC, Reset_Addr ; 地址为0x8000 0000 LDR PC, Undefined_Addr LDR PC, SWI_Addr LDR PC, Prefetch_Addr LDR PC, Abort_Addr NOP ; R
[单片机]
C51 单片机 串口通讯总结——查询方式与中断方式
查询方式:发送数据——先发后查; 接收数据——先查后收。 中断方式:发送数据——发送、等待中断、中断中发送; 接收数据——等待中断、在中断中接收。 下面让我们通过两个列子进一步看一下两者的区别: /******************查询方式实现的串口通讯*************************/ #include reg52.h #define uint unsigned int #define uchar unsigned char uchar code table = E-mail:xtxy_esl@163.com ; uchar i,temp; //查询方式时必须EA=0;ES=0; //关总中断 void i
[单片机]
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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