【51单片机快速入门指南】4.5:I2C 与 TCA6416实现双向 IO 扩展

目录

  • 硬知识
    • IO 扩展芯片 TCA6416A
      • TAC6416A 的寄存器
        • IO 输入寄存器
        • IO 输出寄存器
        • IO 反相寄存器
        • IO 方向寄存器
      • TCA6416A 的操作
        • TCA6416A 写数据
        • TCA6416A 读数据
        • TCA6416A 的 IO 输入寄存器
    • 硬件布局
  • 示例程序
    • TCA6416A.c
    • TCA6416A.h
  • 测试程序
    • main.c
    • 实验现象

普中51-单核-A2
STC89C52
MSP430G2553 Launchpad 扩展板
Keil uVision V5.29.0.0
PK51 Prof.Developers Kit Version:9.60.0.0
上位机:Vofa+ 1.3.10


       摘自《Launchpad口袋实验平台(指导书)》、《AY-G2PL KIT_用户手册》

硬知识

       对于低速的 IO,可以通过串行转并行的方法扩展。1 片 I2C 接口控制的 IO 扩展芯片 TCA6416A可为 单片机额外扩展出 16 个双向 IO。
       扩展输出口的方法其实就是将串行数据转为并行数据输出,串入并出移位寄存器加一个锁存器就可以将串行转并行输出(也就是扩展了 IO 口),比如 74 系列通用数字逻辑器件74HC595,可以任意级联扩展输出口。
       串行转并行的代价就是速度会变慢,理论上,1 串转 16 并输出,速度至少要降 16 倍。假如普通 IO 翻转电平的速度是 1MHz,转 16 并输出后,速度将降为 62.5kHz。这个速度对于很多应用已绰绰有余,比如和人有关的输入输出设备(键盘、段式 LCD/LED 驱动、点阵LCD/LED 驱动等)。
       扩展输入口的方法类似,只不过使用的是并入串出的移位寄存器。

IO 扩展芯片 TCA6416A

       类似 74HC595 的串并转换芯片虽然廉价,但是它只能扩展输出口,不能同时扩展出双向IO 口。而TCA6416A则是基于 I2C 控制的双向 IO 扩展芯片。
在这里插入图片描述

  1. TCA6416A 可以扩展出 16 个双向 IO 口,为了与单片机原生的 IO 区别,图中TCA6416A 扩展出的 IO 标注为 IO00-IO07,IO10-IO17。
  2. ADDR 引脚是 I2C 设备的地址引脚,通过接地或 VCC 可设置为两个不同的地址,换句话说,1 组 I2C 总线上可挂两片 TCA6416A(ADDR 引脚分别接地和接 VCC)。
  3. /INT 引脚是专门为扩展输入引脚设计的,相当于单片机的外部中断。当扩展 IO 设为输入模式,且输入电平变化时,/INT 引脚便会触发下降沿中断,单片机的 IO 再去检测/INT 的下降沿,触发真正的单片机中断。单片机通过 I2C 协议查看 TCA6416A 的相关寄存器,便知晓是哪个 IO 被按下。
  4. /RESET 引脚地位相当于单片机的复位引脚,为了节约单片机为数不多的 IO口,这里仿照单片机的上电复位电路用 R2 和 C6 给 TCA6416 也设计了上电复位电路。
  5. SDA、SCL 和/INT 引脚必须外接上拉电阻(R31/32/33)。
  6. 电源 VCC 和地 GND 之间接电容 C5(100nF,标柱为 104)进行去耦,起到“有病治病无病强身”的作用。

TAC6416A 的寄存器

       首先我们把 TCA6416A 扩展出的 16 个普通 IO 口,理解为成单片机的 P0 和 P1 口,CPU对 IO 口的读写实际上都是通过寄存器这个中介进行的。其次,参考图 12.3 的移位寄存器原理,扩展出的 IO 也是无法位操作的,读写都必须多位同时进行。TAC6416A 的寄存器设计其实很好理解,共 4 组寄存器,我们不妨先分析一下需要哪 4 组。

  1. 需要 16 位的 Input Port Registers 来存储 16 个 IO 的输入状态,相当于单片机中的PxIN。
  2. 需要 16 位的 Output Port Registers 来存储 16 个 IO 的输入状态,相当于单片机中的PxOUT。
  3. 需要 16 位的 Configuration Registers 来存储 IO 的输入输出方向,相当于单片机中的PxDIR。
  4. 需要 16 位的 Polarity Inversion Registers 来存储是否对 IO1/0 取反操作,这个功能在单片机中没有。

       CPU 对于 IO 口的操作有置 1,置 0 和取反三种,单片机可以通过先读出 IO 状态,再做异或逻辑的办法实现取反。但是在 TCA6416A 中,就必须先用 I2C 协议读 Input Port Registers ,CPU 运算后,再用 I2C 写 Output Port Registers ,这个时间非常长。所以TCA6416A 直接就集成了硬件 IO 电平翻转电路,相当于“复杂指令集”了一回。
       实际的 TCA6416A 寄存器,使用 TCA6416A 的过程就是配置这几个寄存器。

