STM32模拟I2C通讯的驱动程序
目录
STM32模拟I2C通讯的驱动程序
开发环境
立创天空星开发板、主控芯片为STM32F407VxT6
引脚连接
使用stm32的PB9引脚模拟I2C时钟线SCL、PB8引脚模拟I2C数据线SDA
驱动程序
i2c.h文件如下:
#ifndef _I2C_H
#define _I2C_H
#include "stm32f4xx.h"
//端口宏定义
#define RCC_I2C_GPIO RCC_AHB1Periph_GPIOB
#define PORT_I2C_GPIO GPIOB
#define GPIO_SDA GPIO_Pin_8
#define GPIO_SCL GPIO_Pin_9
//设置SDA输出模式
#define SDA_OUT() { \
GPIO_InitTypeDef GPIO_InitStructure; \
GPIO_InitStructure.GPIO_Pin = GPIO_SDA; \
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; \
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; \
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; \
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; \
GPIO_Init(PORT_I2C_GPIO, &GPIO_InitStructure); \
}
//设置SDA输入模式
#define SDA_IN() { \
GPIO_InitTypeDef GPIO_InitStructure; \
GPIO_InitStructure.GPIO_Pin = GPIO_SDA; \
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; \
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; \
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; \
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; \
GPIO_Init(PORT_I2C_GPIO, &GPIO_InitStructure); \
}
//获取SDA引脚的电平
#define SDA_GET() GPIO_ReadInputDataBit(PORT_I2C_GPIO, GPIO_SDA)
//SDA与SCL输出高低电平
#define SDA(x) GPIO_WriteBit(PORT_I2C_GPIO, GPIO_SDA, (x?Bit_SET:Bit_RESET) )
#define SCL(x) GPIO_WriteBit(PORT_I2C_GPIO, GPIO_SCL, (x?Bit_SET:Bit_RESET) )
//模拟I2C引脚初始化
void I2C_GPIO_Init(void);
//I2C起始时序
void I2C_Start(void);
//I2C停止时序
void I2C_Stop(void);
//主机发送应答或者非应答信号
void I2C_Send_Ack(unsigned char ack);
//主机等待从机应答
unsigned char I2C_WaitAck(void);
//主机发送一个字节数据
void Send_Byte(uint8_t dat);
//主机接收一个字节数据
unsigned char Read_Byte(void);
#endif
i2c.c文件如下:
#include "i2c.h"
/******************************************************************
* 函 数 名 称:I2C_GPIO_Init
* 函 数 说 明:模拟IIC引脚初始化
* 函 数 形 参:无
* 函 数 返 回:无
* 备 注:无
******************************************************************/
void I2C_GPIO_Init(void)
{
RCC_AHB1PeriphClockCmd(RCC_I2C_GPIO, ENABLE); // 使能GPIO时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_SDA | GPIO_SCL;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(PORT_I2C_GPIO, &GPIO_InitStructure);
}
/******************************************************************
* 函 数 名 称:I2C_Start
* 函 数 说 明:IIC起始时序
* 函 数 形 参:无
* 函 数 返 回:无
* 备 注:无
******************************************************************/
void I2C_Start(void)
{
SDA_OUT();
SCL(1);
SDA(0);
SDA(1);
delay_us(5);
SDA(0);
delay_us(5);
SCL(0);
}
/******************************************************************
* 函 数 名 称:I2C_Stop
* 函 数 说 明:I2C停止信号
* 函 数 形 参:无
* 函 数 返 回:无
* 备 注:无
******************************************************************/
void I2C_Stop(void)
{
SDA_OUT();
SCL(0);
SDA(0);
SCL(1);
delay_us(5);
SDA(1);
delay_us(5);
}
/******************************************************************
* 函 数 名 称:I2C_Send_Ack
* 函 数 说 明:主机发送应答或者非应答信号
* 函 数 形 参:0发送应答 1发送非应答
* 函 数 返 回:无
* 备 注:无
******************************************************************/
void I2C_Send_Ack(unsigned char ack)
{
SDA_OUT();
SCL(0);
SDA(0);
delay_us(5);
if(!ack)
SDA(0);
else
SDA(1);
SCL(1);
delay_us(5);
SCL(0);
SDA(1);
}
/******************************************************************
* 函 数 名 称:I2C_WaitAck
* 函 数 说 明:主机等待从机应答
* 函 数 形 参:无
* 函 数 返 回:0有应答 1超时无应答
* 备 注:无
******************************************************************/
unsigned char I2C_WaitAck(void)
{
char ack = 0;
unsigned char ack_flag = 10;
SCL(0);
SDA(1);
SDA_IN();
SCL(1);
while( (SDA_GET()==1) && ( ack_flag ) )
{
ack_flag--;
delay_us(5);
}
if( ack_flag <= 0 )
{
I2C_Stop();
return 1;//应答超时返回1
}
else
{
SCL(0);
SDA_OUT();
}
return ack;//正常通讯返回应答
}
/******************************************************************
* 函 数 名 称:Send_Byte
* 函 数 说 明:主机发送一个字节数据
* 函 数 形 参:dat要发送的数据
* 函 数 返 回:无
* 备 注:无
******************************************************************/
void Send_Byte(uint8_t dat)
{
int i = 0;
SDA_OUT();
SCL(0);//拉低时钟开始数据传输
for( i = 0; i < 8; i++ )
{
SDA( (dat & 0x80) >> 7 );
delay_us(1);
SCL(1);
delay_us(5);
SCL(0);
delay_us(5);
dat<<=1;
}
}
/******************************************************************
* 函 数 名 称:Read_Byte
* 函 数 说 明:主机接收一个字节数据
* 函 数 形 参:无
* 函 数 返 回:接收到的数据
* 备 注:无
******************************************************************/
unsigned char Read_Byte(void)
{
unsigned char i,receive=0;
SDA_IN();
for(i=0;i<8;i++ )
{
SCL(0);
delay_us(5);
SCL(1);
delay_us(5);
receive<<=1;
if(SDA_GET())
{
receive |= 1;
}
delay_us(5);
}
SCL(0);
return receive;
}
原文地址:https://blog.csdn.net/qq_45143522/article/details/144348971
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!