首页 > 其他分享 >TX2 核心板 GPIO、IO扩展器、拨码开关、LED灯 使用总结

TX2 核心板 GPIO、IO扩展器、拨码开关、LED灯 使用总结

时间:2023-02-11 17:47:21浏览次数:35  
标签:扩展器 LED 器件 fd IO 寄存器 I2C reg

PS:要转载请注明出处,本人版权所有。

PS: 这个只是基于《我自己》的理解,

如果和你的原则及想法相冲突,请谅解,勿喷。

前置说明

  本文作为本人csdn blog的主站的备份。(BlogID=087)
  本文发布于 2019-08-24 11:48:24,现用MarkDown+图床做备份更新。blog原图已丢失,使用csdn所存的图进行更新。(BlogID=087)

环境说明

  无

起因


  我们有个项目,做了一个基于TX2核心板的硬件板卡,这个板卡除了做相关算法的检测之外,还得提供一些控制LED啊、通过拨码开关这些来设置一些内容的小功能,你说气不气,这些小功能还必须要实现。如果LED和拨码开关直接挂载到tx2的gpio上的话,就没有必要写本文了,没意义,因为只要学过嵌入式的人,给他一个板子,再差劲,读取和设置一个gpio的高低电平总会吧。如果不会,建议还多学学嵌入式基础知识(从单片机玩起来,先裸奔,再上OS)。

  这里我们知道,其实对于芯片来说,引脚是非常珍贵的,如果芯片所需要实现的功能复杂,那么通用的io管脚异常珍贵,这里就出现了一个种器件,叫做IO扩展器(所实话,我都不知道这样翻译对不对),从名字可知,就是较少的引脚扩展出更多的引脚,本文就是用两个引脚扩展出了16个引脚。

  TX2上,由于使用了Linux,读取和设置gpio也是非常简单的,直接打开相关的gpio设备,读写即可。不要问我为啥要用linux,不用其他os,或者直接裸机控制,我只能够回答曰:我是想啊,可是我实力不允许啊,什么caffe、opencv、ncnn、cuda等等堆到其他系统或者裸机下,我着实能力不够,弄不过去,关键还麻烦。





IO扩展器




IO扩展器原理简介

  其实本文的核心就是IO扩展器,这个器件由于我玩的板子少,见识少,我是第一次见到这种器件。下图就是这种器件在tx2手册里面的推荐使用方法。

rep_img

  这种器件就是通过某种总线,然后扩展出尽可能多的io口。这里的这个器件通过I2C总线,扩展出16个io口。

  这里我们可以看到:SCL和SDA是I2C通信总线,A0和A1是可编程配置I2C从器件地址。(这里不懂也没关系,就是这个器件的地址可以编程设置,至于为啥要有这个地址,可以简单理解为一个总线挂载多个设备,某一时刻总线只能为其中一个设备提供服务,这些设备的区分就是通过地址来完成的。)

  P00-P17是扩展出来的IO口。

  知道以上足够了,没学过的也足够了。

  这个器件的特性是:通过I2C协议操作他的寄存器,他有8个8位寄存器,0-1寄存器是INPUT用,2-3寄存器是OUTPUT用,4-5好像是优先级裁决,6-7是配置寄存器,就是配置IO口是输出还是输入,如果接触过单片机、stm32这种的GPIO程序的话,是很好理解的。(手动滑稽,我出了校门就没接触过了)

  不要问下图的是什么器件(问就是不知道,手动滑稽),这只是举个例子,这个io扩展器的寄存器分配以及功能就是这样的。

rep_img
rep_img


IO扩展器编程操作---shell command

  首先这个器件是通过I2C协议操作的,不用关心I2C是什么,他们你可以类比为HTTP。
那么Linux上怎么通过I2C操作这个器件呢?

  首先,Linux上有一组工具:i2c-tool,它可以读取所有芯片的i2c bus上挂载的芯片,设置和读取寄存器等等,拿来做测试或者封装一个程序都是不错的。TX2的ubuntu16.04是自带这个工具的,他的详细用法大家去百度,我不造轮子了。

  在Ubuntu里面操作I2C是非常简单的,你不需要关心I2C的具体传输规定,不用管时序这些烦人的事情。

  首先我们先用工具来测试,美滋滋:

  还记得上文我提了这个IO扩展器的从地址的事情吗?由于我的A0和A1都是接的低电平,在这里我的器件地址是0x74,怎么来的,看下图。

rep_img

  然后通过i2cdetect查看我们器件的位置(0x74)(注意,这个命令需要传入一个I2C总线序号,我这里是0,也就是说你要知道你这个IO扩展器挂载到哪个总线上的,这和SCL和SDL接线有关,有兴趣的可以去翻一翻手册就知道了,UU代表有人在占用这个设备)

  shell:>i2cdetect -y -r -a 0