IO 输入寄存器

在这里插入图片描述

IO 输出寄存器

在这里插入图片描述

IO 反相寄存器

在这里插入图片描述

IO 方向寄存器

在这里插入图片描述

TCA6416A 的操作

TCA6416A 写数据

       对 TCA6416A 来说,可能要写 3 种数据,IO 输出电平寄存器,IO 方向寄存器,IO 电平极性翻转寄存器,3 个寄存器都影响实际的 IO 输出,所以这 3 者的地位是完全平等的,写的方法也一样。
       如图 12.9 所示为 TCA6416A 的写寄存器操作时序图。原说明书中将写 IO 与写寄存器分开画图,其实这完全没有必要,写 IO 的本质还是写寄存器。一次完整的写寄存器分 4 部分:

  1. 从机地址:从机地址的前 6 位固定为 010000,为什么不定成 000000 呢?这是因为如果每种类型的 I2C 从机设备都从 000000 起始的话,那地址就区分不开了,所以每种 I2C 设备都会跳开一段地址赋值。第 7 位是真正的地址,只有两种可能。第 8 位用于表示读操作还是写操作。
  2. 命令字:这 8 位实际就是选择写哪个寄存器。高 5 位固定,用低 3 位表示 8 种寄存器。
  3. 寄存器 0:先写寄存器 0,高位在前,低位在后。
  4. 寄存器 1:后写寄存器 1。

在这里插入图片描述

TCA6416A 读数据

       单片机在真正读 TCA6416A 数据前,需要写命令告诉 TCA6416A 是操作哪个寄存器。然后才是真正的读数据。写命令需要 2 字节,从机地址+命令。读数据需要 3 个字节,从机地址+低位数据+高位数据。
在这里插入图片描述

TCA6416A 的 IO 输入寄存器

       如图 12.11 所示为读 IO 输入寄存器的“读数据”操作时序图部分(即为图 12.10 的后半部分,不包括写命令部分)。为了把个各种异常情况下的现象都描述清楚,图 12.11 做的非常复杂。
       只需注意,图中 IO 电平共变化了 5 次,而实际被单片机读到的却是两次锁存 IO 电平时刻对应的数据 Data1 和数据 Data4。
在这里插入图片描述
       为了模拟普通 IO 的输入中断,TAC6416A 启用了一个类似的/INT 中断来提示输入 IO 有变化。但是由于 IO 输入的变化速度可能远高于读 IO 输入寄存器的速度,所以,TAC6416A的中断和单片机的 IO 外部中断还不太一样。输入 IO 的变化可以触发/INT 产生下降沿变成低电平,但是/INT 要等 I2C 的应答位才能恢复高电平(重新具备中断能力)。也就是说,TCA6416A 的/INT 中断无法响应快速变化的输入信号,当然我们也可以不用中断的方法判断IO 输入,定时扫描的方法同样适用于 TCA6416A。

硬件布局

在这里插入图片描述
如图所示,扩展出 16 个 IO 口中,8 个作为输出口用于控制 8 个 LED,4 个作为输
出口用于控制 LCD 驱动器(这个另行介绍),4 个作为输入口用于识别 4 个机械按键。
在这里插入图片描述
下图所示为 8 个 LED 以及 4 个机械按键在扩展板中的位置
在这里插入图片描述

示例程序

       stdint.h见【51单片机快速入门指南】1:基础知识和工程创建
       软件I2C程序见【51单片机快速入门指南】4: 软件 I2C

TCA6416A.c

