Stm32 iic初始化介绍

本文详细介绍了STM32微控制器中I2C(Inter-Integrated Circuit)总线的配置与使用方法,包括初始化过程、起始及终止信号的生成、数据传输流程等关键技术点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2018/5/27

1.iic介绍:

iic (Inter_Integrated Circuit)集成电路总线,是一种二线制的同步串行总线,一共有着SCL(时钟线)和SDA(数据线)

2.配置步骤:

<1>:iic的初始化

按照对GPIO口的设置来配置iic相关的端口(这里以Stm32F103rc为例)

注:可以使用定义的方法先定义相应端口

//IO方向设置
#define SDA_IN()  {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=8<<12;}//1000 上拉输入
#define SDA_OUT() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=3<<12;}//0011 推挽输出(50MHZ)
//IO操作函数	 
#define IIC_SCL    PCout(12) //SCL
#define IIC_SDA    PCout(11) //SDA	 
#define READ_SDA   PCin(11)  //输入SDA 


void IIC_Init(void)
{					     
	GPIO_InitTypeDef GPIO_InitStructure;
	//RCC->APB2ENR|=1<<4;//先使能外设IO PORTC时钟 
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOC, ENABLE );	//使能GPIOC时钟
	//IIC SCL(PC12)IIC SDA(PC11)   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_11;//change the channel
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);
 
	IIC_SCL=1;//初始化拉高SCL
	IIC_SDA=1;//初始化拉高SDA
}

在初始化的时候,SDA和SCL都置为1,表示拉高闲置状态

<2>:产生起始信号


先将SDA和SCL置高,然后在SDA拉低时进行延时,然后将SCL拉低

void IIC_Start(void)
{
	SDA_OUT();     //sda线输出 0011 
	IIC_SDA=1;	  	  
	IIC_SCL=1;
	delay_us(4);//保持SCL稳定
 	IIC_SDA=0;// SDA开始从高向低跳变
	delay_us(4);
	IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 
}	  

<3>产生终止信号

先确定SCL SDA为拉低状态,然后在SCL拉高的期间实现SDA的拉高

void IIC_Stop(void)
{
	SDA_OUT();//sda线输出
	IIC_SCL=0;
	IIC_SDA=0;//准备进行跳变
 	delay_us(4);
	IIC_SCL=1; 
	delay_us(4);
	IIC_SDA=1;//发送I2C总线结束信号
								   	
}

<4>:等待信号

设置等待时间 如果超过该时间则发送失败;

实现SCL=0 便于下一次数据的传输


//等待应答信号到来,将SCL SDA拉高 等待应答
//返回值: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);	 
	//SCL SDA拉高 等待接收器返回应答信号
	while(READ_SDA) 
	{
		ucErrTime++;
		if(ucErrTime>250)//如果大于250,说明数据无效
		{
			IIC_Stop();//停止
			return 1;//返回,超过相应的时间 接收失败
		}
	}
	IIC_SCL=0;//钳位 方便下一次传输	   
	return 0;  
} 

<5>:ACK应答(拉低SDA产生应答 主机反馈信号)(升高SDA则不产生应答 ))

void IIC_Ack(void)
{
	IIC_SCL=0;
	SDA_OUT();//主机接收应答信号,相当于反馈信号
	IIC_SDA=0;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
	//保证SDA为低的时候产生应答
}
void IIC_NAck(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=1;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
	//保证SDA为高的时候不产生应答
}				

<6>发送字节(使用循环发送8字节,拉低SCL位实现字节的传输)


//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答	
//SCL在高电平的时候 无法改变SDA的数据 
//SCL为低电平的时候 可以改变SDA的数据 		  
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);
    }	 
} 	    

<7>:读取字节,通过标志位主机是否应答(SCL=1开始读字节)

//读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;//SCL为高电平的时候开始读取信号
        receive<<=1;
        if(READ_SDA)receive++; //最低位+1;
		delay_us(1); 
    }					 
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}


