STM32的IIC应用详解1

发布者:EtherealJourney最新更新时间:2018-09-11 来源: eefocus关键字:STM32  IIC应用 手机看文章 扫描二维码
随时随地手机看文章

概要

IIC(IIC,inter-Integrated circuit),两线式串行总线,用于MCU和外设间的通信。 
IIC只需两根线:数据线SDA和时钟线SCL。以半双工方式实现MCU和外设之间数据传输,速度可达400kbps。

多主机I2C总线结构

注意SDA和SCL两根总线需要上拉,使总线处于空闲状态。

这里写图片描述

IIC协议

空闲状态

协议规定,SDA和SCL同时为高电平时,总线处于空闲状态。上拉电阻保证电平处于高电平。

起始信号和停止信号

起始信号:SCL为高电平时,SDA电平发生高到低的跳变 
停止信号:SCL为高电平时,SDA电平发生低到高的跳变

这里写图片描述

应答信号

发送器每发送完一个字节(8个脉冲),在第9个脉冲间释放总线,接收器返回一个ACK信号,协议规定,低电平为有效应答,高电平为无效应答。

这里写图片描述

数据有效性

协议对有效数据进行了规定:即时钟信号为高电平期间,数据必须保持稳定,时钟信号低电平期间,数据线上的电平才允许变化。也就是说,数据在时钟信号到来前必须准备好,并保持到时钟信号的下降沿之后。

这里写图片描述

数据传输

I2C为同步传输,时钟控制数据位的传输,边沿触发。

驱动程序

直接引用实验中的代码。测试没问题。

起始信号


//产生IIC起始信号

void IIC_Start(void)

{

    SDA_OUT();     //sda线输出

    IIC_SDA=1;        

    IIC_SCL=1;

    delay_us(4);

    IIC_SDA=0;//START:when CLK is high,DATA change form high to low 

    delay_us(4);

    IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 

}   

停止信号


//产生IIC停止信号

void IIC_Stop(void)

{

    SDA_OUT();//sda线输出

    IIC_SCL=0;

    IIC_SDA=0;//STOP:when CLK is high DATA change form low to high

    delay_us(4);

    IIC_SCL=1; 

    IIC_SDA=1;//发送I2C总线结束信号

    delay_us(4);                                

}

有效应答


//产生ACK应答

void IIC_Ack(void)

{

    IIC_SCL=0;

    SDA_OUT();

    IIC_SDA=0;

    delay_us(2);

    IIC_SCL=1;

    delay_us(2);

    IIC_SCL=0;

}

无效应答


//不产生ACK应答          

void IIC_NAck(void)

{

    IIC_SCL=0;

    SDA_OUT();

    IIC_SDA=1;

    delay_us(2);

    IIC_SCL=1;

    delay_us(2);

    IIC_SCL=0;

}   

发送单字节


//IIC发送一个字节

//返回从机有无应答

//1,有应答

//0,无应答           

void IIC_Send_Byte(u8 txd)

{                        

    u8 t;   

    SDA_OUT();      

    IIC_SCL=0;//拉低时钟开始数据传输

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

    {              

        IIC_SDA=(txd&0x80)>>7;

        txd<<=1;      

        delay_us(2);   //对TEA5767这三个延时都是必须的

        IIC_SCL=1;

        delay_us(2); 

        IIC_SCL=0;  

        delay_us(2);

    }    

接收单字节


//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   

u8 IIC_Read_Byte(unsigned char ack)

{

    unsigned char i,receive=0;

    SDA_IN();//SDA设置为输入

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

    {

        IIC_SCL=0; 

        delay_us(2);

        IIC_SCL=1;

        receive<<=1;

        if(READ_SDA)receive++;   

        delay_us(1); 

    }                    

    if (!ack)

        IIC_NAck();//发送nACK

    else

        IIC_Ack(); //发送ACK   

    return receive;

}

EEPROM

24C02为IIC接口,容量为256字节。

封装如下图:

这里写图片描述

管脚定义:

这里写图片描述

设备地址的高四位固定,中间为地址线定义的地址,最后一位为读写位。 
由于A0,A1,A2设置为0,所以 
读的时候:Device Address = 0xA1; 
写的时候:Device Address = 0xA0;

这里写图片描述

24C02字节写时序


起始信号

写设备地址,Device Address = 0xA0;

等待应答

确定写入的EEPROM地址即WORD ADDRESS

等待应答

向SDA数据线上写入数据DATA

等待应答

停止信号

这里写图片描述


//在AT24CXX指定地址写入一个数据

//WriteAddr  :写入数据的目的地址    

//DataToWrite:要写入的数据

void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)

