程序中为什么串口接收不到数据串口发来的数据,而串口

新手园地& & & 硬件问题Linux系统管理Linux网络问题Linux环境编程Linux桌面系统国产LinuxBSD& & & BSD文档中心AIX& & & 新手入门& & & AIX文档中心& & & 资源下载& & & Power高级应用& & & IBM存储AS400Solaris& & & Solaris文档中心HP-UX& & & HP文档中心SCO UNIX& & & SCO文档中心互操作专区IRIXTru64 UNIXMac OS X门户网站运维集群和高可用服务器应用监控和防护虚拟化技术架构设计行业应用和管理服务器及硬件技术& & & 服务器资源下载云计算& & & 云计算文档中心& & & 云计算业界& & & 云计算资源下载存储备份& & & 存储文档中心& & & 存储业界& & & 存储资源下载& & & Symantec技术交流区安全技术网络技术& & & 网络技术文档中心C/C++& & & GUI编程& & & Functional编程内核源码& & & 内核问题移动开发& & & 移动开发技术资料ShellPerlJava& & & Java文档中心PHP& & & php文档中心Python& & & Python文档中心RubyCPU与编译器嵌入式开发驱动开发Web开发VoIP开发技术MySQL& & & MySQL文档中心SybaseOraclePostgreSQLDB2Informix数据仓库与数据挖掘NoSQL技术IT业界新闻与评论IT职业生涯& & & 猎头招聘IT图书与评论& & & CU技术图书大系& & & Linux书友会二手交易下载共享Linux文档专区IT培训与认证& & & 培训交流& & & 认证培训清茶斋投资理财运动地带快乐数码摄影& & & 摄影器材& & & 摄影比赛专区IT爱车族旅游天下站务交流版主会议室博客SNS站务交流区CU活动专区& & & Power活动专区& & & 拍卖交流区频道交流区
稍有积蓄, 积分 437, 距离下一级还需 63 积分
论坛徽章:0
各位,最近我遇到一个问题
在写串口程序的时候,把串口设置好后,用串口线把PC和ARM试验箱连接起来,然后在试验箱上运行接收程序
然后在PC的虚拟机的linux下运行串口发送程序向arm发送数据。每次向arm发送一句话“hello this is a test”
结果我晕连续运行发送程序2到4次后,arm才能收到一次数据。而且数据还不完整,那句话经常会缺一个h字母。
各位,请问这是为什么啊 ?
论坛徽章:6
还是先验证一个字符吧
小富即安, 积分 3435, 距离下一级还需 1565 积分
论坛徽章:8
回复 #1 feiyinziiu 的帖子
串口设置成原始模式 看看 还会不会丢字符 接收不及时 可能是程序读的慢 或串口阻塞
稍有积蓄, 积分 437, 距离下一级还需 63 积分
论坛徽章:0
回复 #2 yidou 的帖子
。。郁闷。我验证一个字符有时候后也会丢失。。。
稍有积蓄, 积分 437, 距离下一级还需 63 积分
论坛徽章:0
回复 #3 zhj1011 的帖子
设置成原始模式了,但是数据还是会出现丢失。我的串口读程序时一个字符一个字符的读然后打印出来。
还有,我的串口每次要向他发送2到4次数据后他才会接收到一次,串口怎么会阻塞呢?
白手起家, 积分 69, 距离下一级还需 131 积分
论坛徽章:0
接收端可以用select()函数设置成非阻塞模式
稍有积蓄, 积分 437, 距离下一级还需 63 积分
论坛徽章:0
回复 #6 vincentve 的帖子
恩。我试试。我不知道我的这种情况输不输于因为阻塞了才收不到信息。
小富即安, 积分 3435, 距离下一级还需 1565 积分
论坛徽章:8
回复 #5 feiyinziiu 的帖子
阻塞的情况 我碰到过
我的是因为程序是个死循环 而且跑得太快了 导致串口会阻塞
我改成没循环一次 就打开和关闭一次串口 问题就没有了
北京盛拓优讯信息技术有限公司. 版权所有 京ICP备号 北京市公安局海淀分局网监中心备案编号:22
广播电视节目制作经营许可证(京) 字第1234号
中国互联网协会会员&&联系我们:
感谢所有关心和支持过ChinaUnix的朋友们
转载本站内容请注明原作者名及出处21ic官方微信-->
ST MCU Finder
安装免费手机应用,
寻找理想的ST MCU
串口无法接受数据
实习生, 积分 16, 距离下一级还需 34 积分
实习生, 积分 16, 距离下一级还需 34 积分
实习生, 积分 16, 距离下一级还需 34 积分
实习生, 积分 16, 距离下一级还需 34 积分
用STM32CubeMX 生成的串口初始代码,通过hal接口无法接收串口数据,一般会是什么原因
if (HAL_UART_Receive_IT(&huart1, &uartData.rxbuf[0], uartData.len)==HAL_OK){
& & & & & & & & & & & & HAL_GPIO_WritePin(LD2_Green_GPIO_Port,LD2_Green_Pin,GPIO_PIN_RESET);
& & & & & & & & }
回掉函数不会进入
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
& & & & if (UartHandle==&huart1){
& & & & & & & & HAL_GPIO_TogglePin(LD2_Green_GPIO_Port,LD2_Green_Pin);
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
串口是嵌入式开发中最常前的外设设备,既可以用作不同单片机之间的通信,也可以用作在STM32 MCU和PC机之间的通信,STM32F407的串口功能非常强大,可以接红外,可以接流控,也可以接SIM卡接口,但我这里只介绍我们最常用的UART通信的一点调试经验,以STM32F407为例,对其它STM32芯片也适用,希望对大家有所帮助,如有错误不当之处欢迎大家联系指正。
一、串口的三种工作方式
操作串口一般有两种方式:查询和中断;STM32还支持第三种DMA方式。
(1)查询:串口程序不断地循环查询标志,看看当前有没有数据要它传送或接收。如果有的话进行相应的写操作和读操作进行传送或接收数据。
(2)中断:平时串口只要打开中断即可。如果发现有一个中断来,则意味着有数据需要接收(接收中断)或数据已经发送完成(发送中断)。
(3)DMA方式,设置好DMA工作方式,由DMA来自动接收或发送数据。
一般来说,查询方式的效率是比较低的,并且由于STM32的UART硬件上没有FIFO,如果程序功能比较多,查询不及时的话很容易出现数据丢失的现象, 故实际项目中这种方式用的并不多。
中断方式的话我们可以分别设置接收中断和发送中断,当串口有数据需要接收时才进入中断程序进行读读操,这种方式占用CPU资源比较少,实际项目中比较常用,但需要注意中断程序不要太复杂使执行时间太长,如果执行时间超过一个字符的时间的话也会出现数据丢失的现象,这个波特率比较高的串口编程中比较容易出现,可以考虑用循环BUF方法,在中断程序中只负责实时地接收实数数和发送时的填数(写发送寄存器),其它操作放在中断外处理。
STM32还提供了第三种DMA方式用来支持高速地串口传输。这种方式只要设置好接收和发送缓冲位置,可以由DMA来自动接收和发送数据,这可以最小化占用CPU时间。
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
二、串口的使用步骤
(1)中断方式
基本步骤是初试化时钟,脚位、波特率设置、安装中断服务程序、开中断等,参考代码如下:
void uart_init(void)
& &USART_InitTypeDef USART_InitS
&&NVIC_InitTypeDef NVIC_InitS
&&GPIO_InitTypeDef&&GPIO_InitS
&&/* Enable GPIO clock&&*/
& &RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
& &/* Enable USART clock */
& &RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
& &/* Connect USART pins to AF7 */
& &GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3);
&&GPIO_PinAFConfig(GPIOC, GPIO_PinSource11,&&GPIO_AF_USART3);
&&/* Configure USART Tx and Rx as&&alternate function push-pull */
& &GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
&&GPIO_InitStructure.GPIO_Speed =&&GPIO_Speed_100MHz;
& &GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
&&GPIO_InitStructure.GPIO_PuPd =&&GPIO_PuPd_UP;
& &GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
&&GPIO_Init(GPIOC,&&&GPIO_InitStructure);
&&GPIO_InitStructure.GPIO_Pin =&&GPIO_Pin_11;
&&GPIO_Init(GPIOC,&&&GPIO_InitStructure);
&&/*&&USARTx configuration&&----------------------------------------------------*/
&&/* USARTx configured as follow:
& && &&&- BaudRate = 3750000 baud
&&- Maximum BaudRate that can be achieved when&&using the Oversampling by 8
& &&&is: (USART APB Clock / 8)
& &- (USART3 APB1&&Clock / 8) = (30 MHz / 8) = 3750000 baud
& &- (USART1 APB2 Clock / 8) = (60 MHz / 8) = 7500000&&baud
&&- Maximum BaudRate that can&&be achieved when using the Oversampling by 16
& & is: (USART APB Clock / 16)
Example: (USART3 APB1 Clock / 16) = (30 MHz / 16)&&= 1875000 baud
Example: (USART1&&APB2 Clock / 16) = (60 MHz / 16) = 3750000 baud
& && &&&- Word Length = 8 Bits
& && &&&- one Stop Bit
& && &&&- No parity
& && &&&- Hardware flow control disabled (RTS and&&CTS signals)
& && &&&- Receive and&&transmit enabled
& &USART_InitStructure.USART_BaudRate = 115200;
&&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_N
& &USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
&&USART_Init(USART3,&&&USART_InitStructure);
&&/* NVIC configuration&&*/
&&/* Configure the Priority&&Group to 2 bits */
& &NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
& &/* Enable the USARTx Interrupt */
&&NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
& &NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
&&NVIC_InitStructure.NVIC_IRQChannelSubPriority =&&0;
& &NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
& &NVIC_Init(&NVIC_InitStructure);
&&/* Enable USART&&*/
&&USART_Cmd(USART3,&&ENABLE);
&&USART_ITConfig(USART3,&&USART_IT_RXNE, ENABLE);
中断服务程序如下:
void USART3_IRQHandler(void)
if(USART_GetITStatus(USART3,&&USART_IT_RXNE) != RESET)
& & /* Read one byte from the&&receive data register */
& & ch =&&(USART_ReceiveData(USART3));
& &&&printf(&in[%c].\r\n&,ch);
直接把接收到的字符打印出来。
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
(2)DMA方式
基本步骤同中断方式,额外需要DMA的初始化配置,参考代码如下:
void&&uart_init(void)
&&USART_InitTypeDef&&USART_InitS
& &NVIC_InitTypeDef NVIC_InitS
&&GPIO_InitTypeDef GPIO_InitS
&&DMA_InitTypeDef DMA_InitS
& &/* Enable GPIO clock */
& &RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
& &/* Enable USART clock */
& &RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
& &/* Connect USART pins to AF7 */
& &GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3);
&&GPIO_PinAFConfig(GPIOC, GPIO_PinSource11,&&GPIO_AF_USART3);
&&/* Configure USART Tx and Rx as&&alternate function push-pull */
& &GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
&&GPIO_InitStructure.GPIO_Speed =&&GPIO_Speed_100MHz;
& &GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
&&GPIO_InitStructure.GPIO_PuPd =&&GPIO_PuPd_UP;
& &GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
&&GPIO_Init(GPIOC,&&&GPIO_InitStructure);
&&GPIO_InitStructure.GPIO_Pin =&&GPIO_Pin_11;
&&GPIO_Init(GPIOC,&&&GPIO_InitStructure);
&&/*&&USARTx configuration&&----------------------------------------------------*/
&&/* USARTx configured as follow:
& && &&&- BaudRate = 3750000 baud
&&- Maximum BaudRate that can be achieved when&&using the Oversampling by 8
& &&&is: (USART APB Clock / 8)
& &- (USART3 APB1&&Clock / 8) = (30 MHz / 8) = 3750000 baud
& &- (USART1 APB2 Clock / 8) = (60 MHz / 8) = 7500000&&baud
&&- Maximum BaudRate that can&&be achieved when using the Oversampling by 16
& & is: (USART APB Clock / 16)
Example: (USART3 APB1 Clock / 16) = (30 MHz / 16)&&= 1875000 baud
Example: (USART1&&APB2 Clock / 16) = (60 MHz / 16) = 3750000 baud
& && &&&- Word Length = 8 Bits
& && &&&- one Stop Bit
& && &&&- No parity
& && &&&- Hardware flow control disabled (RTS and&&CTS signals)
& && &&&- Receive and&&transmit enabled
& &USART_InitStructure.USART_BaudRate = 115200;
&&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_N
& &USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
&&USART_Init(USART3,&&&USART_InitStructure);
/*&&DMA_Configuration */
& &DMA_DeInit(DMA1_Stream1);
&&DMA_InitStruct.DMA_Channel =&&DMA_Channel_4;& &
& &DMA_InitStruct.DMA_PeripheralBaseAddr =&&(u32)&USART3-&DR; //source&&buf
& &DMA_InitStruct.DMA_Memory0BaseAddr = (u8) //target buf
&&DMA_InitStruct.DMA_DIR =&&DMA_DIR_PeripheralToM
& &DMA_InitStruct.DMA_BufferSize =&&//BuffS
&&DMA_InitStruct.DMA_PeripheralInc =&&DMA_PeripheralInc_D
& &DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_E
&&DMA_InitStruct.DMA_PeripheralDataSize =& &DMA_PeripheralDataSize_W
& &DMA_InitStruct.DMA_MemoryDataSize =&&DMA_MemoryDataSize_B
&&DMA_InitStruct.DMA_Mode = DMA_Mode_C&&//DMA_Mode_N
& &DMA_InitStruct.DMA_Priority = DMA_Priority_H
&&DMA_InitStruct.DMA_FIFOMode =&&DMA_FIFOMode_D
& &DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfF
&&DMA_InitStruct.DMA_MemoryBurst =&&DMA_MemoryBurst_S
& &DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_S
&&DMA_Init(DMA1_Stream1,&&&DMA_InitStruct);
&&/* NVIC configuration&&*/
&&/* Configure the Priority&&Group to 2 bits */
& &NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
& &/* Enable the USARTx Interrupt */
&&NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream1_IRQn;&&
& &NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
&&NVIC_InitStructure.NVIC_IRQChannelSubPriority =&&0;
& &NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
&&NVIC_Init(&NVIC_InitStructure);&&
&&/* Open DMA&&interrupt*/
& &DMA_ITConfig(DMA1_Stream1, DMA_IT_TC, ENABLE);
&&DMA_Cmd(DMA1_Stream1, ENABLE);
&&USART_Cmd(USART3, ENABLE);
& &USART_DMACmd(USART3,USART_DMAReq_Rx,ENABLE);
DMA中断服务程序如下:
void DMA1_Stream1_IRQHandler(void) //UART3_RX
& & //When a&&Transfer Complete
if(SET ==&&DMA_GetITStatus(DMA1_Stream1, DMA_IT_TCIF1))
DMA_ClearITPendingBit(DMA1_Stream1, DMA_IT_TCIF1);
上面程序只配了DMA接收,发送类似。
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
三、实现DMX512协议
DMX512 协议是美国剧场技术协会( United States Institute for Theater Technology,&&USITT) 制定的数字多路复用协议, 其制定的初衷是为了使舞台、剧场等地所使用的众多的调光器和控制器能相互兼容。虽然它不是一个行业或国家标准, 但是由于它的简单性和实用性, 自从出台以来, 得到了世界各地生产商和使用者普遍承认,这个协议在LED控制方面应用很广泛,利用STM32 USART可以高速传输的特性,我们很容易用STM32来实现DMX512协议。
(1)数据的格式及传输
DMX512&&协议规定数据以数据包的形式通过异步通讯的方式进行传输。每个数据包由若干数据帧组成, 每帧数据包括1 位低电平起始位、8 位数据位和2 位高电平停止位。DMX 协议要求数据传输的波特率为250kb/s, 亦即每位的传输时间为4us, 每帧数据的传输时间为44us, 它支持多达512 帧数据传输, 每帧数据与相应的控制支路相对应。数据包的传送要符合一定的格式和时序要求。为了使接收器能够分辨出第一帧数据, 每一个数据包以一个不短于88us 的低电平信号为起始信号, 即所谓的“Break”信号, 接收器接收到“Break”信号就准备接受随后而来的数据帧; 紧接着“Break”信号之后是不短于8us 的高电平信号M. a. b ( Mark after&&Break) ; 之后就是数据帧。在DMX512 协议中, M. a. b 之后的第一帧数据被称
为“Star-t code”, 在协议中规定其为零, 但在实际应用中可以由生产厂家自己确定其具体的值,&&以传递特殊消息。“Star-t&&code”标明其后面的数据是8&&位控制信号数据帧。数据帧之间可以有时间间隔, 也可以没有;&&同样, 数据包之间可以有时间间隔, 也可以没有。DMX512 协议规定“Break”信号、M. a. b 信号的最短时间, 并规定“Break”信号、M. a. b 信号、
数据帧之间及数据包之间的时间间隔的最大值不得超过1s, 否则做出错处理, 但是DMX512 协议并未对出错处理做任何规定。为了严格实现DMX512&&数据的时序要求,“Break”和M.&&a. b信号我们可以用定时器来实现。
具体的UART配置如下:
&&USART_InitStructure.USART_BaudRate =&&250000;
& &USART_InitStructure.USART_WordLength = USART_WordLength_8b;
&&USART_InitStructure.USART_StopBits =&&USART_StopBits_2;
& &USART_InitStructure.USART_Parity = USART_Parity_No;
&&USART_InitStructure.USART_HardwareFlowControl =&&USART_HardwareFlowControl_N
& &USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
&&USART_Init(USART1,&&&USART_InitStructure);
发送DMX512信号过程如下,先把UART的TX脚配置为普通的GPIO并输出低电平,然后启动定时器计时88us,&&时器到后把TX脚置为高电平并计时8us, 时器到了后在配为UART模式用DMA方式把数据发出。
DMX512信号的接收是个难点,一般直接配为UART接收就行,不需要在UART模式和GPIO模式间切换,但需要在接收过程中检查接收到“Break”信号时的状态是有帧错误出现,并且接收数据全为零,这样的话可以确认已经收到“Break”信号,随后数据正常DMA接收就行了。
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
接下来再说说cubeMX的
开发环境:MDK5.14 和STM32CubeMX4.11。
& && & 在上一个帖子STM32CubeMX按键控制流水灯()的基础上,继续学习串口通信。
& && & 使用STM32CubeMX配置串口通信,需要用到HAL库。HAL库中实现串口通信有三种方式:轮询、中断和DMA。和串口通信相关的初始化部分通过STM32CubeMX软件配置,具体过程在下面的例子中说明。& && & 轮询模式:为堵塞模式,使用超时管理机制。发送函数:HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
[color=rgb(51, 102, 153) !important]复制代码
参数:huart: 指向串口结构体(通过STM32CubeMX软件配置串口时会生成,包含串口通信相关的信息)的指针。pData: 指向发送数据块的指针Size: 发送数据的数量Timeout: 超时周期返回值:HAL status:HAL_OK ,HAL_ERROR,HAL_BUSY ,HAL_TIMEOUT
接收函数:HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
[color=rgb(51, 102, 153) !important]复制代码
参数:huart: 指向串口结构体的指针。pData: 指向接收数据块的指针Size: 接收数据的数量Timeout: 超时周期返回值:HAL status,HAL_OK ,HAL_ERROR,HAL_BUSY ,HAL_TIMEOUT必须在指定的时间内接收到指定数量的数据才会返回HAL_OK。
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
& & &&中断模式: 非堵塞模式。和UART相关的中断:发生完成中断,结束中断和错误中断。发送函数: 用于开启中断发送HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
[color=rgb(51, 102, 153) !important]复制代码
参数:huart: 指向串口结构体的指针。pData: 指向发送数据块的指针Size: 发送数据的数量返回值:HAL status:HAL_OK ,HAL_ERROR,HAL_BUSY
接收函数:用于开启中断接收HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
[color=rgb(51, 102, 153) !important]复制代码
参数:huart: 指向串口结构体的指针。pData: 指向接收数据块的指针Size: 接收数据的数量返回值:HAL status,HAL_OK ,HAL_ERROR,HAL_BUSY ,HAL_TIMEOUT必须接收到指定数量的数据才会触发中断。相关的回调函数:HAL_UART_TxCpltCallback():发送完成后,通过中断处理函数调用。HAL_UART_RxCpltCallback():接收完成后,通过中断处理函数调用。HAL_UART_ErrorCallback():传输过程中出现错误时,通过中断处理函数调用。可以在回调函数里定制自己的代码。
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
&&&&DMA模式:非堵塞模式。发送函数: 用于开启DMA发送HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
[color=rgb(51, 102, 153) !important]复制代码
参数:huart: 指向串口结构体的指针。pData: 指向发送数据块的指针Size: 发送数据的数量返回值:HAL status,HAL_OK ,HAL_ERROR,HAL_BUSY
接收函数:用于开启DMA接收HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
[color=rgb(51, 102, 153) !important]复制代码
参数:huart: 指向串口结构体的指针。pData: 指向接收数据块的指针Size: 接收数据的数量返回值:HAL status,HAL_OK ,HAL_ERROR,HAL_BUSY ,HAL_TIMEOUT必须接收到指定数量的数据才会完成一次DMA传输。相关的回调函数(使用回调函数需要开启串口中断):HAL_UART_TxHalfCpltCallback():一半数据(half transfer)发送完成后,通过中断处理函数调用。HAL_UART_TxCpltCallback():发送完成后,通过中断处理函数调用。HAL_UART_RxHalfCpltCallback():一半数据(half transfer)接收完成后,通过中断处理函数调用。HAL_UART_RxCpltCallback():接收完成后,通过中断处理函数调用。HAL_UART_ErrorCallback():传输过程中出现错误时,通过中断处理函数调用。可以在回调函数里定制自己的代码。& &&&暂停DMA传输:HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart)
[color=rgb(51, 102, 153) !important]复制代码
& & 恢复DMA传输:HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart)
[color=rgb(51, 102, 153) !important]复制代码
& &&&停止DMA传输:HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart)
[color=rgb(51, 102, 153) !important]复制代码
参数:huart: 指向串口结构体的指针。返回值:HAL status,HAL_OK
& &&&下面通过简单的例子说明:& && &发板的USART3使用的是PB10和PB11引脚,但是使能USART3的时候默认引脚是PC10和PC11。因此需要先配置PB10和PB11引脚,在使能USART。相关的电路图如下:
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
&&轮询模式:在STM32CubeMX软件中,分别配置PB10和PB11为串口收发,接着使能USART3,最后配置串口通信相关的参数:生成MDK工程并打开,在main.c文件中,定义全局变量用于收发:uint8_t aTxBuffer[] = &** UART__ComPolling ** \r\n&;uint8_t aRxBuffer[32];
[color=rgb(51, 102, 153) !important]复制代码
在主函数的while循环之前,发送一个字符串,如果发送失败,点亮LED:HAL_GPIO_WritePin(GPIOG,GPIO_PIN_6,GPIO_PIN_SET);& && &&&HAL_GPIO_WritePin(GPIOD,GPIO_PIN_4,GPIO_PIN_SET);& && &&&HAL_GPIO_WritePin(GPIOD,GPIO_PIN_5,GPIO_PIN_SET);& && &&&HAL_GPIO_WritePin(GPIOK,GPIO_PIN_3,GPIO_PIN_SET);& && &&&if(HAL_UART_Transmit(&huart3,(uint8_t *)aTxBuffer,32,5000)!= HAL_OK)& && &&&{& && && && && && && && &HAL_GPIO_WritePin(GPIOD,GPIO_PIN_4,GPIO_PIN_RESET);& && &&&}
[color=rgb(51, 102, 153) !important]复制代码
在while循环中,等待接收到指定数量的字符,然后将接收的字符发送出去,超时时间设置为1秒(单位为ms):while(HAL_UART_Receive(&huart3, (uint8_t *)aRxBuffer, 5, 1000) != HAL_OK)& && && && && & {& && && && && && && && &HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_5);& && && && && & }& && && && && & if(HAL_UART_Transmit(&huart3,(uint8_t *)aRxBuffer,5,1000) == HAL_OK)& && && && && & {& && && && && && && && &HAL_GPIO_TogglePin(GPIOG,GPIO_PIN_6);& && && && && & }& && && && && & HAL_Delay(1000);
[color=rgb(51, 102, 153) !important]复制代码
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
编译下载,使用串口调试助手,调试过程如下:中断模式:在上面配置的基础上,使能串口中断,并配置优先级,也可以改变优先级分组:
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
在生成的MDK工程中,定义全局变量用于收发:uint8_t aTxBuffer[] = &** UART__IT ** \r\n&;uint8_t aRxBuffer[32];uint8_t Rx_flag = 0;
[color=rgb(51, 102, 153) !important]复制代码
通过Rx_flag控制发送接收的数据。在主函数的while循环之前开启发送和接收中断:HAL_GPIO_WritePin(GPIOG,GPIO_PIN_6,GPIO_PIN_SET);& && &&&HAL_GPIO_WritePin(GPIOD,GPIO_PIN_4,GPIO_PIN_SET);& && &&&HAL_GPIO_WritePin(GPIOD,GPIO_PIN_5,GPIO_PIN_SET);& && &&&HAL_GPIO_WritePin(GPIOK,GPIO_PIN_3,GPIO_PIN_SET);& && &&&HAL_UART_Transmit_IT(&huart3,(uint8_t *)aTxBuffer,32);& && &&&HAL_UART_Receive_IT(&huart3,(uint8_t *)aRxBuffer,12);
[color=rgb(51, 102, 153) !important]复制代码
在while循环中将接收的数据发送出去:if(Rx_flag == 1)& && && && && & {& && && && && && && && &HAL_UART_Transmit_IT(&huart3,(uint8_t *)aRxBuffer,32);& && && && && && && && &Rx_flag = 0;& && && && && & }
[color=rgb(51, 102, 153) !important]复制代码
在usart.c文件中声明外部变量:extern uint8_t aRxBuffer[32];extern uint8_t Rx_
[color=rgb(51, 102, 153) !important]复制代码
加入收发回调函数,在接收回调函数里将Rx_flag置1控制发送,并在此开始中断接收:void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle){&&HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_4);}void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle){& && &&&Rx_flag = 1;& && &&&HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_5);& && &&&HAL_UART_Receive_IT(&huart3,(uint8_t *)aRxBuffer,12);}
[color=rgb(51, 102, 153) !important]复制代码
编译下载,使用串口调试助手,调试过程如下:
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
DMA模式:在上面配置的基础上,使能DMA,并为发送和接收选择DMA通道:在生成的MDK工程中定义如下全局变量用于收发:uint8_t aTxBuffer[] = &** UART__DMA ** \r\n&;uint8_t aRxBuffer[32];uint8_t Rx_flag = 0;
[color=rgb(51, 102, 153) !important]复制代码
通过Rx_flag控制发送接收的数据。在主函数的while循环之前开启DMA发送和接收:
HAL_GPIO_WritePin(GPIOG,GPIO_PIN_6,GPIO_PIN_SET);& && &&&HAL_GPIO_WritePin(GPIOD,GPIO_PIN_4,GPIO_PIN_SET);& && &&&HAL_GPIO_WritePin(GPIOD,GPIO_PIN_5,GPIO_PIN_SET);& && &&&HAL_GPIO_WritePin(GPIOK,GPIO_PIN_3,GPIO_PIN_SET);& && &&&HAL_UART_Transmit_DMA(&huart3,(uint8_t *)aTxBuffer,32);& && &&&HAL_UART_Receive_DMA(&huart3,(uint8_t *)aRxBuffer,12);
[color=rgb(51, 102, 153) !important]复制代码
在while循环中将接收的数据发送出去:
if(Rx_flag == 1)& && && && && & {& && && && && && && && &HAL_UART_Transmit_DMA(&huart3,(uint8_t *)aRxBuffer,32);& && && && && && && && &Rx_flag = 0;& && && && && & }& && && && && & if(Rx_flag == 2)& && && && && & {& && && && && && && && &HAL_GPIO_TogglePin(GPIOG,GPIO_PIN_6);& && && && && && && && &Rx_flag = 0;& && && && && & }
[color=rgb(51, 102, 153) !important]复制代码
在usart.c文件中声明外部变量:
extern uint8_t aRxBuffer[32];extern uint8_t Rx_
[color=rgb(51, 102, 153) !important]复制代码
加入收发回调函数,在接收回调函数里将Rx_flag置1控制发送,并在此开始中断接收,通过控制LED简单的验证发送和接收一半数据的回调函数:
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle){&&HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_4);}void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle){& && &&&Rx_flag = 1;& && &&&HAL_UART_Receive_DMA(&huart3,(uint8_t *)aRxBuffer,12);}void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart){& && &&&HAL_GPIO_TogglePin(GPIOK,GPIO_PIN_3);}void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart){& && &&&Rx_flag = 2;}
[color=rgb(51, 102, 153) !important]复制代码
编译下载,使用串口调试助手,调试过程如下:
最后,关于串口重定向可以参考一下代码,需要包含stdio.h,可以替换成中断或DMA模式,这样就可以使用printf和scanf函数:
int fputc(int ch,FILE *fp){& && &&&HAL_UART_Transmit(&huart3,(uint8_t *)&ch,1,5000);& && &&&}int fgetc(FILE *fp){& && &&&uint8_& && &&&HAL_UART_Receive(&huart3,(uint8_t *)ch,1,5000);& && &&&}
[color=rgb(51, 102, 153) !important]复制代码
[color=rgb(51, 102, 153) !important]
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
资深工程师, 积分 11899, 距离下一级还需 8101 积分
其实我都是从这里看到的,
提示: 作者被禁止或删除 内容自动屏蔽
助理工程师, 积分 1048, 距离下一级还需 952 积分
助理工程师, 积分 1048, 距离下一级还需 952 积分
助理工程师, 积分 1048, 距离下一级还需 952 积分
助理工程师, 积分 1048, 距离下一级还需 952 积分
初始化不成功造成的,或者波特率不对
初级工程师, 积分 2547, 距离下一级还需 453 积分
初级工程师, 积分 2547, 距离下一级还需 453 积分
初级工程师, 积分 2547, 距离下一级还需 453 积分
初级工程师, 积分 2547, 距离下一级还需 453 积分
波特率怎么设置的
初级工程师, 积分 2343, 距离下一级还需 657 积分
初级工程师, 积分 2343, 距离下一级还需 657 积分
初级工程师, 积分 2343, 距离下一级还需 657 积分
初级工程师, 积分 2343, 距离下一级还需 657 积分
数据发送出去了吗,只是接受不到吗
实习生, 积分 16, 距离下一级还需 34 积分
实习生, 积分 16, 距离下一级还需 34 积分
实习生, 积分 16, 距离下一级还需 34 积分
实习生, 积分 16, 距离下一级还需 34 积分
谢谢楼上,提供翔实的回答,我已经解决了
中级技术员, 积分 138, 距离下一级还需 162 积分
中级技术员, 积分 138, 距离下一级还需 162 积分
中级技术员, 积分 138, 距离下一级还需 162 积分
中级技术员, 积分 138, 距离下一级还需 162 积分
谢谢楼上,提供翔实的回答,我已经解决了
你好,我也遇到同样的问题,请问下,你是怎么解决的呢
中级技术员, 积分 172, 距离下一级还需 128 积分
中级技术员, 积分 172, 距离下一级还需 128 积分
中级技术员, 积分 172, 距离下一级还需 128 积分
中级技术员, 积分 172, 距离下一级还需 128 积分
& & 请问cube mx生成的函数HAL_SPI_TransmitReceive_IT这个函数是不是表示同时开启发送与接收中断,若调用回调函数HAL_SPI_TxRxCpltCallback,是不是指发送与接收触发中断后,都会各自调用一次HAL_SPI_TxRxCpltCallback中的程序?
扫描二维码,随时随地手机跟帖
技术新星奖章
人才类勋章
湍急之河流
发帖类勋章
社区建设奖章
等级类勋章
时间类勋章
技术高手奖章
人才类勋章
时间类勋章
您需要登录后才可以回帖

我要回帖

更多关于 单片机串口接收程序 的文章

 

随机推荐