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 -> %100 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 -> %100 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 -> %100 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 -> %100 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
Firstly, I would recommend that you use STM's library AN4502.
The difference between the master and the slave is the same as for the i2c bus. All bus transfers are initialized by the master.
I think there is not emulator of EMC2301. But to test the bus you can use examples from the STM AN4502.
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.
Is there a way to get the same result with a smaller size of code in c?
My Function:
void PCA9575_set_gpio_level(uint8_t gpio_num, uint8_t level) {
uint8_t reg, data, pin;
uint8_t buf[1] = {0};
buf[1] = PCA9575_read_register(OUT0);
if (gpio_num >= 28 && gpio_num <= 35) {
reg = OUT0;
pin = gpio_num - 27;
if (pin == 3) {
pin = 4;
} else if (pin == 4) {
pin = 8;
} else if (pin == 5) {
pin = 16;
} else if (pin == 6) {
pin = 32;
} else if (pin == 7) {
pin = 64;
} else if (pin == 8) {
pin = 128;
} else {
return;
}
if (level == 1) {
if (buf[1] == 0) {
data = pin;
} else if (buf[1] == 0xFF) {
data = 0xFF;
} else {
data = buf[1] ^ pin;
}
} else if (level == 0) {
if (buf[1] == 0) {
data = 0;
} else {
data = buf[1] ^ pin;
}
} else {
return;
}
}
else if (gpio_num >= 36 && gpio_num <= 43) {
reg = OUT1;
pin = gpio_num - 35;
if (pin == 3) {
pin = 4;
} else if (pin == 4) {
pin = 8;
} else if (pin == 5) {
pin = 16;
} else if (pin == 6) {
pin = 32;
} else if (pin == 7) {
pin = 64;
} else if (pin == 8) {
pin = 128;
} else {
return;
}
if (level == 1) {
if (buf[1] == 0) {
data = pin;
} else {
data = buf[1] ^ pin;
}
} else if (level == 0) {
if (buf[1] == 0) {
data = 0;
} else {
data = buf[1] ^ pin;
}
} else {
return;
}
}
else {
return;
}
PCA9575_write_to_register(reg, data);
}
The buf[1] variable is a value from 00000000 - 11111111 which is based on what has already been set.
The data variable is a value from 00000000 - 11111111 which will set the gpio pins.
The code should read what gpio pins are set and keep them set. Also at the same time set the new desired gpio pin.
GPIO pins are values from 28 - 43.
maybe:
void PCA9575_set_gpio_level(uint8_t gpio_num, uint8_t level)
{
uint8_t reg, pin;
uint8_t buf = PCA9575_read_register(OUT0);
if (gpio_num > 27 && gpio_num < 36)
{
reg = OUT0;
pin = gpio_num - 27;
}
else
{
if (gpio_num > 35 && gpio_num < 44)
{
reg = OUT1;
pin = gpio_num - 35;
}
}
else return;
pin = 1 << (pin - 1);
if(level < 2)
{
if(!buf) data = level * pin;
else if(buf == 0xff && gpio_num < 36) data = 0xff;
else data = buf ^pin;
}
PCA9575_write_to_register(reg, data);
}
I have an Adafruit feather 32u4 LoRa transmitter, I want to make a digital Morse transmitter, I took the transmission code from the internet and decided to write my own code for the rest. The two transistors transmit to each other but the micro don sees my input buttons.
int StatoPrecP2 = 0;
int i;
char SendData;
void loop()
{
switch (Stato) {
StatoAttP1 = digitalRead(P_Riga);
StatoAttP2 = digitalRead (P_Punto);
case 0:
if (StatoAttP1 == 1) /*&& (StatoPrecP1 != StatoAttP1 )) */{
digitalWrite(ButtonRecived, HIGH);
delay (250);
digitalWrite(ButtonRecived, LOW);
Stato = 1;
SendData = ".";
}
if ((StatoAttP2 == 1) && (StatoPrecP2 != StatoAttP1)) {
digitalWrite(ButtonRecived, 1);
delay (250);
digitalWrite(ButtonRecived, 0);
Stato = 1;
SendData = "-";
}
if (rf95.available())
{
// Should be a message for us now
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
uint8_t len = sizeof(buf);
if (rf95.recv(buf, &len))
{
digitalWrite(LED, HIGH);
RH_RF95::printBuffer("Received: ", buf, len);
Serial.print("Got: ");
Serial.println((char*)buf);
Serial.print("RSSI: ");
Serial.println(rf95.lastRssi(), DEC);
if (*buf = ".") {
PORTF = PORTF | 0x20;
delay(1000);
PORTF = PORTF & ~0x20;
}
else if (*buf = "-") {
PORTF = PORTF | 0x20;
delay(2500);
PORTF = PORTF & ~0x20;
}
}
else
{
Serial.println("Receive failed");
}
case 1:
// Send a reply
for (i = 0; i < 5000; i++) {
uint8_t data = SendData;
rf95.send(data, sizeof(data));
rf95.waitPacketSent();
Serial.println("Sent a reply");
digitalWrite(LED, LOW);
if ((StatoAttP1 = 1) & (StatoAttP1 != StatoPrecP1)) {
PORTF = PORTF | 0x10;
delay (250);
PORTF = PORTF & ~0x10;
Stato = 1;
uint8_t data[] = ".";
i = 0;
}
else if ((StatoAttP2 = 1) & (StatoAttP2 != StatoPrecP2)) {
PORTF = PORTF | 0x10;
delay (250);
PORTF = PORTF & ~0x10;
Stato = 1;
uint8_t data[] = "-";
i = 0;
}
delay (1);
}
Stato = 0;
}
}
StatoPrecP1 = StatoAttP1;
StatoPrecP2 = StatoAttP2;
}
While it's allowed to put statements inside a switch that still are outside any case, those will simply not be executed.
You have:
switch (Stato) {
StatoAttP1 = digitalRead(P_Riga);
StatoAttP2 = digitalRead (P_Punto);
case 0:
But the two digitalRead calls will never happen, which is the source of your problem.
You need to place those statements outside the switch:
StatoAttP1 = digitalRead(P_Riga);
StatoAttP2 = digitalRead (P_Punto);
switch (Stato) {
case 0:
A decent compiler should be able to warn about this problem, and if not you need to enable more warnings. And you should treat those warnings as errors the must be fixed.
I have problem, microcontroller simply doesnt register when i press button. As it didnt happened. Here is my code.
#ifndef F_CPU
#define F_CPU 1000000UL
#endif
#define bit_is_clear(byte, bit) (!(byte & (1 << bit)))
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
typedef enum { false, true } boolean;
boolean clicked = false;
int sigurno_pritisnut = 0;
void pressed();
void unpressed();
int main(void)
{
//LED OUTPUT
DDRB |= (1 << PINB0) | (1 << PINB1) | (1 << PINB2);
//LED LOW
PORTB &= ~((1 << PINB0) | (1 << PINB1) | (1 << PINB2));
//BUTTON INPUT
DDRC &= ~(1 << PINC5);
//BUTTON HIGH
PORTC |= (1 << PINC5);
/* Replace with your application code */
while (1)
{
if(bit_is_clear(PINC, PINC5)){
sigurno_pritisnut++;
if(sigurno_pritisnut > 400){
clicked = !clicked;
sigurno_pritisnut = 0;
}
}
if(clicked){
pressed();
}else{
unpressed();
}
}
}
void pressed(){
PORTB ^= (1 << PINB0);
_delay_ms(500);
PORTB ^= (1 << PINB1);
_delay_ms(500);
PORTB ^= (1 << PINB2);
_delay_ms(500);
sigurno_pritisnut = 0;
}
void unpressed(){
PORTB ^= (1 << PINB0);
_delay_ms(500);
PORTB ^= (1 << PINB0);
PORTB ^= (1 << PINB1);
_delay_ms(500);
PORTB ^= (1 << PINB1);
PORTB ^= (1 << PINB2);
_delay_ms(500);
PORTB ^= (1 << PINB2);
}
...................................................................
I have tried with other buttons, tried with other pins but nothing.
...................................................................
The problem seem to be your delay statements. In both pressed and unpressed you wait 3 x 500ms.
In the loop you want to see bit_is_clear 400 times before changing clicked.
So it seems that bit_is_clear must be true in 600 seconds before you change clicked.
Notice that this
if(clicked){
pressed();
}else if(!clicked){
unpressed();
}
is the same as
if(clicked){
pressed();
}else
unpressed();
}
so in every loop you'll enter one of them.
Further it seems strange that you don't an else here:
if(bit_is_clear(PINC, PINC5)){
sigurno_pritisnut++;
if(sigurno_pritisnut > 500){
clicked = !clicked;
sigurno_pritisnut = 0;
}
}
else
{
// ... don't you need some code here?
}
So button works like this
bit_is_clear == true means pressed
bit_is_clear == false means released
you'll need something like:
while (1)
{
while (1) // Loop until a state is changed
{
if(bit_is_clear(PINC, PINC5))
{
// pressed
if (clicked)
{
// Same state so just continue...
sigurno_pritisnut = 0;
continue;
}
sigurno_pritisnut++;
if(sigurno_pritisnut > 400){
clicked = 1;
sigurno_pritisnut = 0;
// State change - break out
break;
}
}
else
{
// released
if (!clicked)
{
sigurno_pritisnut = 0;
continue;
}
sigurno_pritisnut++;
if(sigurno_pritisnut > 400){
clicked = 0;
sigurno_pritisnut = 0;
break;
}
}
}
if(clicked){
pressed();
}else{
unpressed();
}
}
In this way you only call pressed / unpressed when something new has happened.
Can any one help with the errors im receiving
c55 error:general error
c55 error:faliure
I'm trying to compile the code and these are the errors im receiving and I dont know how to correct them at all
failed to locate output file 'pic control 1.obj'
#include <system.h>
#include <stdio.h>
unsigned char state, nxtstate, inbyte,g1,g2;
void checkS1S2()
{
inbyte=porta;
if ((inByte & 0x0F) == 0x07) //70%
{
nextstate =1; // turn on G1
}
if ((inByte & 0xF0) == 0x20) // 50%
{
nextstate =2; // turn on G2
}
if ((inByte & 0xF0) == 0xFF) // 100%
{
nextstate =3; // turn on G1 and G2
}
if (((inByte & 0xF0) == 0x00) || ((inByte & 0xF0) == 0x01))
{
nextState = 4; // TurnoFF G2
}
if (((inByte & 0x0F) == 0x00) || ((inByte & 0x0F) == 0x01) || ((inByte & 0x0F) == 0x02) )
{
nextState = 5; // TurnoFF G1
}
}
void state1(void)
{
bitset(portb1); // switch on G1
nextstate = 1;
g1 =1;
}//end of state1.
void state2(void)
{
bitset(portb2); // switch on G2
nextstate = 1;
g2 =1;
}//end of state2
void state3(void)
{
checktime;
{
if time up && (g1 ==1) && (g2 ==1);
state6;
else
state1;
}
}
void state6(void)
{
// switch OFF G0,G1,G2
bitclear(portb,0);
bitclear(portb,1);
bitclear(portb,2);
bitset(portb3);
nextstate = 1;
g1 =0;
g2=0;
}//end of state6
void state4(void)
{
bitclear(portb,1); // Switch OFF G1
nextstate =1;
g1 =0;
}
void state5()
{
bitclear(portb,2); // Switch OFF G2
g2 =0;
}
int main(void)
{
// Configure RA0-RA3 as S1 , RA4-RA7 as S2
// Configure RB0 as G0 , RB1 as G1 , RB2 as G2 and RB3 as LED
config();
nxtstate=0;
}
Your function state3 contains line that are not valid C code:
void state3(void)
{
checktime;
{
if time up && (g1 ==1) && (g2 ==1);
state6;
else
state1;
}
}
I assume that your intention was to add a comment and to invoke functions. In thart case you should do this:
void state3(void)
{
/* checktime */
{
if time up && (g1 ==1) && (g2 ==1);
state6();
else
state1();
}
}
Probably the checktime should be an boolean expression:
void state3(void)
{
if (checktime)
{
if time up && (g1 ==1) && (g2 ==1);
state6();
else
state1();
}
}
As you can see, the question left enough room for guessing.