通过串口的范例测试可以接收和发送数据,在串口调试助手中发送和接收都正常,下图为测试过程,无论发送的字符串长短不同,开发板均能返回正确的字符串。
但是我试图的开发板中将接收到的字符串显示在LCD屏幕上却遇到了问题,接收函数总是按照每7个字符截取,无法获得完整的字符串。如下图,我发送的是“2020-10-06 14:36:50”,但最后只显示"36:50",之前的“2020-10-06 14:"却看不到,仔细分析是先显示前7个字符”2020-10“,然后显示第二组7个字符”-06 14:"时覆盖了前7个字符,最后的5个字符“36:50"又将第二组字符覆盖了。
下图是发送”2020-10-06 14:36:50 Test"字符串(长度24),显示的是最后3个字符“est”(第3组的最后一个“T”没有被覆盖)。
下图是发送“2020-10-06”字符串(10个字符),也是按照7+3的方式显示。
查看资料说是接收函数设定的每次接收长度为7个字节,我找了很久也没有发现是在哪里设定的,是不是可以将这个长度设定为16个字节或者更多,或者用什么办法才能将接收到的每段字符串“拼接”起来?希望能够得到各位大佬帮助,谢谢!
补充内容 (2020-10-19 09:39): 按照damiaa版主的提示,终于能显示出完整的串口接收字符了,详见11楼。我是在串口中断函数中设置一个接收标志,然后在主循环中根据这个标志来显示接收到的字符串,并清除标志。下面是串口中断函数,这里除了添加了设置标志的代码外,未作任何修改:
void UART1_IRQHandler(void)
{
UINT8 i;
switch( UART1_GetITFlag() )
{
case UART_II_LINE_STAT: // 线路状态错误
UART1_GetLinSTA();
break;
case UART_II_RECV_RDY: // 数据达到设置触发点
for(i=0; i!=trigB; i++)
{
RxBuff[i] = UART1_RecvByte();
UART1_SendByte(RxBuff[i]);
}
rxok = i; //设置接收标志
break;
case UART_II_RECV_TOUT: // 接收超时,暂时一帧数据接收完成
i = UART1_RecvString(RxBuff);
UART1_SendString( RxBuff, i );
break;
case UART_II_THR_EMPTY: // 发送缓存区空,可继续发送
break;
case UART_II_MODEM_CHG: // 只支持串口0
break;
default:
break;
}
}
下面是主循环中的判断和显示的代码:
if(rxok>0){
LCD_clear_line(2); //清除当前行
LCD_clear_line(3);
LCD_clear_line(4);
LCD_write_BG(0,2,RxBuff); //显示接收到的字符
LCD_write_ASCII(0,4,1,RxBuff);
LCD_write_value(0,5,3,0,0,rxok);
UART1_CLR_RXFIFO(); //清除缓存
rxok = 0;
}
我将串口接收中断函数中的接收循环trigB用16替换,串口调试助手接收到的数据却与发送的不同:
修改的代码见下面粗体字部分:
void UART1_IRQHandler(void)
{
UINT8 i;
switch( UART1_GetITFlag() )
{
case UART_II_LINE_STAT: // 线路状态错误
UART1_GetLinSTA();
break;
case UART_II_RECV_RDY: // 数据达到设置触发点
for(i=0; i!=trigB; i++) //其中的i!=trigB;修改为i < 16
{
RxBuff = UART1_RecvByte();
UART1_SendByte(RxBuff);
}
rxok = i; //设置接收标志
break;
case UART_II_RECV_TOUT: // 接收超时,暂时一帧数据接收完成
i = UART1_RecvString(RxBuff);
UART1_SendString( RxBuff, i );
break;
case UART_II_THR_EMPTY: // 发送缓存区空,可继续发送
break;
case UART_II_MODEM_CHG: // 只支持串口0
break;
default:
break;
}
}
引用: littleshrimp 发表于 2020-10-6 20:07 加一个简单的协议,比如以'\n'结尾,收到\n时再处理数据
谢谢指点!我试试看。
尝试加结束标志测试了一下,但没有成功,串口辅助调试助手接收的数据与发送的不一致(见下图):
其中不可见字符是十六进制11:
单片机中显示出来的字符如下:
也许是我的测试的代码不正确,代码如下:
case UART_II_RECV_RDY: // 数据达到设置触发点
/*
for(i=0; i!=trigB; i++){
RxBuff = UART1_RecvByte();
UART1_SendByte(RxBuff);
}
*/
while(ok < 2){
RxBuff = UART1_RecvByte();
UART1_SendByte(RxBuff);
if((RxBuff == 'n') & (ok > 0))
ok++; //收到结束标志2
else{
if(RxBuff == '/')
ok = 1;
else
ok = 0;
}
i++;
if(i>15)
ok = 2; //最长不超过16个字节
}
rxok = i; //设置接收标志
break;
我想要是直接修改设置的触发点可能更方便些,因为我目前只想通过串口来设置日期和时间,字符串长度有16位就基本可行(年月日共8位、时分共4位,再加上若干标识符),现在就是不清楚在哪里可以修改这个接收长度。
引用: freebsder 发表于 2020-10-11 21:36 要自己处理,你可以百度一下 串口完整数据包 的相关文章.
谢谢指点!我去搜索看看。
串口程序一般可以这样处理。
接收单字节串口数据==》环形缓冲区=》解析程序读环形缓冲并释放已经读的数据,然后放到解析缓冲中解析数据=》(如果解析到一个完整命令)执行解析命令
接收单字节串口数据==》环形缓冲区 放在中断函数中
解析程序读环形缓冲并释放已经读的数据,然后放到解析缓冲中解析数据=》(如果解析到一个完整命令)执行解析命令 放在主程序中
本帖最后由 damiaa 于 2020-10-12 09:00 编辑这是串口中断设置的代码:
// 中断方式:接收数据后发送出去
UART1_ByteTrigCfg( UART_1BYTE_TRIG );
trigB = 1;
UART1_INTCfg( ENABLE, RB_IER_RECV_RDY|RB_IER_LINE_STAT );
NVIC_EnableIRQ( UART1_IRQn );
这是串口中断处理的代码(部分):
case UART_II_RECV_RDY: // 数据达到设置触发点
buf = UART1_RecvByte();
UART1_SendByte(buf);
RxBuff[RxID] = buf;
RxID++;
if(RxID > 49)
RxID = 0;
引用: 程英茂 发表于 2024-10-7 07:38 有直接可用的压缩包吗?
找到了之前的压缩文件,希望能够帮到你。