Linux 学习记录59(ARM篇)

这篇具有很好参考价值的文章主要介绍了Linux 学习记录59(ARM篇)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Linux 学习记录59(ARM篇)

Linux 学习记录59(ARM篇),Linux学习记录,linux,学习,arm开发,IIC

一、IIC总线

1. 概念

  1. I2C总线是PHLIPS公司在八十年代初推出的一种串行半双工同步总线,主要用于连接整体电路
  1. 两个芯片之间通讯 SOC(stm32mp157a)<------- IIC总线 ------->温湿度传感器(si7006)
  2. 两个设备之间通讯 PC<------ UART总线 ------>开发板
  1. I2C总线为两线制,只有两根双向信号线,一根是数据线SDA,另一根是时钟线SCL
  1. SDA数据线作用:完成数据传输
  2. SCL时钟线作用:完成数据收发同步
  1. IIC传输速率
  1. 低速:100K
  2. 中速:400K
  3. 高速:3.4M
  1. I2C硬件结构简单,接口连接方便,成本较低。因此在各个领域得到了广泛的应用
  2. 、IIC总线外接两个上拉电阻作用:在总线处于空闲状态时,SCL线和SDA线处于高电平状态

Linux 学习记录59(ARM篇),Linux学习记录,linux,学习,arm开发,IIC

2. IIC总线硬件连接

Linux 学习记录59(ARM篇),Linux学习记录,linux,学习,arm开发,IIC

1. IIC总线支持多主机多从机模式,在同一时刻,只能与一个从机进行通讯
2. 在实际使用过程中,大多数都使用单主机多从机模式
3. 挂接到IIC总线上的每个从机设备,都有自己唯一的7位从机地址(从对应的芯片手册中进行查找从机地址)
4. 主动发起数据的叫做主机(起始信号),只能被动接收数据的叫做从机
5. 在总线上,发送数据叫做发送器,接收数据的叫做接收器
6. 起始信号、时钟信号、停止信号都是由主机产生
7. 时钟信号只能由主机产生,作用给从机,完成数据收发同步

二、系统框图

Linux 学习记录59(ARM篇),Linux学习记录,linux,学习,arm开发,IIC

三、IIC时序

1. 起始信号 / 停止信号

Linux 学习记录59(ARM篇),Linux学习记录,linux,学习,arm开发,IIC

1、起始信号:在SCL为高电平期间,SDA从高到低的变化(下降沿)
2、停止信号:在SCL为高电平期间,SDA从低到高的变化(上升沿)
3、起始信号和停止信号由主机产生
4、起始信号产生之后,总线处于占用状态
5、停止信号产生之后,总线处于空闲状态

2. 数据传输信号

Linux 学习记录59(ARM篇),Linux学习记录,linux,学习,arm开发,IIC

1、在SCL为高电平期间,数据线上数据保持稳定,接收器从数据线上读取数据
2、在SCL为低电平期间,数据线上数据允许发生变化,发送器向数据线上写入数据

3. 应答信号 / 非应答信号

Linux 学习记录59(ARM篇),Linux学习记录,linux,学习,arm开发,IIC

1、每一个字节必须保证是8位长度,数据传输时,先传送最高位,在传送低位
	每一个被传送的字节后面都必须跟随一位应答位,一帧数据 = 8位数据位 + 1位应答位 = 92、发送器在发送完8位数据之后,接收器在第九个时钟周期,返回一个应答信号(0)/非应答信号(1)
第九个时钟周期,接收器向数据线上写入应答/非应答信号
第九个时钟周期,发送器从数据线上读
读0:应答信号
读1:非应答信号

4. 寻址信号

Linux 学习记录59(ARM篇),Linux学习记录,linux,学习,arm开发,IIC

1、IIC总线上数据传输是广义的,包括从机地址,传输数据信号
2、在起始信号产生之后,寻址从机,需要发送7位从机地址 +(1)/(0)
3、从总线上读取数据:7位从机地址 +(1)
4、向总线上写入数据:7位从机地址 +(0)

四、IIC协议

1. 主机给从机发送一个字节(写)

主机作为 “发送器” 从机作为“接收器”

