stm32通用II2驱动
程序源码
bsp_i2c.c
#include "bsp_i2c.h"
#include "config.h"
#define DEFAULT_ACK 1 // 修改为 0 则固定发送 NACK
void SDA_Input_Mode(iic_bus_t *bus)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = bus->IIC_SDA_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(bus->IIC_SDA_PORT, &GPIO_InitStructure);
}
void SDA_Output_Mode(iic_bus_t *bus)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = bus->IIC_SDA_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(bus->IIC_SDA_PORT, &GPIO_InitStructure);
}
void SDA_Output(iic_bus_t *bus, uint16_t val)
{
GPIO_WriteBit(bus->IIC_SDA_PORT, (uint16_t)bus->IIC_SDA_PIN, (val?Bit_SET:Bit_RESET));
}
void SCL_Output(iic_bus_t *bus, uint16_t val)
{
GPIO_WriteBit(bus->IIC_SCL_PORT, (uint16_t)bus->IIC_SCL_PIN, (val?Bit_SET:Bit_RESET));
}
uint8_t SDA_Input(iic_bus_t *bus)
{
return (GPIO_ReadInputDataBit(bus->IIC_SDA_PORT, bus->IIC_SDA_PIN));
}
//SCL1 SDA1-SDA0
/**
* @brief IIC起始信号
* @param None
* @retval None
*/
void i2c_start(iic_bus_t *bus)
{
SDA_Output(bus,1);
delay_us(5);
SCL_Output(bus,1);
delay_us(5);
SDA_Output(bus,0);
delay_us(5);
SCL_Output(bus,0);
delay_us(5);
}
//SCL1 SDA0-SDA1
/**
* @brief IIC结束信号
* @param None
* @retval None
*/
void i2c_stop(iic_bus_t *bus)
{
SCL_Output(bus,0);
delay_us(5);
SDA_Output(bus,0);
delay_us(5);
SCL_Output(bus,1);
delay_us(5);
SDA_Output(bus,1);
delay_us(5);
}
void i2c_send_ack(iic_bus_t *bus,unsigned char ack)
{
SDA_Output_Mode(bus);
SCL_Output(bus,0);
SDA_Output(bus,0);
delay_us(5);
SDA_Output(bus,ack ? 1 : 0); // 根据 ack 的值设置 SDA
SCL_Output(bus,1);
delay_us(5);
SCL_Output(bus,0);
SDA_Output(bus,1);
}
void i2c_ack(iic_bus_t *bus)
{
SDA_Output(bus,0);
delay_us(1);
SCL_Output(bus,1);
delay_us(1);
SCL_Output(bus,0);
delay_us(1);
}
void i2c_noack(iic_bus_t *bus)
{
SDA_Output(bus,1);
delay_us(1);
SCL_Output(bus,1);
delay_us(1);
SCL_Output(bus,0);
delay_us(2);
}
unsigned char i2c_wait_ack(iic_bus_t *bus)
{
unsigned short cErrTime = 5;
SDA_Input_Mode(bus);
delay_us(2);
SCL_Output(bus,1);
while(SDA_Input(bus))
{
cErrTime--;
delay_us(5);
if (0 == cErrTime)
{
SDA_Output_Mode(bus);
i2c_stop(bus);
//printf("I2C ACK Timeout\n"); // 增加调试信息
return 1;
}
}
SDA_Output_Mode(bus);
SCL_Output(bus,0);
delay_us(5);
return 0;
}
void i2c_send_byte(iic_bus_t *bus,unsigned char cSendByte)
{
unsigned char i = 8;
while (i--)
{
SCL_Output(bus,0);
delay_us(2);
SDA_Output(bus, cSendByte & 0x80);
delay_us(1);
cSendByte += cSendByte;
delay_us(1);
SCL_Output(bus,1);
delay_us(1);
}
SCL_Output(bus,0);
delay_us(2);
//printf("I2C Send Byte: 0x%02X\n", cSendByte); // 增加调试信息
}
unsigned char i2c_receive_byte(iic_bus_t *bus)
{
unsigned char i, byte = 0;
SDA_Input_Mode(bus); // 设置 SDA 为输入模式
delay_us(2);
for (i = 0; i < 8; i++)
{
SCL_Output(bus,0); // 拉低 SCL 准备读取
delay_us(2);
SCL_Output(bus,1); // 拉高 SCL,采样 SDA
delay_us(1);
byte <<= 1; // 左移一位
if (SDA_Input(bus)) // 如果 SDA 为高
{
byte |= 0x01; // 置为 1
}
}
SCL_Output(bus,0);
SDA_Output_Mode(bus);
return byte;
}
void iic_init(iic_bus_t *bus)
{
/*GPIO Init*/
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd((uint32_t)bus->IIC_SCL_PORT, ENABLE);
GPIO_InitStructure.GPIO_Pin = bus->IIC_SCL_PIN | bus->IIC_SDA_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(bus->IIC_SCL_PORT, &GPIO_InitStructure);
SCL_Output(bus,1);
SDA_Output(bus,1);
}
bsp_i2c.h
#ifndef __I2C_H__
#define __I2C_H__
#include "stm32f10x.h"
typedef struct
{
GPIO_TypeDef * IIC_SDA_PORT;
GPIO_TypeDef * IIC_SCL_PORT;
uint16_t IIC_SDA_PIN;
uint16_t IIC_SCL_PIN;
//void (*CLK_ENABLE)(void);
}iic_bus_t;
#define I2C_SCL_Port GPIOB
#define I2C_SCL_Pin GPIO_Pin_13
#define I2C_SDA_Port GPIOB
#define I2C_SDA_Pin GPIO_Pin_12
#define I2C_SCL(x) GPIO_WriteBit(I2C_SCL_Port, I2C_SCL_Pin, (x?Bit_SET:Bit_RESET))
#define I2C_SDA(x) GPIO_WriteBit(I2C_SDA_Port, I2C_SDA_Pin, (x?Bit_SET:Bit_RESET))
#define GETSDA() GPIO_ReadInputDataBit(I2C_SDA_Port, I2C_SDA_Pin)
//SDA输入模式
#define SDA_IN() { GPIO_InitTypeDef GPIO_InitStructure;\
GPIO_InitStructure.GPIO_Pin = I2C_SDA_Pin;\
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;\
GPIO_Init(I2C_SDA_Port, &GPIO_InitStructure);\
}
//SDA输出模式
#define SDA_OUT() { GPIO_InitTypeDef GPIO_InitStructure; \
GPIO_InitStructure.GPIO_Pin = I2C_SDA_Pin;\
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;\
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;\
GPIO_Init(I2C_SDA_Port, &GPIO_InitStructure);\
}
void i2c_start(iic_bus_t *bus);
void i2c_stop(iic_bus_t *bus);
void i2c_send_ack(iic_bus_t *bus,unsigned char ack);
void i2c_ack(iic_bus_t *bus);
void i2c_noack(iic_bus_t *bus);
unsigned char i2c_wait_ack(iic_bus_t *bus);
void i2c_send_byte(iic_bus_t *bus,unsigned char byte);
unsigned char i2c_receive_byte(iic_bus_t *bus);
void iic_init(iic_bus_t *bus);
#endif