STM32重难点-IIC原理及应用详细步骤

发布者:脑力风潮最新更新时间:2022-05-29 来源: eefocus关键字:STM32 手机看文章 扫描二维码
随时随地手机看文章

IIC概述

IIC介绍

I2C(IIC,Inter-Integrated Circuit),两线式串行总线,由PHILIPS公司开发用于连接微控制器及其外围设备。它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbps以上。是半双工通信方式。


IIC特性


相对于UART,IIC的优点在于可以一对多,缺点在于无论主从器件均不对消息进行确认。


模拟IIC优点是可以任意选择SDA和SCL,不受管脚限制而比较灵活。它的缺点是不可用DMA。


硬件IIC优点是可用DMA减轻CPU负担,速度也比模拟IIC快,但是实际调试时可能会出现死锁。


IIC时钟信号是由主控器件产生,所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。对于并联在一条总线上的每个IC都有唯一的地址。


一般情况下,数据线SDA和时钟线SCL都是处于上拉电阻状态。因为:在总线空闲状态时,这两根线一般被上面所接的上拉电阻拉高,保持着高电平。

 在这里插入图片描述

IIC各种状态解析

在这里插入图片描述

空闲状态

I2C总线总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。

 

开/起始信号(必须的)

当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变(边沿触发)时序信号,而不是一个 电平信号。


在这里插入图片描述

停止信号(非必须)

当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。

在这里插入图片描述

应答信号(非必须)

发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。


应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;

应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。

注:如图接收器在第9个时钟脉冲之前的低电平期间将数据线SDA拉低,并且确保在该时钟的高电平期间为稳定的低电平。

在这里插入图片描述

数据的有效性


I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。

即:数据在SCL的上升沿到来之前就需准备好。并在在下降沿到来之前必须稳定。

在这里插入图片描述

数据传输


在I2C总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。数据位的传输是边沿触发。


IIC底层代码

IIC.h


#ifndef __IIC_H

#define __IIC_H

#include "stm32f4xx.h"

#include "sys.h"



#define SCL  PBout(8)

#define SDA_OUT  PBout(9)

#define SDA_IN  PBin(9)


void Iic_Init(void);

void AT24C02_Write(u8 addr, u8 *write_buf, u8 len);

void AT24C02_Read(u8 addr, u8 *read_buf, u8 len);


#endif


IIC.c


#include "iic.h"

#include "delay.h"


/*

引脚说明:


PB8 -- SCL

PB9 -- SDA



*/


void Iic_Init(void)

{

GPIO_InitTypeDef  GPIO_InitStruct;


RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);


GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9; //引脚8 9

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; //输出模式

GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; //推挽

GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //快速

GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;     //上拉

GPIO_Init(GPIOB, &GPIO_InitStruct);


//总线空闲

SCL = 1;

SDA_OUT = 1;

}


//SDA模式

void Iic_Sda_Mode(GPIOMode_TypeDef Mode)

{

GPIO_InitTypeDef  GPIO_InitStruct;

GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; //引脚9

GPIO_InitStruct.GPIO_Mode = Mode;

GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; //推挽

GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //快速

GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;     //上拉

GPIO_Init(GPIOB, &GPIO_InitStruct);


}



//开始信号

void Iic_Start(void)

{

Iic_Sda_Mode(GPIO_Mode_OUT);


//总线空闲

SCL = 1;

SDA_OUT = 1;

delay_us(5);

SDA_OUT = 0;

delay_us(5);

SCL = 0;  //钳住总线

}


//停止信号

void Iic_Stop(void)

{

Iic_Sda_Mode(GPIO_Mode_OUT);

SCL = 0;

SDA_OUT = 0;

delay_us(5);

SCL = 1;

delay_us(5);

SDA_OUT = 1;

}


//发送一位数据 

void Iic_Send_Ack(u8 ack)

{

Iic_Sda_Mode(GPIO_Mode_OUT);

SCL = 0;

//准备数据

//要发数据1

if(ack == 1)

{

SDA_OUT = 1; //引脚输1

}

//要发数据0

if(ack == 0)

{

SDA_OUT = 0; //引脚输0

}

delay_us(5);

SCL = 1;

delay_us(5);

SCL = 0;


}


//发一个字节

void Iic_Send_Byte(u8 data)

{

u8 i;

Iic_Sda_Mode(GPIO_Mode_OUT);

SCL = 0;

for(i=0; i<8; i++)

{

//准备数据 如数据 0x87 1 0 0 0 0 1 1 1 

if(data & (1<<(7-i)))  

{

SDA_OUT = 1; //引脚输1

}

//要发数据0

else

{

SDA_OUT = 0; //引脚输0

}

delay_us(5);

SCL = 1;

delay_us(5);

SCL = 0;

}


}


//接受一位数据

u8 Iic_Recv_Ack(void)

