stm32 pca9555读写

时间: 2023-05-12 20:00:59 浏览: 184
PCA9555是一种I2C接口的16位I/O扩展芯片,可用于将I/O口扩展到稍远距离的位置。STM32 MCU和PCA9555之间的通信是通过I2C接口进行的。当要读取PCA9555的输入引脚状态或设置其输出引脚状态时,STM32 MCU通过I2C接口向PCA9555发送相应的控制字节和地址。当PCA9555接收到STM32 MCU发送的命令后,它会执行相应的操作,并将结果数据返回给STM32 MCU。读操作时,数据将存储在接收数据缓冲区中,然后可以通过STM32 MCU处理。在写入操作中,STM32 MCU向PCA9555发送要设置的输出端口值,并等待PCA9555响应。 对于PCA9555读写操作,需要先初始化I2C接口,然后通过生成必要的I2C数据包来读取或写入内部寄存器的值。读取操作涉及向I2C总线发送请求来获取数据,而写入操作涉及将所需的数据发送到要设置的设备上。有关可用的数据包格式和传输速率的详细信息可以在相关的参考手册中找到。 总的来说,STM32 PCA9555读写操作具有较高的可扩展性、多功能、易于调试等优点,能够为用户提供更便捷的扩展接口服务,因此广泛应用于各种嵌入式设备中。
相关问题

完整的STM32F4 I2C HAL驱动PCA9555程序带读写容错功能,出错重新初始化PCA9555;包含I2C1初始化代码

以下是一个基于STM32F4 HAL库的I2C驱动PCA9555的代码示例,包含了读写容错功能,以及出错重新初始化PCA9555的处理。 ```c #include "stm32f4xx_hal.h" /* PCA9555 I2C地址 */ #define PCA9555_ADDR 0x40 /* PCA9555寄存器地址 */ #define PCA9555_INPUT 0x00 /* 输入寄存器 */ #define PCA9555_OUTPUT 0x01 /* 输出寄存器 */ #define PCA9555_POLAR 0x02 /* 极性反转寄存器 */ #define PCA9555_CONFIG 0x03 /* 配置寄存器 */ /* PCA9555输出状态宏定义 */ #define PCA9555_OUTPUT_HIGH 0xFF #define PCA9555_OUTPUT_LOW 0x00 /* I2C句柄 */ extern I2C_HandleTypeDef hi2c1; /* PCA9555初始化函数 */ void PCA9555_Init(void) { /* PCA9555配置字节,配置所有IO口为输出模式 */ uint8_t config_byte = 0x00; HAL_I2C_Mem_Write(&hi2c1, PCA9555_ADDR, PCA9555_CONFIG, 1, &config_byte, 1, 100); } /* PCA9555重新初始化函数 */ void PCA9555_ReInit(void) { /* 先关闭I2C外设 */ HAL_I2C_DeInit(&hi2c1); /* 等待一段时间 */ HAL_Delay(100); /* 重新初始化I2C外设 */ MX_I2C1_Init(); /* 重新初始化PCA9555 */ PCA9555_Init(); } /* PCA9555读取输入寄存器函数 */ uint8_t PCA9555_ReadInput(void) { /* 读取输入寄存器 */ uint8_t input_byte = 0x00; if (HAL_I2C_Mem_Read(&hi2c1, PCA9555_ADDR, PCA9555_INPUT, 1, &input_byte, 1, 100) != HAL_OK) { /* 读取失败,重新初始化PCA9555 */ PCA9555_ReInit(); /* 返回默认值 */ return 0xFF; } return input_byte; } /* PCA9555写入输出寄存器函数 */ void PCA9555_WriteOutput(uint8_t output_byte) { /* 写入输出寄存器 */ if (HAL_I2C_Mem_Write(&hi2c1, PCA9555_ADDR, PCA9555_OUTPUT, 1, &output_byte, 1, 100) != HAL_OK) { /* 写入失败,重新初始化PCA9555 */ PCA9555_ReInit(); } } /* PCA9555输出高电平函数 */ void PCA9555_OutputHigh(void) { PCA9555_WriteOutput(PCA9555_OUTPUT_HIGH); } /* PCA9555输出低电平函数 */ void PCA9555_OutputLow(void) { PCA9555_WriteOutput(PCA9555_OUTPUT_LOW); } ``` 以上代码中,`PCA9555_Init()`函数用于初始化PCA9555,将所有IO口配置为输出模式;`PCA9555_ReInit()`函数用于重新初始化PCA9555,当I2C通信出现错误时调用该函数;`PCA9555_ReadInput()`函数用于读取PCA9555的输入寄存器,并且在读取失败时重新初始化PCA9555;`PCA9555_WriteOutput()`函数用于写入PCA9555的输出寄存器,并且在写入失败时重新初始化PCA9555;`PCA9555_OutputHigh()`和`PCA9555_OutputLow()`函数用于将PCA9555的输出状态设置为高电平和低电平。需要注意的是,以上代码中的`hi2c1`变量是I2C句柄,需要在主函数中初始化。

