Hallo,
ich versuche einen Treiber für einen BQ40Z50 Akku zu implementieren der
über SMBUS auf einem STM32H7xx kommuniziert.
Ich benutze hierfür das STM32 SMBus/PMBusTM Expansion Package (AN4502)
Die Initialisierung des SmbusStacks funktioniert soweit. Es hapert
allerdings
meiner READ bzw WRITE Methode.
HEADER FILE:
...
1 | SMBUS_StackHandleTypeDef smbusStackHandle;
|
...
INIT Methode: (CHIP_DATA[] ist die Commandtable)
1 | uint32_t BQ40Z50::init() {
|
2 | smbusStackHandle.CMD_table = (st_command_t *) &CHIP_DATA[0];
|
3 | smbusStackHandle.CMD_tableSize = sizeof(CHIP_DATA)/sizeof(CHIP_DATA[0]);
|
4 | smbusStackHandle.StateMachine = SMBUS_SMS_NONE;
|
5 | smbusStackHandle.Device = &BSP_BATTERY_I2C;
|
6 | smbusStackHandle.SRByte = 0x55U;
|
7 | smbusStackHandle.CurrentCommand = NULL;
|
8 | if(initSmbus() == HAL_OK){
|
9 | return 0;
|
10 | }
|
11 | else return 1;
|
12 | }
|
INITSMBUS Methode:
1 | HAL_StatusTypeDef BQ40Z50::initSmbus() {
|
2 | HAL_StatusTypeDef r = STACK_SMBUS_Init(&smbusStackHandle);
|
3 | if(r == HAL_OK){
|
4 | uint32_t t = HAL_GetTick();
|
5 | while(!STACK_SMBUS_IsReady(&smbusStackHandle)){
|
6 | if((HAL_GetTick() - t) > 100){
|
7 | return HAL_ERROR;
|
8 | }
|
9 | }
|
10 | smbusInitialized = true;
|
11 | return r;
|
12 | }
|
13 | }
|
WRITE Methode:
1 | template <typename DATATYPE>
|
2 | uint16_t writeRegister(st_command_t *cmd, int16_t data) {
|
3 | uint8_t* ioBuffer = STACK_SMBUS_GetBuffer(&smbusStackHandle);
|
4 | (*((DATATYPE*)ioBuffer)) = data;
|
5 | HAL_StatusTypeDef r = STACK_SMBUS_HostCommand(&smbusStackHandle,
|
6 | const_cast<st_command_t*>(cmd), 0x16, WRITE);
|
7 | if(r != HAL_OK){
|
8 | return 0;
|
9 | } else {
|
10 | uint8_t t = HAL_GetTick();
|
11 | while ( ! STACK_SMBUS_IsReady(&smbusStackHandle)) {
|
12 | if(HAL_GetTick() - t > 100){
|
13 | printf("TIMEOUT\n");
|
14 | return 0;
|
15 | }else break;
|
16 | }
|
17 | return 2;
|
18 | }
|
19 | }
|
READ Methode:
1 | template <typename DATATYPE>
|
2 | DATATYPE readRegister(st_command_t* cmd) {
|
3 | HAL_StatusTypeDef r = STACK_SMBUS_HostCommand(&smbusStackHandle,
|
4 | const_cast<st_command_t*>(cmd), BSP_BATTERY_ADDR, READ);
|
5 | uint32_t t = HAL_GetTick();
|
6 | while ( ! STACK_SMBUS_IsReady(&smbusStackHandle)) {
|
7 | if((HAL_GetTick() - t) > 100){
|
8 | return -1;
|
9 | }
|
10 | }
|
11 | if(!smbusInitialized){
|
12 | return -1;
|
13 | }
|
14 | uint8_t* ioBuffer = STACK_SMBUS_GetBuffer(&smbusStackHandle);
|
15 | DATATYPE result = (*((DATATYPE*)ioBuffer));
|
16 | return result;
|
17 | }
|
Ich kann alle Register auslesen. Aber
1. Beim READ Vorgang zeigt mir mein Logic Analyzer am Ende immer ein
NACK.
2. Normalerweise sollte ja bei jedem Readvorgang der Buffer des smbus
mit dem neuen Readresult überschrieben werden. Tut er aber nicht.
3. Wenn ich ein Register beschreibe kommt ein ACK zurück. Eigentlich
müsste dann aber beim anschliessenden lesen ja das Geschriebene gelesen
werden können. Es kommt dann aber meist was falsches raus.
Meine Frage nun. Könnte sich jemand mit smbus Erfahrung die Methoden mal
anschauen und mir sagen ob da evtl was fehlt?
Vielen Dank schon mal im Vorraus :-)