{

u8 ack = 0;

Iic_Sda_Mode(GPIO_Mode_IN);

SCL = 0;

delay_us(5);

SCL = 1;

delay_us(5);

if(SDA_IN == 1) //判断引脚电平是否为高电平

{

ack = 1;

}

if(SDA_IN == 0) //判断引脚电平是否为低电平

{

ack = 0;

}

SCL = 0;


return ack;

}


//接受一个字节

//表示读取一个字节之后,需要给对方应答信号或非应答信号。

u8 Iic_Recv_Byte(void)

{

u8 i, data = 0;  //0 0 0 0 0 0 0 0

Iic_Sda_Mode(GPIO_Mode_IN);

SCL = 0;

//循环8次,接受一个字节

for(i=0; i<8; i++)

{

delay_us(5);

SCL = 1;

delay_us(5);

if(SDA_IN == 1) //判断引脚电平是否为高电平

{

data |= (1<<(7-i));

}


SCL = 0;

}

return data;

}


24C02–EEPROM

简介

24C02是一个2K位串行CMOS 的EEPROM,内部含有256个8位字节。

与 400KHz I2C 总线兼容

1.8 到 6.0 伏工作电压范围

低功耗 CMOS 技术

写保护功能 当 WP 为高电平时进入写保护状态

页写缓冲器

自定时擦写周期

1,000,000 编程/擦除周期

可保存数据 100 年

8 脚 DIP SOIC 或 TSSOP 封装

温度范围 商业级 工业级和汽车级

本人所用的stm32f4:总容量是256(2K/8)个字节,接口:IIC

在这里插入图片描述
在这里插入图片描述

写入过程

发送器件地址(0XA0)

发送要写入24C02的内存地址

发送要写入的数据

高四位1010是24Cxx系列的固定器件地址,接下来是A2、A1、A0是根据器件连接来决定,我们的原理图都接地所以是000。R/W为是选择读还是写,1的时候是读,0的时候是写。所以写的地址为0xA0。

在这里插入图片描述
在这里插入图片描述

读出过程

发送写入的器件地址(0XA0)

发送要读的24C02的内存地址

发送读出的器件地址(0XA1)

读取数据

当读取的时候,地址的最后一位R/W为是选择读,也就是该位为1。所以读取的地址为0xA1。

在这里插入图片描述

24C02的读写代码

void AT24C02_Write(u8 addr, u8 *write_buf, u8 len)

{

u8 ack;

//开始信号

Iic_Start();

//发送设置地址,并执行写操作

Iic_Send_Byte(0xA0);

ack = Iic_Recv_Ack();

if(ack == 1)

{

printf("ack failuren");

Iic_Stop();

return;

}

//发送写数据的起始地址

Iic_Send_Byte(addr);

ack = Iic_Recv_Ack();

if(ack == 1)

{

printf("ack failuren");

Iic_Stop();

return;

}

while(len--)

{

//发送数据

Iic_Send_Byte(*write_buf);

ack = Iic_Recv_Ack();

if(ack == 1)

{

printf("ack failuren");

Iic_Stop();

return;

}

//地址加1

write_buf++;

}

Iic_Stop();

printf("write finishn");


}



void AT24C02_Read(u8 addr, u8 *read_buf, u8 len)

{

u8 ack;

//开始信号

Iic_Start();

//发送设置地址,并执行写操作

Iic_Send_Byte(0xA0);

ack = Iic_Recv_Ack();

if(ack == 1)

{

printf("ack failuren");

Iic_Stop();

return;

}

//发送读数据的起始地址

Iic_Send_Byte(addr);

ack = Iic_Recv_Ack();

if(ack == 1)

{

printf("ack failuren");

Iic_Stop();

return;

}

//开始信号

Iic_Start();

//发送设置地址,并执行读操作

Iic_Send_Byte(0xA1);

ack = Iic_Recv_Ack();

if(ack == 1)

{

printf("ack failuren");

Iic_Stop();

return;

}

while(len--)  //len = 5

{

// len 4 3 2 1 0

//接受数据

*read_buf = Iic_Recv_Byte();

//地址加1

read_buf++;

if(len > 0)

Iic_Send_Ack(0);

}

//发送非应答

Iic_Send_Ack(1);

Iic_Stop();

printf("read finishn");

}


IIC总结

进行数据传送时,在SCL为高电平期间,SDA线上电平必须保持稳定,只有SCL为低时,才允许SDA线上电平改变状态。并且每个字节传送时都是高位在前;

对于应答信号,ACK=0时为有效应答位,说明从机已经成功接收到该字节,若为1则说明接受不成功;

如果从机需要延迟下一个数据字节开始传送的时间,可以通过把SCL电平拉低并保持来强制主机进入等待状态;

