STM32串口使用总结
扫描二维码
随时随地手机看文章
一、串口使用:
原则:尽量中断中不要有延时(比如自定义delay 和自定义printf串口打印,明显找事啊这么慢能不发生溢出error嘛),接收和发送尽量分开处理
1.串口发送数据丢失:
1)通常是因为发送之前未检测TC状态位之前是否处于发送完成标志导致,关于STM32之·的测试程序来讲会导致第一个字符丢失,之后都完全正常。
因此发送一串数据的逻辑必须按照先检测TC再发送字符的顺序进行.即:
void Usart1_Send_Data(u8 *buf,u32 len)
{
u32 i;
for(i = 0;i
{
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)== RESET) ; //
USART_SendData( USART1,*(buf+i));
}
while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET) ; //提升代码健壮性
}
//绿色部分提高了代码的健壮性,虽说可有可无,但是避免其他部分代码出现类似不检测发送的问题。
2)监测发送状态位用TC而尽量不要使用TXE,毕竟前者是监测的是否数据发送完而后者只是监测缓存区是否移位到移位寄存器而已。(在485这种半双工的模式下就有差别,后者会导致自己发送后自己又接收到数据)
2.接收数据丢失:
何时串口需要使用流控(即串口硬件流控制):硬件流控制是用在单片机与另一台设备串口通信时,单片机处理速度相对比如PC机慢,单片机接收数据处理速度低于pc机发送速度,这样会造成数据丢失,这样就需要加入硬件流控了。流控制能解决这个问题,当接收端数据处理不过来时,就发出“不再接收”的信号,发送端就停止发送,直到收到“可以继续发送”的信号再发送数据。因此流控制可以控制数据传输的进程,防止数据的丢失。我们通常在串口助手这种速率情况下单片机处理速度是完全ok的,不需流控。只是应用在两者处理速度确实差异较大情况下;另外接收数据丢失就是自己在中断中添加了延迟操作比如delay 或者printf这种超消耗时间并伴随着数据溢出error出现这种低级错误!!
3.关于串口数据的接收与发送处理的几种模式:(以只以接收中断为例)
1)(一般用于测试)接收一个字符就发送一个字符:
这种模式多用在串口测试收发的数据,即用在测试中较多,可以在串口接收中断将收到的数据直接发送即可:逻辑即以下代码:(像这种中断中接收中断中发送的模式通常只在我们测试环境中使用,而实际通信中接收和发送一般都是分开的,接收我们设立专门的缓存区,
void USART1_IRQHandler(void)
{
u8 res=0;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
res =USART_ReceiveData(USART1);
while (USART_GetFlagStatus(UART1, USART_FLAG_TC) == RESET);
USART_SendData(UART1, res);
}
}
2)(用于实际应用)建立接收缓存区,串口驱动层存取数据和进行数据缓存大小的简单、帧是否结束判断,而受到数据根据具体协议由协议层对接收到的数据进行校验;接收与发送是不同的进程,通过一个自定义状态寄存器实现数据的检测。
void USART1_IRQHandler(void)
{
u8 res,num;
if( USART_GetITStatus(USART1,USART_IT_RXNE) ==SET)
{
res = USART_ReceiveData(USART1);
num = Usart1_Rx_Sta&0x03ff; //接收数据序号
//可接收数据帧
if( !(Usart1_Rx_Sta>>15) )
{
Usart1_Buf[num] =res;
Usart1_Rx_Sta++;
Fream_Record(res); //调用协议层处理
if( ( Usart1_Rx_Sta&0x03ff) >=USART1_BUF_SIZE ) //越界
Data_Reset();
if( (Usart1_Rx_Sta>>12&0x07) == FRAME_HEAD )
Usart1_Rx_Sta|=0x01<<15; //接受完一帧
}
}
}
总结来说上面即两种方式
法1 UART的发送寄存器空的位测试
命令
法2完整的接收到来自发送设备的数
据,来确认发送数据完成,以便及时地关闭
发送(即接收到完整帧)
毕竟软件是活的,方法思路不是死的,下面这两种思路用于测试也不错的:
1.通过串口接收中断一个字节一个字节接收数据,同时用定时器来计算接收到数据的时间间隔,如果超过一定时间没有接收到数据则判断为一帧数据接受完,然后再对数据进行解析
2,通过DMA接收,加串口空闲中断方式,只在接收完一帧数据后才会产生中断,然后对数据进行解析。
二、关于串口助手:(由于我们串口一般按字节接收)
注意:有的串口助手比如正点原子提供的ATKXCOM串口助手本身其实就是有很大问题的。
串口助手发送有两种模式,普通字符串和十六进制形式。
若发送选字符串形式,那么发送的每个都是字符而不是"十进制数",比如空格也是字符,并不是没有发数据!!
而选择十六进制数形式,则意味着每两个十六进制数构成一个字节发送(由于我们串口正常都是按照8bit即单字节接收)。既然是十六进制,那么你发送的数值形式至少满足是0-f之间啊。像sscom这种串口助手上如果非正常输入就会有警告提示,这是相对好的一点。
而我们说像ATKXCOM这种串口助手的更大的问题是如果非十六进制下是否做了处理,像sscom在十六进制下空格是忽视的,也就是无效,这是很容易接受的,毕竟不是十六进制,并且十六进制下发送新行按钮即回车和换行这种非十六进制是屏蔽的,也是无效,这是应该的。而ATKXCOM1.4版本本身竟然在十六进制下将空格和新行也发了出去,这本身就是错误的,而2.0版本依然没有改新行这个功能在十六进制下屏蔽这个问题。这个最简单的方法就是可查看助手下面发送数据计数即可看出,所以ATKXCOM串口助手这种带问题的串口不要使用...
总结串口助手:
1:勾选发送换行只有在是字符串格式下才有效,空格有效;十六进制模式只能发送十六进制数,空格无效,新行无效。
2:下面记录的发送数据个数可记录我们实际发送的数据个数
三、串口使用不要时不要添加多余操作:
1)比如在初始化串口中无故添加 USART_ClearFlag(USART3,USART_FLAG_TC)某个串口状态,如果程序中有重新初始化串口也就是重复无条件执行USART_ClearFlag(USART3,USART_FLAG_TC)会导致某串口挂掉或者整个板子挂掉
2)争强代码健壮性可在串口初始化开始先进行串口复位操作
四、串口部分寄存器位说明
SR状态寄存器先读状态再读数据(调用对应接口)实现的是清除SR状态位,但并不会使接收缓存器(DR)内数据丢失,仍是当前数据
五、关于STM32带奇偶校验接收发送的串口配置问题
STM32如果串口含有就校验那么32自身的串口的数据位应配置为9位模式,其最高位硬件给为校验位(实际数据位仍是8位),而如果我们配置数据位为8位,则最高位会配置为奇偶校验位,那么实际数据位只有7位,这时与串口通信的PC为7位数据位才数据可能正确。具体参见STM32手册p519下图
换句话说就是STM32的“数据位”长度不同于我们实际串口专指的“数据部分”的长度。当无奇偶校验时,则32的数据位就是实际的数据部分长度,与串口助手上数据位一样;而当有就校验时,由奇偶校验位会占用32所谓“数据位”最高位,因此当32串口配置9位时实际数据位为8位,配置为8位时实际数据位为7位。
即:如果PC端设置为: 数据位=8,停止位=1,奇偶检验=偶/奇
则STM32的设置为:数据位=9,停止位=1,奇偶检验=偶/奇
请记住,在STM32上,奇偶检验位要计算在数据位中。
2.串口助手有的不支持奇偶校验功能,比如丁丁(sscomm)的3.3版本不支持,而4.2版本则支持这个功能,而正点原子串口助手本身bug太多就不推荐使用了
四、网络助手无非基于本地ip的一个应用进程,因此其处于本地ip的应用层,这点要注意。也就意味着应用层以下的协议你是不能用网络助手作为一个进程进行通信使用的