基于HAL库的STM32F4 I2C驱动的示例代码,可以读写两个PCA9555芯片,并且具有读写容错功能与操作PCA9555输出PIN脚电平功能。如果出现错误,代码将重新初始化PCA9555芯片

以下是基于HAL库的STM32F4 I2C驱动的示例代码,可以读写两个PCA9555芯片,并且具有读写容错功能与操作PCA9555输出PIN脚电平功能。如果出现错误,代码将重新初始化PCA9555芯片。 ```c #include "stm32f4xx_hal.h" #define PCA9555_ADDRESS_1 0x40 // I2C address of PCA9555 #1 #define PCA9555_ADDRESS_2 0x41 // I2C address of PCA9555 #2 #define PCA9555_INPUT_PORT_0 0x00 // Input port register address of PCA9555 #define PCA9555_OUTPUT_PORT_0 0x02 // Output port register address of PCA9555 #define PCA9555_CONFIG_PORT_0 0x06 // Configuration port register address of PCA9555 I2C_HandleTypeDef hi2c1; // I2C handle // Function prototypes void I2C_Init(void); void PCA9555_Init(uint8_t address); void PCA9555_WritePin(uint8_t address, uint8_t pin, uint8_t value); uint8_t PCA9555_ReadPin(uint8_t address, uint8_t pin); void PCA9555_RetryInit(uint8_t address); int main(void) { HAL_Init(); I2C_Init(); PCA9555_Init(PCA9555_ADDRESS_1); PCA9555_Init(PCA9555_ADDRESS_2); while (1) { // Read the state of pin 0 on PCA9555 #1 uint8_t state = PCA9555_ReadPin(PCA9555_ADDRESS_1, 0); if (state == 0) { // If pin 0 is low, set pin 1 on PCA9555 #2 to high PCA9555_WritePin(PCA9555_ADDRESS_2, 1, 1); } else { // If pin 0 is high, set pin 1 on PCA9555 #2 to low PCA9555_WritePin(PCA9555_ADDRESS_2, 1, 0); } HAL_Delay(100); // Delay for 100ms } } // Initialize the I2C peripheral void I2C_Init(void) { hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 100000; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { Error_Handler(); } } // Initialize the PCA9555 at the specified address void PCA9555_Init(uint8_t address) { // Initialize the configuration port to set all pins as outputs uint8_t config = 0x00; HAL_I2C_Mem_Write(&hi2c1, address, PCA9555_CONFIG_PORT_0, 1, &config, 1, 100); // Initialize the output port to set all pins to low uint8_t output = 0x00; HAL_I2C_Mem_Write(&hi2c1, address, PCA9555_OUTPUT_PORT_0, 1, &output, 1, 100); } // Write the specified value to the specified pin on the PCA9555 at the specified address void PCA9555_WritePin(uint8_t address, uint8_t pin, uint8_t value) { uint8_t output = 0x00; HAL_I2C_Mem_Read(&hi2c1, address, PCA9555_OUTPUT_PORT_0, 1, &output, 1, 100); // Set the specified pin to the specified value if (value == 0) { output &= ~(1 << pin); } else { output |= (1 << pin); } // Write the updated output value to the PCA9555 uint8_t data[2] = { PCA9555_OUTPUT_PORT_0, output }; if (HAL_I2C_Master_Transmit(&hi2c1, address, data, 2, 100) != HAL_OK) { // If there is an error, retry initializing the PCA9555 PCA9555_RetryInit(address); } } // Read the state of the specified pin on the PCA9555 at the specified address uint8_t PCA9555_ReadPin(uint8_t address, uint8_t pin) { uint8_t input = 0x00; if (HAL_I2C_Mem_Read(&hi2c1, address, PCA9555_INPUT_PORT_0, 1, &input, 1, 100) != HAL_OK) { // If there is an error, retry initializing the PCA9555 PCA9555_RetryInit(address); return 0; } return (input >> pin) & 0x01; } // Retry initializing the PCA9555 at the specified address void PCA9555_RetryInit(uint8_t address) { // Clear the I2C error flags and reset the I2C peripheral __HAL_I2C_CLEAR_FLAG(&hi2c1, I2C_FLAG_AF | I2C_FLAG_ARLO | I2C_FLAG_BERR); HAL_I2C_DeInit(&hi2c1); HAL_Delay(100); HAL_I2C_Init(&hi2c1); // Re-initialize the PCA9555 PCA9555_Init(address); } ``` 这段代码中,需要注意以下几个点: - 在 `I2C_Init()` 函数中初始化了 I2C1 的参数,并初始化了 I2C 外设。 - `PCA9555_Init()` 函数用于初始化 PCA9555 芯片。首先将配置端口全部设置为输出模式,然后将输出端口全部设置为低电平。 - `PCA9555_WritePin()` 函数用于向 PCA9555 芯片的指定引脚写入指定值。函数首先读取当前输出状态,然后根据参数设置需要修改的引脚状态,最后将更新后的输出状态写入 PCA9555 芯片。如果写入过程中发生错误,函数会调用 `PCA9555_RetryInit()` 函数重新初始化 PCA9555 芯片。 - `PCA9555_ReadPin()` 函数用于读取 PCA9555 芯片的指定引脚状态。函数首先读取输入状态,并根据参数返回指定引脚的状态。如果读取过程中发生错误,函数会调用 `PCA9555_RetryInit()` 函数重新初始化 PCA9555 芯片。 - `PCA9555_RetryInit()` 函数用于重新初始化 PCA9555 芯片。函数首先清除外设的 I2C 错误标志,并重置 I2C 外设。然后调用 `PCA9555_Init()` 函数重新初始化 PCA9555 芯片。