主机完成一次通信后还想继续占用总线在进行一次通信,而又不释放总线,就要利用重启动信号。它既作为前一次数据传输的结束,又作为后一次传输的开始;

总线冲突时,按“低电平优先”的仲裁原则,把总线判给在数据线上先发送低电平的主器件;

在特殊情况下,若需禁止所有发生在I2C总线上的通信,可采用封锁或关闭总线,具体操作为在总线上的任一器件将SCL锁定在低电平即可;

SDA仲裁和SCL时钟同步处理过程没有先后关系,而是同时进行的。

关键字:STM32 引用地址:STM32重难点-IIC原理及应用详细步骤

上一篇:初学stm32-外部中断(EXTI按键中断)
下一篇:STM32进阶-独立看门狗应用的详细步骤

推荐阅读最新更新时间:2024-11-10 11:12

STM32-外部中断学习笔记
中断分类 STM32的EXTI控制器支持19 个外部中断/ 事件请求。每个中断设有状态位,每个中断/ 事件都有独立的触发和屏蔽设置。 STM32的19个外部中断对应着19路中断线,分别是EXTI_Line0-EXTI_Line18: 线0~15:对应外部 IO口的输入中断。 线16:连接到 PVD 输出。 线17:连接到 RTC 闹钟事件。 线18:连接到 USB 唤醒事件。 触发方式:STM32 的外部中断是通过边沿来触发的,不支持电平触发。 外部中断分组:STM32 的每一个GP
[单片机]
STM32-外部中断学习笔记
stm32 pwm的原理及主要参数的意义
pwm的原理如图 ARR:最值,定时器最值 CCRx:PWM的比较值 CNT:为计数器值 原理就是,CCRx的值和CNT比较大小,通过判断结果来决定输出是高电平还是低电平。 将代码定位到TIM_OC_InitTypeDef类中,然后看注释 uint32_t Pulse; /*! Specifies the pulse value to be loaded into the Capture Compare Register. This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */
[单片机]
用VisualStudio开发STM32遇到的问题(一)
我现在已经用VS2017写STM32的程序有一段时间了,在这段时间里,遇到了不少问题,今天就和大家分享一下有关于printf的故事.... 之前用MDK开发STM32的时候用正点原子教给大家的printf,很好用,但是在VS上,一直打印不出来东西,于是,我打算重新写printf 废话不多说,直接上代码 void myPrintf(char* fomat, ...) { char buf = ; char* p; u16 i = 0; int num; float fnum; char* str; char tem = ; va_list va; va_start(va, fomat); p = fom
[单片机]
用VisualStudio开发<font color='red'>STM32</font>遇到的问题(一)
STM32 实战 按键点亮LED(中断)
来看看最简单的点亮一个灯的实验你把,实验要求使用KEY4*4按键,按键按下灯亮,按键拿起灯灭,如此一直循环: 程序的思路如下: 1、首先需要设置的是时钟:你将灯的管脚连在哪个端口的某个引脚上面,你就开启哪个端口的时钟,比如灯连在A端口的某个引脚,就要开启A端口的时钟。 2、其次,设置管脚(我们要设置LED和矩阵键盘中的一个键的管脚): 我们需要对GPIO进行初始化设置,我们只需调用 GPIO_InitTypeDef的结构体,对每个成员进行设置,要设置的有PIN管脚的位置GPIO_Pin,还有管脚的速率GPIO_Speed,还有管脚的工作状态GPIO_Mode,最后在调用一下初始化的函数GPIO_Init, 3、然后就开始写我们的
[单片机]
stm32 引脚功能设定及应用
GPIO_Mode_AIN = 0x0, 模拟输入 GPIO_Mode_IN_FLOATING = 0x04, 浮空输入 GPIO_Mode_IPD = 0x28, 带下拉输入 GPIO_Mode_IPU = 0x48, 带上拉输入 GPIO_Mode_Out_OD = 0x14, 表示配置相应管脚为GPIO开漏输出(真双向IO) GPIO_Mode_Out_PP = 0x10, 通用推挽输出模式 GPIO_Mode_AF_OD = 0x1C, 表示配置相应管脚为复用功能的开漏输出 GPIO_Mode_AF_PP = 0x18 复用功能的推挽输出模式 推挽输出:可以输出高
[单片机]
stm32串口usart的使用
一、串口的定义 用来与外界交互数据。 二、usart的配置: 1、开启时钟。 stm32的usart1挂载在apb2上,USART2、usart3挂载在apb1上。 2、串口的基本配置。 void USART1_Configuration(void) { USART_InitTypeDef USART_InitStructure; USART_DeInit (USART1 ); USART_InitStructure .USART_BaudRate =9600; USART_InitStructure .USART_WordLength =USART_WordLength_8b ; USART_InitStructure .USA
[单片机]
STM32 USB学习笔记1
主机环境:Windows 7 SP1 开发环境:MDK5.14 目标板:STM32F103C8T6 开发库:STM32F1Cube库和STM32_USB_Device_Library 之前在STM32论坛里领取过一块STM32开发板,本来以为是带有USB模块接口的,最后发现NUCLEO里是没有把USB模块外接出来的,所以就自个儿掏钱买了一块单板,如下图所示: 单板很简单,单纯是为了学习一下STM32的USB模块,之所以选择这个是因为它便宜,而且ST官方有提供USB模块库方便开发。 USB开发博大精深,比之串口,SPI,I2C来说多了很多东西,一个很简单的例子就是串口,SPI,I2C都可以使用通用IO口
[单片机]
<font color='red'>STM32</font> USB学习笔记1
STM32流水灯实验编程
首先,在上一节的模板基础上建立一个新的Keil工程,取名为LED。打开main.c函数,可以直接在这里写代码,当然也可以重新建立.c文件,这里我们直接在main文件中写程序。第一步,也是最重要的一步就是配置作为输出的IO口,代码如下: GPIO_InitTypeDef GPIO_Structure; //定义GPIO结构体 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); //使能PEIO口的时钟 GPIO_Structure.GPIO_Pin = GPIO_Pin_9; //结构体引脚为PE9 GPIO_Structure.GPIO_Mode = GPIO_
[单片机]
<font color='red'>STM32</font>流水灯实验编程

推荐帖子

基于ARM+fpga架构的运动控制卡
有从事ARM+FPGA架构运动控制卡底层开发的朋友,愿意出售方案的请联系我,企鹅号37353543需要4轴控制,最少3轴联动,带直线圆弧插补,S样条曲线等基本功能,最好是以太网接口。本论坛中有相关论文基于ARM+fpga架构的运动控制卡
tanic1985 ARM技术
【ST NUCLEO-U5A5ZJ-Q开发板测评】01 开箱
前言感谢EEWorld提供这次试用STNUCLEO-U5A5ZJ-Q开发板的机会,也非常感谢ST提供这次机会,这是个人首次申请到试用ST开发板的机会,谢谢。在微信群里看到一些大佬推荐ST开发板时,多次提到这款开发板,并且也看到它的存储竟然有4MB,所以就想体验一下,这块开发板。一、开箱得知入围名单,还是很开心的,立马就去确认信息了。过了几天,收到快递,ST的包装是这样的,依然具有ST的特色,还采用了环保包装。先给开发板来一个怼脸照。二、板载资源
怀揣少年梦 stm32/stm8
硬件面试题目-基础知识
电阻、电容、电感封装的含义:0402、0603、0805表示的是尺寸参数。0402:40*20mil;0603:60*30mil;0805:80*50mil字母所代表的电容的精度:J、K、M、ZJ——±5%;K——±10%;M——±20%;Z——+80%~-20%电阻、电容、电感的封装大小分别与什么参数有关电阻封装大小与电阻值、额定功率有关;电容封装大小与电容值、额定电压有关;电感封装大小与电感量、额定电流有关。常
cheungchew 模拟电子
找到个坦克底座,看起来不错!
找到个坦克底座,看起来不错!就是价格高了点找到个坦克底座,看起来不错!看不清,图片这么小也不说说哪里有还谈什么价格,显摆么大的弄不下来啊!TAOBAO里看到的368一台回复沙发wangfuchong的帖子有点贵啊!!你也看到这个底盘了啊近期我们也打算做个履带地盘,到时候来分享啦坐等楼上DIY履带地盘,,,,看看这个全金属的
蓝雨夜 DIY/开源硬件专区
【15周年庆】约不?一起来DIY电子工具箱~功能你做主
Hello,大家好~~请看我搞事情的小眼睛。作为一名电子工程师,日常工作,生活中,总要备一些常用的小工具,比如一个下载器,一个多口的转接器。那么,我们是不是可以一起来做一个常用工具的DIY呢,嗯,再打上个咱们EE的大logo~趁着EEWorld15周年打造一波DIY工具做纪念品呀~~有没有兴趣呀~~要约的小伙伴来举个小手手呀~~想法是有了,那么具体要做些什么
EEWORLD社区 DIY/开源硬件专区
五分钟科普—三大触摸屏技术In-cell、On-cell和OGS扫盲
本帖最后由jameswangsynnex于2015-3-320:02编辑目前,新兴嵌入式触摸屏技术主要可以分为三大阵营,分别是以苹果iPhone5为代表的in-cell阵营,以三星为代表的on-cell阵营和以HTC、谷歌Nexus7等为代表的OGS阵营。这三大技术在一段时间内将主导智能便携设备,这里对三大技术原理进行分析。一、OGSOGS全称OneGlassSolution,字面上的意思是单玻璃解决方案,其定义目前比较混乱。一部分技
wstt 移动便携
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved