168 lines
5.1 KiB
C
168 lines
5.1 KiB
C
/**
|
|
* @file PCA9535D_Driver.c
|
|
*
|
|
* Driver Software for the PCA9535D Port exteneder Peripheral
|
|
*
|
|
* @author Maximilian Mönikes
|
|
*/
|
|
|
|
#include "PCA9535D_Driver.h"
|
|
|
|
static I2C_HandleTypeDef* pcai2c;
|
|
static uint8_t deviceadr = 0;
|
|
|
|
static uint8_t gpioa_shadow_reg_out = 0;
|
|
static uint8_t gpiob_shadow_reg_out = 0;
|
|
static uint8_t gpioa_shadow_reg_dir = 0xFF;
|
|
static uint8_t gpiob_shadow_reg_dir = 0xFF;
|
|
static uint8_t gpioa_shadow_reg_inv = 0;
|
|
static uint8_t gpiob_shadow_reg_inv = 0;
|
|
|
|
/**@brief Initalize the PCA9535 Port extender
|
|
*
|
|
* All GPIOs are Initialized as Inputs with normal Polarity
|
|
*
|
|
* @param hi2c Pointer to I2C Handle struct for the peripheral in
|
|
* @param subaddress of the port expander
|
|
* @retval none
|
|
*/
|
|
|
|
void PCA9535_init(I2C_HandleTypeDef* hi2c, uint8_t subadr) {
|
|
pcai2c = hi2c;
|
|
deviceadr = PCA_I2C_BASE_ADDRESS | (subadr << 1);
|
|
|
|
uint8_t initalizationconfig[7] = {0x02, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF};
|
|
HAL_I2C_Master_Transmit(pcai2c, deviceadr, initalizationconfig, 7, 1000);
|
|
}
|
|
|
|
void PCA9535_setGPIOPinDirection(uint8_t Port, uint8_t pin, uint8_t state) {
|
|
if (Port == PC9535_PORTA) {
|
|
if (state)
|
|
gpioa_shadow_reg_dir |= (1 << pin);
|
|
else
|
|
gpioa_shadow_reg_dir &= ~(1 << pin);
|
|
|
|
uint8_t data[2] = {CONFIGURATION_REG_BASE_ADDRESS, gpioa_shadow_reg_dir};
|
|
HAL_I2C_Master_Transmit(pcai2c, deviceadr, data, 2, 1000);
|
|
} else if (Port == PC9535_PORTB) {
|
|
if (state)
|
|
gpiob_shadow_reg_dir |= (1 << pin);
|
|
else
|
|
gpiob_shadow_reg_dir &= ~(1 << pin);
|
|
|
|
uint8_t data[2] = {CONFIGURATION_REG_BASE_ADDRESS | 1,
|
|
gpiob_shadow_reg_dir};
|
|
HAL_I2C_Master_Transmit(pcai2c, deviceadr, data, 2, 1000);
|
|
}
|
|
}
|
|
|
|
void PCA9535_setGPIOPinOutput(uint8_t Port, uint8_t pin, uint8_t state) {
|
|
if (Port == PC9535_PORTA) {
|
|
if (state)
|
|
gpioa_shadow_reg_out |= (1 << pin);
|
|
else
|
|
gpioa_shadow_reg_out &= ~(1 << pin);
|
|
|
|
uint8_t data[2] = {OUTPUT_REG_BASE_ADDRESS, gpioa_shadow_reg_out};
|
|
HAL_I2C_Master_Transmit(pcai2c, deviceadr, data, 2, 1000);
|
|
} else if (Port == PC9535_PORTB) {
|
|
if (state)
|
|
gpiob_shadow_reg_out |= (1 << pin);
|
|
else
|
|
gpiob_shadow_reg_out &= ~(1 << pin);
|
|
|
|
uint8_t data[2] = {OUTPUT_REG_BASE_ADDRESS | 1, gpiob_shadow_reg_out};
|
|
HAL_I2C_Master_Transmit(pcai2c, deviceadr, data, 2, 1000);
|
|
}
|
|
}
|
|
|
|
void PCA9535_invertGPIOPinPolarity(uint8_t Port, uint8_t pin, uint8_t state) {
|
|
if (Port == PC9535_PORTA) {
|
|
if (state)
|
|
gpioa_shadow_reg_inv |= (1 << pin);
|
|
else
|
|
gpioa_shadow_reg_inv &= ~(1 << pin);
|
|
|
|
uint8_t data[2] = {INPUT_POLARITY_INVERSION_REG_BASE_ADDRESS,
|
|
gpioa_shadow_reg_inv};
|
|
HAL_I2C_Master_Transmit(pcai2c, deviceadr, data, 2, 1000);
|
|
} else if (Port == PC9535_PORTB) {
|
|
if (state)
|
|
gpiob_shadow_reg_inv |= (1 << pin);
|
|
else
|
|
gpiob_shadow_reg_inv &= ~(1 << pin);
|
|
|
|
uint8_t data[2] = {INPUT_POLARITY_INVERSION_REG_BASE_ADDRESS | 1,
|
|
gpiob_shadow_reg_inv};
|
|
HAL_I2C_Master_Transmit(pcai2c, deviceadr, data, 2, 1000);
|
|
}
|
|
}
|
|
|
|
uint8_t PCA9535_readGPIOPinInput(uint8_t Port, uint8_t pin) {
|
|
if (Port == PC9535_PORTA) {
|
|
uint8_t command = INPUT_REG_BASE_ADDRESS;
|
|
HAL_I2C_Master_Transmit(pcai2c, deviceadr, &command, 1, 1000);
|
|
} else if (Port == PC9535_PORTB) {
|
|
uint8_t command = INPUT_REG_BASE_ADDRESS | 1;
|
|
HAL_I2C_Master_Transmit(pcai2c, deviceadr, &command, 1, 1000);
|
|
}
|
|
|
|
uint8_t reval = 0;
|
|
HAL_I2C_Master_Receive(pcai2c, deviceadr, &reval, 1, 1000);
|
|
|
|
reval &= (1 << pin);
|
|
reval = reval >> (pin);
|
|
return reval;
|
|
}
|
|
|
|
void PCA9535_setGPIOPortDirection(uint8_t Port, uint8_t bitmask) {
|
|
uint8_t command[2] = {0x00, bitmask};
|
|
if (Port == PC9535_PORTA) {
|
|
gpioa_shadow_reg_dir = bitmask;
|
|
command[0] = CONFIGURATION_REG_BASE_ADDRESS;
|
|
} else if (Port == PC9535_PORTB) {
|
|
gpiob_shadow_reg_dir = bitmask;
|
|
command[0] = CONFIGURATION_REG_BASE_ADDRESS | 1;
|
|
}
|
|
HAL_I2C_Master_Transmit(pcai2c, deviceadr, command, 2, 1000);
|
|
}
|
|
|
|
void PCA9535_setGPIOPortOutput(uint8_t Port, uint8_t bitmask) {
|
|
uint8_t command[2] = {0x00, bitmask};
|
|
if (Port == PC9535_PORTA) {
|
|
gpioa_shadow_reg_out = bitmask;
|
|
command[0] = OUTPUT_REG_BASE_ADDRESS;
|
|
} else if (Port == PC9535_PORTB) {
|
|
gpiob_shadow_reg_out = bitmask;
|
|
command[0] = OUTPUT_REG_BASE_ADDRESS | 1;
|
|
}
|
|
HAL_I2C_Master_Transmit(pcai2c, deviceadr, command, 2, 1000);
|
|
}
|
|
|
|
void PCA9535_invertGPIOPortPolarity(uint8_t Port, uint8_t bitmask) {
|
|
uint8_t command[2] = {0x00, bitmask};
|
|
if (Port == PC9535_PORTA) {
|
|
gpioa_shadow_reg_inv = bitmask;
|
|
command[0] = INPUT_POLARITY_INVERSION_REG_BASE_ADDRESS;
|
|
} else if (Port == PC9535_PORTB) {
|
|
gpiob_shadow_reg_inv = bitmask;
|
|
command[0] = INPUT_POLARITY_INVERSION_REG_BASE_ADDRESS | 1;
|
|
}
|
|
HAL_I2C_Master_Transmit(pcai2c, deviceadr, command, 2, 1000);
|
|
}
|
|
|
|
uint8_t PCA9535_readGPIOPortInput(uint8_t Port) {
|
|
uint8_t command = 0;
|
|
|
|
if (Port == PC9535_PORTB)
|
|
command |= INPUT_REG_BASE_ADDRESS;
|
|
else if (Port == PC9535_PORTA)
|
|
command |= INPUT_REG_BASE_ADDRESS | 1;
|
|
|
|
HAL_I2C_Master_Transmit(pcai2c, deviceadr, &command, 1, 1000);
|
|
uint8_t reval = 0;
|
|
HAL_I2C_Master_Receive(pcai2c, deviceadr, &reval, 1, 1000);
|
|
|
|
return reval;
|
|
}
|