当前位置:首页 > 单片机 > 单片机
[导读]在 《STM32串口向世界问好》介绍过如何发送消息,那么又如何接收消息呢?也很简单,只需要配置好串口接收,配置好中断,并在串口中断函数里面进行数据接收就可以了。通用配置代码如下:/***@brief初始化IO串口1*@par

在 《STM32串口向世界问好》介绍过如何发送消息,那么又如何接收消息呢?

也很简单,只需要配置好串口接收,配置好中断,并在串口中断函数里面进行数据接收就可以了。通用配置代码如下:

/***@brief初始化IO串口1*@parambound:波特率*@retvalNone*/voidUSART1_Debug_Init(u32bound){//GPIO端口设置GPIO_InitTypeDefGPIO_InitStructure;USART_InitTypeDefUSART_InitStructure;NVIC_InitTypeDefNVIC_InitStructure;assert_param(bound>0&&bound<=256000);RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);USART_DeInit(USART1);//复位串口1//USART1_TXPA.9GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//PA.9GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化PA9//USART1_RXPA.10GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化PA10//USART初始化设置USART_InitStructure.USART_BaudRate=bound;USART_InitStructure.USART_WordLength=USART_WordLength_8b;//字长为8位数据格式USART_InitStructure.USART_StopBits=USART_StopBits_1;//一个停止位USART_InitStructure.USART_Parity=USART_Parity_No;//无奇偶校验位USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//收发模式USART_Init(USART1,&USART_InitStructure);//初始化串口NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_Init(&NVIC_InitStructure);USART_ClearFlag(USART1,USART_FLAG_TC);//防止第一个数据被覆盖USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启中断USART_Cmd(USART1,ENABLE);//使能串口}

中断处理接收函数为:

voidUSART1_IRQHandler(void){u8res;if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)//接收中断有数据为1SET{res=(u8)USART_ReceiveData(USART1);res=res;}}

如果此时需要判断当接收的数据为1时点亮LED1,当接收数据为2时熄灭LED1则可在中断里作如下处理:

voidUSART1_IRQHandler(void){u8res;if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)//接收中断有数据为1SET{res=(u8)USART_ReceiveData(USART1);if(0x01==res){LED1=ON;}if(0x02==res){LED1=OFF;}}}

但这种接收控制方法是不够稳定与灵活的,比如在传输的过程中受到干扰,0x01 变成 0x02,则就会出现错误的控制。又比如我要接收一串数据并进行处理,这样就不好控制了。

这时我们就要想着制定一套通信协议来方便通信。

在此介绍一种简单通信协议,是我在设计一款无人机数据链通信时用到的一开源协议:MAVLink,另外加上CRC校验,进一步保证接收数据的可靠性。

其通信数据格式如下:


红色部分代表起始帧 STX 为 0xFE ; LEN表示要发送的数据长度(PAYLOAD长度);SEQ表示数据的序列号,循环从0至255发送(可以检测是否丢包,并可能过此来判断信号强度);SYS是用来表示区分同一网络中不同飞行器号的,即系统ID;COMP代表组件ID,表示飞行器上各个组成部分,如飞控单元,GPS等;MSG则代表消息ID,即要发送不同控制命令ID;PAYLOAD表示此命令的内容;最后两字节是自动生的的CRC校验码 。

从上图也可以看出PAYLOAD有效长度可为0至255字节(因为LEN来表示,它们都是无符号8位数据类型),所以一条消息长度最小为8字节,最大为263字节。

至此一简单通信协议就介绍过了,说的有点多。下面就是如何对其解析,话不多说直接代码说明:

#defineMavlinkLenMin8#defineMavlinkLenMax263#defineSTX0xFE//MAVLINKHEAD#defineAdd_STX0x00#defineAdd_LEN0x01#defineAdd_SEQ0x02#defineAdd_SYS0x03#defineAdd_COMP0x04#defineAdd_MSG0x05#defineAdd_PAYLOAD0x06//PAYLOADstartfrom0x06typedefenum{BEEN_RECEIVED=0,RECEIVING=!BEEN_RECEIVED}Receive_Status;typedefstruct{booleanGet;u16Len;u8Cache[MavlinkLenMax];}MAVLink_Data_Struct,*MAVLink_Data_Struct_p;MAVLink_Data_StructMsg_Rev;voidMsg_Recv_Data_Analyse_Irq(u8data){if(RECEIVING==Msg_Rev.Get){Msg_Rev.Cache[Msg_Rev.Len++]=data;if(STX!=Msg_Rev.Cache[Add_STX]){Msg_Rev.Len=0;}if(((u16)Msg_Rev.Cache[Add_LEN]+MavlinkLenMin)==Msg_Rev.Len){Msg_Rev.Get=BEEN_RECEIVED;}}}

可在串口中断接收函数里调用此函数用作协议数据接收解析

voidUSART1_IRQHandler(void){u8res;if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)//接收中断有数据为1SET{res=(u8)USART_ReceiveData(USART1);Msg_Recv_Data_Analyse_Irq(res);}}

当一条消息接收完成后,Msg_Rev.Get的状态就会被设置成BEEN_RECEIVED ,这时就可在相关函数中对此条消息进行处理。

另外为了消息的更可靠,还可加入CRC校验,如下函数就是一简单通用的CRC16校验码生成函数:

u16crc_chk_value(u8*data_value){u16crc_value=0xFFFF;u16length=(uint16_t)data_value[1]+6;u16i;while(length--){crc_value^=*data_value++;for(i=0;i<8;i++){if(crc_value&0x0001)crc_value=(crc_value>>1)^0xa001;elsecrc_value=crc_value>>1;}}return(crc_value);}

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