Linux 学习记录59(ARM篇),Linux学习记录,linux,学习,arm开发,IIC

IIC_Start();//起始信号
/*add_RH 为从机地址例如0x40 或上0表示要写入数据*/
IIC_Send_Byte((add_RH << 1) | 0);//发送从机地址
IIC_Wait_Ack();//等待回应
/*USER_W表示要写入的寄存器或命令*/
IIC_Send_Byte(USER_W);//发送从机地址
IIC_Wait_Ack();//等待回应
/*start_M表示要写入该寄存器的数据*/
IIC_Send_Byte(start_M);//发送从机地址
IIC_Wait_Ack();//等待回应
IIC_Stop();

2. 主机给从机发送多个连续字节

每发送一个8位数据后寄存器地址自动偏移
Linux 学习记录59(ARM篇),Linux学习记录,linux,学习,arm开发,IIC

3. 从机给主机发送一个字节(读)

Linux 学习记录59(ARM篇),Linux学习记录,linux,学习,arm开发,IIC

uint8_t buf;
IIC_Start();//起始信号
/*add_RH 为从机地址例如0x40 或上0表示要写入数据*/
IIC_Send_Byte(add_RH << 1);//发送从机地址
IIC_Wait_Ack();//等待回应
/*USER_R表示要读取的寄存器或命令*/
IIC_Send_Byte(USER_R);//发送从机命令
IIC_Wait_Ack();//等待回应
/*从机开始作为发送方*/
IIC_Start();//起始信号
/*add_RH 为从机地址例如0x40 或上1表示要读取数据*/
IIC_Send_Byte((add_RH << 1) |1);//发送从机地址
IIC_Wait_Ack();//等待回应
/*IIC_R_NACK 表示不读取后续数据*/
buf= IIC_Read_Byte(IIC_R_NACK);//IIC读取一个字节
IIC_Stop();

4. 从机给主机发送多个连续字节

Linux 学习记录59(ARM篇),Linux学习记录,linux,学习,arm开发,IIC文章来源地址https://www.toymoban.com/news/detail-612319.html

五、软件模拟IIC

1. IIC的GPIO初始化

//初始化IIC
void IIC_Init(void)
{			
    GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_MP_AHB4_ENSETR |= (0x1 << 1);//使能GPIO F-E时钟;//使能GPIOB时钟

    //GPIOB8,B9初始化设置
    GPIO_InitStructure.GPIO_Pin = IIC_SCL_Pin;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Fast_Speed;//100MHz
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
    GPIO_Init(IIC_GPIOx, &GPIO_InitStructure);//初始化

    GPIO_InitStructure.GPIO_Pin = IIC_SDA_Pin;
    GPIO_Init(IIC_GPIOx, &GPIO_InitStructure);//初始化

    IIC_SCL_H;//将时钟线和数据线拉高
    IIC_SDA_H;
}

2. 宏定义及函数声明

#define IIC_GPIOx GPIOF

#define IIC_R_ACK 1
#define IIC_R_NACK 0

#define IIC_SCL_Pin 14
#define IIC_SDA_Pin 15

#define IIC_SCL_H   GPIO_SetBits(IIC_GPIOx,IIC_SCL_Pin)
#define IIC_SDA_H   GPIO_SetBits(IIC_GPIOx,IIC_SDA_Pin)

#define IIC_SCL_L   GPIO_ResetBits(IIC_GPIOx,IIC_SCL_Pin)
#define IIC_SDA_L   GPIO_ResetBits(IIC_GPIOx,IIC_SDA_Pin)

#define READ_SDA	GPIO_ReadInputDataBit(IIC_GPIOx,IIC_SDA_Pin)


//IIC所有操作函数
void IIC_Init(void);                //初始化IIC的IO口				 
void IIC_Start(void);				//发送IIC开始信号
void IIC_Stop(void);	  			//发送IIC停止信号
void IIC_Send_Byte(uint8_t txd);			//IIC发送一个字节
uint8_t IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
uint8_t IIC_Wait_Ack(void); 				//IIC等待ACK信号
void IIC_Ack(void);					//IIC发送ACK信号
void IIC_NAck(void);				//IIC不发送ACK信号