/** TCA6416A.c**  Created on: 2013-4-6*      Author: Administrator*/
#include "./Software_I2C/Software_I2C.h"#define		TCA6416A_ADDR	0x20	/*从机TCA6416A的7位地址*///-----控制寄存器定义-----
#define		In_CMD0			0x00	//读取管脚输入状态寄存器;只读
#define		In_CMD1			0x01
#define		Out_CMD0		0x02	//控制管脚输出状态寄存器;R/W
#define		Out_CMD1		0x03
#define		PIVS_CMD0		0x04	//反向控制管脚输出状态寄存器;R/W
#define		PIVS_CMD1		0x05
#define		CFG_CMD0		0x06	//管脚方向控制:1:In;0::Out。
#define		CFG_CMD1		0x07volatile unsigned int TCA6416A_InputBuffer=0;
unsigned char pinW0 = 0xff;						//用于缓存已写入相应管脚的状态信息,此操作避免读回TCA6416A中当前寄存器的值
unsigned char pinW1 = 0xff;						//用于缓存已写入相应管脚的状态信息,此操作避免读回TCA6416A中当前寄存器的值void Delay_ms(int i);/******************************************************************************************************* 名       称:TCA6416A_Init()******************************************************************************************************/
void TCA6416A_Init(void)
{unsigned char conf;Delay_ms(5);						//TCA6416的复位时间比单片机长,延迟确保可靠复位//----根据扩展板的引脚使用,将按键所在管脚初始化为输入,其余管脚初始化为输出conf = 0x00;						//  0 0 0 0_0 0 0 0  (LED0~LED7)i2c_mem_write(TCA6416A_ADDR, CFG_CMD0, &conf, 1);	conf = 0x0f;						//  0 0 0 0_1 1 1 1 (按键)i2c_mem_write(TCA6416A_ADDR, CFG_CMD1, &conf, 1);	//----上电先将管脚输出为高(此操作对输入管脚无效)conf = 0xff;						// 某位置1,输出为高,0为低i2c_mem_write(TCA6416A_ADDR, Out_CMD0, &conf, 1);conf = 0xff;						i2c_mem_write(TCA6416A_ADDR, Out_CMD1, &conf, 1);
}/******************************************************************************************************* 名       称:PinOUT()******************************************************************************************************/
void PinOUT(unsigned char pin,unsigned char status)
{if(pin<=7)												//所选管脚为pin0~pin7 ,刷新所要操作的输出缓存pinW0 状态{if(status == 0)pinW0 &= ~(1<<pin);elsepinW0 |= 1<<pin;			i2c_mem_write(TCA6416A_ADDR, Out_CMD0, &pinW0, 1);	// 将更新后的数据包,写入芯片寄存器}else if(pin>=10 && pin<=17)								//所选管脚为pin10~pin17 ,刷新所要操作的输出缓存pinW1 状态{if(status == 0)pinW1 &= ~(1<<(pin%10));elsepinW1 |= 1<<(pin%10);i2c_mem_write(TCA6416A_ADDR, Out_CMD1, &pinW1, 1);	// 将更新后的数据包,写入芯片寄存器}
}/******************************************************************************************************* 名       称:PinIN()******************************************************************************************************/
unsigned char PinIN(unsigned char pin)
{unsigned char temp[2];i2c_mem_read(TCA6416A_ADDR, In_CMD0, temp, 2);					// 读取按键所在管脚信息TCA6416A_InputBuffer = (((unsigned int)temp[1])<<8)|temp[0];if(pin<=7)												{if(temp[0] & (1<<pin))return 1;elsereturn 0;}else if(pin>=10 && pin<=17)							{if(temp[1] & (1<<(pin%10)))return 1;elsereturn 0;}
}/******************************************************************************************************* 名       称:PinToggle()******************************************************************************************************/
void PinToggle(unsigned char pin)
{unsigned char status;if(pin<=7)												//所选管脚为pin0~pin7 ,刷新所要操作的输出缓存pinW0 状态{status = !(pinW0 & (1<<pin));if(status)pinW0 |= 1<<pin;elsepinW0 &= ~(1<<pin);i2c_mem_write(TCA6416A_ADDR, Out_CMD0, &pinW0, 1);	// 将更新后的数据包,写入芯片寄存器}else if(pin>=10 && pin<=17)								//所选管脚为pin10~pin17 ,刷新所要操作的输出缓存pinW1 状态{status = !(pinW1 & (1<<(pin%10)));if(status)pinW1 |= 1<<(pin%10);elsepinW1 &= ~(1<<(pin%10));i2c_mem_write(TCA6416A_ADDR, Out_CMD1, &pinW1, 1);	// 将更新后的数据包,写入芯片寄存器}
}

TCA6416A.h

/** TCA6416A.h**  Created on: 2013-4-6*      Author: Administrator*/#ifndef TCA6416A_H_
#define TCA6416A_H_extern unsigned char PinIN(unsigned char pin);
extern void PinOUT(unsigned char pin,unsigned char status);
extern void PinToggle(unsigned char pin);
extern void TCA6416A_Init();
extern volatile unsigned int TCA6416A_InputBuffer;#endif /* TCA6416A_H_ */

