完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
近段时间学习到 STM32 USART 部分,基本上在接收数据的时候都是采用定长,所以一直想实现接收任意长度的字符串。这里的任意长度不是指的无限长,而是在自己定义的缓冲区范围之类。比如说缓冲区的大小是 1024 Byte,那么就能接收不大于 1024 个字符串。
当时有两个思路: 1、使用结尾标志,如 "rn" 什么的 2、定时判断接收数据的长度,如果在规定的时间内长度没有发生变化,证明已经接收完了任意长度的字符 因为思路 1 比较好实现,而且网上也有很多例程,所以着重讲思路 2 宏定义: usart.h 文件 #ifndef USART_H #define USART_H #include "stm32f4xx.h" #define MAX_LENGTH 1024 #define USARTX USART3 #define USART_CLK RCC_APB1Periph_USART3 #define USART_BAUD_TATE 115200 #define USART_GPIO_PORT GPIOB #define USART_GPIO_CLK RCC_AHB1Periph_GPIOB #define USART_RX_PIN GPIO_Pin_11 #define USART_TX_PIN GPIO_Pin_10 #define USART_RX_PINSOURCE GPIO_PinSource11 #define USART_TX_PINSOURCE GPIO_PinSource10 #define GPIO_AF_USART GPIO_AF_USART3 #define USART_IRQN USART3_IRQn #define USART_IRQ_HANDLDER USART3_IRQHandler void USART_Init(void); char* USART_GetString(void); 注意: 本文中使用的是 STM32F405 系列的单片机,使用的是 USART3 ,请读者根据自己的单片机型号和 USART 做出相应更改 usart.c 文件 #include "./XXX/usart.h" //XXX 代表存放 usart.h 文件的路径 volatile char receiveBuffer[MAX_LENGTH]; volatile uint16_t receiveLength = 0; volatile uint8_t rxFlag = 0; static char str[MAX_LENGTH + 1]; static void GPIO_Config(void) { GIPO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(USART_GPIO_PORT, ENABLE); GPIO_PinAFConfig(USART_GPIO_PORT, USART_RX_PINSOURCE, GPIO_AF_USART); GPIO_PinAFConfig(USART_GPIO_PORT, USART_TX_PINSOURCE, GPIO_AF_USART); GPIO_InitStructure.GPIO_Pin = USART_RX_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(USART_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = USART_TX_PIN; GPIO_Init(USART_GPIO_PORT, &GPIO_InitStructure); } static void NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); NVIC_InitStructure.NVIC_IRQChannel = USART_IRQN; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } static void delay_us(uint16_t time) { uint8_t count; while(time--) { count = 10; while(count--); } } void USART_Init(void) { USART_InitTypeDef USART_InitStructure; RCC_APB1PeriphClockCmd(USART_CLK, ENABLE); GPIO_Config(); NVIC_Config(); USART_InitStructure.USART_BaudRate = USART_BAUD_TATE; USART_InitStructure.USART_WordLength = USART_WordLength_8b; 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(USARTX, &USART_InitStructure); USART_ITConfig(USARTX, USART_IT_RXNE, ENABLE); USART_Cmd(USARTX, ENABLE); } char* USART_GetString(void) { uint16_t temp; while(!rxFlag); //等待接收数据,在串口接收到一帧数据时 rxFlag 将会被置 1 (USART3 中断服务函数中) while(rxFlag) { temp = receiveLength; delay_us(500); //等待 500us if(temp == receiveLength) //判断 receiveLength 是否发生变化(USART3 中断函数中 receiveLength 会有变化),如果没有,证明已经收完所有的数据,否则等待接收完成 { rxFlag = 0; } } for(temp = 0; temp < receiveLength; temp++) { str[temp] = receiveBuffer[temp]; } receiveLength = 0; str[temp] = " "; return str; } stm32f4xx_it.c 文件 #include "./XXX/usart.h" //XXX 代表存放 usart.h 文件的路径 extern volatile char receiveBuffer[MAX_LENGTH]; extern volatile uint16_t receiveLength; extern volatile uint8_t rxFlag; /*USART3 中断服务函数*/ void USART_IRQ_HANDLDER(void) { char temp; if(USART_GetITStatus(USARTX, USART_IT_RXNE)) { USART_ClearITPendingBit(USARTX, USART_IT_RXNE); temp = USART_ReceiveData(USARTX) if(receiveLength == MAX_LENGTH) { return; } if(!rxFlag) { rxFlag = 1; } receiveBuffer[receiveLength++] = temp; } } main.c 文件 #include "./XXX/usart.h" //XXX 代表存放 usart.h 文件的路径 int main() { char* temp = NULL; USART_Init(); temp = USART_GetString(); while(1) { } } 总结: 当 USART 接收到一个字符时进入中断服务函数,在中断服务函数中会将 rxFlag 标志置 1 ,然后判断接收缓冲区 receiveBuff 是否溢出。若没有溢出,则将字符存储到接收缓冲区中,接收长度 receiveLength 做自加运算。 接收函数 GetString() 通过 500us 的间隔检测 receiveLength 是否发生改变,若没有发生改变,意味着 USART 已经接受完所有数据,则从接收缓冲区中取出接收到的数据。若发生改变,则意味着 USART 尚未接收完所有数据,所以等待其接收完所有数据。 本程序中存在一些不足,首先是如果接收缓冲区溢出了并不会报错,不过只能接收和缓冲区长度一致的字符。还有就是 receiveLength 的检测时间,理论上来说只需要设定为 3 * 接收一位数据的时间,即 3 / Baud 秒,但是通过逐一调试,发现只有大于 500us 时才能出现正确的结果。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1659 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1571 浏览 1 评论
998 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
695 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1617 浏览 2 评论
1877浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
663浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
529浏览 3评论
548浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
517浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-30 07:08 , Processed in 0.836633 second(s), Total 79, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号