3. 切换SDA的GPIO模式

void SDA_OUT(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    //GPIOB8,B9初始化设置
    GPIO_InitStructure.GPIO_Pin = IIC_SDA_Pin;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Fast_Speed;//100MHz
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
    GPIO_Init(IIC_GPIOx, &GPIO_InitStructure);//初始化
}

void SDA_IN(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    //GPIOB8,B9初始化设置
    GPIO_InitStructure.GPIO_Pin = IIC_SDA_Pin;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输出模式
    GPIO_Init(IIC_GPIOx, &GPIO_InitStructure);//初始化
}

4. 起始信号

//产生IIC起始信号
void IIC_Start(void)
{
	SDA_OUT();     //sda线输出
    IIC_SDA_H;
	IIC_SCL_H;
	delay_us(4);
 	IIC_SDA_L;//START:when CLK is high,DATA change form high to low 
	delay_us(4);
	IIC_SCL_L;//钳住I2C总线,准备发送或接收数据 
}

5. 停止信号

//产生IIC停止信号
void IIC_Stop(void)
{
	SDA_OUT();//sda线输出
	IIC_SCL_L;
	IIC_SDA_L;//STOP:when CLK is high DATA change form low to high
 	delay_us(4);
	IIC_SCL_H;
    IIC_SDA_H;//发送I2C总线结束信号
	delay_us(4);							   	
}

6. 等待应答信号

//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
uint8_t IIC_Wait_Ack(void)
{
	uint8_t ucErrTime=0;
	SDA_IN();      //SDA设置为输入  
	IIC_SDA_H;delay_us(1);	   
	IIC_SCL_H;delay_us(1);	 
	while(READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL_L;//时钟输出0 	   
	return 0;  
}

7. ACK应答

//产生ACK应答
void IIC_Ack(void)
{
	IIC_SCL_L;
	SDA_OUT();
	IIC_SDA_L;
	delay_us(2);
	IIC_SCL_H;
	delay_us(2);
	IIC_SCL_L;
}
//不产生ACK应答		    
void IIC_NAck(void)
{
	IIC_SCL_L;
	SDA_OUT();
	IIC_SDA_L;
	delay_us(2);
	IIC_SCL_H;
	delay_us(2);
	IIC_SCL_L;
}

8. 发送/读取一个字节

//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答			  
void IIC_Send_Byte(uint8_t txd)
{                        
    uint8_t t;   
	SDA_OUT(); 	    
    IIC_SCL_L;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {
        if((txd&0x80)>>7){
            IIC_SDA_H;
        }else{
            IIC_SDA_L;
        }
        txd<<=1; 	  
		delay_us(2);   //对TEA5767这三个延时都是必须的
		IIC_SCL_H;
		delay_us(2); 
		IIC_SCL_L;	
		delay_us(2);
    }	 
} 	    
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
uint8_t IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
	{
        IIC_SCL_L; 
        delay_us(2);
		IIC_SCL_H;
        receive<<=1;
        if(READ_SDA)
            receive |= 1;   
        else 
            receive |= 0; 

		delay_us(1); 
    }					 
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}

