当前位置:首页 > 单片机 > 单片机
[导读]问题及现象(STM32F103系列:http://www.y-ec.com/cpcp/class/?32.html)使用USART_SendData()函数非连续发送单个字符是没有问题的;当连续发送字符时(两个字符间没有延时),就会发现发送缓冲区有溢出现象。若发送的

问题及现象(STM32F103系列:http://www.y-ec.com/cpcp/class/?32.html)

使用USART_SendData()函数非连续发送单个字符是没有问题的;当连续发送字符时(两个字符间没有延时),就会发现发送缓冲区有溢出现象。若发送的数据量很小时,此时串口发送的只是最后一个字符,当发送数据量大时,就会导致发送的数据莫名其妙的丢失。

如:

for(TxCounter = 0;TxCounter < RxCounter; TxCounter++)

USART_SendData(USART1, RxBuffer[TxCounter]);

原因

此API函数不完善,函数体内部没有一个判断一个字符是否发送完毕的语句,而是把数据直接放入发送缓冲区,当连续发送数据时,由于发送移位寄存器的速度限制(与通信波特率有关),导致发送缓冲区的数据溢出,老的数据还未及时发送出去,新的数据又把发送缓冲区的老数据覆盖了。

解决方法(目前总结的两种方案)

方案1.加入延时函数(下下策),不需要修改USART_SendData()函数

for(TxCounter = 0;TxCounter < RxCounter; TxCounter++)

{

USART_SendData(USART1, RxBuffer[TxCounter]);

DelayMS(2); //加入一个小的延时

}

方案2.修改USART_SendData()函数,在其内部加入发送缓冲区的USART_FLAG_TXE状态检测语句,确保一个字符完全发送出去,才进行下一个字符的发送。

实现方法:每发送一个字符都检测状态寄存器,确保数据已经发送完毕。具体操作步骤如下所示。

修改前的函数定义体

void USART_SendData(USART_TypeDef* USARTx, u16 Data)

{

assert_param(IS_USART_ALL_PERIPH(USARTx));

assert_param(IS_USART_DATA(Data));

USARTx->DR = (Data & (u16)0x01FF);

}

修改后的函数定义体

void USART_SendData(USART_TypeDef* USARTx, u16 Data)

{

assert_param(IS_USART_ALL_PERIPH(USARTx));

assert_param(IS_USART_DATA(Data));

USARTx->DR = (Data & (u16)0x01FF);

while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET){} //等待发送缓冲区空才能发送下一个字符

}

方案3.不修改原来的库函数,在每一个字符发送后检测状态位。

USART_SendData(USART1, RxBuffer[TxCounter]);

while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET){} //等待发送缓冲区空才能发送下一个字符

ST这么做的原因是:使用发送中断功能。

STM32(Cortex-M3)中的优先级概念

STM32(Cortex-M3)中有两个优先级的概念——抢占式优先级和响应优先级,有人把响应优先级称作'亚优先级'或'副优先级',每个中断源都需要被指定这两种优先级。

具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。

当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。

既然每个中断源都需要被指定这两种优先级,就需要有相应的寄存器位记录每个中断的优先级;在Cortex-M3中定义了8个比特位用于设置中断源的优先级,这8个比特位可以有8种分配方式,如下:

所有8位用于指定响应优先级

最高1位用于指定抢占式优先级,最低7位用于指定响应优先级

最高2位用于指定抢占式优先级,最低6位用于指定响应优先级

最高3位用于指定抢占式优先级,最低5位用于指定响应优先级

最高4位用于指定抢占式优先级,最低4位用于指定响应优先级

最高5位用于指定抢占式优先级,最低3位用于指定响应优先级

最高6位用于指定抢占式优先级,最低2位用于指定响应优先级

最高7位用于指定抢占式优先级,最低1位用于指定响应优先级

这就是优先级分组的概念。--------------------------------------------------------------------------------
Cortex-M3允许具有较少中断源时使用较少的寄存器位指定中断源的优先级,因此STM32把指定中断优先级的寄存器位减少到4位,这4个寄存器位的分组方式如下:

第0组:所有4位用于指定响应优先级

第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级

第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级

第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级

第4组:所有4位用于指定抢占式优先级

可以通过调用STM32的固件库中的函数NVIC_PriorityGroupConfig()选择使用哪种优先级分组方式,这个函数的参数有下列5种:

NVIC_PriorityGroup_0 => 选择第0组

NVIC_PriorityGroup_1 => 选择第1组

NVIC_PriorityGroup_2 => 选择第2组

NVIC_PriorityGroup_3 => 选择第3组

NVIC_PriorityGroup_4 => 选择第4组

接下来就是指定中断源的优先级,下面以一个简单的例子说明如何指定中断源的抢占式优先级和响应优先级:

// 选择使用优先级分组第1组

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

// 使能EXTI0中断

NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQChannel;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 指定抢占式优先级别1

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 指定响应优先级别0

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

// 使能EXTI9_5中断

NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 指定抢占式优先级别0

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 指定响应优先级别1

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

--------------------------------------------------------------------------------
要注意的几点是:(STM32F101系列:http://www.y-ec.com/cpcp/class/?31.html)

1)如果指定的抢占式优先级别或响应优先级别超出了选定的优先级分组所限定的范围,将可能得到意想不到的结果;

2)抢占式优先级别相同的中断源之间没有嵌套关系;

3)如果某个中断源被指定为某个抢占式优先级别,又没有其它中断源处于同一个抢占式优先级别,则可以为这个中断源指定任意有效的响应优先级别。

