串口一次发大量数据时怎么操作?
我发现串口发送时,最多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);
大量数据 相关文章: