Home > Back-end >  smBus communication testing for fan driver IC in STM32 with C
smBus communication testing for fan driver IC in STM32 with C

Time:01-26

I developed a library for fan IC which use smbus protocol. However ı have some problems and questions. 1 -) what is diff between master and slave for smbus? whether the IC should be slave or master is not specified in the datasheet. Therefore, how can ı decide that stm32 developer board should be slave or master. 2-) unfortunately, ı cannot try my code because fan driver IC ı have not received yet sensor. Do u know any method to test my code. Maybe ardunio library. 3-) to receive data, ı firstly tranmit the register address of data ı want to read. is it correct. You can find datasheet of IC and code ı wrote below

C file

#include "smbusDriver.h"
#include "stm32f0xx_hal_smbus.h"
#include "stm32f0xx_hal.h"
#include "smbusDriver.h"




resultConditions_t InitializeDriver(SMBUS_HandleTypeDef *hsmbus, uint8_t address, addressValues_t *Daddress){

    Daddress->Fields.configurationRegisterAddress = 0x20;
    Daddress->Fields.FanStatusRegisterAddress = 0x24;
    Daddress->Fields.FanStallRegisterAddress = 0x25;
    Daddress->Fields.FanSpinRegisterAddress = 0x26;
    Daddress->Fields.DriveFailStatusAddress = 0x27;
    Daddress->Fields.FanInterruptEnableRegisterAddress = 0x29;
    Daddress->Fields.PwmPolarityRegisterAddress = 0x2A;
    Daddress->Fields.PwmOutputTypeRegisterAddress = 0x2B;
    Daddress->Fields.PwmFrequency45Address = 0x2C;
    Daddress->Fields.PwmFrequency123Address = 0x2D;
    Daddress->Fields.PwmDivider1Address = 0x31;
    Daddress->Fields.PwmDivider2Address = 0x41;
    Daddress->Fields.PwmDivider3Address = 0x51;
    Daddress->Fields.PwmDivider4Address = 0x61;
    Daddress->Fields.PwmSettingAddress1  = 0x30;
    Daddress->Fields.PwmSettingAddress2  = 0x40;
    Daddress->Fields.PwmSettingAddress3  = 0x50;
    Daddress->Fields.PwmSettingAddress4  = 0x60;
    resultConditions_t result = RESULT_OK;
    uint8_t buf[2];
    configuration_t confDriver;
    confDriver.Fields.MASK = 0 ; // Alert pin activated.
    confDriver.Fields.DIS_TO = 0; // smBUS enabled. If 1, I2C is compatible
    confDriver.Fields.WD_EN = 0; // Watchdog is not enabled
    confDriver.Fields.DRECK = 1; // Enabled internal clock
    confDriver.Fields.USECK = 0; // Connecting internal oscillator
    FanInterruptEnableRegister_t FanIntEn;
    FanIntEn.Fields.F1ITEN = 1;
    FanIntEn.Fields.F2ITEN = 1;
    FanIntEn.Fields.F3ITEN = 1;
    FanIntEn.Fields.F4ITEN = 1;
    FanIntEn.Fields.F5ITEN = 0;
    PwmPolarityRegister_t PwmPolarity;
    PwmPolarity.Fields.PLRITY1 = 0; // FF => 255, 00 => 00
    PwmPolarity.Fields.PLRITY1 = 0; // FF => 255, 00 => 00
    PwmPolarity.Fields.PLRITY1 = 0; // FF => 255, 00 => 00
    PwmPolarity.Fields.PLRITY1 = 0; // FF => 255, 00 => 00
    PwmOutputTypeRegister_t OutputType;
    OutputType.Fields.PMOT1 = 0;
    OutputType.Fields.PMOT2 = 0;
    OutputType.Fields.PMOT3 = 0;
    OutputType.Fields.PMOT4 = 0;
    PwmFrequency45_t BaseFrequency_45;
    PwmFrequency123_t BaseFrequency_123;
    BaseFrequency_45.Fields.PwmFrequency4 = 0; // 26kHz
    BaseFrequency_45.Fields.PwmFrequency5 = 0; // 26kHz
    BaseFrequency_123.Fields.PwmFrequency1 = 0; // 26kHz
    BaseFrequency_123.Fields.PwmFrequency2 = 0; // 26kHz
    BaseFrequency_123.Fields.PwmFrequency3 = 0; // 26kHz
    PwmDividerRegister_t Divider;
    Divider.Fields.pwmDivider_1 = 0x01; // PWM Divider
    Divider.Fields.pwmDivider_2 = 0x01; // PWM Divider
    Divider.Fields.pwmDivider_3 = 0x01; // PWM Divider
    Divider.Fields.pwmDivider_4 = 0x01; // PWM Divider
    HAL_SMBUS_Init(hsmbus);
    HAL_Delay(10);
    uint16_t DeviceAddress = 0x0000;
    DeviceAddress = DeviceAddress | address;
    result = HAL_SMBUS_IsDeviceReady(hsmbus, DeviceAddress, 5 , 1000);
    if (result != RESULT_OK) return result;
    HAL_SMBUS_EnableAlert_IT(hsmbus);
    if (result != RESULT_OK) return result;
    HAL_SMBUS_EnableListen_IT(hsmbus);
    if (result != RESULT_OK) return result;

    HAL_Delay(20);
    buf[0] = Daddress->Fields.configurationRegisterAddress; // The configuration of board is set
    buf[1] = confDriver.value;
    result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
    if (result != RESULT_OK) return result;
    HAL_Delay(20);
    buf[0] = Daddress->Fields.FanInterruptEnableRegisterAddress; // If any alert shows up, Fans can interrupt the operation
    buf[1] = FanIntEn.value;
    result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
    HAL_Delay(20);
    if (result != RESULT_OK) return result;
    buf[0] = Daddress->Fields.PwmPolarityRegisterAddress; // The high to high, low to low
    buf[1] = PwmPolarity.value;
    result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
    HAL_Delay(20);
    if (result != RESULT_OK) return result;
    buf[0] = Daddress->Fields.PwmOutputTypeRegisterAddress; // Pull-push and Open Drain choose
    buf[1] = OutputType.value;
    result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
    HAL_Delay(20);
    if (result != RESULT_OK) return result;
    buf[0] = Daddress->Fields.PwmFrequency45Address; // Base Frequency 4-5
    buf[1] = BaseFrequency_45.value;
    result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
    HAL_Delay(20);
    if (result != RESULT_OK) return result; // Base Frequency 1-2-3
    buf[0] = Daddress->Fields.PwmFrequency123Address;
    buf[1] = BaseFrequency_123.value;
    result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
    HAL_Delay(20);
    if (result != RESULT_OK) return result;
    buf[0] = Daddress->Fields.PwmDivider1Address; // Divider of frequency => frequency / divide factor (Duty Cycle is not affected)
    buf[1] = Divider.Fields.pwmDivider_1;
    result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
    HAL_Delay(20);
    if (result != RESULT_OK) return result;
    buf[0] = Daddress->Fields.PwmDivider2Address; // Divider of frequency
    buf[1] = Divider.Fields.pwmDivider_2;
    result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
    HAL_Delay(20);
    if (result != RESULT_OK) return result;
    buf[0] = Daddress->Fields.PwmDivider3Address; // Divider of frequency
    buf[1] = Divider.Fields.pwmDivider_3;
    result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
    HAL_Delay(20);
    if (result != RESULT_OK) return result;
    buf[0] = Daddress->Fields.PwmDivider4Address; // Divider of frequency
    buf[1] = Divider.Fields.pwmDivider_4;
    result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
    if (result != RESULT_OK) return result;
    return result;
}



resultConditions_t setPwmConfig(uint8_t Pwm, addressValues_t *Daddress,SMBUS_HandleTypeDef *hsmbus, uint8_t address){
    resultConditions_t result = HAL_OK;
    PwmSettings_t pwmSet;
    uint8_t buf[2];
    pwmSet.Fields.pwmSettings1 = Pwm;
    pwmSet.Fields.pwmSettings2 = Pwm;
    pwmSet.Fields.pwmSettings3 = Pwm;
    pwmSet.Fields.pwmSettings4 = Pwm;
    uint16_t DeviceAddress = 0x0000;
    DeviceAddress = DeviceAddress | address;
    buf[0] = Daddress->Fields.PwmSettingAddress1; // Pwm set
    buf[1] = pwmSet.Fields.pwmSettings1;
    result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC); // => 0xHH -> 0 Duty Cycle /\ 0x00 -> %0 Duty Cycle
    if (result != RESULT_OK) return result;
    buf[0] = Daddress->Fields.PwmSettingAddress2; // Pwm set
    buf[1] = pwmSet.Fields.pwmSettings2;
    result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC); // => 0xHH -> 0 Duty Cycle /\ 0x00 -> %0 Duty Cycle
    if (result != RESULT_OK) return result;
    buf[0] = Daddress->Fields.PwmSettingAddress3; // Pwm set
    buf[1] = pwmSet.Fields.pwmSettings3;
    result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC); // => 0xHH -> 0 Duty Cycle /\ 0x00 -> %0 Duty Cycle
    if (result != RESULT_OK) return result;
    buf[0] = Daddress->Fields.PwmSettingAddress4; // Pwm set
    buf[1] = pwmSet.Fields.pwmSettings4;
    result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC); // => 0xHH -> 0 Duty Cycle /\ 0x00 -> %0 Duty Cycle
    if (result != RESULT_OK) return result;
    return result;
}