相关推荐

以下是基于HAL库的STM32F4 DMA方式I2C驱动的示例代码,可以读写两个PCA9555芯片,并且具有读写容错功能与操作PCA9555输出PIN脚电平功能。如果连续多次出现错误,代码将重新初始化PCA9555芯片: c #include "stm32f4xx_hal.h" #define PCA9555_I2C_ADDRESS_1 0x40 #define PCA9555_I2C_ADDRESS_2 0x41 #define PCA9555_INPUT_PORT_REGISTER 0x00 #define PCA9555_OUTPUT_PORT_REGISTER 0x01 #define PCA9555_POLARITY_INVERSION_REGISTER 0x02 #define PCA9555_CONFIGURATION_REGISTER 0x03 #define PCA9555_PIN_0 0x01 #define PCA9555_PIN_1 0x02 #define PCA9555_PIN_2 0x04 #define PCA9555_PIN_3 0x08 #define PCA9555_PIN_4 0x10 #define PCA9555_PIN_5 0x20 #define PCA9555_PIN_6 0x40 #define PCA9555_PIN_7 0x80 #define PCA9555_MAX_ERRORS 5 I2C_HandleTypeDef hi2c; uint8_t pca9555_1_input_port = 0; uint8_t pca9555_1_output_port = 0; uint8_t pca9555_1_polarity_inversion = 0; uint8_t pca9555_1_configuration = 0; uint8_t pca9555_2_input_port = 0; uint8_t pca9555_2_output_port = 0; uint8_t pca9555_2_polarity_inversion = 0; uint8_t pca9555_2_configuration = 0; uint8_t error_count = 0; void PCA9555_Init(I2C_HandleTypeDef *hi2c, uint8_t i2c_address) { uint8_t data[2]; // Configure PCA9555 data[0] = PCA9555_CONFIGURATION_REGISTER; data[1] = 0x00; // All pins are configured as outputs HAL_I2C_Master_Transmit(hi2c, i2c_address, data, 2, 100); // Set all pins to low data[0] = PCA9555_OUTPUT_PORT_REGISTER; data[1] = 0x00; HAL_I2C_Master_Transmit(hi2c, i2c_address, data, 2, 100); } void PCA9555_Write(I2C_HandleTypeDef *hi2c, uint8_t i2c_address, uint8_t data) { uint8_t result; uint8_t retries = 0; while (retries < 3) { result = HAL_I2C_Master_Transmit(hi2c, i2c_address, &data, 1, 100); if (result == HAL_OK) { error_count = 0; break; } retries++; } if (retries >= 3) { error_count++; if (error_count >= PCA9555_MAX_ERRORS) { error_count = 0; PCA9555_Init(hi2c, i2c_address); } } } uint8_t PCA9555_Read(I2C_HandleTypeDef *hi2c, uint8_t i2c_address) { uint8_t result; uint8_t data[1]; uint8_t retries = 0; while (retries < 3) { result = HAL_I2C_Master_Receive(hi2c, i2c_address, data, 1, 100); if (result == HAL_OK) { error_count = 0; return data[0]; } retries++; } if (retries >= 3) { error_count++; if (error_count >= PCA9555_MAX_ERRORS) { error_count = 0; PCA9555_Init(hi2c, i2c_address); } } return 0; } void PCA9555_SetPin(I2C_HandleTypeDef *hi2c, uint8_t i2c_address, uint8_t pin) { pca9555_output_port |= pin; PCA9555_Write(hi2c, i2c_address, pca9555_output_port); } void PCA9555_ClearPin(I2C_HandleTypeDef *hi2c, uint8_t i2c_address, uint8_t pin) { pca9555_output_port &= ~pin; PCA9555_Write(hi2c, i2c_address, pca9555_output_port); } void PCA9555_TogglePin(I2C_HandleTypeDef *hi2c, uint8_t i2c_address, uint8_t pin) { pca9555_output_port ^= pin; PCA9555_Write(hi2c, i2c_address, pca9555_output_port); } int main(void) { // Initialize HAL library HAL_Init(); // Initialize I2C peripheral __HAL_RCC_GPIOB_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); __HAL_RCC_I2C1_CLK_ENABLE(); hi2c.Instance = I2C1; hi2c.Init.ClockSpeed = 100000; hi2c.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c.Init.OwnAddress1 = 0; hi2c.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c.Init.OwnAddress2 = 0; hi2c.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; HAL_I2C_Init(&hi2c); // Initialize PCA9555 chips PCA9555_Init(&hi2c, PCA9555_I2C_ADDRESS_1); PCA9555_Init(&hi2c, PCA9555_I2C_ADDRESS_2); while (1) { // Read input port of PCA9555 #1 pca9555_1_input_port = PCA9555_Read(&hi2c, PCA9555_I2C_ADDRESS_1); // Write output port of PCA9555 #1 PCA9555_Write(&hi2c, PCA9555_I2C_ADDRESS_1, pca9555_1_output_port); // Read input port of PCA9555 #2 pca9555_2_input_port = PCA9555_Read(&hi2c, PCA9555_I2C_ADDRESS_2); // Write output port of PCA9555 #2 PCA9555_Write(&hi2c, PCA9555_I2C_ADDRESS_2, pca9555_2_output_port); } } 在上述示例代码中,我们通过使用 HAL库中的I2C API,实现了对PCA9555芯片的初始化、读取和写入操作。为了确保代码稳定性,我们增加了错误计数器,并在出现多次错误时重新初始化PCA9555芯片。此外,我们还实现了在输出端口上设置、清除或翻转单个引脚的功能。
以下是基于HAL库的STM32F4 I2C驱动的示例代码,包含了对两个PCA9555芯片的读写操作,并且具有容错功能,出错时会重新初始化PCA9555芯片。 c #include "stm32f4xx_hal.h" #define PCA9555_I2C_ADDRESS_1 0x20 #define PCA9555_I2C_ADDRESS_2 0x21 I2C_HandleTypeDef hi2c1; void I2C1_Init(void) { hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 100000; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { Error_Handler(); } } HAL_StatusTypeDef PCA9555_WriteByte(I2C_HandleTypeDef *hi2c, uint8_t address, uint8_t reg, uint8_t data) { HAL_StatusTypeDef status; uint8_t buffer[2]; uint16_t timeout = 0; buffer[0] = reg; buffer[1] = data; do { status = HAL_I2C_Mem_Write(hi2c, address, reg, 1, buffer + 1, 1, 1000); if (status != HAL_OK) { HAL_I2C_DeInit(hi2c); HAL_I2C_Init(hi2c); timeout++; } } while ((status != HAL_OK) && (timeout < 3)); if (timeout >= 3) { return HAL_ERROR; } return HAL_OK; } HAL_StatusTypeDef PCA9555_ReadByte(I2C_HandleTypeDef *hi2c, uint8_t address, uint8_t reg, uint8_t *data) { HAL_StatusTypeDef status; uint16_t timeout = 0; do { status = HAL_I2C_Mem_Read(hi2c, address, reg, 1, data, 1, 1000); if (status != HAL_OK) { HAL_I2C_DeInit(hi2c); HAL_I2C_Init(hi2c); timeout++; } } while ((status != HAL_OK) && (timeout < 3)); if (timeout >= 3) { return HAL_ERROR; } return HAL_OK; } void PCA9555_Init(I2C_HandleTypeDef *hi2c, uint8_t address) { PCA9555_WriteByte(hi2c, address, 0x06, 0x00); PCA9555_WriteByte(hi2c, address, 0x07, 0x00); } int main(void) { HAL_Init(); I2C1_Init(); PCA9555_Init(&hi2c1, PCA9555_I2C_ADDRESS_1); PCA9555_Init(&hi2c1, PCA9555_I2C_ADDRESS_2); uint8_t value; PCA9555_ReadByte(&hi2c1, PCA9555_I2C_ADDRESS_1, 0x00, &value); PCA9555_WriteByte(&hi2c1, PCA9555_I2C_ADDRESS_2, 0x01, value); while (1) { } } 在上面的代码中,我们首先初始化了I2C1总线,并定义了两个PCA9555芯片的地址。然后,我们定义了两个函数PCA9555_ReadByte()和PCA9555_WriteByte(),分别用于读和写PCA9555芯片的寄存器。这些函数还包含了容错功能,即在写或读操作失败时,会重新初始化PCA9555芯片。 最后,在主函数中,我们调用了PCA9555_Init()函数对两个PCA9555芯片进行初始化,并且读取了第一个PCA9555的第0个寄存器的值,并将其写入第二个PCA9555的第1个寄存器。 请注意,上述示例代码是基于HAL库的,因此需要在使用前将其添加到您的项目中。
以下是一个基于HAL库的STM32F4 I2C驱动的示例代码,可以读写两个PCA9555芯片,并且具有容错功能与操作PCA9555输出PIN脚电平功能。如果出现错误,代码将重新初始化PCA9555芯片。此代码需要使用I2C2总线来连接PCA9555芯片。 c #include "stm32f4xx_hal.h" #define PCA9555_ADDRESS_1 0x40 #define PCA9555_ADDRESS_2 0x41 I2C_HandleTypeDef hi2c2; void PCA9555_Write(I2C_HandleTypeDef *hi2c, uint8_t address, uint8_t reg, uint8_t value) { uint8_t data[2]; data[0] = reg; data[1] = value; while (HAL_I2C_Master_Transmit(hi2c, address, data, 2, 1000) != HAL_OK) { if (HAL_I2C_GetError(hi2c) != HAL_I2C_ERROR_AF) { /* Reinitialize I2C */ HAL_I2C_DeInit(hi2c); HAL_I2C_Init(hi2c); } } } uint8_t PCA9555_Read(I2C_HandleTypeDef *hi2c, uint8_t address, uint8_t reg) { uint8_t value; while (HAL_I2C_Master_Transmit(hi2c, address, ®, 1, 1000) != HAL_OK) { if (HAL_I2C_GetError(hi2c) != HAL_I2C_ERROR_AF) { /* Reinitialize I2C */ HAL_I2C_DeInit(hi2c); HAL_I2C_Init(hi2c); } } while (HAL_I2C_Master_Receive(hi2c, address, &value, 1, 1000) != HAL_OK) { if (HAL_I2C_GetError(hi2c) != HAL_I2C_ERROR_AF) { /* Reinitialize I2C */ HAL_I2C_DeInit(hi2c); HAL_I2C_Init(hi2c); } } return value; } void PCA9555_SetOutput(I2C_HandleTypeDef *hi2c, uint8_t address, uint8_t pin, uint8_t level) { uint8_t reg = PCA9555_OUTPUT; uint8_t value = PCA9555_Read(hi2c, address, reg); if (level == 0) { value &= ~(1 << pin); } else { value |= (1 << pin); } PCA9555_Write(hi2c, address, reg, value); } int main(void) { /* Initialize I2C2 */ hi2c2.Instance = I2C2; hi2c2.Init.ClockSpeed = 400000; hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c2.Init.OwnAddress1 = 0; hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c2.Init.OwnAddress2 = 0; hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c2) != HAL_OK) { /* Initialization Error */ while (1); } /* Write to PCA9555 #1 */ PCA9555_Write(&hi2c2, PCA9555_ADDRESS_1, PCA9555_OUTPUT, 0xAA); /* Read from PCA9555 #1 */ uint8_t value = PCA9555_Read(&hi2c2, PCA9555_ADDRESS_1, PCA9555_INPUT); /* Set Output pin #0 on PCA9555 #2 to high */ PCA9555_SetOutput(&hi2c2, PCA9555_ADDRESS_2, 0, 1); while (1); } 请注意,此示例代码中的错误处理程序仅尝试重新初始化I2C总线以解决故障。在实际应用中,您可能需要更复杂的错误处理机制,例如记录错误并在发生多个错误时采取更严格的措施。
以下是基于HAL库的STM32F4 + DMA方式I2C驱动的示例代码,可以读写两个PCA9555芯片,并且具有读写容错功能与操作PCA9555输出PIN脚电平功能。如果连续多次出现错误,代码将重新初始化PCA9555芯片: c /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "i2c.h" #include "gpio.h" #include <stdbool.h> /* Private variables ---------------------------------------------------------*/ #define PCA9555_ADDR_0 0x40 // I2C address of PCA9555 #0 #define PCA9555_ADDR_1 0x42 // I2C address of PCA9555 #1 #define PCA9555_INPUT_PORT_REG 0x00 // Input port register address #define PCA9555_OUTPUT_PORT_REG 0x02 // Output port register address #define PCA9555_POLARITY_INVERSION_REG 0x04 // Polarity inversion register address #define PCA9555_CONFIGURATION_REG 0x06 // Configuration register address #define PCA9555_RESET_TRIES 10 // Number of times to reset PCA9555 before giving up #define PCA9555_RESET_DELAY_MS 10 // Delay in ms between PCA9555 reset attempts typedef struct { uint8_t address; bool initialized; uint8_t output_port_state; uint8_t read_tries; uint8_t write_tries; } PCA9555; PCA9555 pca9555[2] = { {PCA9555_ADDR_0, false, 0x00, 0, 0}, {PCA9555_ADDR_1, false, 0x00, 0, 0} }; /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* Private user code ---------------------------------------------------------*/ void PCA9555_Init(PCA9555 *pca) { uint8_t data[] = {PCA9555_CONFIGURATION_REG, 0x00}; // Configure all pins as outputs HAL_I2C_Master_Transmit_DMA(&hi2c1, pca->address, data, sizeof(data)); HAL_Delay(5); pca->initialized = true; } uint8_t PCA9555_Read_Input_Port(PCA9555 *pca) { uint8_t data = 0x00; if (HAL_I2C_Master_Transmit_DMA(&hi2c1, pca->address, &PCA9555_INPUT_PORT_REG, sizeof(PCA9555_INPUT_PORT_REG)) == HAL_OK && HAL_I2C_Master_Receive_DMA(&hi2c1, pca->address, &data, sizeof(data)) == HAL_OK) { pca->read_tries = 0; return data; } else { pca->read_tries++; if (pca->read_tries >= PCA9555_RESET_TRIES) { pca->initialized = false; PCA9555_Init(pca); } return 0xFF; } } bool PCA9555_Write_Output_Port(PCA9555 *pca, uint8_t data) { if (HAL_I2C_Master_Transmit_DMA(&hi2c1, pca->address, &(uint8_t){PCA9555_OUTPUT_PORT_REG}, sizeof(PCA9555_OUTPUT_PORT_REG)) == HAL_OK && HAL_I2C_Master_Transmit_DMA(&hi2c1, pca->address, &data, sizeof(data)) == HAL_OK) { pca->write_tries = 0; pca->output_port_state = data; return true; } else { pca->write_tries++; if (pca->write_tries >= PCA9555_RESET_TRIES) { pca->initialized = false; PCA9555_Init(pca); } return false; } } void PCA9555_Set_Pin_Level(PCA9555 *pca, uint8_t pin, bool level) { uint8_t data = pca->output_port_state; if (level) { data |= (1 << pin); } else { data &= ~(1 << pin); } PCA9555_Write_Output_Port(pca, data); } /* Main function -------------------------------------------------------------*/ int main(void) { /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_I2C1_Init(); /* Infinite loop */ while (1) { for (int i = 0; i < 2; i++) { if (!pca9555[i].initialized) { PCA9555_Init(&pca9555[i]); } uint8_t input_port_state = PCA9555_Read_Input_Port(&pca9555[i]); if (input_port_state != 0xFF) { uint8_t output_port_state = pca9555[i].output_port_state; for (int j = 0; j < 8; j++) { bool input_pin_state = input_port_state & (1 << j); bool output_pin_state = output_port_state & (1 << j); if (input_pin_state != output_pin_state) { PCA9555_Set_Pin_Level(&pca9555[i], j, input_pin_state); } } } } HAL_Delay(10); } } /* System Clock Configuration--------------------------------------------------*/ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 8; RCC_OscInitStruct.PLL.PLLN = 360; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 7; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(); } } 在此示例代码中,我们定义了一个名为PCA9555的结构体来存储与PCA9555芯片相关的信息。其中包括I2C地址、是否已初始化、输出端口状态、读取失败次数和写入失败次数。我们还定义了两个PCA9555结构体实例pca9555[0]和pca9555[1],分别代表两个PCA9555芯片。在main函数中,我们使用了一个无限循环,不断读取和写入两个PCA9555芯片。 在PCA9555_Init函数中,我们配置了所有引脚作为输出。在PCA9555_Read_Input_Port函数中,我们尝试读取输入端口寄存器的值,并返回读取的值。如果读取失败,则增加读取失败次数。如果读取失败次数达到了PCA9555_RESET_TRIES,则将initialized标志设置为false,并重新初始化PCA9555芯片。在PCA9555_Write_Output_Port函数中,我们尝试写入数据到输出端口寄存器,并返回写入是否成功的布尔值。如果写入失败,则增加写入失败次数。如果写入失败次数达到了PCA9555_RESET_TRIES,则将initialized标志设置为false,并重新初始化PCA9555芯片。在PCA9555_Set_Pin_Level函数中,我们根据传递的引脚和电平设置输出端口的状态。 最后,在main函数的无限循环中,我们轮流读取和写入两个PCA9555芯片,如果出现错误,则尝试重新初始化PCA9555芯片。我们使用HAL_Delay函数来添加延迟,以避免频繁读写I2C总线。

