物联网硬件设计时IO不够用?IO扩展芯片的使用

电子说

1.3w人已加入

描述

一 概述

XL9535是一款24引脚CMOS器件,通过I²C总线/SMBus接口 串行时钟线(SCL)、串行数据(SDA)为大多数微控制器系列提供16位通用并行输入/输出(GPIO)扩展。这些设备设计用于2.3-V至5.5-V Vcc操作。这些改进包括更高的驱动能力、5V I/O容差、更低的电源电流、单独的I/O配置和更小的封装。 通电时,I/O被配置为输入。系统主机可以通过写入I/O配置位来启用I/O作为输入或输出。每个输入或输出的数据都保存在相应的输入或输出寄存器中。输入端口寄存器的极性可以用极性反转寄存器反转。所有寄存器均可由系统主控器读取。 当任何输入状态与其对应的输入端口寄存器状态不同时,这些设备开漏中断(/INT)输出被激活,并用于向系统主机指示输入状态已改变。在超时或其他不当操作的情况下,系统主设备可以利用上电重置功能重置这些设备。通电重置将寄存器设置为默认值,并初始化I²C/SMBus状态机。三个硬件引脚(A0、A1和A2)改变固定的I²C总线地址,并允许多达八个设备共享同一I²C总线/SMBus。

二 特性

I²C总线至16位GPIO扩展器

工作电源电压范围为2.3 V至5.5 V

低待机电流消耗

5 V容错I/O端口

400 kHz快速模式I²C总线时钟频率

SCL/SDA输入上的噪声滤波器

内部通电复位

通电时无故障

极性反转寄存器

开漏有源低中断输出

16个I/O引脚,默认为16个输入

三 引脚配置和功能

物联网

物联网

四 功能框图

物联网

五 XL9535组件的使用

1 Gitee链接地址

Demo位于amaziot_bloom_os_sdksample3rd1.0_XL9535

Gitee源码地址:https://gitee.com/ning./hongdou

Github源码地址:https://github.com/ayumid/hongdou

编译指令:.build.bat -l .amaziot_bloom_os_sdksample3rd1.0_XL9535

2 组件功能介绍

  驱动XL9535芯片,实现输入IO检测。

3 代码讲解

1 drv_xl9535_i2c_init

功能:该函数用于,将发送数据长度写入xl9535寄存器。

参数:五

返回值:无

示例:

 

//初始化i2c总线
ret = drv_xl9535_i2c_init();

 

2 drv_xl9535_i2c_read

功能:该函数用于,读取I2C从机。

参数:五

返回值:无

示例:

 

RegAddr       = 0x00;
ret = drv_xl9535_i2c_read(&RegAddr, &RegReadValue0);
sample_xl9535_catstudio_printf("read reg 00 i2c value=0x%x, ret=%dn", RegReadValue0, ret);

 

3 drv_xl9535_i2c_write

功能:该函数用于,发送数据到I2C从机。

参数:五

返回值:无

示例:

 

RegAddr       = 0x06;
RegWriteValue = 0xFF;
ret = drv_xl9535_i2c_write(&RegAddr, &RegReadValue0);
sample_xl9535_catstudio_printf("write i2c value=0x%x, ret=%dn", RegWriteValue, ret);

 

4 Demo实战

4.1 概述

  上电后,按下按键,串口会打印出按下了哪一个按键

4.2 测试

测试步骤:

参考编译教程,和文档开头的编译指令,进行编译

按照编译教程选择对应的选项

烧录

4.3 宏定义介绍

sample_xl9535_uart_printf

输出日志到DEBUG 串口,日志比较少,可以输出到这个串口,如果日志比较多,需要输出到usb口,以免不必要的问题出现

sample_xl9535_catstudio_printf

输出日志到USB 串口,使用catstudio查看,catstudio查看日志需要更新对应版本mdb.txt文件,软件打开filtter过滤日志,只查看用户输出的日志

SAMPLE_XL9535_STACK_SIZE

栈空间宏定义

4.4 全局变量介绍

sample_xl9535_int_detect_stack_ptr

任务栈空间,本例使用数组实现,用户在做项目时,可以预先估算下当先任务需要的大致栈空间,OS没有提供可以查看栈空间使用情况的API

sample_xl9535_int_detect_task_ref

任务指针

4.5 函数介绍

Phase1Inits_enter

底层初始化,本例空

Phase1Inits_exit

底层初始化,本例空

Phase2Inits_enter

底层初始化,本例空

Phase2Inits_exit

创建主任务,初始化INT 引脚