{                                                                                            

    IIC_Start();  

    if(EE_TYPE>AT24C16)

    {

        IIC_Send_Byte(0XA0);        //发送写命令

        IIC_Wait_Ack();

        IIC_Send_Byte(WriteAddr>>8);//发送高地址   

    }else IIC_Send_Byte(0XA0+((WriteAddr/256)<<1));   //发送器件地址0XA0,写数据   

    IIC_Wait_Ack();    

    IIC_Send_Byte(WriteAddr%256);   //发送低地址

    IIC_Wait_Ack();                                                        

    IIC_Send_Byte(DataToWrite);     //发送字节                             

    IIC_Wait_Ack();                    

    IIC_Stop();//产生一个停止条件 

    delay_ms(10);    

}

24C02字节读时序


起始信号

写设备地址,Device Address = 0xA0;

等待应答

确定写入的EEPROM地址即WORD ADDRESS

等待应答

起始信号

读设备地址,Device Address = 0xA1;

等待应答

读SDA上数据

等待应答

停止信号

这里写图片描述

//在AT24CXX指定地址读出一个数据

//ReadAddr:开始读数的地址  

//返回值  :读到的数据

u8 AT24CXX_ReadOneByte(u16 ReadAddr)

{                 

    u8 temp=0;                                                                               

    IIC_Start();  

    if(EE_TYPE>AT24C16)

    {

        IIC_Send_Byte(0XA0);       //发送写命令

        IIC_Wait_Ack();

        IIC_Send_Byte(ReadAddr>>8);//发送高地址      

    }else IIC_Send_Byte(0XA0+((ReadAddr/256)<<1));   //发送器件地址0XA0,写数据      

    IIC_Wait_Ack(); 

    IIC_Send_Byte(ReadAddr%256);   //发送低地址

    IIC_Wait_Ack();     

    IIC_Start();           

    IIC_Send_Byte(0XA1);           //进入接收模式            

    IIC_Wait_Ack();  

    temp=IIC_Read_Byte(0);         

    IIC_Stop();//产生一个停止条件       

    return temp;

}

参考


STM32F3与 F4 系列 Cortex M4 内核编程手册 

STM32F4xxx中文参考手册 

STM32F4xxx英文参考手册 

STM32F4 开发指南(寄存器版)


关键字:STM32  IIC应用 引用地址:STM32的IIC应用详解1

上一篇:STM32的IIC应用详解2
下一篇:STM32F030控制LED

推荐阅读最新更新时间:2024-03-16 16:13