通信方式

通信方式多种多样,可以从不同的角度划分,按照数据流的组织方式分为并行通信和串行通信;按照传输信号频率范围分为基带传输和宽带传输;按照信息同时传输的方向分为单工通信、半双工和全双工通信三种;按照通信两端通信的同步方式分为异步通信和同步通信

4.2.1 同步和异步通信

所谓同步是指接收端要按照发送端所发送的每个数据的起止时间和重复频率来接收数据,既收发双方在时间上必须一致.数据传输的同步方式有异步传输与同步传输两种。

同步和异步通信区分重点:是否要解决时钟合拍问题

1、异步通信

异步传输是以字符为单位的数据传输,每个字符都要附加1位起始位和l位停止位以标记一个字符的开始和结束。此外,还要附加1位寄偶校验位,可以选择奇校验或偶校验方式对该字符实施简单的差错控制。一个字符占用5~8位,具体取决于数据所采用的字符集。例如,电报码字符为5位、ASCll码字符为7位、汉字码则为8位。起始位和停止位结合起来,便可实现字符的同步。

发送端与接收端除了采用相同的数据格式(字符的位数、停止位的位数、有无核验位及校验方式等)外,还必须采用相同的传输速率。典型的速率有: 1200、2400、4800、9600和19200 b/s等。

异步传输又称为起止式异步通信方式。其优点是简单、可靠,常用于面向字符的、低速的异步通信场合。例如,主计算机与终端之间的交互式通信通常采用这种方式。

2、同步通信

同步传输是以数据块为单位的数据传输。每个数据块的头部和尾部都要附加一个特殊的字符或比特序列,标记一个数据块的开始和结束,一般还要附加一个校验序列(如16位或32位CRC校验码),以便对数据块进行差错控制。根据同步通信规程,同步传输又分为面向字符的同步传输和面向位流的同步传输。

4.2.2 基带传输与频带传输

基带传输:基带传输是指在线路上直接传输基带信号或略加整形后进行的传输。基带是原始信号所占用的基本频带,当终端把数字,信息转换为适合于传送的电信号时,这个电信号所固有的频带即为基带使用单路数字信号,信号可双向传输。数字信号的基带传输就是以原来的“0”和“1”的形式直接用数字信号在信道上传输。这是一种最简单的传输方式,一般在微机通信中采用。

频带传输:当进行远距离通信时,往往将数字数据转换成模拟信号后传输,在接收端再进行信号的恢复,当调制成频率信号的频率范围在音频范围(200Hz—3.4 kHz)内时,这种传输方式称为频带传输。其频率范围比音频范围宽时,则称之为宽带传输。

4.

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

在微控制器领域,MSP430与STM32无疑是两颗璀璨的明星。它们各自凭借其独特的技术特点和广泛的应用领域,在市场上占据了重要的位置。本文将深入解析MSP430与STM32之间的区别,探讨它们在不同应用场景下的优势和局限...

关键字: MSP430 STM32 单片机

STM32是由意法半导体公司(STMicroelectronics)推出的基于ARM Cortex-M内核的32位微控制器系列,以其高性能、低功耗、丰富的外设接口和强大的生态系统深受广大嵌入式开发者喜爱。本文将详细介绍S...

关键字: STM32 单片机

STM32与51单片机之间有什么差异呢?两者可以说是一场科技与性能的较量了。在科技飞速发展的今天,微控制器(MCU)已广泛应用于各类电子设备和系统中,发挥着举足轻重的作用。其中,STM32和51单片机作为两种常见的微控制...

关键字: STM32 51单片机 MCU

电磁铁是一种利用电流产生磁场的装置,具有快速响应、易于控制等特点,在工业自动化、电子设备、科学实验等领域有着广泛的应用。STM32是一款功能强大的微控制器,具有高性能、低功耗、易于编程等优点,是控制电磁铁的理想选择。本文...

关键字: 电磁铁 微控制器 STM32

边缘人工智能的实现涉及到三个基本 要素:安全性,连接性、自主性,而其中自主性是AI能力的体现,也是边缘AI有别于其他传统的物联网的关键。而通过ST Edge AI套件,就可以帮助各种不同类型的开发者实现覆盖全硬件平台的全...

关键字: 边缘人工智能 AI STM32

今天,小编将在这篇文章中为大家带来STM32单片机最小系统的有关报道,通过阅读这篇文章,大家可以对它具备清晰的认识,主要内容如下。

关键字: 单片机 单片机最小系统 STM32

STM32是一款由STMicroelectronics生产的微控制器系列,具有高性能、低功耗和丰富的外设资源。其中,串口通信是一种常用的通信方式,可以实现与其他设备之间的数据传输。

关键字: STM32 串口通信 微控制器

STM32是一种广泛使用的微控制器,具有丰富的通信接口。其中,串口通信是STM32与其他设备或系统进行数据交换的重要方式之一。本文将详细介绍STM32串口通信的原理、应用及常见故障。

关键字: STM32 串口通信

由于目前缺乏相应的监测技术,地下电缆线路出现异常运行状态无法被及时发现,久而久之易演变成大故障,最终只能通过更换地下电缆进行修复,耗费大量的人力、物力。鉴于此,开发了一种基于STM32的地下电缆异常状态检测系统,利用热传...

关键字: STM32 地下电缆

交通灯控制器是用于控制交通信号灯运行的设备,它可以根据交通流量、行人需求以及其他因素,动态地调整信号灯的变化时间和绿灯时长,以保证交通的流畅和安全。

关键字: 交通信号灯 STM32
关闭
关闭