芯片引脚及描述:
驱动代码:
头文件: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 <stdio.h>
#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<8;t++)
{
//printf("\r\n1 GPIO_PinInGet(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN) = %d\r\n", 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("\r\n2 GPIO_PinInGet(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN) = %d\r\n", 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!\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级别的延时函数
将对应的的部分替换掉就可以了。
版权声明:本文为CSDN博主「LH_SMD」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/LH_SMD/article/details/121354625
芯片引脚及描述:
驱动代码:
头文件: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 <stdio.h>
#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<8;t++)
{
//printf("\r\n1 GPIO_PinInGet(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN) = %d\r\n", 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("\r\n2 GPIO_PinInGet(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN) = %d\r\n", 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!\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级别的延时函数
将对应的的部分替换掉就可以了。
版权声明:本文为CSDN博主「LH_SMD」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/LH_SMD/article/details/121354625
暂无评论