到了这里,关于Linux 学习记录59(ARM篇)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux 学习记录53(ARM篇)

    在下图界面中可以搜索指定的内存地址 (1. 前索引方式 (2. 后索引方式 (3. 自动索引 结合了前两者的索引方式 (1. 操作码 (2. 格式 (3. 使用示例 (4. 地址增长方式 1 ia后缀 ia后缀:先往指定的寄存器数值为起始地址中存放数据,然后该寄存器数值自动偏移 例:stmia r6!,{r1-r5} 2 ib后缀

    2024年02月16日
    浏览(35)
  • Linux 学习记录54(ARM篇)

    以STM32MP157为例 相关数据手册在文章顶部下载 (1. RCC寄存器 2.5.2 (2. GPIO寄存器 1. 模式配置寄存器 2. 输出模式配置寄存器 3. 速度配置寄存器 4. 上下拉配置寄存器 5. GPIO输出寄存器 (1. RCC寄存器配置 (2. GPIO寄存器配置

    2024年02月16日
    浏览(31)
  • 记录移植Python3到arm开发板linux系统中

    开发板情况 arm板是公司采购的工控机。主要用来 使用python3解析excel表格处理数据。 配置如下: 配置 版本 cpu imx6dl(armv7架构) 操作系统 linux3.10 python版本 2.7 项目情况 项目中最好使用 python3 。可行的有以下几种方式: 方式 优缺点 可行度 重做文件系统 订制程度比较高,后期增

    2024年02月04日
    浏览(50)
  • 嵌入式培训机构四个月实训课程笔记(完整版)-Linux ARM驱动编程第四天-ARM Linux编程之IIC与uart (物联技术666)

    链接:https://pan.baidu.com/s/1V0E9IHSoLbpiWJsncmFgdA?pwd=1688 提取码:1688 教学内容: 1 、 I2C 总线: I2C(Inter-Integrated Circuit),PHILIPS公司开发的两线式半双工同步串行总线;可以用来连接存储器(EEPROM、FLASH)、A/D、D/A转换器、LCD驱动器、传感器等等。 I2C总线有两根信号线:双向数据线

    2024年02月19日
    浏览(43)
  • ARM开发之基于IIC协议的TM1650驱动实现(模拟IIC实现)

    目录 一、内存映射 1、什么是内存映射?为什么要内存映射? 2、gec6818如何进行内存映射?(相关的函数) 3、内存映射代码 : 二、模拟IIC的底层代码实现 1、配置输入输出方向 2、拉高拉低引脚 3、获得总线传回的数据 4、协议的实现 三、TM1650的使用 1、TM1650简介 2、TM1650怎

    2024年02月12日
    浏览(42)
  • ARM+LINUX嵌入式学习路线

    嵌入式学习是一个循序渐进的过程,如果是希望向嵌入式软件方向发展的话,目前最常见的是嵌入式Linux方向,关注这个方向,大概分3个阶段: 1、嵌入式linux上层应用,包括QT的GUI开发 2、嵌入式linux系统开发 3、嵌入式linux驱动开发 嵌入式目前主要面向的几个操作系统是,

    2024年02月02日
    浏览(60)
  • 【Linux下6818开发板(ARM)】硬件空间挂载

    (꒪ꇴ꒪ ),hello我是 祐言 博客主页:C语言基础,Linux基础,软件配置领域博主🌍 快上🚘,一起学习! 送给读者的一句鸡汤🤔: 集中起来的意志可以击穿顽石! 作者水平很有限,如果发现错误,可在评论区指正,感谢🙏         在嵌入式系统开发中,经常需要使用外部硬件

    2024年02月14日
    浏览(40)
  • linux下arm环境启动脚本/etc/init.d/rcS执行命令失败,踩坑记录

    记一次踩坑记录!!! 接触到一个新的系统,需要在这个系统上跑程序,测试的时候,手动执行脚本和程序都没问题,于是将执行命令写入到linux启动脚本/etc/init.d/rcS这个文件中,然后重启,等待程序起来,但是让我意想不到的是,执行到我加的命令的时候,居然报错,找不

    2024年01月21日
    浏览(42)
  • Rust在linux下交叉编译到arm开发板

    前段时间做了rust交叉编译到arm开发板,如果引入的包有些包含OpenSSL,ring...遇见了很多问题在网上也查阅很多资料,今天抽个时间做个汇总吧。 虚拟机里面安装rust环境,做到交叉编译的时候应该都已经有了,这个地方就不过多说了,网上找一下就有的 首先描述一下我的环境

    2024年02月15日
    浏览(48)
  • [ARM+Linux] 基于全志h616外设开发笔记

    修改用户密码 配置网络 nmcli dev wifi  命令扫描周围WIFI热点   nmcli dev wifi connect  xxx  password xxx 命令 连接WiFi 查看ip地址的指令: ifconfig ip addr show wlan0 SSH登录         这是企业开发调试必用方式,比串口来说不用接线,前提是接入网络并获得板子IP 地址,且系统做了SSH的

    2023年04月21日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包