最新推荐

数字化实验优缺点.pdf

数字化实验优缺点.pdf

软件测试方案.pdf

软件测试方案.pdf

在线手写签名认证算法的研究.docx

在线手写签名认证算法的研究.docx

会话控制-所谓会话控制就是 对会话进行控制 HTTP 是一种无状态的协议,它没有办法区分多次的请求是否来自于同一个客户端, 无

会话控制-所谓会话控制就是 对会话进行控制 HTTP 是一种无状态的协议,它没有办法区分多次的请求是否来自于同一个客户端, 无

教师信息化教学能力实践分析.docx

教师信息化教学能力实践分析.docx

代码随想录最新第三版-最强八股文

这份PDF就是最强⼋股⽂! 1. C++ C++基础、C++ STL、C++泛型编程、C++11新特性、《Effective STL》 2. Java Java基础、Java内存模型、Java面向对象、Java集合体系、接口、Lambda表达式、类加载机制、内部类、代理类、Java并发、JVM、Java后端编译、Spring 3. Go defer底层原理、goroutine、select实现机制 4. 算法学习 数组、链表、回溯算法、贪心算法、动态规划、二叉树、排序算法、数据结构 5. 计算机基础 操作系统、数据库、计算机网络、设计模式、Linux、计算机系统 6. 前端学习 浏览器、JavaScript、CSS、HTML、React、VUE 7. 面经分享 字节、美团Java面、百度、京东、暑期实习...... 8. 编程常识 9. 问答精华 10.总结与经验分享 ......

