STM32串口接收数据包(自定义帧头帧尾) 您所在的位置:网站首页 中断函数需要定义吗 STM32串口接收数据包(自定义帧头帧尾)

STM32串口接收数据包(自定义帧头帧尾)

2024-07-03 16:03| 来源: 网络整理| 查看: 265

1、基本概述

     本实验基于stm32c8t6单片机,串口作为基础且重要的外设,具有广泛的应用。本文主要理解串口数据包的发送与接收是如何实现的,重要的是理解程序的实现思路。

2、关键程序

定义好需要用到的变量:

uint8_t rxd_buf[4];//定义数组接收数据包,定长 uint8_t rxd_flag = 0;//接收标志 uint8_t rxd_index = 0;//接收索引

 程序理解:

程序放在串口中断函数里面实现。

首先,我们需要定义一个变量用于接收调试串口发过来的数据

u8 recv_dat;

 recv_dat =USART_ReceiveData(USART1);   USART_ReceiveData()是自带的函数,不需要我们定义,我们使用变量recv_dat接收上位机发送的数据。

2.1接收到数据后,进入switch判断,第一次默认从case 0进入。

2.2如果接收到帧头0xFE,将recv_state置1和索引置0,否则继续等待。

recv_state=1后就进入case 1中,将数据一个一个存入数组rxd_buf[4]中,即rxd_index++。然后我们需要判断是否接收完数据,我这个是接收4个定长数据。

2.3判断接收数据完成后,判断是否接收到帧尾0xFF,接收到帧尾后,将标志位置1,这个标志位是为了方便我们在其它程序里判断执行其它功能。记得将状态清零recv_state =0以接收下一包数据。

void USART1_IRQHandler(void) //串口1中断服务程序 { u8 recv_dat; static uint8_t recv_state = 0;//默认从索引0开始 if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断 { recv_dat =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据 switch(recv_state) { case 0: if(recv_dat == 0XFE)//接收到包头 { recv_state =1;//切换状态 rxd_index = 0; } else { recv_state =0;//切换状态 } break; case 1: rxd_buf[rxd_index]=recv_dat;//接收字符 rxd_index++; if(rxd_index>=4)//判断是否接收数据包完成1 { recv_state =2;//切换状态 } break; case 2: if(recv_dat == 0XFF)//接收到包尾 { rxd_flag = 1;//标志位置1 recv_state =0;//并将状态清零,接收下一包数据 } break; } USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清除中断标志位 } }

完整程序: 

usart.c

#include "usart.h" #include "led.h" uint8_t txd_buf[4]={1,2,3,4};//数据包 uint8_t rxd_buf[4];//定义数组接收数据包,定长 uint8_t rxd_flag = 0;//接收标志 uint8_t rxd_index = 0;//接收索引 /******************************************************************************* * 函 数 名 : USART1_Init * 函数功能 : USART1初始化函数 * 输 入 : bound:波特率 * 输 出 : 无 *******************************************************************************/ void USART1_Init(u32 bound) { //GPIO端口设置 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); /* 配置GPIO的模式和IO口 */ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX //串口输出PA9 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化串口输入IO */ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RX //串口输入PA10 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //浮空输入 GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化GPIO */ //USART1 初始化设置 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); //初始化串口1 USART_Cmd(USART1, ENABLE); //使能串口1 USART_ClearFlag(USART1, USART_FLAG_TC); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断 //Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //响应优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、 } //重定义printf函数 int fputc(int ch,FILE *p) //函数默认的,在使用printf函数时自动调用 { USART_SendData(USART1,(u8)ch); while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET); return ch; } //发送字符 void send_byte(uint8_t byte) { USART_SendData(USART1,byte); while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//等待发送完成 } //发送字符串 void send_string(uint8_t *str)//为什么是指针参数 { while(*str!='\0') //当字符串不为空时 { send_byte(*str++); } } //发送一组数据 void send_buf(uint8_t *buf,uint16_t len) { uint16_t i; for(i=0;iDR); //读取接收到的数据 switch(recv_state) { case 0: if(recv_dat == 0XFE)//接收到包头 { recv_state =1;//切换状态 rxd_index = 0; } else { recv_state =0;//切换状态 } break; case 1: rxd_buf[rxd_index]=recv_dat;//接收字符 rxd_index++; if(rxd_index>=4)//判断是否接收数据包完成1 { recv_state =2;//切换状态 } break; case 2: if(recv_dat == 0XFF)//接收到包尾 { rxd_flag = 1;//标志位置1 recv_state =0;//并将状态清零,接收下一包数据 } break; } USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清除中断标志位 } }

usart.h

#ifndef _usart_H #define _usart_H #include "system.h" #include "stdio.h" extern uint8_t rxd_flag;//接收标志 void USART1_Init(u32 bound); void send_byte(uint8_t byte); void send_string(uint8_t *str); void send_buf(uint8_t *buf,uint16_t len); void send_pack(void); #endif

main.c

#include "system.h" #include "SysTick.h" #include "led.h" #include "pwm.h" #include "usart.h" #include "key.h" #include "oled.h" int main() { SysTick_Init(72); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组 USART1_Init(115200); USART2_Init(115200); OLED_Init(); KEY_Init(); LED_Init(); send_string("hello stm32"); while(1) { if(rxd_flag == 1) { rxd_flag = 0; send_pack();//回显数据包 } } }



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有