当前位置: 首页 > news >正文

《嵌入式硬件(十六):基于IMX6ULL的I2C的操作》

一、IIC的基本概念

        IIC(Inter-Integrated Circuit)又称I2C,是是IICBus简称,所以中文应该叫集成电路总线。是飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发展而来的一种同步串行半双工通信总线方式。该总线允许同时连接多个设备(芯片)。每块芯片在总线上拥有特定的地址。自2006年10月1日起,使用I²C协议已经不需要支付专利费,但制造商仍然需要付费以获取IIC从属设备地址。


➢ 上图所示是IIC的总线的使用场景,所有挂载在IIC总线上的设备都有两根信号线,一根是数据线SDA,
另一根是时钟线SCL。这两个信号线都是双向的。
➢ 作为一种通信方式,IIC总线在某一时刻,总线只允许有一个设备处于发送状态,所发生的数据被总线上所有的设备所接收。IIC通信协议包含有设备地址,只有发送方携带的地址与某个接收方的地址
相同时,接收方才真正执行相关的指令。

➢ IIC总线规定,设备在空闲时,两根总线都处于高电平状态。为保证这种状态,数据线SDA和时钟线SCL都要外接上拉电阻。对于I.MX来说,这个上拉电阻也可以在引脚电器配置中设置。为了让大家释放总线时,能保持高电平。

➢ IIC总线上连接的若干设备中,每次通信前,发送方首先发送一个“起始”信号,其实信号就是在SCL为高电平时,SDA发送一个低电平。当其它设备接收到这个其实信号后,将进行一次“总线仲裁”。意思就是设备(除发送其实信号的那个设备以外的)都将处于聆听状态。

➢ IIC总线进行数据传送时,时钟线(SCL)上的信号为高电平期间,数据线(SDA)上的数据必须保持稳定(接收方在高电平时接收)。只有在时钟线(SCL)上的信号为低电平期间,数据线(SCL)上的高电平或低电平状态才允许变化(发送方在低电平时发送)。同时,SCL信号由数据启动发送的设备提供。输出到数据线(SDA)上的每个字节必须是8位。数据传送时,先传送最高位(MSB),后传送最低位(LSB)。

➢ 发送器每发送一个字节(8个bit),就在时钟脉冲 9 期间释放数据线,由接收器反馈一个应答信号。 主机SCL拉高,读取从机SDA的电平。对于反馈有效应答位ACK的要求是:接收器在第9个时钟脉冲之前的低电平期间将数据线SDA拉低,并且确保在该时钟的高电平期间为稳定的低电平。
➢ 数据线(SDA)为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节。
➢ 数据线(SDA)为高电平时,规定为非应答位(NACK),表示接收器没有成功接收该字节。

➢ 当发送方发送完最后一个bit后,需要发送一个结束标志来终止整个通信过程。当时钟线SCL 为高电平时,数据线SDA 由低电平向高电平跳变。

按照I2C标准,主设备发起通信时先发送一个起始信号,之后发送的第一个字节就是子设备的设备地址。需要注意的是。设备地址本身只占7个比特,最后一个比特所代表的是之后的数据流向。0代表主发从收,通常描述为写,1表示从发主收,通常描述为读。

二、AT24C02

这是一款EEPROM,是一种非易失性存储器。同类型的芯片还有AT24C04,AT24C08,之间的区别仅仅是存储大小不同。既然是一种存储器,那么对其操作无外乎有两种操作,读取和写入操作。

        主机先发STARTS的起始信号,发送设备地址,数据流向位0(主机发,从机收,写流向),从机回ACK,主机发送数据地址,从机回ACK,主机发送数据,从机回ACK,主机发送STOP信号。

        主机先发STARTS的起始信号,发送设备地址,数据流向位0(主机发,从机收,写流向),从机回ACK,主机发送数据地址,从机回ACK,主机发送数据,从机回ACK,主机发送STOP信号。

        主机先发STARTS的起始信号,发送设备地址,数据流向位1(主机收,从机发,读流向),从机回ACK,从机发送数据,主机回ACK,主机发送STOP信号。

        主机先发STARTS的起始信号,发送设备地址,数据流向位0(主机发,从机收,写流向),从机回ACK,主机发送数据地址,从机回ACK(指定数据),主机重发设备地址,数据流向翻过来,主机发送设备地址,从机应答ACK,从机发送数据,主机回ACK,最后一个NO ACK是主机发的,主机发送STOP信号。

        读取到最后一个字节是,一定要回复NACK,否则IIC会死机。

