This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

串口一次发大量数据时怎么操作?



我发现串口发送时,最多128被字节。。。HAL_UART_DMA_RX_MAX        128;#define HAL_UART_DMA_TX_MAX        HAL_UART_DMA_RX_MAX

我现在想在一次发送大于128个字节改怎么操作?

  • Hi wengo

        HAL_UART_DMA_RX_MAX是指DMA的接收缓冲。

    只要你注册了DMA的事件回调函数,DMA有数据时就会通知你(可能是1个或者多个数据),这时你就可以去读取。

    ——一有数据就读走,不管多少个,不必等到所有数据都收齐了再去读。

    而DMA能存的字节数自然由这个缓冲的大小决定,只要你能及时地读取数据,128字节是足够你使用的。

     

  • 怎么注册DMA事件回调啊?我知道有一个串口接收回调函数。。但是这个是接收后的。

    我要发送到串口呢?

    for(uint8 i=0;i<50;i++)
    {
    HalUARTWrite(0,"Hello",5);
    }我这么写之后,PC端串口接收不能显示50个Hello。。在1.4版本调用NPI_WriteTransport("Hello",5);这个也一样。

  • 在初始化串口DMA传输时,就需要传入回调函数的指针:

    NPI_InitTransport(UART_DmaEvtCB);//初始化串口DMA传输、注册回调函数

    发送串口数据也很方便:

    NPI_WriteTransport("Hi wengo\n",sizeof("Hi wengo\n")-1);

    //串口DMA传输事件回调函数
    static void UART_DmaEvtCB( uint8 port,uint8 event)
    {

    uint8 numbyte;
    if(event & HAL_UART_RX_TIMEOUT)//有数据等待接收
    {
        //todo在此接收数据

    }
    if(event & HAL_UART_TX_EMPTY)//发送完成
    {
        //todo
    }
    }

  • 等待查询发送标志!否则缓冲区数据会自动被清除。

     

  • 不好意思,麻烦你了。。。我试了下,还是有问题啊,if(event & HAL_UART_TX_EMPTY)//发送完成。。这个确实是发送完成时进入的。。不能满足我的需求。

    不知你试验了没,我有一堆数据要发送,我现在就简单点发50组Hello。

    for(uint16 cnt=0;cnt<50;cnt++)
    {
    NPI_WriteTransport("Hello",sizeof("Hello")-1);

    //    delay();
    }

    1      但是实际上,PC端接收到

    Hello...HelloBLE Central
    Texas Instruments
    0x883314D6BA3D时,才进入if(event & HAL_UART_TX_EMPTY)。。。而此时,Hello并没有输出50组。程序已经运行到后面 打印Texas完成才进入回调函数。。

    2    而如果我在delay打开后,就能完整打印50组Hello。。但是在打印期间加入延时,可能不是很好的办法。。

    3    如果

    for(uint16 cnt=0;cnt<50;cnt++)
    {
    NPI_WriteTransport("Hello",sizeof("Hello")-1);

    }

      delay();

    把延时函数放到for外面。。延时时间完成,也不能进入回调函数。。。说明如果我一次发多个字节,是不能调用到回调函数里面的事件的!!连发送完成事件也没触发。

    4   if(event & HAL_UART_TX_EMPTY)//发送完成
    {
        sendOKFlag = 1;
    }

    我在里面加一个标志

    {
    NPI_WriteTransport("Hello",sizeof("Hello")-1);
    while(sendOKFlag==0);
    }为什么加while不能进入回调函数,一直挺在while里面。。一去掉while  就能进入发送完成的回调函数里面了??


  • Hi wengo

        前面你自己也提到过了,DMA的缓存是128字节,而我们调用函数NPI_WriteTransport(“Hello”,sizeof(“Hello”)-1);其实只是把数据写入到DMA的缓冲中,并不代表已经发送完成(实际的数据是通过串口按一定的波特率一个一个输出的)。

        1.DMA搬运数据时需要时间的;

        2.串口发送数据也是需要时间的——这个取决于你的波特率;

        3. 你这么循环写入50次,总字节 = 6*50 = 300Byte。缓冲时不够用的。因为DMA搬运数据及串口发送的速度跟不上的写入的速度(进的快,出的慢),这样你的缓存最终就会爆满,我们这边称作数据阻塞(不知道你们叫什么)。

        4.我不明白你为什么要这么做:       

    for(uint16 cnt=0;cnt<50;cnt++)
    {
    NPI_WriteTransport("Hello",sizeof("Hello")-1);

    }

        5.如果你真的需要打印50个Hello,我建议你使用其他的方法。

  • HI shaokai

    谢谢你。。我明白了,肯定是数据阻塞了。。。看来我必须使用延时了,使用延时能完成发送数据的。。多谢!!!

  • Hi wengo

        如果你说的延时是指如下的做法,那么我不赞同这么做。

    for(uint16 cnt=0;cnt<50;cnt++)
    {
    NPI_WriteTransport("Hello",sizeof("Hello")-1);

       delay();
    }

    因为这么样会Hold住CPU,不能执行其他任务。

    我的建议是:将你要发送的大数据分批发送,在前面一批数据发送完成后 才继续发送下一批数据。

    比方说,你可以在回调函数的发送完成处理中置为一个任务事件 osal_set_event(xxtaskid,xxeventid);

    然后你到这个任务事件的处理中去继续发送下一批数据。

    不过我自己没有做过(因为我没有大数据要猛发...),我也只是提供一个建议,可不可行得你自己去试了。

  • HI 大秦正声:

    等待查询发送标志!是那个?

    for(uint16 cnt=0;cnt<70;cnt++)
    {
    NPI_WriteTransport("Hello",sizeof("Hello")-1);
    while((U0CSR&0x02) != 0x02);
    // delay();
    }

    U0CSR 的bit2位是Transmit byte status.好像没起作用。。

  • Hi wengo

    NPI_WriteTransport("Hello",sizeof("Hello")-1);
    while(sendOKFlag==0);
    }为什么加while不能进入回调函数,一直挺在while里面。。一去掉while  就能进入发送完成的回调函数里面了??

        可能你对器件的DMA传输还不是很了解,为何加while不能进入到回调函数呢?先看看回调函数在哪里被调用:

    1.OSAL.C文件中,void osal_run_system(void)有这么一个函数 Hal_ProcessPoll();

    2.点进去,可以找到 HalUARTPoll();

    3.再点进去可以找到 HalUARTPollDMA();

    4.再点进去可以找到 

    if ((evt != 0) && (dmaCfg.uartCB != NULL))//调用回调函数并发送事件通知
    {
    dmaCfg.uartCB(HAL_UART_DMA-1, evt);
    }

    这里调用的dmaCfg.uartCB正是你注册的回调函数。

    也就是说,DMA串口传输的回调函数是放在主循环里面轮询的,你用while(sendOKFlag == 0);Hold住CPU,代码得不到执行,当然不会执行回调函数啦。

        OK,我能帮你的就这么多了,深入的还是请教TI的专家吧。

  • HI shaokai:

    O..非常感谢你!

    我还是按照单片机思维,把那个回调函数当成中断了!!终于明白流程了。。谢谢。#if HAL_UART就关闭了HAL_UART_ISR了~~

  • HI shaokai:

    ~~我的建议是:将你要发送的大数据分批发送,在前面一批数据发送完成后 才继续发送下一批数据。

    比方说,你可以在回调函数的发送完成处理中置为一个任务事件 osal_set_event(xxtaskid,xxeventid);

    然后你到这个任务事件的处理中去继续发送下一批数据。~~

    这个建议我试试。。谢谢

  • 不用dma函数;

    简单点,

    U0DBUF='a';

    while((U0CSR&0x02) != 0x02);