使用帶有dsPIC33FJ128GP802微控制器的MPLAB X 1.70。適用於不同大小陣列的UART DMA
我有一個應用程序從兩個傳感器以不同的採樣率(一個在50Hz,另一個在1000Hz)採集數據,兩個傳感器數據包的大小也不同(一個是5個字節,另一個是21個字節)。到目前爲止我用手動UART transmision所見如下:
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丟失了這些數據包,並在它的位置發送空/奇怪數據包。在構建緩衝區並強制第一次傳輸之前,似乎是輪詢。也許這個力量對於每一次民意測驗都是不必要的我不知道...
任何幫助將是偉大的。
您是否需要在'UART_send()'中禁用中斷以防止在那裏發生中斷? – chux
好建議,明天再試,謝謝。那不會否定DMA的觀點嗎?如果我故意暫停DMA中斷,那麼它不會像手動UART方法一樣快? – ritchie888
也許我應該說「在UART_send()中,您是否需要禁用中斷以防止在那裏處理中斷?」。它可以在例程中產生中斷,但可能需要將例程設爲原子級,並在中間被阻止中斷。我只是建議在'UART_send()'中暫停中斷的處理。 – chux