芯片引脚及描述: 驱动代码: 头文件: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>7);
txd 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级别的延时函数 将对应的的部分替换掉就可以了。
|