代码片段:

 

int ret = 0;
GPIOConfiguration config = {0};

//创建定时器
OSATimerCreate(&sample_xl9535_int_detect_timer_ref);
//创建中断事件
OSAFlagCreate( &sample_xl9535_int_detect_flg_ref);  
Os_Create_HISR(&sample_xl9535_int_detect_hisr, "sample_xl9535_int_detect_hisr", sample_xl9535_detect_handler, 2);
//创建中断处理任务
OSATaskCreate(&sample_xl9535_int_detect_task_ref, sample_xl9535_int_detect_stack_ptr, SAMPLE_XL9535_STACK_SIZE, 100, "detect_task", sample_xl9535_detect_task, NULL);

//初始化int引脚,这里使用70脚 gpio126
config.pinDir = GPIO_IN_PIN;
config.pinEd = GPIO_RISE_EDGE;
config.pinPull = GPIO_PULLUP_ENABLE;
config.isr = sample_xl9535_irq_handler;
GpioInitConfiguration(SAMPLE_GPIO_ISR_PIN_NUM, config);

 

sample_xl9535_detect_task

主任务,代码发分为两部分,一部分是发送不定长数据;另一部分是上电后等待其它模块发送的数据,收到后打印到串口。

代码片段:

 

void sample_xl9535_detect_task(void *param)
{
    GPIO_ReturnCode ret = 0;
    UINT32 value = 0;
    OSA_STATUS status = OS_SUCCESS;
    UINT32 flag_value = 0;
    unsigned char RegAddr = 0;
    unsigned char RegWriteValue = 0;
    unsigned char RegReadValue0 = 0;
    unsigned char RegReadValue1 = 0;
    UINT8 down_en = 0;
    UINT8 up_en = 0;
    UINT8 sig_en = 0;
    UINT8 mul_en = 0;
    UINT8 read_en = 0;
    UINT8 de_en = 0;
    UINT8 ck_en = 0;
    UINT8 sim_en = 0;
    UINT8 gnss_en = 0;
    UINT8 nb_en = 0;
    UINT8 fourg_en = 0;

    //初始化i2c总线
    ret = drv_xl9535_i2c_init();
    sample_xl9535_catstudio_printf("ql_i2c_init ret %d", ret);

    //上电后,读xl9535 io扩展芯片的8个寄存器,测试用
    RegAddr       = 0x00;
    ret = drv_xl9535_i2c_read(&RegAddr, &RegReadValue0);
    sample_xl9535_catstudio_printf("read reg 00 i2c value=0x%x, ret=%dn", RegReadValue0, ret);
    RegAddr       = 0x01;
    ret = drv_xl9535_i2c_read(&RegAddr, &RegReadValue0);
    sample_xl9535_catstudio_printf("read reg 01 i2c value=0x%x, ret=%dn", RegReadValue0, ret);
    RegAddr       = 0x02;
    ret = drv_xl9535_i2c_read(&RegAddr, &RegReadValue0);
    sample_xl9535_catstudio_printf("read reg 02 i2c value=0x%x, ret=%dn", RegReadValue0, ret);
    RegAddr       = 0x03;
    ret = drv_xl9535_i2c_read(&RegAddr, &RegReadValue0);
    sample_xl9535_catstudio_printf("read reg 03 i2c value=0x%x, ret=%dn", RegReadValue0, ret);
    RegAddr       = 0x04;
    ret = drv_xl9535_i2c_read(&RegAddr, &RegReadValue0);
    sample_xl9535_catstudio_printf("read reg 04 i2c value=0x%x, ret=%dn", RegReadValue0, ret);
    RegAddr       = 0x05;
    ret = drv_xl9535_i2c_read(&RegAddr, &RegReadValue0);
    sample_xl9535_catstudio_printf("read reg 05 i2c value=0x%x, ret=%dn", RegReadValue0, ret);
    RegAddr       = 0x06;
    ret = drv_xl9535_i2c_read(&RegAddr, &RegReadValue0);
    sample_xl9535_catstudio_printf("read reg 06 i2c value=0x%x, ret=%dn", RegReadValue0, ret);
    RegAddr       = 0x07;
    ret = drv_xl9535_i2c_read(&RegAddr, &RegReadValue0);
    sample_xl9535_catstudio_printf("read reg 07 i2c value=0x%x, ret=%dn", RegReadValue0, ret);

    //等1s
    OSATaskSleep(1 * 200);

    //初始化xl0535 io扩展芯片的06 07寄存器,设置所有的io都是输入
    RegAddr       = 0x06;
    RegWriteValue = 0xFF;
    ret = drv_xl9535_i2c_write(&RegAddr, &RegReadValue0);
    sample_xl9535_catstudio_printf("write i2c value=0x%x, ret=%dn", RegWriteValue, ret);
    RegAddr       = 0x07;
    RegWriteValue = 0xFF;
    ret = drv_xl9535_i2c_write(&RegAddr, &RegReadValue0);
    sample_xl9535_catstudio_printf("write i2c value=0x%x, ret=%dn", RegWriteValue, ret);
    
    while(1)
    {
//        sample_xl9535_catstudio_printf("sample_xl9535_detect_taskrn");
        status = OSAFlagWait(sample_xl9535_int_detect_flg_ref, 0x01, OSA_FLAG_OR_CLEAR, &flag_value, OSA_SUSPEND);

        //红豆版,设置了边沿,但是还是会上升沿,下降沿都触发,所以会执行两次
        if(flag_value & 0x01)
        {
            RegAddr       = 0x00;
            //ret = ql_i2c_read(i2c_no, SAMPLE_I2C_SLAVE_ADDR, RegAddr, &RegReadValue0, 1);
            ret = drv_xl9535_i2c_read(&RegAddr, &RegReadValue0);
//            sample_xl9535_catstudio_printf("read reg 00 i2c value=0x%x, ret=%dn", RegReadValue0, ret);
            RegAddr       = 0x01;
            //ret = ql_i2c_read(i2c_no, SAMPLE_I2C_SLAVE_ADDR, RegAddr, &RegReadValue0, 1);
            ret = drv_xl9535_i2c_read(&RegAddr, &RegReadValue1);
//            sample_xl9535_catstudio_printf("read reg 01 i2c value=0x%x, ret=%dn", RegReadValue1, ret);

            //寄存器值非默认值,表示有io输入,否则表示是上升沿中断
            if(RegReadValue0 != 0xff || RegReadValue1 != 0x07)
            {
                event_ticks = OSAGetTicks();
                int_status = 0;

                //判断是那个IO这里使用寄存器值判断,后续可以改为根据位判断
                if(RegReadValue1 == DRV_XL9535_BUTTON_DOWN_EN)
                {
//                    sample_xl9535_catstudio_printf("down int");
                    down_en = 1;
                }
                else if(RegReadValue1 == DRV_XL9535_BUTTON_UP_EN)
                {
//                    sample_xl9535_catstudio_printf("up int");
                    up_en = 1;
                }
                else if(RegReadValue1 == DRV_XL9535_BUTTON_SIG_EN)
                {
//                    sample_xl9535_catstudio_printf("sig int");
                    sig_en = 1;
                }
                else if(RegReadValue0 == DRV_XL9535_BUTTON_MUL_EN)
                {
//                    sample_xl9535_catstudio_printf("mul int");
                    mul_en = 1;
                }
                else if(RegReadValue0 == DRV_XL9535_BUTTON_READ_EN)
                {
//                    sample_xl9535_catstudio_printf("read int");
                    read_en = 1;
                }
                else if(RegReadValue0 == DRV_XL9535_BUTTON_DE_EN)
                {
//                    sample_xl9535_catstudio_printf("de int");
                    de_en = 1;
                }
                else if(RegReadValue0 == DRV_XL9535_BUTTON_CK_EN)
                {
//                    sample_xl9535_catstudio_printf("ck int");
                    ck_en = 1;
                }
                else if(RegReadValue0 == DRV_XL9535_BUTTON_SIM_EN)
                {
//                    sample_xl9535_catstudio_printf("sim int");
                    sim_en = 1;
                }
                else if(RegReadValue0 == DRV_XL9535_BUTTON_GNSS_EN)
                {
//                    sample_xl9535_catstudio_printf("gnss int");
                    gnss_en = 1;
                }
                else if(RegReadValue0 == DRV_XL9535_BUTTON_NB_EN)
                {
//                    sample_xl9535_catstudio_printf("nb int");
                    nb_en = 1;
                }
                else if(RegReadValue0 == DRV_XL9535_BUTTON_4G_EN)
                {
//                    sample_xl9535_catstudio_printf("4g int");
                    fourg_en = 1;
                }
            }
            else
            {
                if(int_status == 0)
                {
                    UINT32 keep_ticks = OSAGetTicks() - event_ticks;
                    
                    if(keep_ticks > 20)
                    {
                        //检测到某个IO被按下后,可以在这里,或者发送信号,消息等去其它任务执行相应操作
//                        sample_xl9535_catstudio_printf("keep_ticks:%d, event_ticks:%d", keep_ticks, event_ticks);
                        if(down_en == 1)
                        {
                            sample_xl9535_catstudio_printf("down en");
                        }
                        else if(up_en == 1)
                        {
                            sample_xl9535_catstudio_printf("up en");
                        }
                        else if(sig_en == 1)
                        {
                            sample_xl9535_catstudio_printf("sig en");
                        }
                        else if(mul_en == 1)
                        {
                            sample_xl9535_catstudio_printf("mul en");
                        }
                        else if(read_en == 1)
                        {
                            sample_xl9535_catstudio_printf("read en");
                        }
                        else if(de_en == 1)
                        {
                            sample_xl9535_catstudio_printf("de en");
                        }
                        else if(ck_en == 1)
                        {
                            sample_xl9535_catstudio_printf("ck en");
                        }
                        else if(sim_en == 1)
                        {
                            sample_xl9535_catstudio_printf("sim en");
                        }
                        else if(gnss_en == 1)
                        {
                            sample_xl9535_catstudio_printf("gnss en");
                        }
                        else if(nb_en == 1)
                        {
                            sample_xl9535_catstudio_printf("nb en");
                        }
                        else if(fourg_en == 1)
                        {
                            sample_xl9535_catstudio_printf("4g en");
                        }
                    }
                    down_en = 0;
                    up_en = 0;
                    sig_en = 0;
                    mul_en = 0;
                    read_en = 0;
                    de_en = 0;
                    ck_en = 0;
                    sim_en = 0;
                    gnss_en = 0;
                    nb_en = 0;
                    fourg_en = 0;
                }
                int_status = 1;
            }
            
        }
    }
}

 