三、原理

1.底板原理图

2.地址寄存器(从机时候用)IADR

3.频率分频寄存器(IFDR)

4.I2C控制寄存器(I2CR)

5.I2C状态寄存器(I2SR)

6.I2C数据寄存器(I2DR)

四、流程图

五、代码

1.i2c.c

#include "i2c.h"
#include "fsl_iomuxc.h"
#include "delay.h"#define IEN         (7)
#define MSTA        (5)
#define MTX         (4)
#define TXAK        (3)
#define RSTA        (2)#define ICF         (7)
#define IBB         (5)
#define IAL         (4)
#define IIF         (1)void init_i2c1(void)
{IOMUXC_SetPinMux(IOMUXC_UART4_TX_DATA_I2C1_SCL, 1);IOMUXC_SetPinMux(IOMUXC_UART4_RX_DATA_I2C1_SDA, 1);IOMUXC_SetPinConfig(IOMUXC_UART4_TX_DATA_I2C1_SCL, 0xF0B0);IOMUXC_SetPinConfig(IOMUXC_UART4_RX_DATA_I2C1_SDA, 0xF0B0);  I2C1->I2CR &= ~(1 << 7);I2C1->IFDR = 0x15;I2C1->I2CR |= (1 << 7);    }void i2c_write(I2C_Type *base, unsigned char device_address, unsigned char reg_address, const unsigned char *data, int len)
{base->I2SR &= ~((1 << IAL) | (1 << IIF));while((base->I2SR & (1 << ICF)) == 0);base->I2CR |= (1 << MSTA) | (1 << MTX);base->I2CR &= ~(1 << TXAK);base->I2SR &= ~(1 << IIF);base->I2DR = device_address << 1;while((base->I2SR & (1 << IIF)) == 0);base->I2SR &= ~(1 << IIF);base->I2DR = reg_address;while((base->I2SR & (1 << IIF)) == 0);  while(len--){base->I2SR &= ~(1 << IIF);base->I2DR = *data++;while((base->I2SR & (1 << IIF)) == 0);         }base->I2CR &= ~(1 << MSTA);while((base->I2SR & (1 << IBB)) != 0){delayus(100);}
}void i2c_read(I2C_Type *base, unsigned char device_address, unsigned char reg_address, unsigned char *data, int len)
{base->I2SR &= ~((1 << IAL) | (1 << IIF));while((base->I2SR & (1 << ICF)) == 0);base->I2CR |= (1 << MSTA) | (1 << MTX);base->I2CR &= ~(1 << TXAK);base->I2SR &= ~(1 << IIF);base->I2DR = device_address << 1;while((base->I2SR & (1 << IIF)) == 0);base->I2SR &= ~(1 << IIF);base->I2DR = reg_address;while((base->I2SR & (1 << IIF)) == 0);  base->I2CR |= (1 << RSTA);base->I2SR &= ~(1 << IIF);   base->I2DR = device_address << 1 | 1;while((base->I2SR & (1 << IIF)) == 0); base->I2CR &= ~(1 << MTX);base->I2SR &= ~(1 << IIF);  if(1 == len){base->I2CR |= (1 << TXAK);}*data = base->I2DR;while(len-- != 0){while((base->I2SR & (1 << IIF)) == 0);base->I2SR &= ~(1 << IIF);  if(len == 0)        {base->I2CR &= ~((1 << MSTA) | (1 << TXAK));while((base->I2SR & (1 << IBB)) != 0){delayus(100);}}else if(len == 1){base->I2CR |= (1 << TXAK);}*data++ = base->I2DR;}
}

