芯片引脚及描述:
驱动代码:
头文件:nca9555.h
#ifndef USER_APP_NCA9555_H_
#define USER_APP_NCA9555_H_
#include "em_gpio.h"
#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);
#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
#define INPUT_PORT_REGISTER1 0x01
#define OUTPUT_PORT_REGISTER0 0x02
#define OUTPUT_PORT_REGISTER1 0x03
#define POLARITY_INVERSION_PORT_REGISTER0 0x04
#define POLARITY_INVERSION_PORT_REGISTER1 0x05
#define CONFIG_PORT_REGISTER0 0x06
#define CONFIG_PORT_REGISTER1 0x07
#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);
#endif
源文件:nca9555.c
#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_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 1rn"); 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<8;t++) { //printf("rn1 GPIO_PinInGet(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN) = %drn", GPIO_PinInGet(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN)); IIC_SDA_SET_GPIO_OUTPUT_STATUS((txd&0x80)>>7); txd<<=1; sl_udelay_wait(4); IIC_SCL_SET_GPIO_OUTPUT_STATUS(1); sl_udelay_wait(4); IIC_SCL_SET_GPIO_OUTPUT_STATUS(0); sl_udelay_wait(4); } } //读1个字节,ack=1时,发送ACK,ack=0,发送nACK uint8_t IIC_read_byte(unsigned char ack) { unsigned char i,receive=0; IIC_SDA_set_input();//SDA设置为输入 for(i=0;i<8;i++ ) { IIC_SCL_SET_GPIO_OUTPUT_STATUS(0); sl_udelay_wait(4); IIC_SCL_SET_GPIO_OUTPUT_STATUS(1); receive<<=1; if(IIC_SDA_GET_GPIO_INPUT_STATUS)receive++; //printf("rn2 GPIO_PinInGet(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN) = %drn", GPIO_PinInGet(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN)); sl_udelay_wait(4); } if (!ack) IIC_nack();//发送nACK else IIC_ack(); //发送ACK return receive; } void nca9555_init(void) { 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!rn"); IIC_send_byte(command); ret = IIC_wait_ack(); NCA9555_WAIT_IS_RETURN_SUCCESS(ret, "[ERROR] wait slave ack error!rn"); IIC_send_byte(write_register_data); ret = IIC_wait_ack(); NCA9555_WAIT_IS_RETURN_SUCCESS(ret, "[ERROR] wait slave ack error!rn"); IIC_stop(); sl_udelay_wait(10000); return SUCCESS; } 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!rn"); IIC_send_byte(read_register_data); ret = IIC_wait_ack(); NCA9555_WAIT_IS_RETURN_SUCCESS(ret, "[ERROR] wait slave ack error!rn"); IIC_start(); IIC_send_byte(addr); ret = IIC_wait_ack(); NCA9555_WAIT_IS_RETURN_SUCCESS(ret, "[ERROR] wait slave ack error!rn"); *read_data = IIC_read_byte(0); IIC_stop(); return SUCCESS; } 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)); } } 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); } } 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)); } } } 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 > 0x80rn"); 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!rn"); } return gpio_status; }
注:
NCA9555采用IIC通信,协议中涉及的延时函数务必保证精确。
上面代码可直接运行在芯科科技的EFR32BG22中。需要移植到其他的芯片中只需要确定两点:
①GPIO输入输出设置
②精确到us级别的延时函数
将对应的的部分替换掉就可以了。



