NCA9555/PCA9555代码 通用总线IO扩展器芯片驱动

您所在的位置:网站首页 pca9555pw干什么用的 NCA9555/PCA9555代码 通用总线IO扩展器芯片驱动

NCA9555/PCA9555代码 通用总线IO扩展器芯片驱动

2023-11-14 04:54| 来源: 网络整理| 查看: 265

芯片引脚及描述: 在这里插入图片描述 在这里插入图片描述 驱动代码: 头文件:nca9555.h

/* * nca9555.h * * Created on: 2021年11月11日 * Author: lhsmd */ #ifndef USER_APP_NCA9555_H_ #define USER_APP_NCA9555_H_ #include "em_gpio.h" /***************************************************IIC 驱动部门**********************************************************/ #define IIC_SCL_GPIO_PORT gpioPortB #define IIC_SCL_GPIO_PIN 1 #define IIC_SDA_GPIO_PORT gpioPortB #define IIC_SDA_GPIO_PIN 2 #define IIC_SCL_SET_GPIO_OUTPUT_STATUS(status) if(status == 1) GPIO_PinOutSet(IIC_SCL_GPIO_PORT, IIC_SCL_GPIO_PIN);\ else if(status == 0) GPIO_PinOutClear(IIC_SCL_GPIO_PORT, IIC_SCL_GPIO_PIN); #define IIC_SDA_SET_GPIO_OUTPUT_STATUS(status) if(status == 1) GPIO_PinOutSet(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN);\ else if(status == 0) GPIO_PinOutClear(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN); #define IIC_SDA_GET_GPIO_INPUT_STATUS GPIO_PinInGet(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN) void IIC_gpio_init(void); void IIC_start(void); void IIC_stop(void); uint8_t IIC_wait_ack(void); void IIC_ack(void); void IIC_nack(void); void IIC_send_byte(uint8_t txd); void IIC_send_byte(uint8_t txd); uint8_t IIC_read_byte(unsigned char ack); /***********************************************************IIC 驱动 END**********************************************************************/ /************************************************************NCA9555 驱动***********************************************************/ #define SUCCESS 0 #define ERROR 1 #define SLAVE_ADDR0 0x40 #define SLAVE_ADDR1 0x42 #define SLAVE_ADDR2 0x44 #define HOST_WRITE_COMMAND 0x00 #define HOST_READ_COMMAND 0x01 #define INPUT_PORT_REGISTER0 0x00 /* 输入端口寄存器0,负责IO00-IO07 */ #define INPUT_PORT_REGISTER1 0x01 /* 输入端口寄存器1,负责IO10-IO17 */ #define OUTPUT_PORT_REGISTER0 0x02 /* 输入端口寄存器0,负责IO00-IO07 */ #define OUTPUT_PORT_REGISTER1 0x03 /* 输入端口寄存器1,负责IO10-IO17 */ #define POLARITY_INVERSION_PORT_REGISTER0 0x04 /* 输入端口寄存器0,负责IO00-IO07 */ #define POLARITY_INVERSION_PORT_REGISTER1 0x05 /* 输入端口寄存器1,负责IO10-IO17 */ #define CONFIG_PORT_REGISTER0 0x06 /* 输入端口寄存器0,负责IO00-IO07 */ #define CONFIG_PORT_REGISTER1 0x07 /* 输入端口寄存器1,负责IO10-IO17 */ #define GPIO_PORT0 0 #define GPIO_PORT1 1 #define GPIO_0 0x01 #define GPIO_1 0x02 #define GPIO_2 0x04 #define GPIO_3 0x08 #define GPIO_4 0x10 #define GPIO_5 0x20 #define GPIO_6 0x40 #define GPIO_7 0x80 #define NCA9555_WAIT_IS_RETURN_SUCCESS(flag, tips) if(flag != SUCCESS)\ { \ printf("%s", tips); \ return ERROR;\ } void nca9555_init(void); void nca9555_read_wtite_test(void); void nca9555_set_output_mode(uint8_t slave_num, uint8_t gpio_port, uint8_t gpio_num); void nca9555_set_gpio_output_status(uint8_t slave_num, uint8_t gpio_port, uint8_t gpio_num, uint8_t status); void nca9555_set_input_mode(uint8_t slave_num, uint8_t gpio_port, uint8_t gpio_num); uint8_t nca9555_get_gpio_status(uint8_t slave_num, uint8_t gpio_port, uint8_t gpio_num); /************************************************************NCA9555 驱动 END***********************************************************/ #endif /* USER_APP_NCA9555_H_ */

