This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
我已将 BQ UART 设置为使用 DMA 触发器进行接收。
我将 dma_value 设置为 uint16_t、因为测量数据大小是 uint16_t 但是、初始化数据是 uint8_t
BQInitTest 显示了正确的初始化字节序列。
但我在 dma_value 中看到的内容如图片 dmaValue 所示。 我不了解 dmaValue 中的字节顺序。 如逻辑分析仪中所示、BQ 对初始化的响应是正确的。 我已经附加了 DMA 设置和 DMA ISR uartSend 的代码。uartReceive 也已连接、但问题发生在这之前。
extern uint16_t bq79600Addr; extern BYTE autoaddr_response_frame[(1+6)*TOTALBOARDS]; extern uint16_t response_frame[(8)*TOTALBOARDS]; uint8_t uartRxLen; uint16_t dma_value[(8)*TOTALBOARDS] = {0}; uint8_t startMeasure = 0; uint8_t bqAddr = 0; void DMA_Init(){ __data20_write_long((uintptr_t)&BQUART_DMASA, (uintptr_t)&BQUART_RXBUF); __data20_write_long((uintptr_t)&BQUART_DMADA, (uintptr_t) dma_value); BQUART_DMACTL &= ~DMAEN; DMACTL0 |= BQUART_DMA_RX_TRIGGER; DMACTL4 |= DMARMWDIS; //Repeated single transfer; increment destination address; source address unchanged; //byte to byte transfer source to DMA; byte to byte transfer destination to DMA; //rising edge DMA trigger; DMA enable BQUART_DMACTL |= DMADT_4|DMADSTINCR_3|DMASRCINCR_0|DMASRCBYTE__BYTE|DMADSTBYTE__BYTE|DMA_TRIGGER_RISINGEDGE|DMAEN; } int ReadFrameReq(BYTE bID, uint16_t wAddr, BYTE bByteToReturn, BYTE bWriteType, BYTE rxLen) { bReturn = bByteToReturn - 1; uartRxLen = rxLen; //PN setting a flag to identify when BQ79600 address is being read if (wAddr == 0x2001) bqAddr = 1; if (wAddr != 0x2001) bqAddr = 0; if (bReturn > 127) return 0; return WriteFrame(bID, wAddr, &bReturn, 1, bWriteType); } void uartSend(int length, uint8_t * data){ uint8_t i; BQUART_DMASZ = uartRxLen; BQUART_DMACTL |= DMAEN; BQUART_DMACTL |= DMAIE; for (i = 0; i < length; i++){ while (!(BQUART_IFG & UCTXIFG)); BQUART_TXBUF = data[i]; } } void uartReceive(void){ uint8_t i; uint8_t aaResp[7*TOTALBOARDS]; if (startMeasure == 1){ memcpy(response_frame, dma_value, uartRxLen); } if (bqAddr == 1){ for (i = 0; i < 4; i++){ aaResp[2*i] = (uint8_t) dma_value[i] & 0x00ff; aaResp[2*i+1] = (uint8_t) ((dma_value[i] & 0xff00) >> 8); } memcpy(autoaddr_response_frame, aaResp, uartRxLen+1); bq79600Addr = autoaddr_response_frame[4]; startMeasure = 1; } } #pragma vector=DMA_VECTOR __interrupt void dmaIsrHandler(void) { switch(__even_in_range(DMAIV, BQUART_DMAIV_IFG)) { case BQUART_DMAIV_IFG: BQUART_DMACTL &= ~DMAIE; uartReceive(); // Exit low power mode on wake-up __bic_SR_register_on_exit(LPM4_bits); break; case DMAIV_DMA0IFG: break; case DMAIV_DMA2IFG: break; case DMAIV_DMA3IFG: break; case DMAIV_DMA4IFG: break; case DMAIV_DMA5IFG: break; default: break; } }
从讨论中不清楚您的投诉是什么。 但我看到您告诉 DMA 控制器从源读取一个字节并将一个字节写入目标。 目的恰好是一个 INT 数组。 如果您希望 DMA 控制器知道它是一个整数组并相应地增加其地址、则您将被错误地误认为是正确的。
DMA 控制器可以读取一个字节并写入一个字、如果需要、将字的上半部分清零。 也许这正是您所期望的。 如果是、则需要告知 DMA 控制器。
extern uint16_t bq79600Addr; extern BYTE autoaddr_response_frame[(1+6)*TOTALBOARDS]; extern uint16_t response_frame[(8)*TOTALBOARDS]; uint8_t uartRxLen; uint16_t dma_value[(8)*TOTALBOARDS] = {0}; uint8_t startMeasure = 0; uint8_t bqAddr = 0; void DMA_Init(){ __data20_write_long((uintptr_t)&BQUART_DMASA, (uintptr_t)&BQUART_RXBUF); __data20_write_long((uintptr_t)&BQUART_DMADA, (uintptr_t) dma_value); BQUART_DMACTL &= ~DMAEN; DMACTL0 |= BQUART_DMA_RX_TRIGGER; DMACTL4 |= DMARMWDIS; //Repeated single transfer; increment destination address; source address unchanged; //byte to byte transfer source to DMA; byte to byte transfer destination to DMA; //rising edge DMA trigger; DMA enable BQUART_DMACTL |= DMADT_4|DMADSTINCR_3|DMASRCINCR_0|DMASRCBYTE__WORD|DMADSTBYTE__WORD|DMA_TRIGGER_RISINGEDGE|DMAEN; } void uartSend(int length, uint8_t * data){ uint8_t i; BQUART_DMASZ = uartRxLen; BQUART_DMACTL |= DMAEN; BQUART_DMACTL |= DMAIE; for (i = 0; i < length; i++){ while (!(BQUART_IFG & UCTXIFG)); BQUART_TXBUF = data[i]; } } void uartReceive(void){ uint8_t i; if (startMeasure == 1){ memcpy(response_frame, dma_value, uartRxLen); } if (bqAddr == 1){ for (i = 0; i < uartRxLen; i++){ autoaddr_response_frame[i] = (uint8_t) dma_value[i]; } bq79600Addr = autoaddr_response_frame[4]; startMeasure = 1; } } #pragma vector=DMA_VECTOR __interrupt void dmaIsrHandler(void) { switch(__even_in_range(DMAIV, BQUART_DMAIV_IFG)) { case BQUART_DMAIV_IFG: BQUART_DMACTL &= ~DMAIE; uartReceive(); // Exit low power mode on wake-up __bic_SR_register_on_exit(LPM4_bits); break; case DMAIV_DMA0IFG: break; case DMAIV_DMA2IFG: break; case DMAIV_DMA3IFG: break; case DMAIV_DMA4IFG: break; case DMAIV_DMA5IFG: break; default: break; } }
将字传输到字节会有所帮助。 但是、我不理解 DMA_VALUE 中的字节顺序。
在 dma_value 中、我希望在索引0-5中看到索引1-6中的字节。 索引0中的字节应该位于索引6中、因为它是 CRC 的一部分。
当 dma_value 复制到 autodr_Response_FRAME 时、字节0不会被复制 corretty。 出于某种原因、0x55变为0x9C。 其余副本正常。
由于 您在启用 DMA 之前没有清除 RXIFG、因此在 RXBUF 中悬挂一个字节非常容易。 因此、当您启用 DMA 时、您会立即触发。 这会将前一帧的最后一个字节放入当前帧的第一个字节中。