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来减轻传输大量数据时对系统的压力。我已经在UART接收和ADC方面使用了DMA,但在发送方面遇到了问题。我尝试了ping pong模式开启和关闭、单次和连续模式,但无论何时发送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会错过这些数据包,并在其位置发送null / 奇怪的数据包。在构建缓冲区并强制执行第一次传输之前,它似乎正在轮询。也许不需要每次轮询都进行强制操作;我不知道......
任何帮助都将是极好的。
UART_send()
中,您不需要禁用中断以防止其中断触发吗? - chux - Reinstate MonicaUART_send()
期间暂停_处理_中断。 - chux - Reinstate Monica