事件摄像机的异步事件处理方法及快速目标识别

934}{基于图的异步事件处理的快速目标识别Yijin Li,Han Zhou,Bangbang Yang,Ye Zhang,Zhaopeng Cui,Hujun Bao,GuofengZhang*浙江大学CAD CG国家重点实验室†摘要与传统摄像机不同,事件摄像机捕获异步事件流,其中每个事件编码像素位置、触发时间和亮度变化的极性。在本文中,我们介绍了一种新的基于图的框架事件摄像机,即SlideGCN。与最近一些使用事件组作为输入的基于图的方法不同,我们的方法可以有效地逐个事件处理数据,解锁事件数据的低延迟特性,同时仍然在内部保持图的结构。为了快速构建图,我们开发了一个半径搜索算法,该算法更好地利用了事件云的部分正则结构,而不是基于k-d树的通用方法。实验表明,我们的方法降低了计算复杂度高达100倍,相对于当前的基于图的方法,同时保持最先进的性能上的对象识别。此外,我们验证了我们的方�

下半年软件开发工作计划应该分哪几个模块

通常来说,软件开发工作可以分为以下几个模块: 1. 需求分析:确定软件的功能、特性和用户需求,以及开发的目标和约束条件。 2. 设计阶段:根据需求分析的结果,制定软件的架构、模块和接口设计,确定开发所需的技术和工具。 3. 编码实现:根据设计文档和开发计划,实现软件的各项功能和模块,编写测试用例和文档。 4. 测试阶段:对软件进行各种测试,包括单元测试、集成测试、功能测试、性能测试、安全测试等,确保软件的质量和稳定性。 5. 发布和部署:将软件打包发布,并进行部署和安装,确保用户可以方便地使用软件。 6. 维护和更新:对软件进行维护和更新,修复漏洞和Bug,添加新的特性和功能,保证

数据结构1800试题.pdf

你还在苦苦寻找数据结构的题目吗?这里刚刚上传了一份数据结构共1800道试题,轻松解决期末挂科的难题。不信?你下载看看,这里是纯题目,你下载了再来私信我答案。按数据结构教材分章节,每一章节都有选择题、或有判断题、填空题、算法设计题及应用题,题型丰富多样,共五种类型题目。本学期已过去一半,相信你数据结构叶已经学得差不多了,是时候拿题来练练手了,如果你考研,更需要这份1800道题来巩固自己的基础及攻克重点难点。现在下载,不早不晚,越往后拖,越到后面,你身边的人就越卷,甚至卷得达到你无法想象的程度。我也是曾经遇到过这样的人,学习,练题,就要趁现在,不然到时你都不知道要刷数据结构题好还是高数、工数、大英,或是算法题?学完理论要及时巩固知识内容才是王道!记住!!!下载了来要答案(v:zywcv1220)。

开集域自适应方法及其在靶点发现中的应用

9322基于开集域自适应的新靶点发现Taotao Jing< $,Hongfu LiuXiang,and Zhengming Ding<$†美国杜兰大学计算机科学系‡美国布兰代斯大学Michtom计算机科学学院网址:tjing@tulane.edu,hongfuliu@brandeis.edu,网址:www.example.com,zding1@tulane.edu摘要开集域自适应算法(OSDA)认为目标域包含了在外部源域中未观察到的新类别的样本不幸的是,现有的OSDA方法总是忽略了看不见的类别的信息的需求,并简单地将它们识别为“未知”集合而没有进一步的这促使我们通过探索底层结构和恢复其不可解释的语义属性来更具体地理解未知类别。在本文中,我们提出了一种新的框架,以准确地识别目标领域中的可见类别,并有效地恢复未见过的类别的语义属性具体而言,结构保持部分对齐开发,通过域不变的特征学习识别看到的基于视觉图的属性传播是为了通过视觉语义映射将可见属