rep_img

  i2cdump可以通过标准i2c协议探测出所有的寄存器的值,下图8个寄存器的值就的出来了,分别对应上面的寄存器说明。XX代表没有这个寄存器。

  shell:>i2cdump -f -y 0 0x74

rep_img

  然后:

  • i2cset -f -y i2c_bus_num slave_addr reg_num value 设置寄存器值
  • i2cget -f -y i2c_bus_num slave_addr reg_num 获取寄存器值

  其实通过上面的操作就可以完成整个io扩展器的操作,我们可以通过程序执行shell命令的方式设置和操作值。



IO扩展器编程操作---syscall

  实际上,linux做了很多东西,我们可以用标准的linux sys-api来完成以上内容,其实这些api就是i2ctool使用的部分。

  下面不墨迹,直接给出led操作的接口,有需要的参考吧。

int open_led_device(const char * i2c_bus_num, int slave_addr){

    int fd = 0; 

    if ( 0 > (fd = open(i2c_bus_num, O_RDWR)) ){//打开i2c总线

        perror("open i2c bus error:");
        return -1;
    }

    if(ioctl(fd, I2C_SLAVE_FORCE, DEVICE_I2C_ADDR) < 0) {//设置从器件地址,这里使用I2C_SLAVE_FORCE进行强行设置,那么这个设备忙

        perror("set device slave addr error:"); 
        return -1; 
    }

    if ( 0 > write_led_register(fd, LED_REG1_CFG_ADDR, LED_REG1_CFG_VAL) ){//设置写寄存器值,这两个宏和你的硬件连线有关。这里不给出。

        printf("init pin for output-mode failed.\n");
        close(fd);
        return -1;
    }

    return fd;

}

int read_led_register(int fd, char reg_addr, char *read_val){//读寄存器

    if (write(fd, &reg_addr, 1) != 1){//write reg addr ,从器件地址通过open接口设置好后,先写入要读的reg地址

        perror("set reg addr error:"); 
        return -1; 
    }

    if ( read(fd, read_val, 1) != 1 ){//read data,等待i2c返回刚刚要查询的reg值

        perror("read reg error:"); 
        return -1; 
    }
    return 0;
}

int write_led_register(int fd, char reg_addr, char data){//写寄存器

    char tmp_buf[2];


    tmp_buf[0] =  reg_addr;//reg 地址
    tmp_buf[1] = data;//reg 值


    if (write(fd, tmp_buf, 2) != 2){//write data

        perror("write data error:"); 
        return -1; 
    }

    return 0;
}

void close_led_device(int fd){//关闭

    close(fd);
}




LED灯


  此处省略XXX字。

  相信每个人都知道,常规情况下,在LED灯的两边加电源正极和负极,灯就能亮。在电路设计上,一般来说,LED灯的一端都是和电源正极或者负极是连接好的,另一端和GPIO口接上。如果GPIO输出的电压和另一端电压逻辑一致(比如都是高电平、都是低电平),灯就不亮,反之就亮。

  注意:这段话是有毛病的,但是一般人这样理解就行了(不了解电子电路的就看到这就行了)。对于懂的人,这里多说一句,这里还有一个三极管做开关作用,也是就说LED灯两端都接在电源正负极,中间有个三极管开关。





拨码开关


  这种器件,又是另外一种新奇的东西了,感觉我这两年写的“祖传屎山“太多了,现在看到各种硬件器件都是眼前一亮的感觉。

  就是类似下图这种。

rep_img
rep_img

  其作用是:

  你可以人为的按这个+-号按钮,设置数字,这个数字会反应到电路上,从而芯片可以读取你设置的数字。
说白了,你的系统中有个数字参数,你可以通过这种器件进行手动设置,通过驱动程序,就可以更改这个系统参数,是不是 so 简单。

  这里简单说明一下电路是怎么反应出对应的数字的:

  我就举个栗子,下图是个例子拨码开关(手动滑稽,这里多说一句,上图的拨码开关,是4个拨码开关合在一起的,下图的这个输出编码是一个拨码开关的)

rep_img

  这里可以简单理解为:

  一个拨码开关有5个引脚,一个引脚是C,接GND或者VCC,其他4个是编码引脚,是需要接GPIO,并去取编码的。

  其实很简单:

  例如:C端我接VCC,1248默认值为0,那么数字1,1号引脚接通,那么8421io口输出二进制就是0001,转换为10进制,就是1.

  然后写个程序读取这4个脚的值,转换一下,就OK。





后记


  无

参考文献




打赏、订阅、收藏、丢香蕉、硬币,请关注公众号(攻城狮的搬砖之路)
qrc_img

PS: 请尊重原创,不喜勿喷。

PS: 要转载请注明出处,本人版权所有。

PS: 有问题请留言,看到后我会第一时间回复。

标签:扩展器,LED,器件,fd,IO,寄存器,I2C,reg
From: https://www.cnblogs.com/Iflyinsky/p/17112198.html

相关文章