测试程序

一个LED闪烁,另一个LED由KEY控制翻转。

main.c

#include <STC89C5xRC.H>
#include "intrins.h"
#include "stdint.h"
#include "TCA6416A.h"void Delay1ms()		//@11.0592MHz
{unsigned char i, j;_nop_();i = 2;j = 199;do{while (--j);} while (--i);
}void Delay_ms(int i)
{while(i--)Delay1ms();
}void main(void)
{uint16_t delay_count = 0;TCA6416A_Init();while(1){	if(!PinIN(10)){Delay_ms(20);if(!PinIN(10)){PinToggle(1);while(!PinIN(10));}}if(++delay_count == 500){PinToggle(7);delay_count = 0;}Delay_ms(1);}
}

实验现象

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/400380.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux/window 下 solr5.1 tomcat7.x 环境搭建即简单功能测试

2019独角兽企业重金招聘Python工程师标准>>> 之所以想使用solr来进行学习&#xff0c;很大一部分原因就是&#xff0c;solr能够在某种程度上提供RESTFUL相关的URL请求连接&#xff0c;可以把它理解为 以搜索引擎为基础的存储服务系统 &#xff0c;由于他的搜索可以是…

【Java基础总结】多线程

1. 实现多线程的两种方式 1 //第一种&#xff1a;继承Thread类&#xff0c;重写run()方法2 class ThreadTest1 extends Thread{3 public void run(){4 String threadName Thread.currentThread().getName();5 for(int i0;i<10;i){6 System…

【51单片机快速入门指南】5:软件SPI

目录硬知识SPI协议简介SPI接口介绍SPI接口连接图SPI数据传输方向SPI传输模式软件SPI程序源码Soft_SPI.cSoft_SPI.h普中51-单核-A2 STC89C52 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 上位机&#xff1a;Vofa 1.3.10 源于软件模拟SPI接口程序代码&…

svn搭建本地服务端

使用VisualSVN Server来完成,下载地址:https://www.visualsvn.com/server/download/ 我安装的版本是3.3.1,安装的时候选择了标准版本&#xff0c;另外一个版本需要付费(日志跟踪、VDFS等功能)更多可以参考https://www.visualsvn.com/server/licensing/安装完成之后&#xff0c;…

【51单片机快速入门指南】5.1:SPI与DS1302时钟芯片

目录硬知识DS1302 简介DS1302 使用控制寄存器日历/时钟寄存器DS1302 的读写时序电路设计示例程序DS1302.cDS1302.h测试程序main.c实验现象普中51-单核-A2 STC89C52 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 硬知识 摘自《普中 51 单片机开发攻略》…

【格局视野】三色需求与工作层次

三色需求 人们的社会经济生活本身就是一个互相交换&#xff0c;价值传递的循环&#xff0c;但这个循环有一个核心&#xff0c;这个核心就是社会大众的需求&#xff0c;也可以称为市场需求&#xff0c;围绕这个需求产生了层级递进的需求关系。 第一个层次是蓝色需求 是最基础的社…

关于linux-Centos 7下mysql 5.7.9的rpm包的安装方式

环境介绍>>>>>>>>>>>>>>>>>> 操作系统&#xff1a;Centos 7.1 mysql数据库版本&#xff1a;mysql5.7.9 mysql官方网站&#xff1a;http://www.mysql.com 原文地址&#xff1a;http://www.cnblogs.com/5201351/p/4912614…

【51单片机快速入门指南】5.2:SPI读取 12位ADC XPT2046 芯片

目录硬知识ADC 简介分辨率转换误差转换速率ADC 转换原理逐次逼近型 ADC双积分型 ADCXPT2046 芯片介绍参考电压内部参考电压外部参考电压输入工作模式单端工作模式差分工作模式温度测量电池电压测量压力测量数字接口笔中断输出转换周期16 时钟周期转换数字时序15 时钟周期转换数…

flask中 app.run(host='0.0.0.0', port=5000, debug=False) 不能用外网ip访问的解决办法

pycharm 2018开启debug模式和修改host&#xff1a; 在Pycharm 2018中&#xff0c;如果想要开启debug模式和更改端口号&#xff0c;则需要编辑项目配置。直接在app.run中更改是无效的。示例图如下&#xff1a; 将 app.run() 改成 app.run(debugFalse) 保存文件&#xff0c…

开发第一个spring boot应用

