0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

jf_94171069 来源:jf_94171069 作者:jf_94171069 2024-09-29 14:10 次阅读

一 概述

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个输入

三 引脚配置和功能

wKgZombztCCAKtW4AAJybxJ7opk654.jpg

wKgaombztCGAQaGQAAHFtrmLsyg144.jpg

四 功能框图

wKgZombztCKALC_7AAD_hu4EAhQ700.jpg

五 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 固件

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

wKgZombztCWAVHb9AABMmTPippQ555.jpg

点击下载 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沉淀的技术内容方向如下:

wKgaombqoM2AYL2RAAQrZ8e-uz8392.jpg

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

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

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

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

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

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

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

Hey 物联网从业者,

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

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

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

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

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

    关注

    451

    文章

    49738

    浏览量

    417748
  • 接口
    +关注

    关注

    33

    文章

    8284

    浏览量

    150072
  • 物联网
    +关注

    关注

    2895

    文章

    43569

    浏览量

    367156
收藏 人收藏

    评论

    相关推荐

    ADC实现一个IO上挂多个按键

    有时候做设计时,我们会遇到外部按键比较多,IO不够用的情况。这时大部分人会考虑通过其它芯片扩展IO
    发表于 09-01 13:25 2722次阅读

    单片机IO扩展实例

    我们在做单片机的小项目时,经常会碰到IO不够用的时候,比如控制多个7段数码管,或者要采集多路AD,要连接多个串口传感器等等。这时,更换单片机不一定是最好的选择,使用其他芯片扩展
    发表于 03-27 14:02 3156次阅读
    单片机<b class='flag-5'>IO</b>口<b class='flag-5'>扩展</b>实例

    利用74373芯片进行单片机IO扩展的方法

    在电路设计的某些时候,微处理器(如单片机)IO不够用了,此时该怎么办呢?利用辅助芯片进行IO扩展是个简单直接的方法,能用较少的成本增多
    的头像 发表于 11-02 14:20 1940次阅读
    利用74373<b class='flag-5'>芯片</b>进行单片机<b class='flag-5'>IO</b>口<b class='flag-5'>扩展</b>的方法

    求图中IO扩展的程序!

    本帖最后由 herochenzhao 于 2012-10-25 19:37 编辑 最近在做一个项目,发现单片机的IO不够用,然后得知如上图可以在节省IO口的情况下进行IO
    发表于 10-25 19:35

    液晶显示,IO不够用怎么办?

    我最近在做一个东西,需要用到3.2英寸的tft屏,但IO不够用了,只剩下两个8位IO,但手上的TFT屏都是30针的,请教各位高手该选用什么型号的屏,谢谢啦
    发表于 01-07 09:43

    IO不够用,有没有这种扩展IC,8个按键对应IO口的值为000-111

    IO不够用,有没有这种扩展IC,8个按键对应IO口的值为000-111
    发表于 03-31 14:58

    DSP的PWM口不够用怎么扩展

    如题,DSP的PWM口不够用,也不合适用定时器做。有没有那种PWM发生芯片,由DSP通过并行口之类的把占空比信号给到PWM发生芯片芯片产生对应的PWM波形?
    发表于 06-04 14:41

    想用单片机独立控制100盏呼吸灯 IO不够用 求解决办法

    想用单片机独立控制100盏呼吸灯IO不够用尝试过用595联级太繁复 未成功
    发表于 06-29 11:04

    IO不够用怎么办?

    C51单片机————总线与系统扩展Created with Raphaël 2.1.2张三张三李四李四四哥,IO不够用怎么办?你可以进行系统扩展!什么鬼?那是什么东西?。。。看书去1
    发表于 07-19 07:21

    单片机IO口如何扩展

    单片机IO扩展方法1.使用分压电阻分压,然后用单片机的ADC端口读取不同的电压值。适合应用于多个按键的方案,需要多个输入端口,导致GPIO不够用的情况。使用串入并出芯片(serial
    发表于 11-18 08:41

    CPLD或FPGA扩展IO口与处理器自带IO的区别?

    1.处理器上有64个可复用的IO口,我们需要64个IO口,因为是复用的,我么也会用到部分复用功能,所以IO不够用,有人提出用CPLD或FPGA扩展
    发表于 04-23 14:10

    单片机IO扩展方法

    单片机IO扩展方法1.使用分压电阻分压,然后用单片机的ADC端口读取不同的电压值。适合应用于多个按键的方案,需要多个输入端口,导致GPIO不够用的情况。使用串入并出芯片(serial
    发表于 11-11 10:36 14次下载
    单片机<b class='flag-5'>IO</b>口<b class='flag-5'>扩展</b>方法

    采用ADC扫描实现一个IO上挂多个按键

    有时候做设计时,我们会遇到外部按键比较多,IO不够用的情况。这时大部分人会考虑通过其它芯片扩展IO
    的头像 发表于 08-11 09:16 2077次阅读
    采用ADC扫描实现一个<b class='flag-5'>IO</b>上挂多个按键

    硬件设计如何实现一个IO上挂多个按键?

    有时候做设计时,我们会遇到外部按键比较多,IO不够用的情况。这时大部分人会考虑通过其它芯片扩展IO
    发表于 08-11 09:16 1007次阅读
    <b class='flag-5'>硬件</b>设计如何实现一个<b class='flag-5'>IO</b>上挂多个按键?

    单片机的IO不够用了怎么办?如何扩展单片机的IO口?

    单片机的IO不够用了怎么办?如何扩展单片机的IO口? 单片机是应用广泛的微处理器,其具有较高的可编程性、灵活性和成本效益等优点,在嵌入式系统中得到了广泛的应用。然而,由于每一个单片机
    的头像 发表于 10-24 11:49 6559次阅读