发新帖我要提问
12
返回列表
打印
[技术问答]

UART碰到的一些问题

[复制链接]
楼主: pq113_6
手机看帖
扫描二维码
随时随地手机跟帖
21
lihui567| | 2019-10-31 12:46 | 只看该作者 回帖奖励 |倒序浏览
pq113_6 发表于 2019-10-30 09:45
开一个buffer,UART中断把数据存在buffer中,定时1ms判断这个buffer是否有数据。最大是267个字节数据,我 ...

都设置串口中断优先级了,不会有冲突的,程序问题较大

使用特权

评论回复
22
pq113_6|  楼主 | 2019-11-1 13:23 | 只看该作者
JasonLee27 发表于 2019-10-31 09:14
printf本来就是通过uart2输出格式化字符串,如果uart2在用于打印输出,不建议再通过其他方式使用,或者在 ...

有人可以看看这个问题吗?看看会不会也有问题?

使用特权

评论回复
23
TechHolder| | 2019-11-1 14:51 | 只看该作者
pq113_6 发表于 2019-10-31 11:23
我用官方例程改了一个uart的程序,复现到问题了,测试方法如下:
1. 例程改为2路UART,UART1作为通信使用 ...

你的意思是UART1接收不管怎么样总是会丢一个字节?

使用特权

评论回复
24
pq113_6|  楼主 | 2019-11-1 15:36 | 只看该作者
TechHolder 发表于 2019-11-1 14:51
你的意思是UART1接收不管怎么样总是会丢一个字节?

我基本上是看到丢一个字节,不是固定的位置。

使用特权

评论回复
25
JasonLee27| | 2019-11-4 16:16 | 只看该作者
pq113_6 发表于 2019-10-31 11:23
我用官方例程改了一个uart的程序,复现到问题了,测试方法如下:
1. 例程改为2路UART,UART1作为通信使用 ...
int32_t UART_IRQHandler(uint8_t port, uint32_t LSR0, uint32_t LSR1)
{
    UART_Type *UARTx;
    if(port == 1)
        UARTx = UART1;
    else
        UARTx = UART2;
        if ((UARTx->UARTn_IER.ERXNE == 1) && (LSR0 & LSR0_DR))
    {
        uint8_t uartData = UART_ReceiveData(UARTx);
        UART_SendData(UART2, uartData);
        while(!UART2->UARTn_LSR0.TC);
        if ((!g_recvedDataRdy) && (g_recvDataTtlLen < UART_DATA_LEN_SEL))//½ÓÊÕÊý¾Ý
                {
                        g_recvedDataBuf[g_recvDataTtlLen++] = uartData;
                        if (g_recvDataTtlLen == UART_DATA_LEN_SEL)//Êý¾Ý½ÓÊÕÍê±Ï
                        {
                                g_recvedDataRdy = TRUE;
                                g_recvDataTtlLen = 0;
                        }
                }
    }

    if ((UARTx->UARTn_IER.ETXE == 1) && (LSR0 & LSR0_THRE))//·¢ËÍÊý¾Ý
    {
      
    }

    return 0;
}
我觉得UART中断这部分代码这样写是有问题的,你UART1中断中收到数据后将数据送入UART2并等待UART2发送完成,等于你UART2的发送完全是在UART1中断中执行的,那么很容易导致UART1产生溢出,测试的方法是在中断里面再增加一个溢出标志检查,通过仿真的方式看UART1是否产生溢出标志。或者你可以换种方式,在UART2发送前先判断再发送,或者直接发送不判断。这样可以避免UART2的发送占用UART1的中断时间。

使用特权

评论回复
26
pq113_6|  楼主 | 2019-11-13 16:12 | 只看该作者
Update一下,问题已经解决,不是芯片的问题,是代码有个bug,正好这颗芯片碰到了。

使用特权

评论回复
27
JasonLee27| | 2019-11-13 17:03 | 只看该作者
pq113_6 发表于 2019-11-13 16:12
Update一下,问题已经解决,不是芯片的问题,是代码有个bug,正好这颗芯片碰到了。 ...

所以这颗芯片还有查bug的能力?

使用特权