为什么80%的码农都做不了架构师&#xff1f;>>> 我们来用spring boot开发一个简单的“hello world”web应用&#xff0c;使用maven构建。开始之前&#xff0c;先检查你的java与maven的版本&#xff0c;看是否是spring boot1.3支持的版本&#xff1a; $ java -versi…

机器学习中规则化和模型选择知识

1 问题 模型选择问题&#xff1a;对于一个学习问题&#xff0c;可以有多种模型选择。比如要拟合一组样本点&#xff0c;可以使用线性回归&#xff0c;也可以用多项式回归。那么使用哪种模型好呢&#xff08;能够在偏差和方差之间达到平衡最优&#xff09;&#xff1f; 还有一类…

【51单片机快速入门指南】5.3:SPI控制晶联讯JLX12864G_08602 LCD屏幕

目录示例程序JLX12864G_08602.cJLX12864G_08602.hJLX12864G_08602_Font.cJLX12864G_08602_Font.h测试程序main.c效果STC12LE5A60S2 12MHz Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 示例程序 stdint.h见【51单片机快速入门指南】1&#xff1a;基础知…

Android二维码之创建

由于微信的推出二维码走进了我们的生活&#xff0c;并且越来越多的人们正在发挥着自己的想象力去使用它&#xff0c;来方便我们的生活&#xff0c;我曾经听说过一个笑话&#xff0c;当我们死后&#xff0c;墓碑上不再有墓志铭&#xff0c;而会出现一个记录你一生信息的二维码&a…

如何开展软件架构之概念架构

如何开展软件架构之概念架构 到目前为止&#xff0c;我们已经完成了需求的分析过程&#xff0c;总结来说&#xff0c;主要的步聚是 一&#xff09;需求结构化&#xff0c; 二&#xff09;分析约束影响 三&#xff09;重点关注质量需求。 那么接下来的阶段则是系统的概念架构了&…

【51单片机快速入门指南】6.1:LCD1602的八线、四线控制及自定义符号,完美兼容Proteus仿真

目录硬知识显示特性接口定义操作时序写操作时序读操作时序寄存器忙标志位BF地址计数器&#xff08;AC&#xff09;显示数据寄存器&#xff08;DDRAM&#xff09;CGROMCGRAM指令清屏指令光标归位指令进入模式设置指令显示开关控制指令设定显示屏或光标移动方向指令功能设定指令设…

在MAC OS 下配置python + Flask ,并支持pyCharm编辑器

https://www.cnblogs.com/lgphp/p/3841098.html 在MAC OS 下配置python Flask ,并支持pyCharm编辑器 flask是一个micro framework &#xff0c;伸缩性很强。可以部署到openshift 的PAAS里。这个框架上手非常快。喜欢的可以试试。 若实在MAC里&#xff0c;python已经默认安装了…

MySql简介及概念

关系型数据库系统&#xff1a;建立在关系模型上的数据库系统。 关系模型:当将日常生活中的实体&#xff08;学生&#xff09;&#xff0c;和实体的属性&#xff08;学生的学号&#xff0c;姓名&#xff09;保存数据中时&#xff0c;该如何处理该实体结构。1、数据结构可以规定&…

【51单片机快速入门指南】6.2:SPI 、八线、四线控制 LCD12864 屏幕及Proteus的仿真(支持中文汉字)

目录硬知识LCD12864简介主控芯片ST7920的功能是&#xff1a;驱动芯片ST7921的功能是&#xff1a;引脚功能时序并行通信串行通信指令存储结构操作取模软件的配置示例程序st7920.cst7920.h测试程序显示图片图片1实验现象图片2实验现象显示字符英文实验现象中文实验现象Proteus的仿…

【51单片机快速入门指南】仿真实例:幅值可调、频率可调的函数发生器(方波、三角波、正弦波)(1~10kHz)

目录效果设计思路STC89C52 Windows 10 20H2 Proteus 8 Frofessional v8.9 SP2 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 51函数发生器&#xff0c;附工程源码和Proteus仿真文件 效果 0 ~ 5V &#xff0c;50Hz的正弦波&#xff1a; 1 ~ 4V&…

VisualSvn Server介绍

1 、VisualSvn Server VisualSvn Server是免费的&#xff0c;而VisualSvn是收费的。VisualSvn是Svn的客户端&#xff0c;和Visual Studio集成在一起&#xff0c;但是不免费&#xff0c;使用AnkhSvn&#xff08;VS2008插件&#xff09;来代替VisualSvn。使用 VisualSvn Server是…