STM32用GPIO口模拟IIC通讯

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;
}
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
STM32可以使用GPIO模拟IIC总线,以下是实现的步骤: 1. 配置GPIO为输出模式,将SDA和SCL拉高。 2. 发送起始信号:将SDA从高电平拉到低电平,然后再将SCL从高电平拉到低电平。 3. 发送设备地址入位:先发送设备地址(包括读位),等待设备响应,如果收到ACK(应答)信号,则表示设备已经准备好接受数据。 4. 发送数据:将数据一个字节一个字节地发送,每发送完一个字节,都要等待设备发出ACK信号。 5. 发送停止信号:将SDA从低电平拉到高电平,然后再将SCL从低电平拉到高电平。 以下是一个简单的示例代码: ```c #include "stm32f10x.h" #define SDA GPIO_Pin_8 #define SCL GPIO_Pin_9 void IIC_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = SDA | SCL; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_SetBits(GPIOB, SDA | SCL); } void IIC_Start(void) { GPIO_SetBits(GPIOB, SDA | SCL); GPIO_ResetBits(GPIOB, SDA); GPIO_ResetBits(GPIOB, SCL); } void IIC_Stop(void) { GPIO_ResetBits(GPIOB, SDA); GPIO_SetBits(GPIOB, SCL); GPIO_SetBits(GPIOB, SDA); } void IIC_SendByte(unsigned char byte) { unsigned char i; for (i = 0; i < 8; i++) { if (byte & 0x80) GPIO_SetBits(GPIOB, SDA); else GPIO_ResetBits(GPIOB, SDA); GPIO_SetBits(GPIOB, SCL); GPIO_ResetBits(GPIOB, SCL); byte <<= 1; } GPIO_SetBits(GPIOB, SDA); GPIO_SetBits(GPIOB, SCL); GPIO_ResetBits(GPIOB, SCL); } unsigned char IIC_ReadByte(void) { unsigned char byte = 0; unsigned char i; GPIO_SetBits(GPIOB, SDA); for (i = 0; i < 8; i++) { byte <<= 1; GPIO_SetBits(GPIOB, SCL); if (GPIO_ReadInputDataBit(GPIOB, SDA)) byte |= 0x01; GPIO_ResetBits(GPIOB, SCL); } return byte; } void IIC_Ack(void) { GPIO_ResetBits(GPIOB, SDA); GPIO_SetBits(GPIOB, SCL); GPIO_ResetBits(GPIOB, SCL); GPIO_SetBits(GPIOB, SDA); } void IIC_NAck(void) { GPIO_SetBits(GPIOB, SDA); GPIO_SetBits(GPIOB, SCL); GPIO_ResetBits(GPIOB, SCL); } void IIC_WriteByte(unsigned char addr, unsigned char reg, unsigned char data) { IIC_Start(); IIC_SendByte(addr << 1); if (IIC_ReadByte()) { IIC_Stop(); return; } IIC_SendByte(reg); if (IIC_ReadByte()) { IIC_Stop(); return; } IIC_SendByte(data); if (IIC_ReadByte()) { IIC_Stop(); return; } IIC_Stop(); } unsigned char IIC_ReadByte(unsigned char addr, unsigned char reg) { unsigned char data = 0; IIC_Start(); IIC_SendByte(addr << 1); if (IIC_ReadByte()) { IIC_Stop(); return 0; } IIC_SendByte(reg); if (IIC_ReadByte()) { IIC_Stop(); return 0; } IIC_Start(); IIC_SendByte((addr << 1) | 0x01); if (IIC_ReadByte()) { IIC_Stop(); return 0; } data = IIC_ReadByte(); IIC_NAck(); IIC_Stop(); return data; } int main(void) { IIC_GPIO_Init(); while (1) { // 读取温度传感器数据 unsigned char temp = IIC_ReadByte(0x80, 0x00); printf("Temperature: %d\n", temp); delay_ms(1000); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值