STM32(五)IIC通信原理及IO口软件模拟编程

发布者:量子启示最新更新时间:2019-08-09 来源: eefocus关键字:STM32  IIC通信  IO口  软件模拟 手机看文章 扫描二维码
随时随地手机看文章

一、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


关键字:STM32  IIC通信  IO口  软件模拟 引用地址:STM32(五)IIC通信原理及IO口软件模拟编程

上一篇:STM32模拟I2C时序读写EEPROM精简版
下一篇:stm32 mpu6050 模拟i2c实例实现

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

stm32 NVIC的配置
一、NVIC是中断向量表的统称。因为stm32的中断源非常多,在使用时有些中断必须要具有较高的优先级,那么nvic就诞生了,它就是用来配置中断顺序的。 二、打开misc.c文件,可以看到以下列表。 @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority * 4 bits for subpriority * @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority * 3 bits for subpriority * @arg NVIC
[单片机]
STM32的CAN总线调试
这一周调试STM32的CAN,从网上搜集了一些资料,感谢原作的无私奉献。 重点说明几个问题: 1、CAN的过滤器 对于过滤器,看中文手册上写的不是太清楚,STM32共有14组过滤器,用以对接收到的帧进行过滤。每组过滤器包括了2个可配置的32位寄存器:CAN_FxR0和CAN_FxR1。对于过滤器组,可以将其配置成屏蔽位模式,这样CAN_FxR0中保存的就是标识符匹配值,CAN_FxR1中保存的是屏蔽码,即CAN_FxR1中如果某一位为1,则CAN_FxR0中相应的位必须与收到的帧的标志符中的相应位吻合才能通过过滤器;CAN_FxR1中为0的位表示CAN_FxR0中的相应位可不必与收到的帧进行匹配。过滤器组还可以被配置成标识符列表
[单片机]
STM32_ SPI读写Flash
今天讲解“STM32F103SPI读写Flash”,其实这第一阶段主要是讲解STM32的SPI功能,所有今天的重点是SPI,关于FLASH我应该要在后面再次讲述。 今天提供并讲解的软件工程,基于软件工程“A0.0.0(STM32F10x_TIM延时)”修改而来。若不知道如何而来,请关注微信公众号“EmbeddDeveloper”获取更多信息。 本着免费分享的原则,将讲解的工程源代码分享给大家,还望看到的朋友关注和推广一下微信公众号,增加一下人气。 每天提供下载的“软件工程”都是在硬件板子上进行多次测试、并保证没问题才上传至360云盘。 今天的软件工程下载地址(360云盘): https://yunpan.cn/cP
[单片机]
STM32_ SPI读写Flash
STM32学习之路:I2C的基本读写
宏定义: /*I2C传输速度,最高为400kHz*/ #define I2C_SPEED 400000 /* STM32 自身的 I2C 地址, 这个地址只要与 STM32 外挂的 I2C 器件地址不一样即可 */ #define I2C_OWN_ADDR 0x77 /*EEPROM地址*/ #define EEPROM_ADDR (0x50 1) //0xA0 #define EEPROM_SCL_GPIO_CLK RCC_AHB1Periph_GPIOB #define EEPROM_SCL_PIN GPIO_Pin_6 #define EEPROM_SCL_GPIO_PORT GPIOB #de
[单片机]
STM32最小系统硬件组成部分
STM32最小系统硬件组成 最小系统为单片机工作的最低要求,不含外设控制,原理简单,分析最小系统是STM32入门的基础。 组成: 电源 复位 时钟 调试/下载接口 启动 电源 3.3V的电源从这里接入,其中电容起到滤波的作用。 复位电路 当RESET引脚被拉低产生外部复位时,产生复位脉冲,从而使系统复位。 有三种复位方式: 上电复位 手动复位 程序自动复位 上电复位,在上电瞬间,电容充电,RESET出现短暂的低电平,该低电平持续时间由电阻和电容共同决定,需求的复位信号持续时间约在1ms左右,计算方式如下: t = 1.1RC(固定计算公式) 1.1*10K*0.1uF=1.1ms 手动复位:按键按下时,RESET与地导
[单片机]
<font color='red'>STM32</font>最小系统硬件组成部分
stm32案例分享之使D-CACHE时FMC外设运行不正常原因
前言 前段时间某客户反馈,在使用STM32H7的FMC时,如果使能了D-CACHE就运行不正常。数据没有写到FMC外部的存储器里,FMC接口也没有波形。而不使能D-CACHE是工作则是正常的。 其实对于这个问题,如果了解STM32H7的架构的话,就很容易理解了。下面我们就来看一看到底是什么原因让客户觉得使能DCACHE后FMC就工作不正常了。 STM32H7的架构 下面是STM32H7架构图中和FMC相关的部分。从图中可以看到,STM32H7是基于Cortex-M7内核,在内部的Cortex-M7内核里带有一个16KB的D-CACHE和一个16KB的I-CACHE。内核通过AXIM总线连接到64位的AXI总线矩阵,再经过这
[单片机]
<font color='red'>stm32</font>案例分享之使D-CACHE时FMC外设运行不正常原因
stm32 USART_IT_IDLE
请注意IDLE中断是只检测到空闲帧时产生的中断。 而空闲帧的定义是:被视为完全由 1"组成的一个完整的数据帧,后面跟着包含?数据的下一帧的开始位。 关键是后面半句话,要求有下一帧的开始位,而你的情况恰巧没有下一帧的开始位(传输已经结束),当然不会有中断了。 举例: 如果连续发送一串字符串 123 会发生空闲中断吗? 不会,因为没有下一帧的开始位。 如果进了空闲中断不手动清零,会一直进入空闲中断。 所以用这个IDLEIE来结束DMA方式的接收,是合适的。唯一一个不合适的地方是:如果你发送一个字符串后,将DMA设置好接收传输方式,然后:对方没响应,你一个字符也收不到,这时候,IDLEIE是不会来的,必须有个总超时检测来结束DM
[单片机]
STM32 V3.4库函数使用建立工程方法
清晰地记得刚从51单片机过度到STM32,那种一头雾水的感觉。使用的STM32开发板是非常不适合初学者使用的开发板,它是硬件看上去华丽的神舟开发板。在这里我不评论神舟开发板如何如何,如果你是初学者,建议你不要使用神舟开发板。 拿到神舟开发板的教程,坑爹啊,如何使用STM32库的说明都没有,这对初学者也太不公平了吧。鄙人一个STM32菜鸟在网上花了半天时间才弄明白如何使用这个库,如何建立工程。今天分享我当初是如何使用STM32库文件建立工程的,非常适合初学者。 少废话,上图:
[单片机]
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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