/** * * @file main.c * @brief this file contains example command sequences and functions to interface with the bq76PL455 from a * microcontroller. The examples provided are described in the bq76PL455 Communications Examples application * note, and the sections that correlate to each example are noted in the comments. * * This code was written for the TMS570LS04x Launchpad Board, modified to remove R8, allowing use of the SCI1 UART. * A bq76PL455EVM single-ended communication interface is connected to the Boosterpack connectors J1 and J2 as * shown below. Connection of these boards must be made by the user. * * J1 pin 1 (+3V3) -> bq76PL455EVM J3 pin 3 (VIO) * J1 pin 3 (SCI1_RX) -> bq76PL455EVM J3 pin 5 (TX) **remove R8 from TMS570LS04x Launchpad * J1 pin 4 (SCI1_TX) -> bq76PL455EVM J3 pin 4 (RX) * J2 pin 1 (GND) -> bq76PL455EVM J3 pin 1 (DGND) * J2 pin 3 (GIOA0) -> bq76PL455EVM J3 pin 6 (nWAKE) * J2 pin 4 (GIOA1) -> bq76PL455EVM J3 pin 2 (nFAULT) * * J2 pin 7 (SPI1SOMI) -> bq34z100EVM J7 pin 3 (SDA) * J2 pin 8 (GIOA6) -> bq34z100EVM J7 pin 2 (SCL) * J3 pin 2 (GND) -> bq34z100EVM J7 pin 1 (GND) * * @author Stephen Holland - Texas Instruments, Inc * @date June 2013 * @version 1.0 Initial version*-++++++++ * @note Built with CCS for Hercules Version: 5.4.0 */ /***************************************************************************** ** ** Copyright (c) 2011-2014 Texas Instruments ** ******************************************************************************/ /* USER CODE BEGIN (0) */ /* USER CODE END */ /* Include Files */ #include "sys_common.h" #include "system.h" /* USER CODE BEGIN (1) */ #include "gio.h" #include "sci.h" #include "rti.h" #include "sys_vim.h" #include "swi_util.h" #include "pinmux.h" #include "pl455.h" #include "emb1428.h" #include"can.h" /* Set define below to the following modes: * BalanceToAverage = balance all cells to average, charging and discharging from/to the external isoalted 12V supply * Charge = charge the 16 cells one at a time, charging the lowest cell from the external isoalted 12V supply * Discharge = discharge the 16 cells one at a time, disharging the highest cell to the external isoalted 12V supply */ #define BalanceToAverage // BalanceToAverage, Charge or Discharge #define SIZE 8 // Cantransmit array size int UART_RX_RDY = 0; int RTI_TIMEOUT = 0; BYTE bFrame[132]; // Krunal made global variable. double Battery_Voltage[16]; int a=0,j=0,c=0,d=0,e=0,b=0; uint8 tx_data1[SIZE],tx_data2[SIZE],tx_data3[SIZE],tx_data4[SIZE],tx_data5[SIZE]; // transmit data array void extractelements(uint8 start,uint8 end); // extract data from bframe by venkantesh ,aswini, krunal /* USER CODE END */ /** @fn void main(void) * @brief Application main function * @note This function is empty by default. * * This function is called after startup. * The user can use this function to implement the application. */ /* USER CODE BEGIN (2) */ /* USER CODE END */ void main(void) { /* USER CODE BEGIN (3) */ systemInit(); gioInit(); sciInit(); sciSetBaudrate(sciREG, 250000); rtiInit(); vimInit(); muxInit(); extractelements(0,64); //canInit(); // can1 -> can2 _enable_IRQ(); // initialize local variables int nSent, nRead, nTopFound = 0, nTopID = 0, tempCount; int nDev_ID = 0, nGrp_ID = 0; // BYTE bFrame[132]; uint32 wTemp = 0; BYTE bTemp; float cellSample; int incCount, decCount; float maxCell = 0, minCell = 5, maxCellDelta, cellAverage; int maxCellNum, minCellNum, cellToBalance, cellBalanceDir,cellToBalance1,cellBalanceDir1; // nSent = WriteReg(0, 12, 0x40, 1, FRMWRT_ALL_NR); // send out broadcast pwrdown command // delayms(5); //~5ms // WakePL455(); // CommClear(); // CommReset(); gioSetBit(gioPORTA, 7, 1); // enable TOP delayms(100); //ResetPL455(); //nSent = WriteReg(0, 12, 0x80, 1, FRMWRT_ALL_NR);//to check reset pl455 // Wake all devices // The wake tone will awaken any device that is already in shutdown and the pwrdown will shutdown any device // that is already awake. The least number of times to sequence wake and pwrdown will be half the number of // boards to cover the worst case combination of boards already awake or shutdown. for(nDev_ID = 0; nDev_ID < TOTALBOARDS; nDev_ID++) { nSent = WriteReg(nDev_ID, 12, 0x40, 1, FRMWRT_ALL_NR); // send out broadcast pwrdown command delayms(5); //~5ms WakePL455(); delayms(5); //~5ms } nRead = ReadReg(0, 96, &bTemp, 1, 0); // Read System Fault register // Mask Customer Checksum Fault bit nSent = WriteReg(0, 107, 0x8000, 2, FRMWRT_ALL_NR); // set mask for customer checksum fault // Clear all faults // nSent = WriteReg(0, 82, 0xFFC0, 2, FRMWRT_ALL_NR); // clear all fault summary flags // nSent = WriteReg(0, 81, 0x38, 1, FRMWRT_ALL_NR); // clear fault flags in the system status register // Auto-address all boards nSent = WriteReg(0, 14, 0x18, 1, FRMWRT_ALL_NR); // set auto-address mode on all boards nSent = WriteReg(0, 12, 0x08, 1, FRMWRT_ALL_NR); // enter auto address mode on all boards, the next write to this ID will be its address for (nDev_ID = 0; nDev_ID < TOTALBOARDS; nDev_ID++) { nSent = WriteReg(nDev_ID, 10, nDev_ID, 1, FRMWRT_ALL_NR); // send address to each board } /* Enable all communication interfaces on all boards in the stack */ nSent = WriteReg(0, 16, 0x10F8, 2, FRMWRT_ALL_NR); // set communications baud rate and enable all interfaces on all boards in stack /* Change to final baud rate used in the application (set by BAUDRATE define in pl455.h). * Up to this point, all communication is at 250Kb, as the COMM_RESET done at the initial * startup resets the bq76PL455 UART to 250Kb. */ switch(BAUDRATE) { case 125000: nSent = WriteReg(0, 16, 0x00F8, 2, FRMWRT_ALL_NR); // set communications baud rate and enable all interfaces delayus(100); sciSetBaudrate(sciREG, BAUDRATE); break; case 250000: delayus(100); break; case 500000: nSent = WriteReg(0, 16, 0x20F8, 2, FRMWRT_ALL_NR); // set communications baud rate and enable all interfaces delayus(100); sciSetBaudrate(sciREG, BAUDRATE); break; case 1000000: nSent = WriteReg(0, 16, 0x30F8, 2, FRMWRT_ALL_NR); // set communications baud rate and enable all interfaces delayus(100); sciSetBaudrate(sciREG, BAUDRATE); break; } /* Set communications interfaces appropriately for their position in the stack, and * for baud rate used in the application (set by BAUDRATE define in pl455.h). */ for (nDev_ID = TOTALBOARDS - 1; nDev_ID >= 0; --nDev_ID) { // read device ID to see if there is a response nRead = ReadReg(nDev_ID, 10, &wTemp, 1, 0); // 0ms timeout if(nRead == 0) // if nothing is read then this board doesn't exist nTopFound = 0; else // a response was received { if(nTopFound == 0) { // if the last board was not present but this one is, this is the top board if(nDev_ID == 0) // this is the only board { switch(BAUDRATE) { case 125000: nSent = WriteReg(nDev_ID, 16, 0x0080, 2, FRMWRT_SGL_NR); // enable only single-end comm port on board break; case 250000: nSent = WriteReg(nDev_ID, 16, 0x1080, 2, FRMWRT_SGL_NR); // enable only single-end comm port on board break; case 500000: nSent = WriteReg(nDev_ID, 16, 0x2080, 2, FRMWRT_SGL_NR); // enable only single-end comm port on board break; case 1000000: nSent = WriteReg(nDev_ID, 16, 0x3080, 2, FRMWRT_SGL_NR); // enable only single-end comm port on board break; } } else // this is the top board of a stack { switch(BAUDRATE) { case 125000: nSent = WriteReg(nDev_ID, 16, 0x0028, 2, FRMWRT_SGL_NR); // enable only comm-low and fault-low for the top board break; case 250000: nSent = WriteReg(nDev_ID, 16, 0x1028, 2, FRMWRT_SGL_NR); // enable only comm-low and fault-low for the top board break; case 500000: nSent = WriteReg(nDev_ID, 16, 0x2028, 2, FRMWRT_SGL_NR); // enable only comm-low and fault-low for the top board break; case 1000000: nSent = WriteReg(nDev_ID, 16, 0x3028, 2, FRMWRT_SGL_NR); // enable only comm-low and fault-low for the top board break; } nTopFound = 1; nTopID = nDev_ID; } } else // this is a middle or bottom board { if(nDev_ID == 0) // this is a bottom board of a stack { switch(BAUDRATE) { case 125000: nSent = WriteReg(nDev_ID, 16, 0x00D0, 2, FRMWRT_SGL_NR); // enable comm-high, fault-high and single-end comm port on bottom board break; case 250000: nSent = WriteReg(nDev_ID, 16, 0x10D0, 2, FRMWRT_SGL_NR); // enable comm-high, fault-high and single-end comm port on bottom board break; case 500000: nSent = WriteReg(nDev_ID, 16, 0x20D0, 2, FRMWRT_SGL_NR); // enable comm-high, fault-high and single-end comm port on bottom board break; case 1000000: nSent = WriteReg(nDev_ID, 16, 0x30D0, 2, FRMWRT_SGL_NR); // enable comm-high, fault-high and single-end comm port on bottom board break; } } else // this is a middle board { switch(BAUDRATE) { case 125000: nSent = WriteReg(nDev_ID, 16, 0x0078, 2, FRMWRT_SGL_NR); // enable comm-high, fault-high, comm-low and fault-low on all middle boards break; case 250000: nSent = WriteReg(nDev_ID, 16, 0x1078, 2, FRMWRT_SGL_NR); // enable comm-high, fault-high, comm-low and fault-low on all middle boards break; case 500000: nSent = WriteReg(nDev_ID, 16, 0x2078, 2, FRMWRT_SGL_NR); // enable comm-high, fault-high, comm-low and fault-low on all middle boards break; case 1000000: nSent = WriteReg(nDev_ID, 16, 0x3078, 2, FRMWRT_SGL_NR); // enable comm-high, fault-high, comm-low and fault-low on all middle boards break; } } } } } delayus(100); nSent = WriteReg(0, 40, 0x00, 1, FRMWRT_ALL_NR); // clear communications timeout register // Clear all faults nSent = WriteReg(0, 82, 0xFFC0, 2, FRMWRT_ALL_NR); // clear all fault summary flags nSent = WriteReg(0, 81, 0x38, 1, FRMWRT_ALL_NR); // clear fault flags in the system status register delayms(5); nRead = ReadReg(0, 82, &bTemp, 2, 0); // Read Fault Summary register nRead = ReadReg(0, 96, &bTemp, 1, 0); // Read System Fault register nRead = ReadReg(0, 97, &bTemp, 2, 0); // Read Chip Fault register /* Configure sample period and oversampling * Best results are: * cells/AUX * - 60us ADC sample period (ADC_PERIOD_VOL = 0xB) * - staying on a channel to oversample (CMD_OVS_CYCLE = 0) * - 12.6us ADC sample period when oversampling (CMD_OVS_HPER/CMD_OVS_GPER = 3) * - 8 oversamples (CMD_OVSMP = 3) * - total sample time for all cell and AUX6 channels to be 16 cell channels only: * 100us + (60us + (12.6us x 7)) x 16 = 2.47ms * Internal temperatures * - 100us initial sample delay (ADC_PERIOD_VOL = 0xC) */ // Configure AFE nSent = WriteReg(0, 61, 0x00, 1, FRMWRT_ALL_NR); // set 0 initial delay // Configure cell voltage and internal temp sample period nSent = WriteReg(0, 62, 0xBC, 1, FRMWRT_ALL_NR); // set 60us cell and 100us temp ADC sample period // Configure AUX voltage sample period AUX0-5 are external thermistor, AUX6 is current sense nSent = WriteReg(0, 63, 0x44444444, 4, FRMWRT_ALL_NR); // set 12.6us AUX sample period // Configure the oversampling rate nSent = WriteReg(0, 7, 0x7B, 1, FRMWRT_ALL_NR); // set 8x oversampling, stay on channel for oversample and 12.6us oversample period for cell and AUX // Set AFE_PCTL nSent = WriteReg(0, 15, 0x80, 1, FRMWRT_ALL_NR); // set AFE_PCTL bit to on (only enable AFE when sampling) // Clear all faults nSent = WriteReg(0, 81, 0x38, 1, FRMWRT_ALL_NR); // clear fault flags in the system status register nSent = WriteReg(0, 82, 0xFFC0, 2, FRMWRT_ALL_NR); // clear all fault summary flags // Select identical number of cells and channels on all modules simultaneously nSent = WriteReg(0, 13, 0x10, 1, FRMWRT_ALL_NR); // set number of cells to 16 nSent = WriteReg(0, 3, 0xFFFF0000, 4, FRMWRT_ALL_NR); // select 16 cell, AUX channel 6 // nSent = WriteReg(0, 3, 0xFFFFFF00, 4, FRMWRT_ALL_NR); // select 16 cell, all AUX // Set cell over-voltage and cell under-voltage thresholds on a single board nSent = WriteReg(0, 144, 0xD1EC, 2, FRMWRT_ALL_NR); // set OV threshold = 4.1000V nSent = WriteReg(0, 142, 0x6148, 2, FRMWRT_ALL_NR); // set UV threshold = 1.9000V // Set cell over-voltage and cell under-voltage thresholds on all boards simultaneously nSent = WriteReg(0, 144, 0xD1EC, 2, FRMWRT_ALL_NR); // set OV threshold = 4.1000V nSent = WriteReg(0, 142, 0x6148, 2, FRMWRT_ALL_NR); // set UV threshold = 1.9000V delayms(1); /* Main loop */ for(nDev_ID = 0; nDev_ID < TOTALBOARDS; nDev_ID++) { nRead = ReadReg(nDev_ID, 0, &bTemp, 2, 0); // Read SREV register nRead = ReadReg(nDev_ID, 40, &bTemp, 1, 0); // Read communication timeout register nRead = ReadReg(nDev_ID, 250, &bTemp, 1, 0); // Read burn count register } delayus(100); // Send broadcast request to board 1 to sample and store results // nSent = WriteReg(0, 2, 0, 1, FRMWRT_ALL_NR); // send sync sample and store command nSent = WriteReg(0, 2, 0, 1, FRMWRT_SGL_NR); // send sync sample and store command delayus(2800); // still need to wait for sampling to complete // Read stored sample data from boards // nSent = WriteReg(0, 2, (0x20 | (nTopID & 0x0F)), 1, FRMWRT_ALL_R); // send read stored values command nSent = WriteReg(0, 2, 0x20, 1, FRMWRT_SGL_R); // send read stored values command // nSent = WaitRespFrame(bFrame, (35 * (nTopID + 1)), 0); // 32 bytes data + packet header + CRC, 0ms timeout nSent = WaitRespFrame(bFrame, 35, 0); // 32 bytes data + packet header + CRC, 0ms timeout delayms(5); extractelements(1,32); // Function call for extract elements // extract transmit data on can1 // canTransmit(canREG1, canMESSAGE_BOX1, tx_data1); // canTransmit(canREG1, canMESSAGE_BOX2, tx_data2); // canTransmit(canREG1, canMESSAGE_BOX3, tx_data3); // canTransmit(canREG1, canMESSAGE_BOX4, tx_data4); // canTransmit(canREG1, canMESSAGE_BOX5, tx_data5); /* * Find the max and min cell channels and their voltages. It's pretty self-explanatory ;-) */ // Initialize variables maxCell = 0; minCell = 5; maxCellNum = 0; minCellNum = 0; maxCellDelta = 0; cellAverage = 0; cellToBalance = 0; cellToBalance1 = 3; cellBalanceDir1 = discharge; initEMB1428Interface(0); EMB_Vset(0, 1); // Set the DAC output do{ for(decCount = 16, incCount = 1; incCount < 17; incCount ++, decCount--) { // Send request to board 1 to sample and store results nSent = WriteReg(1, 2, 0, 1, FRMWRT_SGL_NR); // send sync sample and store command delayus(2800); // still need to wait for sampling to complete // Read stored sample data from boards nSent = WriteReg(1, 2, 0x20, 1, FRMWRT_SGL_R); // send read stored values command nSent = WaitRespFrame(bFrame, 35, 0); // 32 bytes data + packet header + CRC, 0ms timeout cellSample = (bFrame[incCount*2-1]<<8|bFrame[incCount*2]) * 0.000076295; if(incCount == 1) { maxCell = cellSample; minCell = cellSample; maxCellNum = 16; minCellNum = 16; cellAverage = cellSample; } else { cellAverage += cellSample; if(cellSample > maxCell) { maxCell = cellSample; maxCellNum = decCount; } else { if(cellSample < minCell) { minCell = cellSample; minCellNum = decCount; } } } } cellAverage /= 16; maxCellDelta = maxCell - cellAverage; /* * Choose cell to balance */ #ifdef BalanceToAverage // Balance to average if(maxCellDelta > 0.005) { if((cellAverage - minCell) > (maxCell - cellAverage)) { maxCellDelta = cellAverage - minCell; cellToBalance = minCellNum; cellBalanceDir = charge; } else { maxCellDelta = maxCell - cellAverage; cellToBalance = maxCellNum; cellBalanceDir = discharge; } } else cellToBalance = 0; #endif #ifdef Charge // Charge to 4.2V if((cellAverage - minCell) > (maxCell - cellAverage)) maxCellDelta = cellAverage - minCell; else maxCellDelta = maxCell - cellAverage; cellToBalance = minCellNum; cellBalanceDir = charge; #endif #ifdef Discharge // Discharge to 2.5V if((cellAverage - minCell) > (maxCell - cellAverage)) maxCellDelta = cellAverage - minCell; else maxCellDelta = maxCell - cellAverage; cellToBalance = maxCellNum; cellBalanceDir = discharge; #endif //Balance target cell for 1 second, then relax for 3 seconds if(cellToBalance1) // Only balance if celToBalance is not set to 0 { EMB_Start(1, cellToBalance1, cellBalanceDir1); delayms(1000); EMB_Stop(1, cellToBalance1); delayms(3000); } #ifdef Discharge }while(minCell > 2.5); // Min threshold for discharge #else }while(maxCell < 4.2); // Max threshold for charge or balance to average #endif //to reset pl455 //nSent = WriteReg(0, 12, 0x80, 1, FRMWRT_ALL_NR); // Send out broadcast pwrdown command nSent = WriteReg(0, 12, 0x40, 1, FRMWRT_ALL_NR); delayms(2); //systemPowerDown(SYS_DOZE_MODE); while(1); /* USER CODE END */ } /* USER CODE BEGIN (4) */ void extractelements(uint8 start,uint8 end) { int i,j1=0,j2=0,j3=0,j4=0,j5=0,j6=0,j7=0; int a=0,j=0,c=0,d=0,e=0,b=0; for(i=start;i<=end;i++) { if(i<=8) { tx_data1[i-1]=bFrame[i]; } else if(i>8&&i<=16) { tx_data2[j1]=bFrame[i]; j1++; } else if(i>16&&i<=24) { tx_data3[j2]=bFrame[i]; j2++; } else if(i>24&&i<=32) { tx_data4[j3]=bFrame[i]; j3++; } } for(b=0;b<16;b++) { if(b<4) { Battery_Voltage[b]=((2*2.5*(tx_data1[a]<<8 | tx_data1[a+1]))/65535); a+=2; } else if(b>3 && b<8) { Battery_Voltage[b] =((2*2.5*(tx_data2[c]<<8 | tx_data2[c+1]))/65535); c+=2; } else if(b>7&&b<12) { Battery_Voltage[b]=((2*2.5*(tx_data3[d]<<8 | tx_data3[d+1]))/65535); d+=2; } else if(b>11&&b<16) { Battery_Voltage[b]=((2*2.5*(tx_data4[e]<<8 | tx_data4[e+1]))/65535); e+=2; } } } /* USER CODE END */
yes i am using the same EM1402EVM code with SPI commands. I am attaching the same. Please go through it.
Thanks,
Gargi