IIC协议--附完整驱动代码

本文详细介绍了STM32F407如何配置GPIO实现I2C通信,包括起始和停止信号的生成、发送与接收数据、应答信号的发送和接收。通过实例代码展示了I2C初始化、数据传输等关键步骤,适用于嵌入式系统中的I2C通信应用。
摘要由CSDN通过智能技术生成

在这里插入图片描述开漏输出:让输出端口有效输出高电平(上拉电阻的作用)且保证不短路(相当于VCC与GND之间多了一个电阻),且开漏输出能构成线与,简化电路。

短路原因:由于多个GPIO口连接到一根线上,当一个IO输出低电平时,另一个IO输出高电平就会造成短路。

线与,即两个输出端(包括两个以上)直接互连就可以实现“AND”的逻辑功能。

在这里插入图片描述
在通信的过程中以下细节:
1、总线空闲状态时,SDA与SCL处于高电平状态。
2、SCL高电平期间,SDA须保持稳定。当SDA状态需要改变时最好在SCL低电平状态(SCL高电平时,SDA状态改变会被认为是有效信号,起始或者停止信号)(这点对数据传输很重要)。
3、在一个在字节的数据传输完成后从机都会向主机发送一个应答信号。

在这里插入图片描述

附上完整的驱动代码(stm32f407):
iic.c

/*****************************
函数说明:
		PB8 -- SCL -- 时钟线
		PB9 -- SDA -- 数据线
******************************/
void IIC_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct;

	//打开GPIOB组时钟 
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);	
	
	GPIO_InitStruct.GPIO_Pin	= GPIO_Pin_8|GPIO_Pin_9;		//引脚9 10
	GPIO_InitStruct.GPIO_Mode	= GPIO_Mode_OUT;				//输出模式
	GPIO_InitStruct.GPIO_OType	= GPIO_OType_PP;				//推挽输出
	GPIO_InitStruct.GPIO_PuPd	= GPIO_PuPd_UP;					//上拉
	GPIO_InitStruct.GPIO_Speed	= GPIO_Speed_50MHz;				//速度
	
	GPIO_Init(GPIOB, &GPIO_InitStruct);
}

//改变端口模式  --- 输出/输入
void IIC_CHANGE_MODE(GPIOMode_TypeDef mode)
{
	GPIO_InitTypeDef  	GPIO_InitStructure;
	
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;				//第9号引脚
	GPIO_InitStructure.GPIO_Mode  = mode;					//输入/输出模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;			//推挽输出,增强驱动能力,引脚的输出电流更大
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		//引脚的速度最大为100MHz
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;		//没有使用内部上拉电阻
	GPIO_Init(GPIOB, &GPIO_InitStructure);	
}

/**************
IIC起始信号
***************/

void IIC_START(void)
{
	IIC_SDA_OUT();  //设置成输出模式
	SCL_H;
	SDA_H;
	
	delay_us(5);
	SDA_L;
	delay_us(5);
	SCL_L;
}

/**************
IIC停止信号
***************/

void IIC_STOP(void)
{
	IIC_SDA_OUT(); //设置成输出模式
	SCL_H;
	SDA_L;
	
	delay_us(5);
	SDA_H;
	delay_us(5);
	SDA_L;
}

/**********************************
函数说明:
		主机:发送应答信号/发送非应答信号
***********************************/
void SEND_NACK_OR_ACK(int flag_bit)
{
	IIC_SDA_OUT();  //设置成输出模式
	SCL_L;
	if(flag_bit == 0)
	{
		SDA_L;
	}
	if(flag_bit == 1)
	{
		SDA_H;
	}
	delay_us(5);
	SCL_H;
	delay_us(5);
	SCL_L;
}

/**********************************
函数说明:
		从机:接收应答信号/发送非应答信号
***********************************/

u8 REC_NACK_OR_ACK(void)
{
	u8 ack = 0;
	
	IIC_SDA_IN(); //设置成输入模式
	
	SCL_L;
	delay_us(5);
	SCL_H;
	delay_us(5);
	
	if(SDA_IN == 0)
	{
		ack = 0;
	}
	if(SDA_IN == 1)
	{
		ack = 1;
	}

	SCL_L;
	
	return ack;
}

/**********************************
函数说明:
		发送一个字节
***********************************/

void IIC_SEND_BYTE(u8 data)
{
	u8 i;
	
	IIC_SDA_OUT();   //设置成输入模式
	
	SCL_L;
	for(i=0;i<8;i++)  //发送8为数据
	{
		if(data & (0x01 << (7-i)))
		{
			SDA_H;
		}
		else 
		{
			SDA_L;
		}
		delay_us(5);
		SCL_H;
		delay_us(5);
		SCL_L;		
	}
	
}

/**********************************
函数说明:
		接收一个字节
***********************************/
u8 IIC_REC_BYTE(void)
{
	u8 i;
	u8 data = 0x00;
	
	IIC_SDA_IN();   //设置成输入模式
	
	SCL_L;
	for(i=0;i<8;i++)
	{
		delay_us(5);
		SCL_H;
		delay_us(5);
		if(SDA_IN == 1)
		{
			data |= (0x01 << (7-i));
		}
		SCL_L;
	}
	return data;	
}

iic.h

#ifndef __IIC_H
#define __IIC_H

#include "stm32f4xx.h"
#include "delay.h"

#define IIC_SDA_OUT() IIC_CHANGE_MODE(GPIO_Mode_OUT)
#define IIC_SDA_IN()  IIC_CHANGE_MODE(GPIO_Mode_IN)
#define SDA_IN    GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_9)

//PB9
#define SDA_H GPIO_SetBits(GPIOB,GPIO_Pin_9)
#define SDA_L GPIO_ResetBits(GPIOB,GPIO_Pin_9)

//PB8
#define SCL_H GPIO_SetBits(GPIOB,GPIO_Pin_8)
#define SCL_L GPIO_ResetBits(GPIOB,GPIO_Pin_8)


void IIC_Init(void);
void IIC_CHANGE_MODE(GPIOMode_TypeDef mode);
void IIC_START(void);
void IIC_STOP(void);
void SEND_NACK_OR_ACK(int flag_bit);
u8 REC_NACK_OR_ACK(void);
void IIC_SEND_BYTE(u8 data);
u8 IIC_REC_BYTE(void);

#endif


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值