Initial rough start to the BQ76PL536A (or BQ76PL536A-Q1) code. Free to use as long as you make any changes/improvements publicly available. Please notify me of any improvements.
bq76pl536a.cpp@1:4ae1a58697d7, 2020-07-29 (annotated)
- Committer:
- dmwahl
- Date:
- Wed Jul 29 03:11:51 2020 +0000
- Revision:
- 1:4ae1a58697d7
- Parent:
- 0:47a258755906
- Child:
- 2:7083c7257556
write and pec functions working
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dmwahl | 0:47a258755906 | 1 | #include "bq76pl536a.h" |
dmwahl | 0:47a258755906 | 2 | //=========================================================================== |
dmwahl | 0:47a258755906 | 3 | // Default constructor. Setup spi interface and run init functions |
dmwahl | 0:47a258755906 | 4 | BQ76PL536A::BQ76PL536A(SPI _spi, PinName _cs, u8t _numDev, u16t _cov, u16t _cuv, u8t _balanceTimeout, bool _balanceEnabled) |
dmwahl | 0:47a258755906 | 5 | //=========================================================================== |
dmwahl | 1:4ae1a58697d7 | 6 | : spi(_spi), |
dmwahl | 1:4ae1a58697d7 | 7 | cs(_cs), |
dmwahl | 1:4ae1a58697d7 | 8 | numDev(_numDev), |
dmwahl | 1:4ae1a58697d7 | 9 | cov(_cov), |
dmwahl | 1:4ae1a58697d7 | 10 | cuv(_cuv), |
dmwahl | 1:4ae1a58697d7 | 11 | balanceTimeout(_balanceTimeout), |
dmwahl | 1:4ae1a58697d7 | 12 | balanceEnabled(_balanceEnabled) |
dmwahl | 0:47a258755906 | 13 | { |
dmwahl | 1:4ae1a58697d7 | 14 | DigitalOut cs(_cs); |
dmwahl | 0:47a258755906 | 15 | cs = 1; |
dmwahl | 1:4ae1a58697d7 | 16 | spi.format(8,1); |
dmwahl | 1:4ae1a58697d7 | 17 | spi.frequency(500000); |
dmwahl | 1:4ae1a58697d7 | 18 | |
dmwahl | 1:4ae1a58697d7 | 19 | cs=0; |
dmwahl | 1:4ae1a58697d7 | 20 | wait_ms(1); |
dmwahl | 1:4ae1a58697d7 | 21 | cs=1; |
dmwahl | 1:4ae1a58697d7 | 22 | wait_ms(1); |
dmwahl | 1:4ae1a58697d7 | 23 | |
dmwahl | 1:4ae1a58697d7 | 24 | //softReset(); |
dmwahl | 0:47a258755906 | 25 | setAddresses(); |
dmwahl | 0:47a258755906 | 26 | }; |
dmwahl | 0:47a258755906 | 27 | |
dmwahl | 0:47a258755906 | 28 | |
dmwahl | 0:47a258755906 | 29 | |
dmwahl | 0:47a258755906 | 30 | |
dmwahl | 0:47a258755906 | 31 | //=========================================================================== |
dmwahl | 0:47a258755906 | 32 | // Start conversion on all devices |
dmwahl | 0:47a258755906 | 33 | void BQ76PL536A::adcConvert() |
dmwahl | 0:47a258755906 | 34 | //=========================================================================== |
dmwahl | 0:47a258755906 | 35 | { |
dmwahl | 0:47a258755906 | 36 | write(BROADCAST_ADDR, ADC_CONVERT_REG, 1); |
dmwahl | 0:47a258755906 | 37 | } |
dmwahl | 0:47a258755906 | 38 | |
dmwahl | 0:47a258755906 | 39 | //=========================================================================== |
dmwahl | 1:4ae1a58697d7 | 40 | // Reset all devices in stack |
dmwahl | 1:4ae1a58697d7 | 41 | void BQ76PL536A::softReset() |
dmwahl | 1:4ae1a58697d7 | 42 | //=========================================================================== |
dmwahl | 1:4ae1a58697d7 | 43 | { |
dmwahl | 1:4ae1a58697d7 | 44 | write(BROADCAST_ADDR, RESET_REG, BQ76PL536A_RESET); |
dmwahl | 1:4ae1a58697d7 | 45 | } |
dmwahl | 1:4ae1a58697d7 | 46 | |
dmwahl | 1:4ae1a58697d7 | 47 | //=========================================================================== |
dmwahl | 0:47a258755906 | 48 | // Address devices |
dmwahl | 0:47a258755906 | 49 | void BQ76PL536A::setAddresses() |
dmwahl | 0:47a258755906 | 50 | //=========================================================================== |
dmwahl | 0:47a258755906 | 51 | { |
dmwahl | 0:47a258755906 | 52 | // Address devices |
dmwahl | 1:4ae1a58697d7 | 53 | for(u8t i=0; i<numDev; i++) { |
dmwahl | 1:4ae1a58697d7 | 54 | write(i, ADDRESS_CONTROL_REG, i+1); //Write address to device 1 (for testing only) |
dmwahl | 1:4ae1a58697d7 | 55 | |
dmwahl | 1:4ae1a58697d7 | 56 | //write(DISCOVERY_ADDR, ADDRESS_CONTROL_REG, i); //Write address to first discovered address |
dmwahl | 0:47a258755906 | 57 | // write 1 then 0 to Alert Status Reg to remove alert |
dmwahl | 0:47a258755906 | 58 | //write(i, ALERT_STATUS_REG, 0b10000000); //Write 1 to address bit of alert register |
dmwahl | 0:47a258755906 | 59 | //write(i, ALERT_STATUS_REG, 0b00000000); //Write 0 to address bit of alert register to clear alert |
dmwahl | 0:47a258755906 | 60 | } |
dmwahl | 0:47a258755906 | 61 | } |
dmwahl | 0:47a258755906 | 62 | |
dmwahl | 0:47a258755906 | 63 | //=========================================================================== |
dmwahl | 1:4ae1a58697d7 | 64 | // Device status |
dmwahl | 1:4ae1a58697d7 | 65 | u8t BQ76PL536A::devStatus() |
dmwahl | 0:47a258755906 | 66 | //=========================================================================== |
dmwahl | 0:47a258755906 | 67 | { |
dmwahl | 1:4ae1a58697d7 | 68 | //update to use numDev |
dmwahl | 1:4ae1a58697d7 | 69 | u8t currentStatus[1]; |
dmwahl | 1:4ae1a58697d7 | 70 | read(1,DEVICE_STATUS_REG,1,currentStatus); |
dmwahl | 1:4ae1a58697d7 | 71 | return currentStatus[0]; |
dmwahl | 0:47a258755906 | 72 | } |
dmwahl | 1:4ae1a58697d7 | 73 | //=========================================================================== |
dmwahl | 1:4ae1a58697d7 | 74 | |
dmwahl | 0:47a258755906 | 75 | |
dmwahl | 0:47a258755906 | 76 | //=========================================================================== |
dmwahl | 0:47a258755906 | 77 | // Read one or more bytes from the BQ76 device stack. Count does not include CRC byte. |
dmwahl | 0:47a258755906 | 78 | bool *BQ76PL536A::read(u8t deviceAddress, u8t regAddress, u8t count, u8t *pRegisterValue) |
dmwahl | 0:47a258755906 | 79 | //=========================================================================== |
dmwahl | 0:47a258755906 | 80 | { |
dmwahl | 0:47a258755906 | 81 | error = 0; |
dmwahl | 0:47a258755906 | 82 | u8t logicalAddress = (deviceAddress << 1 | 0); // Shift address left 1 bit |
dmwahl | 0:47a258755906 | 83 | //static u8t receivedData[length]; |
dmwahl | 0:47a258755906 | 84 | //memset(receivedData, 0, length); |
dmwahl | 1:4ae1a58697d7 | 85 | u8t crcInput[3+count]; |
dmwahl | 1:4ae1a58697d7 | 86 | crcInput[0] = logicalAddress; |
dmwahl | 1:4ae1a58697d7 | 87 | crcInput[1] = regAddress; |
dmwahl | 1:4ae1a58697d7 | 88 | crcInput[2] = count; |
dmwahl | 0:47a258755906 | 89 | |
dmwahl | 0:47a258755906 | 90 | cs = 0; |
dmwahl | 1:4ae1a58697d7 | 91 | spi.write(deviceAddress); |
dmwahl | 0:47a258755906 | 92 | spi.write(regAddress); |
dmwahl | 0:47a258755906 | 93 | spi.write(count); |
dmwahl | 0:47a258755906 | 94 | |
dmwahl | 0:47a258755906 | 95 | //Read data. Last byte is CRC data. |
dmwahl | 0:47a258755906 | 96 | for (int i = 0; i <= count; i++) { |
dmwahl | 0:47a258755906 | 97 | pRegisterValue[i] = spi.write(0x00); |
dmwahl | 1:4ae1a58697d7 | 98 | if (i != count) { |
dmwahl | 1:4ae1a58697d7 | 99 | crcInput[3+i] = pRegisterValue[i]; |
dmwahl | 1:4ae1a58697d7 | 100 | } |
dmwahl | 0:47a258755906 | 101 | if (i == count) { |
dmwahl | 1:4ae1a58697d7 | 102 | if (pec(crcInput,3+count) != pRegisterValue[i]) |
dmwahl | 0:47a258755906 | 103 | error = 1; |
dmwahl | 0:47a258755906 | 104 | } |
dmwahl | 0:47a258755906 | 105 | } |
dmwahl | 0:47a258755906 | 106 | cs = 1; //End of transmission, slave select high |
dmwahl | 0:47a258755906 | 107 | return false; |
dmwahl | 0:47a258755906 | 108 | } |
dmwahl | 0:47a258755906 | 109 | |
dmwahl | 0:47a258755906 | 110 | //=========================================================================== |
dmwahl | 1:4ae1a58697d7 | 111 | // Write one byte to the BQ76 device stack. Should add code to read back written register and compare... |
dmwahl | 0:47a258755906 | 112 | void BQ76PL536A::write(u8t deviceAddress, u8t regAddress, u8t regData) |
dmwahl | 0:47a258755906 | 113 | //=========================================================================== |
dmwahl | 0:47a258755906 | 114 | { |
dmwahl | 1:4ae1a58697d7 | 115 | u8t logicalAddress = (deviceAddress << 1 | 1); // Shift address left one bit and set LSB |
dmwahl | 0:47a258755906 | 116 | u8t crcInput[3] = {logicalAddress, regAddress, regData}; |
dmwahl | 0:47a258755906 | 117 | |
dmwahl | 1:4ae1a58697d7 | 118 | cs = 0; |
dmwahl | 0:47a258755906 | 119 | spi.write(logicalAddress); |
dmwahl | 0:47a258755906 | 120 | spi.write(regAddress); |
dmwahl | 0:47a258755906 | 121 | spi.write(regData); |
dmwahl | 1:4ae1a58697d7 | 122 | spi.write(pec(crcInput, sizeof(crcInput)/sizeof(crcInput[0]))); |
dmwahl | 0:47a258755906 | 123 | cs = 1; |
dmwahl | 0:47a258755906 | 124 | } |
dmwahl | 0:47a258755906 | 125 | |
dmwahl | 0:47a258755906 | 126 | //=========================================================================== |
dmwahl | 0:47a258755906 | 127 | // Calculate CRC byte to verify data integrity |
dmwahl | 1:4ae1a58697d7 | 128 | u8t BQ76PL536A::pec(u8t crcBuffer[], u8t crcLength) |
dmwahl | 0:47a258755906 | 129 | //=========================================================================== |
dmwahl | 0:47a258755906 | 130 | { |
dmwahl | 1:4ae1a58697d7 | 131 | //u8t crcTestInput[3] = {0x01,0x3b,0x01}; // should return 0x02 |
dmwahl | 0:47a258755906 | 132 | u8t crc = 0; |
dmwahl | 1:4ae1a58697d7 | 133 | u8t temp = 0; |
dmwahl | 1:4ae1a58697d7 | 134 | for (u8t i = 0; i < crcLength; i++) { |
dmwahl | 0:47a258755906 | 135 | temp = crc ^ crcBuffer[i]; |
dmwahl | 0:47a258755906 | 136 | crc = crcTable[temp]; |
dmwahl | 0:47a258755906 | 137 | } |
dmwahl | 0:47a258755906 | 138 | return crc; |
dmwahl | 0:47a258755906 | 139 | } |