generalStatus_t getGeneralStatus(addressValues_t *Daddress,SMBUS_HandleTypeDef *hsmbus, uint8_t address){
    uint8_t buf[2];
    uint8_t DeviceAddress;
    DeviceAddress = DeviceAddress | address;
    resultConditions_t result;
    buf[0] = Daddress->Fields.FanStatusRegisterAddress;
    generalStatus_t returnValue = NO_ERROR;
    result = HAL_SMBUS_Master_Transmit_IT(hsmbus, DeviceAddress,buf,1,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
    if (result == RESULT_ERROR) return UNEXPECTED_ERROR;
    result = HAL_SMBUS_Master_Receive_IT(hsmbus, DeviceAddress,buf 1,1,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
    if (result == RESULT_ERROR) return UNEXPECTED_ERROR;
    if (buf[0] == 0x00){
        return returnValue;
    }
    else {
        if ((buf[0] & (uint8_t)0b00100000) == (uint8_t)0b00100000){
            returnValue = DRIVE_FAIL_ERROR;
            return returnValue;
        }
        else if ((buf[0] & (uint8_t)0b01000000) == (uint8_t)0b01000000){
            returnValue = FAN_SPIN_ERROR;
            return returnValue;
        }
        else if ((buf[0] & (uint8_t)0b10000000) == (uint8_t)0b10000000)
        {
            returnValue = FAN_STALL_ERROR;
            return returnValue;
        }
        else{
            returnValue = UNEXPECTED_ERROR;
            return returnValue;
        }
    }
}


specialFanStallStatus_t getStallStatus(addressValues_t *Daddress,SMBUS_HandleTypeDef *hsmbus, uint8_t address){
    uint8_t buf[2];
    uint8_t DeviceAddress;
    DeviceAddress = DeviceAddress | address;
    resultConditions_t result;
    buf[0] = Daddress->Fields.FanStallRegisterAddress;
    specialFanStallStatus_t returnValue = NO_ERROR;
    result = HAL_SMBUS_Master_Transmit_IT(hsmbus, DeviceAddress,buf,1,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
    if (result == RESULT_ERROR) return UNEXPECTED_ERROR;
    result = HAL_SMBUS_Master_Receive_IT(hsmbus, DeviceAddress,buf,1,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
    if (result == RESULT_ERROR) return UNEXPECTED_ERROR;
    if (buf[0] == 0x00){
        return returnValue;
    }
    else {
        if ((buf[0] & (uint8_t)0b10000000) == (uint8_t)0b10000000){
            returnValue = FAN_1_STALL_ERROR;
            return returnValue;
        }
        else if ((buf[0] & (uint8_t)0b10000000) == (uint8_t)0b10000000){
            returnValue = FAN_2_STALL_ERROR;
            return returnValue;
        }
        else if ((buf[0] & (uint8_t)0b00100000) == (uint8_t)0b00100000)
        {
            returnValue = FAN_3_STALL_ERROR;
            return returnValue;
        }
        else if ((buf[0] & (uint8_t)0b00010000) == (uint8_t)0b000100000)
        {
            returnValue = FAN_4_STALL_ERROR;
            return returnValue;
        }
        else{
            returnValue = UNEXPECTED_ERROR;
            return returnValue;
        }
    }
}


specialFanSpinStatus_t getSpinStatus(addressValues_t *Daddress,SMBUS_HandleTypeDef *hsmbus, uint8_t address){
    uint8_t buf[2];
    uint8_t DeviceAddress;
    DeviceAddress = DeviceAddress | address;
    resultConditions_t result;
    buf[0] = Daddress->Fields.FanSpinRegisterAddress;
    specialFanSpinStatus_t returnValue = NO_SPIN_ERROR;
    result = HAL_SMBUS_Master_Transmit_IT(hsmbus, DeviceAddress,buf,1,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
    if (result == RESULT_ERROR) return UNEXPECTED_ERROR;
    result = HAL_SMBUS_Master_Receive_IT(hsmbus, DeviceAddress,buf,1,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
    if (result == RESULT_ERROR) return UNEXPECTED_ERROR;
    if (buf[0] == 0x00){
        return returnValue;
    }
    else {
        if ((buf[0] & (uint8_t)0b10000000) == (uint8_t)0b10000000){
            returnValue = FAN_1_SPIN_ERROR;
            return returnValue;
        }
        else if ((buf[0] & (uint8_t)0b10000000) == (uint8_t)0b10000000){
            returnValue = FAN_2_SPIN_ERROR;
            return returnValue;
        }
        else if ((buf[0] & (uint8_t)0b00100000) == (uint8_t)0b00100000)
        {
            returnValue = FAN_3_SPIN_ERROR;
            return returnValue;
        }
        else if ((buf[0] & (uint8_t)0b00010000) == (uint8_t)0b000100000)
        {
            returnValue = FAN_4_SPIN_ERROR;
            return returnValue;
        }
        else{
            returnValue = UNEXPECTED_ERROR;
            return returnValue;
        }
    }
}

specialFanDriveStatus_t getDriveStatus(addressValues_t *Daddress,SMBUS_HandleTypeDef *hsmbus, uint8_t address){
    uint8_t buf[2];
    uint8_t DeviceAddress;
    DeviceAddress = DeviceAddress | address;
    resultConditions_t result;
    buf[0] = Daddress->Fields.DriveFailStatusAddress;
    specialFanDriveStatus_t returnValue = NO_ERROR;
    result = HAL_SMBUS_Master_Transmit_IT(hsmbus, DeviceAddress,buf,1,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
    if (result == RESULT_ERROR) return UNEXPECTED_ERROR;
    result = HAL_SMBUS_Master_Receive_IT(hsmbus, DeviceAddress,buf,1,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
    if (result == RESULT_ERROR) return UNEXPECTED_ERROR;
    if (buf[0] == 0x00){
        return returnValue;
    }
    else {
        if ((buf[0] & (uint8_t)0b10000000) == (uint8_t)0b10000000){
            returnValue = FAN_1_DRIVE_ERROR;
            return returnValue;
        }
        else if ((buf[0] & (uint8_t)0b10000000) == (uint8_t)0b10000000){
            returnValue = FAN_2_DRIVE_ERROR;
            return returnValue;
        }
        else if ((buf[0] & (uint8_t)0b00100000) == (uint8_t)0b00100000)
        {
            returnValue = FAN_3_DRIVE_ERROR;
            return returnValue;
        }
        else if ((buf[0] & (uint8_t)0b00010000) == (uint8_t)0b000100000)
        {
            returnValue = FAN_4_DRIVE_ERROR;
            return returnValue;
        }
        else{
            returnValue = UNEXPECTED_ERROR;
            return returnValue;
        }
    }
}



H file

#ifndef smbusDriver
#define smbusDriver

#ifdef __cplusplus
 extern "C" {
#endif


#include "smbusDriver.h"
#include "stm32f0xx_hal_smbus.h"
#include "stm32f0xx_hal.h"


typedef union {
    struct{
        uint8_t configurationRegisterAddress;
        uint8_t FanStatusRegisterAddress;
        uint8_t FanStallRegisterAddress;
        uint8_t FanSpinRegisterAddress;
        uint8_t DriveFailStatusAddress;
        uint8_t FanInterruptEnableRegisterAddress;
        uint8_t PwmPolarityRegisterAddress;
        uint8_t PwmOutputTypeRegisterAddress;
        uint8_t PwmFrequency45Address;
        uint8_t PwmFrequency123Address;
        uint8_t PwmDivider1Address;
        uint8_t PwmDivider2Address;
        uint8_t PwmDivider3Address;
        uint8_t PwmDivider4Address;
        uint8_t PwmSettingAddress1;
        uint8_t PwmSettingAddress2;
        uint8_t PwmSettingAddress3;
        uint8_t PwmSettingAddress4;
    }Fields;

}addressValues_t;


typedef enum{
    NO_ERROR,
    DRIVE_FAIL_ERROR, // indicate that one or more fan could not be driven  (ProgrammingError)
    FAN_SPIN_ERROR,  //  indicate that one or more fan spin
    FAN_STALL_ERROR, //  indicate that one or more fan is stuck
    UNEXPECTED_ERROR
} generalStatus_t;

typedef enum {
    NO_STALL_ERROR,
    FAN_5_STALL_ERROR,
    FAN_4_STALL_ERROR,
    FAN_3_STALL_ERROR,
    FAN_2_STALL_ERROR,
    FAN_1_STALL_ERROR,
    UNEXPECTED_STALL_ERROR
} specialFanStallStatus_t;

typedef enum {
    NO_SPIN_ERROR,
    FAN_5_SPIN_ERROR,
    FAN_4_SPIN_ERROR,
    FAN_3_SPIN_ERROR,
    FAN_2_SPIN_ERROR,
    FAN_1_SPIN_ERROR,
    UNEXPECTED_SPIN_ERROR
} specialFanSpinStatus_t;

typedef enum {
    NO_DRIVE_ERROR,
    FAN_5_DRIVE_ERROR,
    FAN_4_DRIVE_ERROR,
    FAN_3_DRIVE_ERROR,
    FAN_2_DRIVE_ERROR,
    FAN_1_DRIVE_ERROR,
    UNEXPECTED_DRIVE_ERROR
} specialFanDriveStatus_t;







typedef enum{
    RESULT_OK,
    RESULT_ERROR,
    RESULT_TIMEOUT,
    RESULT_BUSY,
    RESULT_INVALID,
} resultConditions_t;

typedef union  {
    struct {
        uint8_t USECK       : 1; // 1 => External Clock  &  0 => Internal Clock
        uint8_t DRECK       : 1; // 1 => Clock pin output and push-pull driver 0 => Clock pin input
        uint8_t reserved    : 3;
        uint8_t WD_EN       : 1; // 1 => Watch clock is activated 0 => 0 watch clock is deactivated.
        uint8_t DIS_TO      : 1; // 1 => I2C is compatible 0 => SMBus time-out is enabled
        uint8_t MASK        : 1; // 1 => Alert is deactivated  0 => Alert is activated
        } Fields;
    uint8_t value;
} configuration_t;

typedef union  {
    struct
    {
        uint8_t  FNSTL      : 1; // stall error <=> 1
        uint8_t  FNSPIN     : 1; // Spin up error <=> 1
        uint8_t  DVFAIL     : 1; // Maximum speed PWM error <=> 1
        uint8_t  reserved   : 5;
    }Fields;
    uint8_t value;
}FanStatusRegister_t;

typedef union  {
    struct {
        uint8_t F1STL       : 1; // tachometer count has exceeded maximum valid TACH count, initializing stall <=> 1
        uint8_t F2STL       : 1; // tachometer count has exceeded maximum valid TACH count, initializing stall <=> 1
        uint8_t F3STL       : 1; // tachometer count has exceeded maximum valid TACH count, initializing stall <=> 1
        uint8_t F4STL       : 1; // tachometer count has exceeded maximum valid TACH count, initializing stall <=> 1
        uint8_t F5STL       : 1; // tachometer count has exceeded maximum valid TACH count, initializing stall <=> 1
        uint8_t reserved    : 3; // tachometer count has exceeded maximum valid TACH count, initializing stall <=> 1
    } Fields;
    uint8_t value;
} FanStallStatusRegister_t;


typedef union {
    struct {
        uint8_t F1SPIN      : 1; // spin start error <=> 1
        uint8_t F2SPIN      : 1; // spin start error <=> 1
        uint8_t F3SPIN      : 1; // spin start error <=> 1
        uint8_t F4SPIN      : 1; // spin start error <=> 1
        uint8_t F5SPIN      : 1; // spin start error <=> 1
        uint8_t reserved    : 3; // spin start error <=> 1
    } Fields;
    uint8_t value;
}FanSpinStatusRegister_t;

typedef union {
    struct{
        uint8_t DRVF1       : 1; // rpm error <=> 1
        uint8_t DRVF2       : 1; // rpm error <=> 1
        uint8_t DRVF3       : 1; // rpm error <=> 1
        uint8_t DRVF4       : 1; // rpm error <=> 1
        uint8_t DRVF5       : 1; // rpm error <=> 1
        uint8_t reserved    : 3; // rpm error <=> 1
    }Fields;
    uint8_t value;
} DriveFailStatus_t;

typedef union  {
    struct  {
        uint8_t F1ITEN      : 1; // Alert Fan 1 enable  <=> 1
        uint8_t F2ITEN      : 1; // Alert Fan 2 enable  <=> 1
        uint8_t F3ITEN      : 1; // Alert Fan 3 enable  <=> 1
        uint8_t F4ITEN      : 1; // Alert Fan 4 enable  <=> 1
        uint8_t F5ITEN      : 1; // Alert Fan 5 enable  <=> 1
        uint8_t reserved    : 3;
    }Fields;
    uint8_t value;
}FanInterruptEnableRegister_t;

typedef union  {
    struct {
        uint8_t PLRITY1     : 1; // FFh produce 100% duty cycle <=> 1
        uint8_t PLRITY2     : 1; // FFh produce 100% duty cycle <=> 1
        uint8_t PLRITY3     : 1; // FFh produce 100% duty cycle <=> 1
        uint8_t PLRITY4     : 1; // FFh produce 100% duty cycle <=> 1
        uint8_t PLRITY5     : 1; // FFh produce 100% duty cycle <=> 1
        uint8_t reserved    : 3;
    }Fields;
    uint8_t value;
}PwmPolarityRegister_t;

typedef union  {
    struct {
        uint8_t PMOT1       : 1; // OpenDrain <=> 0 and PullPush output <=> 1
        uint8_t PMOT2       : 1; // OpenDrain <=> 0 and PullPush output <=> 1
        uint8_t PMOT3       : 1; // OpenDrain <=> 0 and PullPush output <=> 1
        uint8_t PMOT4       : 1; // OpenDrain <=> 0 and PullPush output <=> 1
        uint8_t PMOT5       : 1; // OpenDrain <=> 0 and PullPush output <=> 1
        uint8_t reserved    : 3;
    } Fields;
    uint8_t value;
} PwmOutputTypeRegister_t;
typedef union  {
    struct {
        uint8_t PwmFrequency4   : 2;
        uint8_t PwmFrequency5   : 2;
        uint8_t reserved        : 4;
    }Fields;
    uint8_t value;
}PwmFrequency45_t;

typedef union  {
    struct  {
        uint8_t PwmFrequency1   : 2;
        uint8_t PwmFrequency2   : 2;
        uint8_t PwmFrequency3   : 2;
        uint8_t reserved        : 2;
    }Fields;
    uint8_t value;
}PwmFrequency123_t;

typedef union {
    struct {
        uint8_t DriveSetting_1: 8;
        uint8_t DriveSetting_2: 8;
        uint8_t DriveSetting_3: 8;
        uint8_t DriveSetting_4: 8;
    }Fields;
        uint32_t value;
}CurrentDriveSettings_t;

typedef union {
    struct{
        uint8_t pwmDivider_1 :8;
        uint8_t pwmDivider_2 :8;
        uint8_t pwmDivider_3 :8;
        uint8_t pwmDivider_4 :8;
    }Fields;
        uint32_t value;
}PwmDividerRegister_t;

typedef union{
    struct {
        uint8_t pwmSettings1 :8;
        uint8_t pwmSettings2 :8;
        uint8_t pwmSettings3 :8;
        uint8_t pwmSettings4 :8;
    }Fields;
}PwmSettings_t;



resultConditions_t InitializeDriver(SMBUS_HandleTypeDef *hsmbus, uint8_t address, addressValues_t *Daddress);
resultConditions_t setPwmConfig(uint8_t Pwm, addressValues_t *Daddress,SMBUS_HandleTypeDef *hsmbus, uint8_t address);
generalStatus_t getGeneralStatus(addressValues_t *Daddress,SMBUS_HandleTypeDef *hsmbus, uint8_t address);


#endif

Datasheet: https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/EMC2301-2-3-5-Data-Sheet-DS20006532A.pdf

Estimation whether code is working or not

CodePudding user response:

Firstly, I would recommend that you use STM's library AN4502.

  1. The difference between the master and the slave is the same as for the i2c bus. All bus transfers are initialized by the master.
  2. I think there is not emulator of EMC2301. But to test the bus you can use examples from the STM AN4502.
  3. Your code won't work because the HAL_SMBUS_Master_Transmit_IT and HAL_SMBUS_Master_Receive_IT functions are called asynchronously and require you to wait for the execution to finish when you call two functions in a row, you will get the result HAL_BUSY. Use the library AN4502, it will make it easier to interact with the peripheral.
  • Related