4.6 固件

上电后,按下按键,串口会打印出按下了哪一个按键

物联网

点击下载 Lora Demo固件

本文章源自奇迹物联开源的物联网应用知识库Cellular IoT Wiki,更多技术干货欢迎关注收藏Wiki:Cellular IoT Wiki 知识库(https://rckrv97mzx.feishu.cn/wiki/wikcnBvAC9WOkEYG5CLqGwm6PHf)

欢迎同学们走进AmazIOT知识库的世界!

这里是为物联网人构建的技术应用百科,以便帮助你更快更简单的开发物联网产品。

Cellular IoT Wiki初心:

在我们长期投身于蜂窝物联网 ODM/OEM 解决方案的实践过程中,一直被物联网技术碎片化与产业资源碎片化的问题所困扰。从产品定义、芯片选型,到软硬件研发和测试,物联网技术的碎片化以及产业资源的碎片化,始终对团队的产品开发交付质量和效率形成制约。为了减少因物联网碎片化而带来的重复开发工作,我们着手对物联网开发中高频应用的技术知识进行沉淀管理,并基于 Bloom OS 搭建了不同平台的 RTOS 应用生态。后来我们发现,很多物联网产品开发团队都面临着相似的困扰,于是,我们决定向全体物联网行业开发者开放奇迹物联内部沉淀的应用技术知识库 Wiki,期望能为更多物联网产品开发者减轻一些重复造轮子的负担。

Cellular IoT Wiki沉淀的技术内容方向如下:

物联网

奇迹物联的业务服务范围:基于自研的NB-IoT、Cat1、Cat4等物联网模组,为客户物联网ODM/OEM解决方案服务。我们的研发技术中心在石家庄,PCBA生产基地分布在深圳、石家庄、北京三个工厂,满足不同区域&不同量产规模&不同产品开发阶段的生产制造任务。跟传统PCBA工厂最大的区别是我们只服务物联网行业客户。

连接我们,和10000+物联网开发者一起 降低技术和成本门槛

让蜂窝物联网应用更简单~~

哈哈你终于滑到最重要的模块了,

千万不!要!划!走!忍住冲动!~

欢迎加入飞书“开源技术交流群”,随时找到我们哦~

点击链接如何加入奇迹物联技术话题群(https://rckrv97mzx.feishu.cn/docx/Xskpd1cFQo7hu9x5EuicbsjTnTf)可以获取加入技术话题群攻略

Hey 物联网从业者,

你是否有了解过奇迹物联的官方公众号“eSIM物联工场”呢?

这里是奇迹物联的物联网应用技术开源wiki主阵地,欢迎关注公众号,不迷路~

及时获得最新物联网应用技术沉淀发布

注:本文部分内容来源于网络,如有侵权,请及时联系我们。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分