STM32用GPIO口模拟IIC通讯
1.头文件:
#ifndef __I2C_H
#define __I2C_H
#define SlaveAddress 0xD0 //从机地址(写)
#define SDA_D PBin(7) // PB9设置为可读
#define SDA_H PBout(7)=1 // PB9置高
#define SDA_L PBout(7)=0 // PB9置低
#define SCL_H PBout(6)=1 // PB8置高
#define SCL_L PBout(6)=0 // PB8置低
#define SDA_IOOUT() PBout(7) //PB9设置为输出模式
#define SDA_IOIN() PBin(7) //PB9设置为输入模式
void I2C_Configuration(void);
void I2C_Start(void);
void I2C_Stop(void);
u8 I2C_SlaveAck(void);
void I2C_WriteByte(unsigned char a);
u8 I2C_ReadByte(void);
void WriteI2C(unsigned char Regs_Addr,unsigned char Regs_Data);
u8 ReadI2C(unsigned char Regs_Addr);
#endif
2.c文件
#include "I2C.h"
#include "stm32f10x.h"
/*
*=========================================================
* 函数功能:IIC总线引脚初始化
* 参数:无
* 函数返回值:无
* PB6--SCL
* PB7--SDA
*=========================================================
*/
void I2C_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/*
*=========================================================
* 函数功能:IIC总线初始化信号
* 参数:无
* 函数返回值:无
*=========================================================
*/
void I2C_Start(void)
{
SCL_L;
delay_us(2);
SDA_H;
delay_us(2);
SCL_H;
delay_us(2);
SDA_L;
delay_us(2);
}
/*
*=========================================================
* 函数功能:IIC总线停止信号
* 参数:无
* 函数返回值:无
*=========================================================
*/
void I2C_Stop(void)
{
SCL_L;
delay_us(2);
SDA_L;
delay_us(2);
SDA_H;
delay_us(2);
}
/*
*=========================================================
* 函数功能:接收由从机向主机发起的ACK信号。
* 参数: ACKBIT
*
* 函数返回值:MMA_ERROR/MMA_OK
*=========================================================
*/
u8 I2C_SlaveAck(void)
{
SCL_L;
delay_us(2);
SDA_H;
SDA_IOIN(); //SDA设为输入
delay_us(2);
SCL_H;
delay_us(2);
if(SDA_D)
{
SDA_IOOUT(); //SDA设为输出
SCL_L;
return ERROR; //返回错误
}
SCL_L;
SDA_IOOUT(); //SDA设为输出
delay_us(2);
return SUCCESS; //返回正常
}
/*
*=========================================================
* 函数功能:IIC写一个字节数据
* 参数: a:需要写入的一个字节数据
* 函数返回值:无
*=========================================================
*/
void I2C_WriteByte(unsigned char a)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL_L;
if((a&0x80)!=0) SDA_H;
else SDA_L;
a <<= 1;
delay_us(2);
SCL_H;
delay_us(2);
}
SCL_L;
if(I2C_SlaveAck()==ERROR) //等待从机的ACK信号。
{
return ;
}
}
/*
*=========================================================
* 函数功能:IIC读一个字节数据
* 参数:无
* 函数返回值:返回读出的一个字节数据
*=========================================================
*/
u8 I2C_ReadByte(void)
{
unsigned char a =0;
unsigned char i;
SDA_IOIN(); //SDA设为输入
for(i=0; i<8; i++)
{
a <<= 1;
SCL_H;
delay_us(2);
if(SDA_D==1) a |= 0x01;
delay_us(2);
SCL_L;
delay_us(2);
}
return a;
}
/*
*=========================================================
* 函数功能:写寄存器
* 参数:
* Regs_Addr - 寄存器地址
* Regs_Data - 寄存器值
* 函数返回值:
*=========================================================
*/
void WriteI2C(unsigned char Regs_Addr,unsigned char Regs_Data)
{
I2C_Start();
I2C_WriteByte(SlaveAddress); //如果从设备要求写之前需要配置,先写Slave地址,并配置成写模式
I2C_WriteByte(Regs_Addr); //写寄存器地址
I2C_WriteByte(Regs_Data); //写寄存器内容
I2C_Stop(); //结束本段IIC进程
}
/*
*=========================================================
* 函数功能:读寄存器
* 参数
* Regs_Addr - 寄存器地址
* 函数返回值:寄存器值
*=========================================================
*/
u8 ReadI2C(unsigned char Regs_Addr)
{
unsigned char ret;
I2C_Start();
I2C_WriteByte(SlaveAddress); //如果从设备要求写之前需要配置,先写Slave地址,并配置成写模式
I2C_WriteByte(Regs_Addr); //写寄存器地址
I2C_Start();
I2C_WriteByte(SlaveAddress+1); //写Slave地址,并配置成读模式
ret=I2C_ReadByte(); //从传感器中读出数据
I2C_SlaveAck();
I2C_Stop(); //结束本段IIC进程
return ret;
}