我让 MSP-EXP430FR5994通过 UART 与 BQ79600 EVM 通信;DMA 用于 UART 接收。 BQ79600 EVM 连接到定制的 BQ79616 PCB。 通信成功大部分时间、BQ 芯片能够测量电池电压和温度。 我已经通过在 CCS 中启动调试会话来确认这一点、并使用逻辑分析仪捕获5秒的触发。 之后、我停止 CCS 并查看表达式。 附件是成功的 IDE 表达式(BQUartDMASuccesss.PNG)的屏幕截图。
在大约7个这样的 IDE 运行之后、BQ 自动寻址序列在第一个 DLL 丢弃后停止读取。 BQ 芯片正在响应此第一步、如所附的逻辑分析仪屏幕截图(AABREAA.PNG)中所示。 DMA ISR 不会触发。 从随附的 IDE 屏幕截图(dmaRxAA.PNG)中、dma_value 缓冲区正在接收全部7个预期字节。 我想了解 DMA ISR 为什么与触发有关是偶发的。
#define BQUART_enableInterrupt EUSCI_A_UART_enableInterrupt #define BQUART_RX_INT EUSCI_A_UART_RECEIVE_INTERRUPT #define BQUART_clearInterrupt EUSCI_A_UART_clearInterrupt #define BQUART_TXBUF UCA1TXBUF #define BQUART_RXBUF UCA1RXBUF #define BQUART_IFG UCA1IFG #define BQUART_ISR USCI_A1_ISR #define BQUART_VECTOR USCI_A1_VECTOR #define BQUART_IFG UCA1IFG #define BQUART_IV UCA1IV #define BQUART_DMA_RX_TRIGGER DMA1TSEL__UCA1RXIFG #define BQUART_DMASA DMA1SA #define BQUART_DMADA DMA1DA #define BQUART_DMAxCTL DMA1CTL //DMA Channel 1 #define BQUART_DMACTLx DMACTL0 //holds the DMA trigger #define BQUART_DMAIV_IFG DMAIV_DMA1IFG #define BQUART_DMASZ DMA1SZ /* * uartCommands.c * * Created on: Apr 21, 2022 * Author: Priya.Nadathur */ #include <driverlib.h> #include <string.h> #include "bspFuncs.h" #include "mbbConfig.h" #include "timer.h" #include "B0_reg.h" #ifdef BQ_UART #include "uartCommands.h" extern uint16_t bq79600Addr; extern BYTE autoaddr_response_frame[(1+6)*TOTALBOARDS]; extern uint8_t response_frame[(8)*TOTALBOARDS]; uint8_t uartRxLen; uint8_t dmaDataReady = 0; uint16_t dma_value[(8)*TOTALBOARDS] = {0}; uint8_t startMeasure = 0; uint8_t bqAddr = 0; // CRC16 TABLE // ITU_T polynomial: x^16 + x^15 + x^2 + 1 const uint16_t crc16_table[256] = { 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 }; BYTE bBuf[8]; uint8_t pFrame[64]; int bRes = 0; BYTE bReturn = 0; BYTE* currCRC; int crc_i = 0; uint16_t wCRC2 = 0xFFFF; int crc16_i = 0; /** * @brief Setup DMA for BQ UART receive * * Single transfer; increment destination address; source address unchanged; * byte to word transfer source to DMA; word to byte transfer destination to DMA; * rising edge DMA trigger; DMA enable * */ 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_DMAxCTL &= ~DMAEN; BQUART_DMACTLx |= BQUART_DMA_RX_TRIGGER; DMACTL4 |= DMARMWDIS; BQUART_DMAxCTL |= DMADT_0|DMADSTINCR_3|DMASRCINCR_0|DMASRCBYTE__WORD|DMADSTBYTE__WORD|DMA_TRIGGER_RISINGEDGE|DMAEN; } /** * @brief Configure BQ UART @1000000 baud * * software-dl.ti.com/.../index.html */ void UART_Init(void){ BQUART_initParam param = {0}; param.clockPrescalar = 4, param.firstModReg = 0, param.secondModReg = 0, param.selectClockSource = BQUART_CLOCKSOURCE; param.parity = BQUART_PARITY; param.msborLsbFirst = BQUART_BITORDER; param.numberofStopBits = BQUART_STOPBIT; param.uartMode = BQUART_MODE; param.overSampling = BQUART_OVERSAMPLING; if(STATUS_FAIL == BQUART_INIT(BQUART, ¶m)) { return; } BQUART_enable(BQUART); } //FORMAT WRITE DATA, SEND TO //BE COMBINED WITH REST OF FRAME int WriteReg(BYTE bID, uint16_t wAddr, uint64_t dwData, BYTE bLen, BYTE bWriteType){ // device address, register start address, data bytes, data length, write type (single, broadcast, stack) bRes = 0; memset(bBuf,0,sizeof(bBuf)); switch (bLen) { case 1: bBuf[0] = dwData & 0x00000000000000FF; bRes = WriteFrame(bID, wAddr, bBuf, 1, bWriteType); break; case 2: bBuf[0] = (dwData & 0x000000000000FF00) >> 8; bBuf[1] = dwData & 0x00000000000000FF; bRes = WriteFrame(bID, wAddr, bBuf, 2, bWriteType); break; case 3: bBuf[0] = (dwData & 0x0000000000FF0000) >> 16; bBuf[1] = (dwData & 0x000000000000FF00) >> 8; bBuf[2] = dwData & 0x00000000000000FF; bRes = WriteFrame(bID, wAddr, bBuf, 3, bWriteType); break; case 4: bBuf[0] = (dwData & 0x00000000FF000000) >> 24; bBuf[1] = (dwData & 0x0000000000FF0000) >> 16; bBuf[2] = (dwData & 0x000000000000FF00) >> 8; bBuf[3] = dwData & 0x00000000000000FF; bRes = WriteFrame(bID, wAddr, bBuf, 4, bWriteType); break; case 5: bBuf[0] = (dwData & 0x000000FF00000000) >> 32; bBuf[1] = (dwData & 0x00000000FF000000) >> 24; bBuf[2] = (dwData & 0x0000000000FF0000) >> 16; bBuf[3] = (dwData & 0x000000000000FF00) >> 8; bBuf[4] = dwData & 0x00000000000000FF; bRes = WriteFrame(bID, wAddr, bBuf, 5, bWriteType); break; case 6: bBuf[0] = (dwData & 0x0000FF0000000000) >> 40; bBuf[1] = (dwData & 0x000000FF00000000) >> 32; bBuf[2] = (dwData & 0x00000000FF000000) >> 24; bBuf[3] = (dwData & 0x0000000000FF0000) >> 16; bBuf[4] = (dwData & 0x000000000000FF00) >> 8; bBuf[5] = dwData & 0x00000000000000FF; bRes = WriteFrame(bID, wAddr, bBuf, 6, bWriteType); break; case 7: bBuf[0] = (dwData & 0x00FF000000000000) >> 48; bBuf[1] = (dwData & 0x0000FF0000000000) >> 40; bBuf[2] = (dwData & 0x000000FF00000000) >> 32; bBuf[3] = (dwData & 0x00000000FF000000) >> 24; bBuf[4] = (dwData & 0x0000000000FF0000) >> 16; bBuf[5] = (dwData & 0x000000000000FF00) >> 8; bBuf[6] = dwData & 0x00000000000000FF; bRes = WriteFrame(bID, wAddr, bBuf, 7, bWriteType); break; case 8: bBuf[0] = (dwData & 0xFF00000000000000) >> 56; bBuf[1] = (dwData & 0x00FF000000000000) >> 48; bBuf[2] = (dwData & 0x0000FF0000000000) >> 40; bBuf[3] = (dwData & 0x000000FF00000000) >> 32; bBuf[4] = (dwData & 0x00000000FF000000) >> 24; bBuf[5] = (dwData & 0x0000000000FF0000) >> 16; bBuf[6] = (dwData & 0x000000000000FF00) >> 8; bBuf[7] = dwData & 0x00000000000000FF; bRes = WriteFrame(bID, wAddr, bBuf, 8, bWriteType); break; default: break; } return bRes; } //GENERATE COMMAND FRAME int WriteFrame(BYTE bID, uint16_t wAddr, BYTE * pData, BYTE bLen, BYTE bWriteType) { int bPktLen = 0; uint8_t * pBuf = pFrame; uint16_t wCRC; memset(pFrame, 0x7F, sizeof(pFrame)); *pBuf++ = 0x80 | (bWriteType) | ((bWriteType & 0x10) ? bLen - 0x01 : 0x00); //Only include blen if it is a write; Writes are 0x90, 0xB0, 0xD0 if (bWriteType == FRMWRT_SGL_R || bWriteType == FRMWRT_SGL_W) { *pBuf++ = (bID & 0x00FF); } *pBuf++ = (wAddr & 0xFF00) >> 8; *pBuf++ = wAddr & 0x00FF; while (bLen--) *pBuf++ = *pData++; bPktLen = pBuf - pFrame; wCRC = CRC16(pFrame, bPktLen); *pBuf++ = wCRC & 0x00FF; *pBuf++ = (wCRC & 0xFF00) >> 8; bPktLen += 2; //THIS SEEMS to occasionally drop bytes from the frame. Sometimes is not sending the last frame of the CRC. //(Seems to be caused by stack overflow, so take precautions to reduce stack usage in function calls) uartSend(bPktLen, pFrame); return bPktLen; } //GENERATE READ COMMAND FRAME AND THEN WAIT FOR RESPONSE DATA (INTERRUPT MODE FOR SCIRX) int ReadReg(BYTE bID, uint16_t wAddr, BYTE * pData, BYTE bLen, uint32_t dwTimeOut, BYTE bWriteType) { // device address, register start address, byte frame pointer to store data, data length, read type (single, broadcast, stack) int crcChk; bRes = 0; if (bWriteType == FRMWRT_SGL_R) { ReadFrameReq(bID, wAddr, bLen, bWriteType, bLen+6); memset(pData, 0, sizeof(pData)); } else if (bWriteType == FRMWRT_STK_R) { bRes = ReadFrameReq(bID, wAddr, bLen, bWriteType, (bLen + 6) * (TOTALBOARDS - 1)); memset(pData, 0, sizeof(pData)); } else if (bWriteType == FRMWRT_ALL_R) { bRes = ReadFrameReq(bID, wAddr, bLen, bWriteType, (bLen + 6) * TOTALBOARDS); memset(pData, 0, sizeof(pData)); } else { bRes = 0; } // //CHECK IF CRC IS CORRECT for(crc_i=0; crc_i<bRes; crc_i+=(bLen+6)) { if(CRC16(&pData[crc_i], bLen+6)!=0) { // printConsole("\n\rBAD CRC=%04X,i=%d,bLen=%d\n\r",(pData[crc_i+bLen+4]<<8|pData[crc_i+bLen+5]),crc_i,bLen); // PrintFrame(pData, bLen); crcChk = 1; } else crcChk = 0; } /* crc_i = 0; currCRC = pData; for(crc_i=0; crc_i<bRes; crc_i+=(bLen+6)) { printConsole("%x",&currCRC); if(CRC16(currCRC, bLen+6)!=0) { printConsole("BAD CRC=%04X,byte=%d\n\r",(currCRC[bLen+4]<<8|currCRC[bLen+5]),crc_i); PrintFrame(pData, bLen); } *currCRC+=(bLen+6); } */ return crcChk; } 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 (bReturn > 127) return 0; return WriteFrame(bID, wAddr, &bReturn, 1, bWriteType); } uint16_t CRC16(BYTE *pBuf, int nLen) { wCRC2 = 0xFFFF; //printConsole("CRCOUT = \t"); for (crc16_i = 0; crc16_i < nLen; crc16_i++) { //printConsole("%02x ",*pBuf); wCRC2 ^= (*pBuf++) & 0x00FF; wCRC2 = crc16_table[wCRC2 & 0x00FF] ^ (wCRC2 >> 8); } //printConsole("\n\r"); return wCRC2; } /** * @brief MSP430 UART transmit data * * Enable DMA transfer for UART receive and transmit UART data * * @param[in] transmit packet length * data to transmit */ void uartSend(int length, uint8_t * data){ uint8_t i; BQUART_DMASZ = uartRxLen; dmaDataReady = 0; BQUART_IFG &= ~UCRXIFG; //clear UART receive buffer BQUART_DMAxCTL |= DMAEN; BQUART_DMAxCTL |= DMAIE; for (i = 0; i < length; i++){ while (!(BQUART_IFG & UCTXIFG)); BQUART_TXBUF = data[i]; } } /** * @brief Receive MSP430 UART * * After DMA receive transfer is complete, copy the data over to BQ data processing arrays */ void uartReceive(void){ uint8_t i; if (startMeasure == 1){ for (i = 0; i < uartRxLen; i++){ response_frame[i] = dma_value[i]; } dmaDataReady = 1; } if (bq79600Addr != Bridge_DEV_CONF1_Response){ for (i = 0; i < uartRxLen; i++){ autoaddr_response_frame[i] = dma_value[i]; } dmaDataReady = 1; bq79600Addr = autoaddr_response_frame[4]; } } /** * @brief DMA ISR: BQUART_DMA_RX_TRIGGER */ #pragma vector=DMA_VECTOR __interrupt void dmaIsrHandler(void) { switch(__even_in_range(DMAIV, BQUART_DMAIV_IFG)) { case BQUART_DMAIV_IFG: BQUART_DMAxCTL &= ~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; } } #endif