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 바이트) 각 바이트를 통해 루프 크기와 루프에 대한 간단한으로,이 함수에 보내졌다 UART tx 레지스터 U1TXREG를 통해 출력한다.
이제 많은 양의 데이터를 전송할 때 시스템에 대한 압력을 완화하기 위해 DMA를 구현하려고합니다. 내 UART 수신 및 ADC에 DMA를 사용했지만 전송에 문제가 있습니다. 나는 핑퐁 모드를 켜고 끄고, 원샷과 연속 모드를 시도했지만, 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()에서 인터럽트를 비활성화하지 않아도 인터럽트가 처리되는 것을 막을 수 있습니까?"라고 말했어야합니다. " 루틴에서 _cause_ 인터럽트를 실행해도 문제가 없지만 루틴은 원자 적이어야하고 중간에 끼어 들지 않도록 잠겨져 있어야합니다. 'UART_send()'에서 인터럽트 _handling_을 일시 중지하는 것이 좋습니다. – chux