微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > TI蓝牙设计交流 > 串口一次发大量数据时怎么操作?

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

时间:10-02 整理:3721RD 点击:

我发现串口发送时,最多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);

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top