历史上的今天
返回首页

历史上的今天

今天是:2025年08月09日(星期六)

2019年08月09日 | STM32(五)IIC通信原理及IO口软件模拟编程

2019-08-09 来源:eefocus

一、IIC概述

        I2C(IIC,Inter-Integrated Circuit),两线式串行总线,由PHILIPS公司开发用于连接微控制器及其外围设备。

       它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbps以上。

       IIC是半双工通信方式。

       多主机I2C总线系统结构:

二、I2C协议

1、空闲状态

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


2、开始信号

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


3、停止信号

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

4、应答信号

        发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。 应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。 


        对于反馈有效应答位ACK的要求是,接收器在第9个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。 如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器结束数据发送,并释放SDA线,以便主控接收器发送一个停止信号P。

5、数据的有效性

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


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


6、数据传输

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

        ALIENTEK MiniSTM32 开发板板载的 EEPROM 芯片型号为 24C02。该芯片的总容量是 256个字节,该芯片通过 IIC 总线与外部连接。

       目前大部分 MCU 都带有 IIC 总线接口,STM32 也不例外。但是这里我们不使用 STM32的硬件 IIC 来读写 24C02,而是通过软件模拟。STM32 的硬件 IIC 非常复杂,更重要的是不稳定,故不推荐使用。


     本章实验功能简介:开机的时候先检测24C02是否存在,然后在主循环里面检测两个按键,其中 1 个按键(WK_UP)用来执行写入 24C02 的操作,另外一个按键(KEY0)用来执行读出操作,在 TFTLCD 模块上显示相关信息。同时用 DS0 提示程序正在运行。


   

    24C02 的 SCL 和 SDA 分别连在 STM32 的 PC12 和 PC11 上。


三、代码驱动

//打开 myiic.c 文件,代码如下:

#include "myiic.h"

#include "delay.h"

//初始化IIC

void IIC_Init(void)

{      

GPIO_InitTypeDef GPIO_InitStructure;

//RCC->APB2ENR|=1<<4;//先使能外设IO PORTC时钟 

RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );

   

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_11;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOC, &GPIO_InitStructure);

 

IIC_SCL=1;

IIC_SDA=1;

 

}

//产生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);    

}

//等待应答信号到来

//返回值:1,接收应答失败

//        0,接收应答成功

u8 IIC_Wait_Ack(void)

{

u8 ucErrTime=0;

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

IIC_SDA=1;delay_us(1);    

IIC_SCL=1;delay_us(1);  

while(READ_SDA)

{

ucErrTime++;

if(ucErrTime>250)

{

IIC_Stop();

return 1;

}

}

IIC_SCL=0;//时钟输出0    

return 0;  

//产生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;

}

//打开 myiic.h 文件,代码如下:

//该部分为 IIC 驱动代码:

//实现包括 IIC 的初始化(IO 口)、IIC 开始、IIC 结束、ACK、IIC读写等功能

//在其他函数里面,只需要调用相关的 IIC 函数就可以和外部 IIC 器件通信了

//头文件 myiic.h 的代码,里面有两行代码为直接通过寄存器操作设置 IO 口的模式为输入还是输出

//代码如下:

#define SDA_IN() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=8<<12;}

#define SDA_OUT() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=3<<12;}

//完整代码如下:

#ifndef __MYIIC_H

#define __MYIIC_H

#include "sys.h"

           

//IO方向设置

#define SDA_IN()  {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=8<<12;}

#define SDA_OUT() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=3<<12;}

 

//IO操作函数  

#define IIC_SCL    PCout(12) //SCL

#define IIC_SDA    PCout(11) //SDA  

#define READ_SDA   PCin(11)  //输入SDA 

 

//IIC所有操作函数

void IIC_Init(void);                //初始化IIC的IO口  

void IIC_Start(void); //发送IIC开始信号

void IIC_Stop(void);   //发送IIC停止信号

void IIC_Send_Byte(u8 txd); //IIC发送一个字节

u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节

u8 IIC_Wait_Ack(void); //IIC等待ACK信号

void IIC_Ack(void); //IIC发送ACK信号

void IIC_NAck(void); //IIC不发送ACK信号

 

void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);

u8 IIC_Read_One_Byte(u8 daddr,u8 addr);   

#endif


推荐阅读

史海拾趣

Aleph America Corporation公司的发展小趣事

Aleph America Corporation 是一家专注于光电传感器和光电开关解决方案的公司。以下是关于该公司发展的5个相关故事:

  1. 公司成立及发展: Aleph America Corporation 成立于1986年,总部位于美国新泽西州。公司专注于光电传感器技术的研发和生产,并提供广泛的光电开关产品线,包括光电接近传感器、光电开关、光电耦合器等。随着市场对自动化和安全系统需求的增长,Aleph 在行业内逐渐建立了良好的声誉。

  2. 技术创新与产品质量: Aleph America Corporation 致力于技术创新和产品质量的提升。公司拥有一支专业的研发团队,不断引入先进的光电传感技术,并且注重产品的生产工艺和质量控制,确保产品具有稳定的性能和可靠的品质。

  3. 应用领域广泛: Aleph 的产品广泛应用于各种工业和商业应用领域。光电传感器和光电开关被广泛应用于自动门、电梯、安防系统、自动化生产线等领域,为客户提供了安全可靠的解决方案。

  4. 全球市场拓展: 随着全球市场的不断扩大,Aleph 在海外市场的拓展也逐渐加强。除了在美国设立总部和生产基地外,公司还在欧洲、亚洲等地设立了销售办事处和代理商网络,以便更好地满足全球客户的需求。

  5. 参与行业标准和认证: Aleph America Corporation 积极参与行业标准的制定和产品认证工作。公司的产品符合国际标准和认证要求,如CE认证、UL认证等,确保产品在全球范围内的市场准入和使用安全。