源文件:nca9555.c

/* * nca9555.c * * Created on: 2021年11月11日 * Author: lhsmd */ #include "nca9555.h" #include "sl_udelay.h" #include "em_cmu.h" #include #include "ads1220.h" void IIC_gpio_init(void) { CMU_ClockEnable(cmuClock_GPIO, true); /* 使能GPIO时钟 */ GPIO_PinModeSet(IIC_SCL_GPIO_PORT, IIC_SCL_GPIO_PIN, gpioModePushPull, 1); GPIO_PinModeSet(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN, gpioModePushPull, 1); } static void IIC_SDA_set_output(void) { GPIO_PinModeSet(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN, gpioModePushPull, 1); } static void IIC_SDA_set_input(void) { GPIO_PinModeSet(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN, gpioModeInputPull, 0); } //产生IIC起始信号 void IIC_start(void) { IIC_SDA_set_output(); //sda线输出 IIC_SDA_SET_GPIO_OUTPUT_STATUS(1); IIC_SCL_SET_GPIO_OUTPUT_STATUS(1); sl_udelay_wait(6); IIC_SDA_SET_GPIO_OUTPUT_STATUS(0);//START:when CLK is high,DATA change form high to low sl_udelay_wait(6); IIC_SCL_SET_GPIO_OUTPUT_STATUS(0);//钳住I2C总线,准备发送或接收数据 } //产生IIC停止信号 void IIC_stop(void) { IIC_SDA_set_output();//sda线输出 IIC_SCL_SET_GPIO_OUTPUT_STATUS(0); IIC_SDA_SET_GPIO_OUTPUT_STATUS(0);//STOP:when CLK is high DATA change form low to high sl_udelay_wait(6); IIC_SCL_SET_GPIO_OUTPUT_STATUS(1); IIC_SDA_SET_GPIO_OUTPUT_STATUS(1);//发送I2C总线结束信号 sl_udelay_wait(6); } //等待应答信号到来 //返回值:1,接收应答失败 // 0,接收应答成功 uint8_t IIC_wait_ack(void) { uint8_t ucErrTime=0; IIC_SDA_set_input(); //SDA设置为输入 IIC_SDA_SET_GPIO_OUTPUT_STATUS(1); sl_udelay_wait(1); IIC_SCL_SET_GPIO_OUTPUT_STATUS(1); sl_udelay_wait(1); while(IIC_SDA_GET_GPIO_INPUT_STATUS) { ucErrTime++; sl_udelay_wait(1); if(ucErrTime>250) { IIC_stop(); printf("return 1\r\n"); return 1; } } IIC_SCL_SET_GPIO_OUTPUT_STATUS(0);//时钟输出0 return 0; } //产生ACK应答 void IIC_ack(void) { IIC_SCL_SET_GPIO_OUTPUT_STATUS(0); IIC_SDA_set_output(); IIC_SDA_SET_GPIO_OUTPUT_STATUS(1); sl_udelay_wait(5); IIC_SCL_SET_GPIO_OUTPUT_STATUS(1); sl_udelay_wait(5); IIC_SCL_SET_GPIO_OUTPUT_STATUS(0); } //不产生ACK应答 void IIC_nack(void) { IIC_SCL_SET_GPIO_OUTPUT_STATUS(0); IIC_SDA_set_output(); IIC_SDA_SET_GPIO_OUTPUT_STATUS(1); sl_udelay_wait(5); IIC_SCL_SET_GPIO_OUTPUT_STATUS(1); sl_udelay_wait(5); IIC_SCL_SET_GPIO_OUTPUT_STATUS(0); } //IIC发送一个字节 //返回从机有无应答 //1,有应答 //0,无应答 void IIC_send_byte(uint8_t txd) { uint8_t t; IIC_SDA_set_output(); IIC_SCL_SET_GPIO_OUTPUT_STATUS(0);//拉低时钟开始数据传输 for(t=0;t unsigned char i,receive=0; IIC_SDA_set_input();//SDA设置为输入 for(i=0;i IIC_gpio_init(); } uint8_t nca9555_write_byte(uint8_t addr, uint8_t command, uint8_t write_register_data) { uint8_t ret = 1; IIC_start(); IIC_send_byte(addr); ret = IIC_wait_ack(); NCA9555_WAIT_IS_RETURN_SUCCESS(ret, "[ERROR] wait slave ack error!\r\n"); IIC_send_byte(command); ret = IIC_wait_ack(); NCA9555_WAIT_IS_RETURN_SUCCESS(ret, "[ERROR] wait slave ack error!\r\n"); IIC_send_byte(write_register_data); ret = IIC_wait_ack(); NCA9555_WAIT_IS_RETURN_SUCCESS(ret, "[ERROR] wait slave ack error!\r\n"); IIC_stop(); sl_udelay_wait(10000); return SUCCESS; } /* * nca9555读取寄存器值 * * addr 读取地址 * read_register_data 要读取的寄存器 * read_data 读取数据存放地址 * * * 返回值:读取成功返回SUCCESS 失败返回ERROR * * */ uint8_t nca9555_read_byte(uint8_t slave_num, uint8_t addr, uint8_t read_register_data, uint8_t *read_data) { uint8_t ret = 0; IIC_start(); IIC_send_byte(slave_num); ret = IIC_wait_ack(); NCA9555_WAIT_IS_RETURN_SUCCESS(ret, "[ERROR] wait slave ack error!\r\n"); IIC_send_byte(read_register_data); ret = IIC_wait_ack(); NCA9555_WAIT_IS_RETURN_SUCCESS(ret, "[ERROR] wait slave ack error!\r\n"); IIC_start(); /* 开始接收数据 */ IIC_send_byte(addr); ret = IIC_wait_ack(); NCA9555_WAIT_IS_RETURN_SUCCESS(ret, "[ERROR] wait slave ack error!\r\n"); *read_data = IIC_read_byte(0); IIC_stop(); return SUCCESS; } /* * 设置指定GPIO的模式 * * slave_num 需要操作的从机设备 * gpio_port gpio端口 端口0/1 * gpio_num 哪一个GPIO * * 返回值:void * */ void nca9555_set_output_mode(uint8_t slave_num, uint8_t gpio_port, uint8_t gpio_num) { uint8_t register_original_data = 0; if(gpio_port > 1 || gpio_num > 0x80) return; if(gpio_port == 0) { nca9555_read_byte(slave_num, slave_num | HOST_READ_COMMAND, CONFIG_PORT_REGISTER0, ®ister_original_data); nca9555_write_byte(slave_num | HOST_WRITE_COMMAND, CONFIG_PORT_REGISTER0, register_original_data & (~gpio_num)); } else if(gpio_port == 1) { nca9555_read_byte(slave_num, slave_num | HOST_READ_COMMAND, CONFIG_PORT_REGISTER1, ®ister_original_data); nca9555_write_byte( slave_num | HOST_WRITE_COMMAND, CONFIG_PORT_REGISTER1, register_original_data & (~gpio_num)); } } /* * 设置GPIO为输入模式 * * slave_num 需要操作的从机设备 * gpio_port gpio端口 端口0/1 * gpio_num 哪一个GPIO * * 返回值:void **/ void nca9555_set_input_mode(uint8_t slave_num, uint8_t gpio_port, uint8_t gpio_num) { uint8_t register_original_data = 0; if(gpio_port > 1 || gpio_num > 0x80) return; if(gpio_port == 0) { nca9555_read_byte(slave_num, slave_num | HOST_READ_COMMAND, CONFIG_PORT_REGISTER0, ®ister_original_data); nca9555_write_byte(slave_num | HOST_WRITE_COMMAND, CONFIG_PORT_REGISTER0, register_original_data & gpio_num); } else if(gpio_port == 1) { nca9555_read_byte(slave_num, slave_num | HOST_READ_COMMAND, CONFIG_PORT_REGISTER1, ®ister_original_data); nca9555_write_byte(slave_num | HOST_WRITE_COMMAND, CONFIG_PORT_REGISTER1, register_original_data & gpio_num); } } /* * 设置GPIO输出状态 * * slave_num 需要操作的从机设备 * gpio_port gpio端口 端口0/1 * gpio_num 哪一个GPIO * status 输出状态 * * 返回值:void **/ void nca9555_set_gpio_output_status(uint8_t slave_num, uint8_t gpio_port, uint8_t gpio_num, uint8_t status) { uint8_t register_original_data = 0; if(gpio_port > 1 || gpio_num > 0x80) return; if(gpio_port == 0) { nca9555_read_byte(slave_num, slave_num | HOST_READ_COMMAND, OUTPUT_PORT_REGISTER0, ®ister_original_data); if(status == 1) { nca9555_write_byte(slave_num | HOST_WRITE_COMMAND, OUTPUT_PORT_REGISTER0, register_original_data | gpio_num); } else { nca9555_write_byte(slave_num | HOST_WRITE_COMMAND, OUTPUT_PORT_REGISTER0, register_original_data & (~gpio_num)); } } else if(gpio_port == 1) { nca9555_read_byte(slave_num, slave_num | HOST_READ_COMMAND, OUTPUT_PORT_REGISTER1, ®ister_original_data); if(status == 1) { nca9555_write_byte(slave_num | HOST_WRITE_COMMAND, OUTPUT_PORT_REGISTER1, register_original_data | gpio_num); } else { nca9555_write_byte(slave_num | HOST_WRITE_COMMAND, OUTPUT_PORT_REGISTER1, register_original_data & (~gpio_num)); } } } /* * 获取GPIO状态 * * slave_num 需要操作的从机设备 * gpio_port gpio端口 端口0/1 * gpio_num 哪一个GPIO * * 返回值:GPIO状态 **/ uint8_t nca9555_get_gpio_status(uint8_t slave_num, uint8_t gpio_port, uint8_t gpio_num) { uint8_t register_original_data = 0; uint8_t gpio_status = 0; if(gpio_port > 1 || gpio_num > 0x80) { printf("[ERROR] gpio_port > 1 || gpio_num > 0x80\r\n"); return 2; } if(gpio_port == 0) { nca9555_read_byte(slave_num, slave_num | HOST_READ_COMMAND, INPUT_PORT_REGISTER0, ®ister_original_data); } else if(gpio_port == 1) { nca9555_read_byte(slave_num, slave_num | HOST_READ_COMMAND, INPUT_PORT_REGISTER1, ®ister_original_data); } switch(gpio_num) { case 0x01: gpio_status = register_original_data & gpio_num;break; case 0x02: gpio_status = (register_original_data & gpio_num) >> 1;break; case 0x04: gpio_status = (register_original_data & gpio_num) >> 2;break; case 0x08: gpio_status = (register_original_data & gpio_num) >> 3;break; case 0x10: gpio_status = (register_original_data & gpio_num) >> 4;break; case 0x20: gpio_status = (register_original_data & gpio_num) >> 5;break; case 0x40: gpio_status = (register_original_data & gpio_num) >> 6;break; case 0x80: gpio_status = (register_original_data & gpio_num) >> 7;break; default: printf("[ERROR] gpio error!\r\n"); } return gpio_status; }

注: NCA9555采用IIC通信,协议中涉及的延时函数务必保证精确。 上面代码可直接运行在芯科科技的EFR32BG22中。需要移植到其他的芯片中只需要确定两点: ①GPIO输入输出设置 ②精确到us级别的延时函数 将对应的的部分替换掉就可以了。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3