c – 用于不同大小的阵列的UART DMA

c – 用于不同大小的阵列的UART DMA,第1张

概述使用带有dsPIC33FJ128GP802单片机的MPLAB X 1.70. 我有一个应用程序,它以不同的采样率从一个传感器收集数据(一个在50Hz,另一个在1000Hz),两个传感器包也有不同的大小(一个是5个字节,另一个是21个字节).到目前为止,我已经使用了手动UART传输,如下所示: void UART_send(char *txbuf, char size) { // Loop 使用带有dsPIC33FJ128GP802单片机的MPLAB X 1.70.

我有一个应用程序,它以不同的采样率从一个传感器收集数据(一个在50Hz,另一个在1000Hz),两个传感器包也有不同的大小(一个是5个字节,另一个是21个字节).到目前为止,我已经使用了手动UART传输,如下所示:

voID UART_send(char *txbuf,char size) {    // Loop variable.    char i;    // Loop through the size of the buffer until all data is sent. The while    // loop insIDe checks for the buffer to be clear.    for (i = 0; i < size; i++) {        while (U1STAbits.UTXBF);        U1TXREG = *txbuf++;    }}

不同大小的数组(5或21个字节)被发送到这个函数,它们的大小和一个简单的for循环遍历每个字节并通过UART tx寄存器U1TXREG输出.

现在,我想实现DMA以减轻传输大量数据时系统的压力.我已经将DMA用于我的UART接收和ADC,但是在传输时遇到了问题.我已尝试打开和关闭乒乓模式,以及单次和连续模式,但无论何时发送21字节数据包,它都会使用奇怪的值和零值填充.

我正在初始化DMA,如下所示.

voID UART_TX_DMA_init() {        DMA2CONbits.SIZE  = 0;                                  // 0: word; 1: byte        DMA2CONbits.DIR   = 1;                                  // 0: uart to device; 1: device to uart        DMA2CONbits.AMODE = 0b00;        DMA2CONbits.MODE  = 1;                                  // 0: contin,no Ping pong; 1: oneshot,no Ping pong; 2: contin,Ping pong; 3: oneshot,Ping pong.        DMA2PAD = (volatile unsigned int) &U1TXREG;        DMA2REQ = 12;                   // Select UART1 Transmitter        IFS1bits.DMA2IF  = 0;           // Clear DMA Interrupt Flag        IEC1bits.DMA2IE  = 1;           // Enable DMA interrupt}

DMA中断我只是清除标志.为了构建DMA数组,我有以下功能:

char TXBufferADC[5] __attribute__((space(dma)));char TXBufferIMU[21] __attribute__((space(dma)));voID UART_send(char *txbuf,char size) {    // Loop variable.    int i;    DMA2CNT = size - 1; // x DMA requests    if (size == ADCPACKETSIZE) {        DMA2STA = __builtin_dmaoffset(TXBufferADC);        for (i = 0; i < size; i++) {            TXBufferADC[i] = *txbuf++;        }    } else if (size == IMUPACKETSIZE) {        DMA2STA = __builtin_dmaoffset(TXBufferIMU);        for (i = 0; i < size; i++) {            TXBufferIMU[i] = *txbuf++;        }    } else {        NOTIFICATIONLED ^= 1;    }    DMA2CONbits.CHEN = 1; // Re-enable DMA2 Channel    DMA2REQbits.FORCE = 1; // Manual mode: Kick-start the first transfer}

这个例子是关闭乒乓球的.我正在使用相同的DMA2STA寄存器,但根据我的数据包类型更改数组.我正在确定要发送的数据的数据包类型,更改要发送的DMA字节(DMA2CNT),使用for循环构建与之前相同的数组,然后强制第一次传输以及重新启用通道.

处理大数据包的数据需要更长的时间,我开始认为DMA缺少这些数据包并在其位置发送空/奇怪的数据包.在构建缓冲区并强制进行第一次传输之前,它似乎是轮询.也许每次民意调查都不需要这种力量;我不知道…

任何帮助都会很棒.

解决方法 经过几天的努力,我想我已经明白了.

我遇到的主要问题是DMA中断的轮询速度比之前的传输速度快,因此在下一个软件包覆盖前一个软件包之前,我只获得了一些软件包.只需等待UART传输结束即可解决这个问题:

while(!U1STAbits.TRMT);

通过简单地使原始数据阵列成为DMA识别的数据,我设法避免了使用包数据重新创建新DMA的冗余.

最后,该过程非常简单,每次创建包时调用的函数是:

voID sendData() {    // Check that last transmission has completed.    while (!U1STAbits.TRMT);    DMA2CNT = bufferSize - 1;    DMA2STA = __builtin_dmaoffset(data);    DMA2CONbits.CHEN = 1; // Re-enable DMA0 Channel    DMA2REQbits.FORCE = 1; // Manual mode: Kick-start the first transfer}

无论封装的大小如何,DMA都会使用DMA2CNT寄存器更改它发送的数量,然后它只是重新启用DMA并强制第一位.

设置DMA是:

DMA2CONbits.SIZE = 1;DMA2CONbits.DIR = 1; DMA2CONbits.AMODE = 0b00;DMA2CONbits.MODE = 1;DMA2PAD = (volatile unsigned int) &U1TXREG;DMA2REQ = 12;                               // Select UART1 TransmitterIFS1bits.DMA2IF = 0;                        // Clear DMA Interrupt FlagIEC1bits.DMA2IE = 1;                        // Enable DMA interrupt

这是一次性,没有乒乓,字节传输,以及UART1 TX的所有正确参数.

希望这有助于将来的人,一般原则可以应用于大多数PIC微控制器.

总结

以上是内存溢出为你收集整理的c – 用于不同大小的阵列的UART DMA全部内容,希望文章能够帮你解决c – 用于不同大小的阵列的UART DMA所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1227013.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存