以上故事展示了 Aleph America Corporation 在光电传感器和光电开关领域的发展历程和成就,突出了其在技术创新、产品质量、市场拓展和行业认证方面的重要贡献。

Bel Fuse公司的发展小趣事

进入XXXX年代,电子行业经历了深刻的变革,新兴技术的涌现给传统企业带来了挑战。Bel Fuse也面临着市场需求的变化和竞争压力的增加。为了应对这些变革,公司进行了战略调整,将重点放在了连接器、电源、磁性元件和电路保护产品等领域。通过加大研发力度和市场推广,Bel Fuse成功实现了产品升级和市场拓展。

Anderson Power Products公司的发展小趣事

进入XXXX年代,电子行业经历了深刻的变革,新兴技术的涌现给传统企业带来了挑战。Bel Fuse也面临着市场需求的变化和竞争压力的增加。为了应对这些变革,公司进行了战略调整,将重点放在了连接器、电源、磁性元件和电路保护产品等领域。通过加大研发力度和市场推广,Bel Fuse成功实现了产品升级和市场拓展。

AOS公司的发展小趣事

除了热水领域,AOS公司还积极拓展其业务范围,涉足了水处理、空气净化等多个领域。公司坚持创新驱动的发展战略,不断投入研发资源,推出了一系列具有创新性和高性能的产品。这些产品的推出不仅丰富了AOS的产品线,也进一步提升了其在全球市场的竞争力。

Gustav Klauke GmbH公司的发展小趣事

除了热水领域,AOS公司还积极拓展其业务范围,涉足了水处理、空气净化等多个领域。公司坚持创新驱动的发展战略,不断投入研发资源,推出了一系列具有创新性和高性能的产品。这些产品的推出不仅丰富了AOS的产品线,也进一步提升了其在全球市场的竞争力。

Analog Microwave Design公司的发展小趣事

随着公司规模的不断扩大,Analog Microwave Design公司开始将目光投向国际市场。为了更好地拓展海外业务,公司制定了一套完善的国际化战略。首先,公司加强了与国际知名企业的合作,通过技术交流和合作研发,提升了公司的技术水平和国际影响力。其次,公司积极参加国际展览和会议,展示公司的最新产品和技术成果,吸引了众多海外客户的关注。通过这些努力,公司的海外业务得到了快速发展,成为公司新的增长点。

问答坊 | AI 解惑

太阳跟踪电原理

本电路可用在太阳能热水器、太阳能电池等自动跟踪太阳地设备设施上。稍加改动可用于其他的跟踪。本电路是本人精心设计的,PCB和软件暂不上传。若用商业使用,请通知我。xliu001@163.com 否则,属于侵权。(在专利申请中) …

查看全部问答>

神奇的光圈

神奇的光圈                                                 Magic Laser aperture http://www.lotusinvention.c ...…

查看全部问答>

请教:串口,并口,USB,PCI 哪个的相应速度最快?谢谢!

请教: 我发送的数据量不是很大,需要的是响应速度快 如 PC 向单片机端发数据,希望 单片机端快速响应 单片机端向 PC 端发数据,PC 端快速响应 串口,并口,USB,PCI 哪种最好啊 USB 怎么样? 比串口快,还是慢呢? 稳定不? 谢谢!…

查看全部问答>

小人刚接到一个项目,做一个Vxwork的IO驱动,有几点不是很明白,那位大虾能给解释下,不胜感激

一直做Linux驱动,Vxwork也做过一点,但IO驱动一直不是很明白,最近接手一个日本的XXX(没记住名字...)芯片开发,要用Vxwork,而且芯片API很简单,这片子本来不适用Vxwork,但客户要求,没办法了。 芯片本身定义了一个SIO东东的,提供对应寄存器配 ...…

查看全部问答>

[高手进来]C#调用vs2005 vc++ 智能设备编写的dll 出现的问题 急

vc++的“MFCDes.dll”导出函数 __declspec (dllexport)  bool DesGo(char *Out,char *In,long datalen,const char *Key,int keylen,bool Type = 0) 在c#中调用 DllImport(\"MFCDes.dll\", SetLastError = true)] public static exte ...…

查看全部问答>

LM3S8962是否支持linux下gdb调试开发?

有没有人用过? 就是那个LM3S8962开发板.…

查看全部问答>

电子看门狗

本帖最后由 jameswangsynnex 于 2015-3-3 20:03 编辑 如图所示为电子看门狗电路。它具有普通狗看守家门的本领。每当有人进入大门内10米监视区域,它就会发出逼真的狗叫声。这种叫声能维持10秒钟,如果此人不离开,电子看门狗便会一直叫下去 …

查看全部问答>

给位帮帮忙啊,有谁能给我个IAR软件啊,WIN7能用的

真的急用啊,网上找了很久了,实在没办法了,有的可以给我发到758626139@qq.com邮箱,先谢过了,还有破解注册机…

查看全部问答>

干燥除尘设备加热预热高频机

目前,很多厂家在生产干燥设备、储热设备、预热设备、换热器等时,还多用传统加热方式。而无论你所选用的是油气加热、氧气乙炔加热、液化气加热,煤炭加热、电炉加热、电烘箱加热等方式。都比感应式加热技术耗能多、效率低,且有的还存在环保问题 ...…

查看全部问答>

测试驱动开发:XP,敏捷方法的基础

不多说太多,测试,尤其是自动测试,对于高效创建软件,意义是非常重大的。 如何构筑测试? java有junit,C也不落后,C下有Unity,C++下有CppTest。 C下其实还有CUTest,CTest...... 而在这里,我把宝全押在 Unity下,因为我手头唯一能找到的比较 ...…

查看全部问答>