STM32F103标准库开发---IIC主控实验---普通I/O口模拟---底层驱动程序

STM32F103标准库开发—目录
AT24Cxx系列芯片中文数据手册----资源链接 点击下载
AT24C256读写操作----程序源码 点击下载


IIC底层驱动程序

这次I是普通I/O端口模拟IIC通信实验
具体引脚配置如下:

IIC接口GPIO端口
时钟线(SCL)PB6
数据线(SDA)PB7

IIC主控实验----底层驱动GPIO配置

GPIO初始化配置

具体代码如下:

//初始化IIC
void IIC_Init(void)
{					     
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );	//使能GPIOB时钟
	   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7); 	//PB6,PB7 输出高电平---空闲状态
}

时钟线(SCL)—GPIO功能配置

在IIC通信中,主控的时钟线(SCL) 一直是输出状态
具体程序如下:

//时钟线(SCL):PB6输出---高电平
#define SCL_H  		GPIO_SetBits(GPIOB,GPIO_Pin_6)  

//时钟线(SCL):PB6输出---低电平											
#define SCL_L  		GPIO_ResetBits(GPIOB,GPIO_Pin_6)

数据线(SDA)—GPIO功能配置

由于IIC通信是半双工通信方式
因而数据线(SDA)可能会是数据输入,也可能是数据输出。

数据线(SDA)输入模式

//数据线(SDA):PB7输入
#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}

//读取PB7的电平
#define READ_SDA  GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)

数据线(SDA)输出模式

//数据线(SDA):PB7输出
#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}

//数据线(SDA):PB7输出---高电平
#define SDA_H  	GPIO_SetBits(GPIOB,GPIO_Pin_7)	
//数据线(SDA):PB7输出---低电平
#define SDA_L  	GPIO_ResetBits(GPIOB,GPIO_Pin_7)

IIC主控实验----底层驱动程序

开始信号

当时钟线SCL 为高电平时,数据线SDA 由高电平向低电平跳变。
在这里插入图片描述
具体程序如下:

void IIC_Start(void)//开始信号
{
	SDA_OUT();			//数据线(SDA)输出模式
	SDA_H;				//数据线(SDA)输出高电平
	SCL_H;				//时钟线(SCL)输出高电平
	delay_us(5);
	SDA_L;				//数据线(SDA)输出低电平
	delay_us(5);
	SCL_L;				//时钟线(SCL)输出低电平
}

终止信号

当时钟线SCL 为高电平时,数据线SDA 由低电平向高电平跳变。
在这里插入图片描述
具体程序如下:

void IIC_Stop(void)//终止信号
{
	SDA_OUT();		//数据线(SDA)输出模式
	SCL_L;			//时钟线(SCL)输出低电平
	SDA_L;			//数据线(SDA)输出低电平
	delay_us(5);
	SCL_H;			//时钟线(SCL)输出高电平
	SDA_H;			//数据线(SDA)输出高电平
	delay_us(5);
}

应答信号

我们这里写的是IIC主控程序,在读取从控数据的时候,需要回复应答信号。
产生应答信号,表示接收数据成功。
在这里插入图片描述
具体程序如下:

void IIC_Ack(void)//产生应答信号
{
	SCL_L;			//时钟线(SCL)输出低电平
	SDA_OUT();		//数据线(SDA)输出模式
	SDA_L;			//数据线(SDA)输出低电平
	delay_us(2);
	SCL_H;			//时钟线(SCL)输出高电平
	delay_us(5);
	SCL_L;			//时钟线(SCL)输出低电平
}

产生非应答信号,表示接收数据失败。
在这里插入图片描述
具体程序如下:

void IIC_NAck(void)//不产生应答信号
{
	SCL_L;			//时钟线(SCL)输出低电平
	SDA_OUT();		//数据线(SDA)输出模式
	SDA_H;			//数据线(SDA)输出高电平
	delay_us(2);
	SCL_H;			//时钟线(SCL)输出高电平
	delay_us(5);
	SCL_L;			//时钟线(SCL)输出低电平
}

IIC主控程序,在写入数据到从控的时候,需要等待应答信号

//返回值:1,接收应答失败
//        0,接收应答成功
u8 IIC_Wait_Ack(void)//等待应答信号
{
	int uc=0;
	SDA_IN();		//数据线(SDA)输入模式
	SDA_H;  delay_us(1);
	SCL_H;  delay_us(1);
	while(READ_SDA)
	{
		uc++;
		if(uc>250)//接收应答失败
		{
			IIC_Stop();//发送终止信号		
			return 1;
		}
	}
	SCL_L;
	return 0;
}

数据传输

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

在这里插入图片描述

输出到数据线(SDA)上的每个字节必须是8位
数据传送时,先传送最高位(MSB)后传送最低位(LSB)
每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)

在这里插入图片描述

IIC主控发送一个字节数据

具体程序如下:

void IIC_Send_Byte(u8 txdata)//发送一个字节数据---高位在前,低位在后
{
	SDA_OUT();				//数据线(SDA)输出模式
	SCL_L;
	for(int t=0;t<8;t++)	//高位在前,低位在后。
	{
		if((txdata&0x80)>>7)   	SDA_H;
		else                	SDA_L;
		txdata<<=1;
		delay_us(2);
		SCL_H;
		delay_us(2);
		SCL_L;
		delay_us(2);
	}
}

IIC主控接收一个字节数据

具体程序如下:

u8 IIC_Read_Byte(unsigned char ack)//读取一个字节数据---ack=1时,发送ACK,ack=0,发送nACK
{
	unsigned char rxdata=0,i;
	SDA_IN();		//数据线(SDA)输入模式
	for(i=0;i<8;i++)
	{
		SCL_L;
		delay_us(2);
		SCL_H;
		rxdata<<=1;
		if(READ_SDA) rxdata++;
		delay_us(1);
	}
	if(!ack)   IIC_NAck();
	else       IIC_Ack();
	return rxdata;
}


版权声明:本文为MQ0522原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。