时序图还是很重要的!!!





STM32F103ZE I2C1调试手记近日因项目需要,使用100PIN的STM32带FSMC功能驱动3.2"TFTLCD;在使用EEPROM时发现原来的I2C程序居然无法使用,郁闷了! 先说一下我这个I2C的驱动程序是经过STM32的官方库函数整理而成,API支持全系列EEPROM以及8BIT地址的其它I2C设备,一直用的很爽。 赶紧查找问题原因,发现连STA信号都无法启动完成,一直循环在等待状态while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); 真是见鬼了,居然连STA信号都无法建立,首先怀疑是硬件问题,于是赶紧查找硬件问题,换EEPROM,无果。奇了怪了,其它项目用的好好的程序,问百度吧?百度一下,这个问题还真多啊,而且还一模一样,问题都没结果,基本的认识是说ST芯片的问题,只能用模拟总线解决。 难道真是芯片问题?这可能吗?这可是ST啊,放眼全球有几家公司能与之抗衡啊。我首先觉得不可能,理由是为什么我其它项目用的好好的,虽说不是同PIN的芯片,可是同系列啊。于是我用其它项目的程序稍做修改,只开放IIC功能把程序下载到103ZE,运行一切正常。这就验证了我的判断,芯片不可能有问题。可为什么不行呢?难道是底层库函数的问题,于是升级库函数,移植到3.0版本的,这样捣鼓一下,一上午时间就这样没了,郁闷啊郁闷到差点绝望啊!!!先吃完中午饭,准备下午再战。再问百度吧,找来找去还是没结果,都说是芯片问题。纠结,难不成真的要用模拟I2C总线解决。不甘心啊,土法炼钢吧,把所有初始化程序一个一个注释掉,下载测试,当注释掉LCD初始化程序时,奇迹出现了,I2C总线OK了,天啦难道是LCD造成的?查看LCD初始化程序,FSMC初始化程序,没发现问题啊,再加上LCD初始化程序,I2C又不能工作了,看来确实是LCD的功能造成,先把FSMC注释掉,运行I2C又OK了,终于找到你了,就是FSMC造成的,看程序没有任何错误,还是查手册吧,在手册中看到I2C1的SDA脚与FSMC_NADV脚是共用一个端口,难道是这个引起的,查看手册《STM32F101xC/D/E 和 STM32F103xC/D/E勘误表》终于发现问题的根源。原文描述:2.7.15 FSMC和 I2C1以及TIM4_CH2问题描述如果要使用FSMC功能,NADV被配置成复用输出,该信号会被默认地置位。这样就和TIM4_CH2和I2C1的SDA信号发生冲突。暂时解决办法当使用FSMC的同时,不要使用TIM4_CH2。如果要使用I2C1并且封装允许,就把该功能重映射到PB8/PB9。2.7.13 SDIO 和经过重映射的I2C1配置条件当SDIO配置成1位或者4位模式,会和被重映射到PB8/9引脚上的I2C1发生冲突。冲突发生在以下信号之间:● I2C1_SCL和SDIO_D4● I2C1_SDA和SDIO_D5暂时解决办法当使用SDIO的同时,不要重映射I2C1的功能到PB8/PB9。问题找到了,就是这个原因啊,天杀的ST,映射功能只能到PB8 PB9端口上,不能映射到任意商品上,可我的PB8 PB9端口被SDIO功能占用了。I2C2端口也被USART3功能占用了。问题是找到了,可最后结果只能模拟总线来实现了。调试结论:1. ST的芯片不会有问题。ST官方的库函数是非常好用的,用的很爽的!2. 当使用大容量芯片具有FSMC功能与I2C1功能同时使用时, 需要把I2C1映射到PB9 PB9端口上去。3. 如果要同时使用FSMC I2C1 SDIO功能时,I2C1只能用模拟总线方式实现。因为SDIO功能会占用PB8 PB9端口。以下是I2C模拟总线程序源代码
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值