2.i2c.h

#ifndef _I2C_H_
#define _I2C_H_#include "MCIMX6Y2.h"
extern void init_i2c1(void);
extern void i2c_write(I2C_Type *base, unsigned char device_address, unsigned char reg_address, const unsigned char *data, int len);
extern void i2c_read(I2C_Type *base, unsigned char device_address, unsigned char reg_address, unsigned char *data, int len);#endif

3.main.c

#include "beep.h"
#include "led.h"
#include "key.h"
#include "MCIMX6Y2.h" 
#include "core_ca7.h"
#include "gpio.h"
#include "interrupt.h"
#include "clock.h"
#include "epit.h"#include "gpt.h"
#include "delay.h"#include "uart.h"#include "stdio.h"
#include "i2c.h"int main(void)
{init_clock();system_interrupt_init();init_led();init_beep();//init_key();//init_epit1();init_gpt1();init_uart1(); init_i2c1();// const char *s = "Hello";// i2c_write(I2C1, 0x50, 0, (unsigned char *)s, 5);// printf("I2C Write OK");// delayms(500);// unsigned char buffer[16] = {0};// i2c_read(I2C1, 0x50, 0, buffer, 5);// puts((char *)buffer);while(1){char s1[16];scanf("%s", s1);i2c_write(I2C1, 0x50, 0, (unsigned char *)s1, strlen(s1));delayms(500);char s2[16] = {0};i2c_read(I2C1, 0x50, 0, (unsigned char *)s1, strlen(s1));puts((char *)s2);}return 0;
}

http://www.dtcms.com/a/392599.html

相关文章:

  • AI.工作助手.工作提效率
  • 【开题答辩全过程】以 Louis宠物商城为例,包含答辩的问题和答案
  • 微服务-网络模型与服务通信方式openfein
  • 如何快速定位局域网丢包设备?
  • 算法<java>——排序(冒泡、插入、选择、归并、快速、计数、堆、桶、基数)
  • 深入浅出CMMI:从混乱到卓越的研发管理体系化之路
  • Docker一键部署prometheus并实现飞书告警详解
  • 基于“开源AI大模型AI智能名片S2B2C商城小程序”的多平台资源位传播对直播营销流量转化的影响研究
  • 【设计模式】适配器模式 在java中的应用
  • 2013/07 JLPT听力原文 问题四
  • MyBatis 缓存体系剖析
  • MySQL 主从复制 + MyCat 读写分离 — 原理详解与实战
  • Vmake AI:美图推出的AI电商商品图编辑器,快速生成AI时装模特和商品图
  • Debian13 钉钉无法打开问题解决
  • 02.容器架构
  • Diffusion Model与视频超分(1):解读淘宝开源的视频增强模型Vivid-VR
  • 通过提示词工程(Prompt Engineering)方法重新生成从Ollama下载的模型
  • 有没有可以检测反爬虫机制的工具?
  • 大模型为什么需要自注意力机制?
  • 长度为K子数组中的最大和-定长滑动窗口
  • Linux安装Kafka(无Zookeeper模式)保姆级教程,云服务器安装部署,Windows内存不够可以看看
  • WEEX编译|续写加密市场叙事
  • 为 Element UI 表格增添排序功能
  • 点评项目(Redis中间件)第四部分缓存常见问题
  • 动态水印也能去除?ProPainter一键视频抠图整合包下载
  • DevSecOps 意识不足会导致哪些问题
  • LeetCode:27.合并两个有序链表
  • 适用于双节锂电池的充电管理IC选型参考
  • 格式说明符
  • 层数最深叶子节点的和(深度优先搜索)