评论回复
28
TechHolder| | 2019-11-13 17:19 | 只看该作者
pq113_6 发表于 2019-10-31 11:23
我用官方例程改了一个uart的程序,复现到问题了,测试方法如下:
1. 例程改为2路UART,UART1作为通信使用 ...

使用你的代码做了一下测试,没有屏蔽while(!UART2->UARTn_LSR0.TC);代码前是会丢失数据,屏蔽后不会丢失数据,连续测试了几分钟,如下图:

也附上修改后的代码,你可以测试一下。

UART_Sample.rar

2.39 MB

使用特权

评论回复
29
pq113_6|  楼主 | 2019-11-13 17:47 | 只看该作者
JasonLee27 发表于 2019-11-13 17:03
所以这颗芯片还有查bug的能力?

哈哈,确实是,可能正好撞上那个点上了,之前用ST用的比较多,所以没撞到问题,其实ST也有这个问题,只是代码有检查是否错误,ST的多try了几次就通信成功了,现在改了这个bug后通信速率明显上升了。

使用特权

评论回复
30
pq113_6|  楼主 | 2019-11-13 17:49 | 只看该作者
TechHolder 发表于 2019-11-13 17:19
使用你的代码做了一下测试,没有屏蔽while(!UART2->UARTn_LSR0.TC);代码前是会丢失数据,屏蔽后不会丢失 ...

是的,我之前也看到这个问题了,确实是在中断里面处理时间太久导致溢出了,奇怪的是明明有FIFO怎么还溢出。

使用特权

评论回复
31
JasonLee27| | 2019-11-13 18:52 | 只看该作者
pq113_6 发表于 2019-11-13 17:49
是的,我之前也看到这个问题了,确实是在中断里面处理时间太久导致溢出了,奇怪的是明明有FIFO怎么还溢出 ...

这个延时会积累的,所以即使有fifo,延时累积到一定程度后必然会造成溢出

使用特权

评论回复
32
pq113_6|  楼主 | 2019-11-14 16:31 | 只看该作者
本帖最后由 pq113_6 于 2019-11-14 16:34 编辑
JasonLee27 发表于 2019-11-13 18:52
这个延时会积累的,所以即使有fifo,延时累积到一定程度后必然会造成溢出 ...

看到问题点了,测试代码如附件 uart_basic.zip (3.3 KB)
测试方法是发送267字节,然后判断第一个字节为0xaa时就打开使能信息打印。
if(uartData == 0xaa)
{
    count = gTimerDelayCount;
    debug = 1;
}

在main函数的LOOP里面打印接收到数据和读取到这些数据的时间差。
while(1)
{
    //UART_CheckDataDealPrd();
               
    //UART_CheckLEDBlinkPrd();
    uartDebugReceive();
}

打印结果如下:

[16:05:42.682]收←◆uart basic sample

