STM32 IIC通信

一.IIC简介

两根通信线:SCL(Serial Clock)串行时钟线、SDA(Serial Data)串行数据线

同步,半双工

带数据应答

支持总线挂载多设备(一主多从、多主多从)

相同芯片挂载在同一个总线,需要用到器件地址的可变部分,一般器件的最后几位是在电路中可变的,一般由器件引脚确定

二.硬件电路

主机有对SCL的绝对控制权,所以SCL端口配置成推挽输出,从机的SCL就是接收引脚配置成浮空或者上拉输入。

因为是半双工的,SDA在发送的时候是输出,在接收的时候是输入,从机也是如此。为了避免总线没有协调好导致两边都输入高电平,所以IIC禁止所有的设备输出强上拉的,而是采用外置弱上拉电阻,设置成开漏输出。

三.I2C时序基本单元

发送数据 

低电平主机放数据,高电平从机读数据

接收数据 

主机要先释放SDA,切换成从机发送,

低电平从机放数据,高电平主机读数据

应答机制

四.IIC时序 

主机是发送应答,从机是接收应答

指定地址写

当前地址读 指定地址读 

sr相当于另外取一个时序,从头开始,等于是两条时序拼接成一条。

 多个数据的指定地址写

指定地址写是写入了一个字节

指定位置开始读多个数据

皇帝点妃模式:皇帝想接着,就会给应答,不想继续就不给应答,控制权返还给皇帝。

五.模拟实现IIC时序 

#include "stm32f10x.h"                  // Device header
#include "Delay.h"


void MyIIC_W_SCL(uint8_t BitValue)
{
    GPIO_WriteBit(GPIOB,GPIO_Pin_10,(BitAction)BitValue);
    Delay_ms(10);
}
void MyIIC_W_SDA(uint8_t BitValue)
{
    GPIO_WriteBit(GPIOB,GPIO_Pin_11,(BitAction)BitValue);
    Delay_ms(10);
}
uint8_t MyIIC_R_SDA()
{
    uint8_t BitValue;
    BitValue=GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11);
    Delay_ms(10);
    return BitValue;
}


void MyIIC_Init()
{
    //把SCL SDA初始化成开漏输出
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10|GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOB,&GPIO_InitStructure);
    
    GPIO_SetBits(GPIOB,GPIO_Pin_10|GPIO_Pin_11);//SCL SDA为高电平,此时IIC处于空闲
    
}

void MyIIC_Start()
{
    //先将SCL和SDA都释放,就是同时置高电平
    MyIIC_W_SDA(1);//SDA置高电平(为了跟后面的重复条件做区分)
    MyIIC_W_SCL(1);//SCL置高电平    
    MyIIC_W_SDA(0);//先拉低SDA
    MyIIC_W_SCL(0);//再拉低SCL
}

void MyIIC_Stop()
{
    //如果SCL和SDA都是低电平,那就先释放SCL,再释放SDA
    //但是SDA不一定是低电平,所以要先拉低SDA,再释放SCL,SDA
    //终止条件后SCL和SDA都回归高电平,除了终止条件SCL以高电平接收,其他都是低电平
    MyIIC_W_SDA(0);//先拉低SDA
    MyIIC_W_SCL(1);//SCL置高电平    
    MyIIC_W_SDA(1);//先拉低SDA
}

void MyIIC_SendByte(uint8_t Byte)
{
    MyIIC_W_SDA(Byte&0x80);//取出数据的1000 0000位
    MyIIC_W_SCL(1);//SCL拉高
    MyIIC_W_SCL(0);//SCL拉低
    
    MyIIC_W_SDA(Byte&0x40);//取出数据的0100 0000位
    MyIIC_W_SCL(1);//SCL拉高
    MyIIC_W_SCL(0);//SCL拉低
    
    MyIIC_W_SDA(Byte&0x20);//取出数据的0010 0000位
    MyIIC_W_SCL(1);//SCL拉高
    MyIIC_W_SCL(0);//SCL拉低

    MyIIC_W_SDA(Byte&0x10);//取出数据的0001 0000位
    MyIIC_W_SCL(1);//SCL拉高
    MyIIC_W_SCL(0);//SCL拉低  

    MyIIC_W_SDA(Byte&0x08);//取出数据的0000 1000位
    MyIIC_W_SCL(1);//SCL拉高
    MyIIC_W_SCL(0);//SCL拉低    

    MyIIC_W_SDA(Byte&0x04);//取出数据的0000 0100位
    MyIIC_W_SCL(1);//SCL拉高
    MyIIC_W_SCL(0);//SCL拉低  

    MyIIC_W_SDA(Byte&0x02);//取出数据的0000 0010位
    MyIIC_W_SCL(1);//SCL拉高
    MyIIC_W_SCL(0);//SCL拉低 
    
    MyIIC_W_SDA(Byte&0x01);//取出数据的0000 0001位
    MyIIC_W_SCL(1);//SCL拉高
    MyIIC_W_SCL(0);//SCL拉低   

//for(uint8_t i=0;i<8;i++)
//{     
//    MyIIC_W_SDA(Byte&(0x80>>i));//取出数据的0000 1000位
//    MyIIC_W_SCL(1);//SCL拉高
//    MyIIC_W_SCL(0);//SCL拉低    
//}   
}

uint8_t MyIIC_ReceiveByte()
{
    uint8_t Byte=0x00;
    MyIIC_W_SDA(1);//从机接收之前要先置高
    for(uint8_t i=0;i<8;i++)
    {
        MyIIC_W_SCL(1);//SCL拉高接收从机数据
        if(MyIIC_R_SDA()==1)//如果读取到是高电平
        {
            Byte|=(0x80>>i);//把Byte最高位置1
        }
        MyIIC_W_SCL(0); 
    }  
    return Byte;
}

//发送应答是发送的简化版,只用发移位就可以了
void MyIIC_SendAck(uint8_t AckBit)
{
    MyIIC_W_SDA(AckBit);
    MyIIC_W_SCL(1);//SCL拉高
    MyIIC_W_SCL(0);//SCL拉低   
}

uint8_t MyIIC_ReceiveAck()
{
    uint8_t AckBit;
    MyIIC_W_SDA(1);//从机接收之前要先置高
    MyIIC_W_SCL(1);//SCL拉高接收从机数据
    AckBit=MyIIC_R_SDA();//读取到应答信号
    MyIIC_W_SCL(0);//SCL拉高接收从机数据
    return AckBit;
}

六.硬件实现IIC

STM32内部集成了硬件I2C收发电路,可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能,减轻CPU的负担

支持多主机模型

支持7位/10位地址模式

支持不同的通讯速度,标准速度(高达100 kHz),快速(高达400 kHz)

支持DMA

兼容SMBus协议

STM32F103C8T6 硬件I2C资源:I2C1、I2C2

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值