栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

芯片引脚及描述:


驱动代码:
头文件: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级别的延时函数
将对应的的部分替换掉就可以了。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/511221.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号