[16:05:46.778]收←◆recv count:f000
count:effd
0xaa 0x55 0x0 0x4 0x1 0x4 0x0 0x0 0x0 0x0 0x78 0x9c 0xec 0x9d 0x7f 0x6c 0x23 0xd7 0x7d 0xe0 0x4d 0x5e 0x89 0x25 0xb8 0xe8 0x70 0x59 0x92 0x65 0x78 0xd 0x9 0x32 0xa2 0x4 0xfe 0x10 0x49 0x95 0xa0 0xc8 0x52 0x14 0x24 0xc 0x53 0x51 0x50 0xa6 0x77 0x9 0xc5 0x52 0x71 0x55 0x61 0xc5 0x70 0xb9 0x58 0x46 0x62 0x4f 0xeb 0xf8 0x7 0x23 0xfb 0x84 0x8 0x56 0x28 0x68 0xe3 0x54 0x52 0x5c 0x57 0xe0 0x69 0x77 0x5 0x9 0x4c 0x16 0xda 0x36 0x36 0x4e 0x4a 0xac 0x83 0x7b 0x67 0x41 0xce 0x26 0x3e 0x6c 0x37 0xf1 0xfa 0x92 0xb5 0xef 0x10 0xe0 0x72 0xc0 0xa5 0x69 0x70 0xb8 0x3a 0xce 0xa1 0xed 0xfa 0x8f 0x2 0xed 0xbd 0xef 0x7b 0x6f 0x86 0x33 0xe4 0xf0 0x87 0xd6 0x6b 0x89 0xf2 0xea 0xeb 0xba 0x70 0xa4 0xe1 0xf0 0x91 0x7a 0x9f 0xf9 0xfe 0xfe 0xbe 0x9f 0x7d 0xb0 0x8f 0xfe 0xf9 0xaf 0x91 0xbf 0x18 0xfd 0xd9 0x7 0xb1 0x91 0x77 0xee 0x7f 0xfa 0xd9 0xf7 0x9f 0xfb 0xab 0x77 0xbf 0xf7 0xc5 0x60 0xfe 0x5f 0xfe 0xa5 0xe3 0xd9 0xeb 0xef 0xbf 0x73 0xbf 0xff 0x97 0x5b 0xef 0xce 0xbd 0x5f 0xfe 0xda 0xf5 0xf7 0xdf 0x7f 0xee 0x3f 0xbc 0xd5 0xf3 0xd5 0xd9 0xb7 0x12 0x5f 0xef 0xf9 0xaa 0xf6 0xab 0x8f 0xbf 0xb9 0xfe 0xee 0xc1 0xbb 0x13 0xbf 0xfc 0xa7 0x9f 0x7d 0xee 0xab 0xef 0xbe 0xfe 0xd3 0x77 0x3f 0x78 0x7d 0xef 0xd5 0x3f 0x99 0x9e 0x7b 0x7f 0xa8 0xfc 0x3b 0xff 0xeb 0x73 0xb3 0xbf 0xf7
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0

收到0xaa的时间时0xf000,第一次打印的时间时0xeffd,时间中断时1ms一次,即第一次进LOOP的时间是3ms(0xf000-0xeffd),应该是串口中断一直独占CPU了,而且第一笔读到的数据是256字节(估计是软件每次传输的字节数)。问题就是串口中断一直没有释放出来,这点很奇怪,不知道有没有办法释放?
另外,测试了一下STM32F072的平台,收到19个字节就能进LOOP,时间是小于1ms的。
[16:33:15.288]收←◆recv count:f827
RecvIn:19, RecvRd:0, count:f827




使用特权

评论回复
33
JasonLee27| | 2019-11-15 18:54 | 只看该作者
pq113_6 发表于 2019-11-14 16:31
看到问题点了,测试代码如附件
测试方法是发送267字节,然后判断第一个字节为0xaa时就打开使能信息打印。
...
void uartDebugReceive(void)
{
    uint16_t i;
        uint16_t currentCount;
    if(debug == 0)
        return;
        currentCount = gTimerDelayCount;
    Printf("recv count:%x\n", count);
    Printf("count:%x\n", currentCount);
    for(i = 0; i < sizeof(g_recvedDataBuf); i++)
    {
        Printf("0x%x ", g_recvedDataBuf[i]);
    }
    Printf("\n\n");
    //debug = 0;
}


你这样改试试,这里使用的printf函数是实时打印的,按115200的速度计算,十几个字节就有1ms时间了

使用特权

评论回复
34
operating| | 2019-11-17 17:44 | 只看该作者
一般串口都是要自己开缓冲buffer的

使用特权

评论回复
35
pq113_6|  楼主 | 2019-11-18 10:24 | 只看该作者
operating 发表于 2019-11-17 17:44
一般串口都是要自己开缓冲buffer的

PC一次发送267个字节,串口开了267个字节的buffer。现在的问题是串口中断似乎一直占用CPU,不知道是不是进出串口中断时间太长了导致的问题。

使用特权

评论回复
36
gyxlizhong| | 2020-5-7 17:36 | 只看该作者
pq113_6 发表于 2019-11-18 10:24
PC一次发送267个字节,串口开了267个字节的buffer。现在的问题是串口中断似乎一直占用CPU,不知道是不是 ...

你可以在串口中断入口、出口各加一个GPIO置位、复位代码,用示波器观察时间就可判断。你原代码在串口接受中断里一直判断另一个串口的发送完成,当两个串口波特率一致时,将会因为PC串口和MCU串口速率微小差异的持续累积导致丢字节

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则