关于“使用XCOM串口助手向单片机发送指令、单片机回复了重复多次”的问题
最近在复习stm32串口通信时,简单包装了个接收串口数据的函数,并重定向了printf发送函数。测试功能大致是:XCOM(PC主机)像单片机发送一串字符后,单片机每接收一段即立刻向PC端回复一串字符串作为调试消息。测试代码如下有:
bsp_usart.c
#include "bsp_usart.h"
#include <stm32ff10x.h>
void Bsp_Usart1_Init(uint32_t bps)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = bps;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
//打开串口1
}
void USART1_SendByte(uint8_t value)
{
USART_SendData(USART1,value);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
}
uint8_t USART1_ReceiveByte(void)
{
if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)!=RESET)
{
USART_ClearFlag(USART1,USART_FLAG_RXNE);
return USART_ReceiveData(USART1);
}
return 0;
}
#if 1
#pragma import(__use_no_semihosting)
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x) //这里有的版本没有void会导致错误
{
}
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//重定向fputc函数
int fputc(int ch, FILE *f)
{
while((USART1->SR & 0x40)==0); //循环发送,直到发送完毕
USART_SendData(USART1,(uint8_t)ch);
return ch;
}
#endif
main.c
#include<stm32f10x.h>
#include <stdio.h>
#include "delay.h"
#include "bsp_usart.h"
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Bsp_Usart1_Init(9600); //串口1
uint8_t a;
printf("Hello World!\r\n");
printf("你好,世界\r\n");
while(1){
Delay_us(10);
a=USART1_ReceiveByte();
if(a)
{
printf("%.2f",3.14f);
printf("\r\n");
}
}
}
测试现象:
烧录、运行上述代码到stm32f1单片机,打开串口助手XCOM并打开串口,单片机按键复位,上位机发送单串字符给单片机接收后,发现单片机会回复重复的两段消息?!,不禁然后感到十分的疑惑。。
经过一番挣扎后,把上面的这段PC端发给单片机的消息解析成”以16进制发送“(勾选)的话,上面这两个字符其实是两个8位16进制码(ascii码),我板子接收两个回复两次是正常的:
而我如果只发一个字符也就是一段8位数据的话,确实就只回复一次消息了:
但是如果发三个字母、四个字母、五个字母。。n个字母呢?似乎发多少个并不会跟着就收到多少个然后相应地回复多少次。。。例如我发4个字符的字符,就只收到2个消息;发4~6个字符都是回复2次;
发7~13个字符,回复3次(可以理解是单片机其实只接收到了3次??)
加长到发送14~19个字符时,变成回复4段消息了(单片机似乎只接收了4次):
加长到发送20~26个字符,则回复5段消息;
发送27~33个字符,则回复6段消息;
发送34~50个字符,则回复7段消息;
…
关于“使用XCOM串口助手向单片机发送字段、回收字段有丢失”的问题
对于上述问题,我觉得基本可排除不是printf发送函数的原因,并且若我单片机回收改为接收到的字符串返回,每次发送都很正常地只回复1次(当然可能其实也不一定是只接收到了1次,不懂。。),代码改动和测试结果如下:
printf("Hello World!\r\n");
printf("你好,世界\r\n");
while(1){
Delay_us(10);
a=USART1_ReceiveByte();
if(a)
{
printf("%c\n",a);
}
}
&emsp;
然后新的疑惑又来了(但我觉得刨下去应该跟上面的现象是一个原因导致。。),我发送若干长的字符串,单片机接收并返回的字符串超过3位后会丢失某几位!!
总结问题:1)向下发送字符接收固定回复时,回复的消息数随PC端串口软件发送的字符串的字符数量而不对等的增加;2)向下发送字符回收发送下去的字符串时,回收的字符串若超过3位会丢失后续某好几位。。。
上百度查询看到可能是片上串口接收缓冲区的大小问题,但是又更有点感觉像是没对上码的样子。。烦啊,解决不了这个很水的问题,太菜了,因此发成博客的形式希望求助大佬帮看一下,感谢呜呜呜~~