笔者在进行一个项目开发时用到了PCA9536这款芯片,在进行驱动开发时找了好几家的手册,这些芯片厂家的手册对于芯片的说明根本不详细,看似说了很多,结果却是开发人员看不出来这个芯片的驱动到底怎么设计。最后的最后,找到了NXP家的手册,才看懂这个芯片的驱动逻辑。点名表扬NXP。
PS:呼吁芯片生产厂家将自家芯片驱动的开发逻辑画个流程图,方便使用芯片的开发者快速了解。芯片不只有硬件指标,开发驱动也是重点。
言归正传,在进行PCA9536驱动开发时,手册关于读写寄存器的描述如下图所示:
手册连接:https://www.nxp.com.cn/docs/en/data-sheet/PCA9536.pdf
根据手册描述可以得出驱动开发的流程如下:
案例:笔者开发需要设置为端口输出,当某个条件达到时令GPIO1和2置1或置0。
开发源码如下:
#define PCA9536_Addr 0x82
void PCA9536_init(void)
{
// ESP_ERROR_CHECK(my_i2c_init());//如果在其它地方进行过I2C初始化,这个地方就注释掉,如果没有就自己写一个I2C初始化
PCA9536_readCmd(my_i2c_mum_0,PCA9536_Addr,0X00);//所有的GPIO设置为输出
PCA9536_readData(my_i2c_mum_0,PCA9536_Addr,0X00);//所有的GPIO设置为0
ESP_LOGI(TAG,"PCA9536 OK");
}
/**
* @brief 主机向PCA9536发送指令
*
* @param i2c_port_mum
* @param slaveAddr
* @param byte
* @return esp_err_t
*/
esp_err_t PCA9536_readCmd(i2c_port_t i2c_port_mum,uint8_t slaveAddr, uint8_t byte)
{
esp_err_t err;
i2c_cmd_handle_t my_cmd = i2c_cmd_link_create();
i2c_master_start(my_cmd);
i2c_master_write_byte(my_cmd , slaveAddr,ACK_CHECK_EN);
i2c_master_write_byte(my_cmd,0x03,ACK_CHECK_EN);
i2c_master_write_byte(my_cmd,byte,ACK_CHECK_EN);
i2c_master_stop(my_cmd);
err = i2c_master_cmd_begin(i2c_port_mum, my_cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(my_cmd);
return err;
}
/**
* @brief 主机向 PCA9536发送数据
*
* @param i2c_port_mum
* @param slaveAddr
* @param byte
* @return esp_err_t
*/
esp_err_t PCA9536_readData(i2c_port_t i2c_port_mum,uint8_t slaveAddr, uint8_t byte)
{
esp_err_t err;
i2c_cmd_handle_t my_cmd = i2c_cmd_link_create();
i2c_master_start(my_cmd);
i2c_master_write_byte(my_cmd , slaveAddr,ACK_CHECK_EN);
i2c_master_write_byte(my_cmd,0x01,ACK_CHECK_EN);
i2c_master_write_byte(my_cmd,byte,ACK_CHECK_EN);
i2c_master_stop(my_cmd);
err = i2c_master_cmd_begin(i2c_port_mum, my_cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(my_cmd);
return err;
}
需要特别注意:
每次设置GPIO端口的值之前最好再进行端口设置;
例如:
PCA9536_readCmd(my_i2c_mum_0,PCA9536_Addr,0X00);//所有的GPIO设置为输出
PCA9536_readData(my_i2c_mum_0,PCA9536_Addr,0X03);//所有的GPIO1和2设置为1,GPIO3和4设置为0。
在其它地方再设置:
PCA9536_readCmd(my_i2c_mum_0,PCA9536_Addr,0X00);//所有的GPIO设置为输出
PCA9536_readData(my_i2c_mum_0,PCA9536_Addr,0X01);//所有的GPIO1设置为1,GPIO2、3和4设置为0。