管脚配置(我是用的是PA9和PA10):

stm32 hal 模拟i2c

stm32 hal 模拟i2c

//i2c.h
#include "stm32f0xx_hal.h"

#define GPIO_PORT_I2C	GPIOA			     // GPIO端口 
#define I2C_SCL_PIN		SCL_Pin			 // 连接到SCL时钟线的GPIO 
#define I2C_SDA_PIN		SDA_Pin			 // 连接到SDA数据线的GPIO 


/* 定义读写SCL和SDA的宏 */
#define I2C_SCL_1()  GPIO_PORT_I2C->BSRR = I2C_SCL_PIN											// SCL = 1 
#define I2C_SCL_0()  GPIO_PORT_I2C->BSRR = (uint32_t)I2C_SCL_PIN << 16U  		// SCL = 0 

#define I2C_SDA_1()  GPIO_PORT_I2C->BSRR = I2C_SDA_PIN   										// SDA = 1 
#define I2C_SDA_0()  GPIO_PORT_I2C->BSRR = (uint32_t)I2C_SDA_PIN << 16U  		// SDA = 0 

#define I2C_SDA_READ()  (GPIO_PORT_I2C->IDR & I2C_SDA_PIN)										// 读SDA口线状态 
#define I2C_SCL_READ()  (GPIO_PORT_I2C->IDR & I2C_SCL_PIN)									// 读SCL口线状态 


void i2c_Start(void);
//停止信号
void i2c_Stop(void);
//发送一个字节
void i2c_SendByte(uint8_t _ucByte);
//读取一个字节
uint8_t i2c_ReadByte(void);
//等待应答信号
uint8_t i2c_WaitAck(void);
//应答信号
void i2c_Ack(void);
//检查设备
uint8_t i2c_CheckDevice(uint8_t _Address);
//发送数据
void  Device_WriteData(uint8_t DeciveAddr,uint8_t *Data,int size);
//i2c.c
#include "i2c.h"
#include "main.h"

static void i2c_Delay(void)
{
	uint8_t i;
	for (i = 0; i < 40; i++);
}
//开始信号
void i2c_Start(void)
{
	// 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 
	I2C_SDA_1();
	I2C_SCL_1();
	i2c_Delay();
	I2C_SDA_0();
	i2c_Delay();
	I2C_SCL_0();
	i2c_Delay();
}

//停止信号
void i2c_Stop(void)
{
	// 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 
	I2C_SDA_0();
	I2C_SCL_1();
	i2c_Delay();
	I2C_SDA_1();
	i2c_Delay();
}
//发送一个字节
void i2c_SendByte(uint8_t _ucByte)
{
	uint8_t i;
	
	// 先发送字节的高位bit7 
	for (i = 0; i < 8; i++)
	{
		if (_ucByte & 0x80)
		{
			I2C_SDA_1();
		}
		else
		{
			I2C_SDA_0();
		}
		i2c_Delay();
		I2C_SCL_1();
		i2c_Delay();
		I2C_SCL_0();
		if (i == 7)
		{
			 I2C_SDA_1(); 	// 释放总线
		}
		_ucByte <<= 1;		// 左移一个bit 
		i2c_Delay();
	}
}
//读取一个字节
uint8_t i2c_ReadByte(void)
{
	uint8_t i;
	uint8_t value;
	
	/* 读到第1个bit为数据的bit7 */
	value = 0;
	for (i = 0; i < 8; i++)
	{
		value <<= 1;
		I2C_SCL_1();
		i2c_Delay();
		if (I2C_SDA_READ())
		{
			value++;
		}
		I2C_SCL_0();
		i2c_Delay();
	}
	return value;
}

//等待应答信号
uint8_t i2c_WaitAck(void)
{
	uint8_t re;

	I2C_SDA_1();	/* CPU释放SDA总线 */
//	i2c_Delay();
	I2C_SCL_1();	/* CPU驱动SCL = 1, 此时器件会返回ACK应答 */
	i2c_Delay();

	if (I2C_SDA_READ())	/* CPU读取SDA口线状态 */
	{
		re = 1;
	}
	else
	{
		re = 0;
	}

	I2C_SCL_0();
	i2c_Delay();
	return re;
}
//应答信号
void i2c_Ack(void)
{
	I2C_SDA_0();	/* CPU驱动SDA = 0 */
	i2c_Delay();
	I2C_SCL_1();	/* CPU产生1个时钟 */
	i2c_Delay();
	I2C_SCL_0();
	i2c_Delay();
	I2C_SDA_1();	/* CPU释放SDA总线 */
}


uint8_t i2c_CheckDevice(uint8_t _Address)
{
	uint8_t ucAck;

	if (I2C_SDA_READ() && I2C_SCL_READ())
	{
		i2c_Start();		/* 发送启动信号 */

		/* 发送设备地址+读写控制bit(0 = w, 1 = r) bit7 先传 */
		i2c_SendByte(_Address | 0);
		ucAck = i2c_WaitAck();	/* 检测设备的ACK应答 */

		i2c_Stop();			/* 发送停止信号 */

		return ucAck;
	}
	return 1;	/* I2C总线异常 */
}


void  Device_WriteData(uint8_t DeciveAddr,uint8_t *Data,int size)
{
    int count=size;
		uint8_t *pData=Data;
		//起始信号
    i2c_Start();    
    //发送器件地址                         
    i2c_SendByte(DeciveAddr);       
    //等待应答
    i2c_WaitAck();                          
    while(count--)
		{
			//发送数据
			i2c_SendByte(*pData++);                     
			//等待应答
			i2c_WaitAck();   
		}			 
                       
    //结束信号
    i2c_Stop();     
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

相关文章:

  • 2021-04-02
  • 2021-10-09
  • 2022-12-23
  • 2022-12-23
  • 2021-06-07
  • 2021-07-01
  • 2022-01-20
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2021-04-05
  • 2022-12-23
  • 2021-10-10
  • 2021-05-08
  • 2021-07-18
相关资源
相似解决方案