STM32库函数和寄存器的区别
库函数版和寄存器版的系统时钟设置的区别: **1.**库函数的目的是让用户应用的,而寄存器更加原始 库函数的系统时钟是默认设置的,且放在启动文件里。而寄存器版的系统时钟是Stm32_Clock_Init(336,8,2,7);. **2.**库函数的快捷的,但不是每个芯片都有的;寄存器是复杂的,但是每个芯片厂商都有提供系统的寄存器设置信息。 分别打开库函数和寄存器版的I/O口设置: 库函数: RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);gotoh后先通过assert_param();函数检查格式是否正确同时只要是ENABLE,RCC- AHB1ENR |=
[单片机]
<font color='red'>STM32</font>库函数和寄存器的区别
stm32矩阵键盘原理图及程序介绍
STM32F0 系列产品基于超低功耗的 ARM Cortex-M0 处理器内核,整合增强的技术和功能,瞄准超低成本预算的应用。该系列微控制器缩短了采用 8 位和 16 位微控制器的设备与采用 32 位微控制器的设备之间的性能差距,能够在经济型用户终端产品上实现先进且复杂的功能。本文为大家介绍stm32矩阵键盘原理图及程序 stm32矩阵键盘原理图 stm32矩阵键盘程序介绍 主要实现:扫描矩阵键盘,将检测到的数据通过spi 通信发送到数码管显示。 主要步骤: 1:初始化时钟 void RCC_Configuration(void) { //----------使用外部RC晶振----------- RCC_DeIn
[单片机]
<font color='red'>stm32</font>矩阵键盘原理图及程序介绍
STM32为什么需要模块的DeInit()函数
简介:一直有一个疑惑,为什么Stm32的每个模块基本上都有一个DeInit()函数。这个函数是否和Init()函数在功能上重复了。查过一部分资料以后,发现有以下的说法。 在main()函数开始时,不管各模块处于什么状态,先执行该模块的DeInit()操作,然后在程序中较晚的时间或真正需要时再开启相应的模块。这样保证在刚进入调试状态时,调试器能够有充足的时间完成初始化和下载程序的操作。先执行该模块的DeInit()操作的目的是为了关闭哪些上一次操作开启的模块。
[单片机]
浅谈STM32 模数转换器 (ADC)(下)
温度传感器和VRENFINT通道框图 要使用传感器,请执行以下操作: 选择 ADC1_IN16 或 ADC1_IN18 输入通道。 选择一个采样时间,该采样时间要大于数据手册中所指定的最低采样时间。 在 ADC_CCR 寄存器中将 TSVREFE 位置 1,以便将温度传感器从掉电模式中唤醒。 通过将 SWSTART 位置 1(或通过外部触发)开始 ADC 转换 读取 ADC 数据寄存器中生成的 V SENSE 数据 使用以下公式计算温度: 温度(单位为 °C)= {(V SENSE — V 25 ) / Avg_Slope} + 25 其中: — V 25 = 25 °C 时的 V SENSE 值 — Avg
[单片机]
浅谈<font color='red'>STM32</font> 模数转换器 (ADC)(下)
STM32——MDK4与MDK5中对于数据类型的不同
首先我们来看MD4中的对于数据类型的定义: 然后我们跳转到其定义处查看对其的定义: typedef unsigned long u32; typedef unsigned short u16; typedef unsigned char u8; /*首先我们来认识typedef,这是用来为复杂的声明定义简单的别名,也就是说,我们可以用它来给我们的数据类型来进行定义。*/ /* 然后我们再来看之后的unsigned,unsigned用于限定后面的为无符号类型,如果后面不加什么的话,就默认为unsigned int。*/ /*unsigned long 无符号长数据 unsigned char 无符号字符型 u
[单片机]
STM32的GPIO输入输出模式配置
最近在看数据手册的时候,发现STM32的GPIO输入输出模式的配置种类有8种之多(输入和输入各4种): (1)GPIO_Mode_AIN模拟输入 (2)GPIO_Mode_IN_FLOATING浮空输入 (3)GPIO_Mode_IPD下拉输入 (4)GPIO_Mode_IPU上拉输入 (5)GPIO_Mode_Out_OD开漏输出 (6)GPIO_Mode_Out_PP推挽输出 (7)GPIO_Mode_AF_OD复用开漏输出 (8)GPIO_Mode_AF_PP复用推挽输出 我们平时接触的最多的也就是推挽输出、开漏输出、上拉输入这三种,但对于各种模式下IO口的内部电路和典型应用,STM32的数据手册中也未曾做过详细的说明和归纳
[单片机]
STM32高级开发(13)-Ubuntu下的串口助手minicom
在这么长时间里我们在Ubuntu上调试stm32,大家在使用串口的时候是不是一直都是在宿主机上的串口助手中查看串口信息呢?来回切换是不是很麻烦?那么在这篇中我们就来介绍一下在Ubuntu下的串口助手,或者准确点说应该叫串口终端,它就是minicom。 终端与串口助手的区别 在我们正式介绍minicom之前,我们首先来关注一个问题即:终端与串口助手有什么区别?(注意这里的终端不是指Ubuntu的shell指令终端,而是说串口软件终端) 其实如果大家接触过Linux嵌入式开发应该就很明白这其中的差别了,不过鉴于大家可能之前没有接触过Linux嵌入式开发,我们这里就为大家详细的讲解一下他们。 在Linux嵌入式开发中,很多时
[单片机]
<font color='red'>STM32</font>高级开发(13)-Ubuntu下的串口助手minicom
STM32单片机中断详解
中断,在单片机中占有非常重要的地位。代码默认地从上向下执行,遇到条件或者其他语句,会按照指定的地方跳转。而在单片机执行代码的过程中,难免会有一些突发的情况需要处理,这样就会打断当前的代码,待处理完突发情况之后,程序会回到被打断的地方继续执行。 1 EXTI控制器 外部中断/事件控制器(EXTI)管理了控制器的 23 个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。EXTI 可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。 外部信号进入经过1的边沿检测电路,检测是否符合(有2和3的上升沿和下降沿选择寄存器决定),产生信号,然后和4软件
[单片机]
<font color='red'>STM32</font>单片机中断详解
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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