在编制程序是,遇到这么一个问题:
这一段程序的输出,应该是 57H 53H 07H D0H
但是,实际调试中输出的是53H 07H D0H,第一个字节57H丢失了。
其实在此之前,我调试甲醛传感器的时候就发现,第一次发送命令无法对甲醛传感器失效,我天真的以为是传感器的问题,没有对我发的命令产生有效响应。
但是,今天的现象表明,是单片机的串口没能将第一个字节发送出来。
于是,我动用了百度,找到了如下文摘:
——————————————————————————————————————————
——————————————————————————————————————————
STM32 串口 发送 必须 先检测 状态,否则 第一个 字节 无法 发出,发送完毕,必须检测发送状态是否完成,否则,发送不成功,
使用stm32f10x调试串口通讯时,发现一个出错的现象,硬件复位重启之后,发送测试数据0x01 0x02 0x03 0x04..接收端收到的数据为:0x02 0x03 0x04,第一个数据丢失。换成发送别的数值的数据,如0x06 0x0ff,则接收到0x0ff,0x06丢失。错误依旧。
故障排除过程:
1、刚开始怀疑是接收端的错误,我是使用电脑串口,运行串口辅助调试工具接收,换成其他软件后,发现故障依旧,而且电脑软件一直是开启状态,不像和电脑软件有关。
2、使用单步调试,单步运行各个发送指令,都正常。能收到0x01 0x02 0x03 0x04的数据。间接的排除了不是电脑软件的问题,而是其他的错误。
3、单步调试运行虽然正常了,但连续运行时,错误依旧。现在有点摸不到头绪了,单步运行正常,看起来编程没有出错,那故障在哪里呢?测试程序如下
USART_SendData(USART2, 0x01); //A
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); //B
USART_SendData(USART2, 0x02); //C
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
USART_SendData(USART2, 0x03);
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
USART_SendData(USART2, 0x04);
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
4、猜测,也许是因为某个特殊原因,使第二个数据覆盖了首个数据,使得首个数据丢失。假设:在执行B指令时,USART的 TC 状态位==SET,那么就会紧接着执行C指令,也就有可能发生数据的覆盖。于是,在A指令前,加入如下指令:
USART_ClearFlag(USART2,USART_FLAG_TC);
5、加入上一条指令后,运行,错误消失了。说明上一个假设,应该是成立的。
6、查阅stm32f10x参考手册,找到这样一句话:
TC:发送完成
当包含有数据的一帧发送完成后,由硬件将该位置位。如果USART_CR1中的TCIE为1,则产生中断。由软件序列清除该位(先读USART_SR,然后写入USART_DR)。TC位也可以通过写入0来清除,只有在多缓存通讯中才推荐这种清除程序。
0:发送还未完成;
1:发送完成。
7、注意到这一句:由软件序列清除该位(先读USART_SR,然后写入USART_DR)。 也就是说,要先read USART_SR,然后write USART_DR,才能完成TC状态位的清除。而硬件复位后,串口发送的首个数据之前没有read SR的操作,是直接write DR,也就是说,TC没有被清除掉。 说明第4步的猜测是对的。
8、那么,应该把指令A前面加的USART_ClearFlag(USART2,USART_FLAG_TC); 改为USART_GetFlagStatus(USART2, USART_FLAG_TC);,应该也能消除错误。测试后证实,确实如此,在发送首个数据之前,先读取一下USART_SR,那么就不会出现首个数据丢失的情况了。
9、总结:硬件复位后,串口发送首个数据之前,先读取一下USART_SR,则能够保证首个数据发送时,不出现覆盖的情况。当然,也有别的方法,比如先清除TC状态位,或是,在write USART_DR之后,加入一个小延时,让数据发送完毕,应该也能间接排除这个错误。
————————————————————————————————————————————
————————————————————————————————————————————
在此文章的启发下,我做了如下的操作,按照第7条和第8条的提示,我在发送第一个字节的时候,先读一下USART_SR。我是把这个操作放到了串口初始化里,这样就不必每个发送字节函数都进行此操作,至解决初始化后的第一个字节就可以了。
如下图。
就这么解决了这个问题。
关键字:STM 连续发送 丢失
引用地址:
STM连续发送时丢失第一个字节
推荐阅读最新更新时间:2024-03-16 16:16
STM32的GPIO设置
最近刚开始学习STM32,所以从最基本的GPIO开始学起;首先看看STM32的datasheet上对GPIO口的简单介绍: 每个GPI/O 端口有两个32 位配置寄存器(GPIOx_CRL,GPIOx_CRH),两个32位数据寄存器(GPIOx_IDR,GPIOx_ODR),一个32 位置位/复位寄存器(GPIOx_BSRR),一个16 位复位寄存器(GPIOx_BRR)和一个32 位锁定寄存器(GPIOx_LCKR)。 GPIO 端口的每个位可以由软件分别配置成多种模式。每个I/O 端口位可以自由编程,然而I/0 端口寄存器必须按32 位字被访问(不允许半字或字节访问)。GPIOx_BSRR 和GPIOx_BRR 寄存器允许对
[单片机]
再造STM32---第十八部分:DMA—直接存储区访问
本章参考资料:《STM32F4xx 中文参考手册》 DMA 控制器章节。 学习本章时,配合《STM32F4xx 中文参考手册》 DMA 控制器章节一起阅读,效果会更佳,特别是涉及到寄存器说明的部分。本章内容专业名称较多,内容丰富也较难理解,但非常有必要细读研究。 特别说明,本章内容是以 STM32F42xxx 系列资源讲解。 18.1 DMA简介: DMA: Data Memory Access,直接存储器访问 DMA1: P- M, M- P, DMA2: P- M, M- P, M- M 1-通道+流 2-仲裁器 3-FIFO 4-存储器接口 5-外设接口 6-编程接口 流: 是数据传输的一条链路,每个DMA控制器有8
[单片机]
ST-LINK/V2 + STM8 + STVP 下载程序+Error on Option Bytes
gdi-error : Option bytes read error: not complemented; please use a programmer 个人感觉,ST-LINk/V2太坑,浪费了我一天的时间找原因! 首先是连接,这个得保证正确: LED状态说明 闪烁红色:ST-LINK/V2连接到计算机后,第一次USB枚举过程 红色:ST-LINK/V2与计算机已建立连接 闪烁绿色/红色:目标板和计算机在进行数据交换 绿色:通讯完成 橙色(红色+绿色):通讯失败 我也是按照网上的方法,连接ST-LINK和STM8对应接口; ST-LINK连接PC,然后打开STVP下载程序,总是弹出如下对话框
[单片机]
关于STM32F103型号的矩阵按键的程序书写
最近参加电子大赛要写一个矩阵按键,刚开始写了好长时间换了好几个矩阵按键都不好使,但是 我感觉我的程序和原理都没有错,调试了好久也没有发现问题在哪?我按照我自己的思路把程序重写了一遍bug消失了,程序很好的运行。程序贴出来,纪念一下。 #include keypad.h #include stm32f10x.h #include delay.h /*************************************************************************/ /****************************************************************
[单片机]
UCOS2_STM32F1移植详细过程(三)
Ⅰ、概述 上一篇文章是讲述ST芯片相关的配置和OS裁剪相关的配置,接着上一篇文章来讲述关于UCOS的移植,该文主要 针对uC/OS-II Ports下面 os_cpu_a.asm、os_cpu_c.c和os_cpu.h文件 底层端口代码来讲述。 请下载“UCOS2_STM32F1_3个简单任务”作为参考工程。 笔者将“UCOS移植详细过程”分为多篇文章来讲述,敬请关注。 关于本文的详情请往下看(微信请点击“阅读原文”查看内容链接内容)。 Ⅱ、下载 笔者将F0、F1、F3、F4移植到最新UCOS2.92上。移植好的、独立的4个工程供大家下载学习、研究。建立的任务都是一样的,只是针对芯片不同,Ports目录下相关的源代码有差
[单片机]
STM32F103的GPIO配置方式
一、GPIO的配置过程 (1)、开启外设时钟 (2)、初始化GPIO 配置成输出模式程序 void GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStruce;//结构体属于变量,变量的声明必须位于函数可执行的语句之前 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启GPIOB的时钟 GPIO_InitStruce.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_InitStruce.GPIO_Pin=GPIO_Pin_5; GPIO_InitStruce.GPI
[单片机]
STM32(6) STM32时钟系统精讲(正点原子)
讲解内容: 时钟系统框图 时钟配置相关函数 参考资料 《STM32F4开发指南库函数版本》4.3小节STM32F4时钟系统 《STM32F4中文参考手册》第六章 复位和时钟系统 先看开发指南4.3小节的时钟树 时钟框图在中文参考手册的6.2小节,STM32的时钟系统还是很复杂的,为什么ARM的时钟系统要做的这么复杂,采用 多时钟源, 时钟频率越高功耗 越高。 F4与F1类似也有5个时钟来源 1 LSIRC 低速 的内部时钟 2 LSEOSC 低速的外部时钟 3 HSIRC 高速的内部时钟 4 PLLCLK 锁相环时钟输出 5 HSEOSC 也是一个很重要的时钟源,也是我们最常用的
[单片机]
STM32的串口通信原理介绍
介绍串口通信 按照数据传送方向分类 单工:数据传输只支持数据在一个方向上传输 半双工:允许数据在两个方向上传输。但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;它不需要独立的接收端和发送端,两者可以合并一起使用一个端口 全双工:允许数据同时在两个方向上传输。因此,全双工通信是两个单工通信方式的结合,需要独立的接收端和发送端 按照通信方式分类 同步通信:带时钟同步信号传输。比如:SPI,IIC通信接口 异步通信:不带时钟同步信号。比如:UART(通用异步收发器),单总线 在同步通讯中,收发设备上方会使用一根信号线传输信号,在时钟信号的驱动下双方进行协调,同步数据。例如,通讯中通常双方会统一规定在时
[单片机]