一、硬件连接
| 功能口 | 引脚 |
|---|---|
| SCL | PB.6 |
| SDA | PB.5 |
链接:https://pan.baidu.com/s/1wxbQTMlnX2pavrbW2RYg4g 提取码:dxex
将 board_i2c.c 和 board_i2c.h 两个文件加入工程的User文件夹下
注意:延时函数使用了FreeRTOS的vTaskDelay任务延时函数
2.1 board_i2c.c
/*********************************************************************
* INCLUDES
*/
#include 'FreeRTOS.h'
#include 'task.h'
#include 'board_i2c.h'
#include 'board_systick.h'
static void SDA_OUT_MODE(void);
static void SDA_IN_MODE(void);
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/**
@brief I2C驱动初始化,采用模拟IO的方式实现
@param 无
@return 无
*/
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(IIC_SCL_CLK | IIC_SDA_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = IIC_SCL_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(IIC_SCL_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
IIC_Stop(); // 给一个停止信号, 复位I2C总线上的所有设备到待机模式
}
/**
@brief CPU发起I2C总线启动信号
@param 无
@return 无
*/
void IIC_Start(void)
{
SDA_OUT_MODE(); // SDA线输出模式
IIC_SDA_1();
IIC_SCL_1();
vTaskDelay(1);
IIC_SDA_0(); // 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号
vTaskDelay(1);
IIC_SCL_0(); // 钳住I2C总线,准备发送或接收数据
}
/**
@brief CPU发起I2C总线停止信号
@param 无
@return 无
*/
void IIC_Stop(void)
{
SDA_OUT_MODE(); // SDA线输出模式
IIC_SCL_0();
IIC_SDA_0();
IIC_SCL_1();
vTaskDelay(1);
IIC_SDA_1(); // 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号
vTaskDelay(1);
}
/**
@brief CPU向I2C总线设备发送8bit数据
@param ucByte -[in] 等待发送的字节
@return 无
*/
void IIC_SendByte(uint8_t ucByte)
{
uint8_t i;
SDA_OUT_MODE(); // SDA线输出模式
IIC_SCL_0(); // 拉低时钟开始数据传输
for(i = 0; i < 8; i++)
{
if(ucByte & 0x80)
{
IIC_SDA_1();
}
else
{
IIC_SDA_0();
}
ucByte <<= 1;
vTaskDelay(1);
IIC_SCL_1();
vTaskDelay(1);
IIC_SCL_0();
vTaskDelay(1);
}
}
/**
@brief CPU从I2C总线设备读取8bit数据
@param 无
@return 读到的数据
*/
uint8_t IIC_ReadByte(void)
{
uint8_t i = 0;
uint8_t value = 0;
SDA_IN_MODE(); // SDA线输入模式
for(i = 0; i < 8; i++)
{
value <<= 1;
IIC_SCL_1();
vTaskDelay(1);
if(IIC_SDA_READ())
{
value++;
}
IIC_SCL_0();
vTaskDelay(1);
}
IIC_Ack();
return value;
}
/**
@brief CPU产生一个时钟,并读取器件的ACK应答信号
@param 无
@return 返回0表示正确应答,1表示无器件响应
*/
uint8_t IIC_WaitAck(void)
{
uint8_t result = 0;
SDA_IN_MODE(); // SDA线输入模式
IIC_SDA_1(); // CPU释放SDA总线
vTaskDelay(1);
IIC_SCL_1(); // CPU驱动SCL = 1, 此时器件会返回ACK应答
vTaskDelay(1);
if(IIC_SDA_READ())
{
result = 1;
}
else
{
result = 0;
}
IIC_SCL_0();
vTaskDelay(1);
return result;
}
/**
@brief CPU产生一个ACK信号
@param 无
@return 无
*/
void IIC_Ack(void)
{
SDA_OUT_MODE(); // SDA线输出模式
IIC_SDA_0(); // CPU驱动SDA = 0
vTaskDelay(1);
IIC_SCL_1(); // CPU产生1个时钟
vTaskDelay(1);
IIC_SCL_0();
vTaskDelay(1);
IIC_SDA_1(); // CPU释放SDA总线
}
/**
@brief CPU产生1个NACK信号
@param 无
@return 无
*/
void IIC_NAck(void)
{
SDA_OUT_MODE(); // SDA线输出模式
IIC_SDA_1(); // CPU驱动SDA = 1
vTaskDelay(1);
IIC_SCL_1(); // CPU产生1个时钟
vTaskDelay(1);
IIC_SCL_0();
vTaskDelay(1);
}
/**
@brief 检测I2C总线设备,CPU向发送设备地址,然后读取设备应答来判断该设备是否存在
@param address -[in] 设备的I2C总线地址+读写控制bit(0 = w, 1 = r)
@return 0 - 表示正确, 1 - 表示未探测到
*/
uint8_t IIC_CheckDevice(uint8_t address)
{
uint8_t ucAck;
IIC_Init(); // 初始化I2C
IIC_Start(); // 发送启动信号
IIC_SendByte(address); // 设备的I2C总线地址+读写控制bit(0 = w, 1 = r)
ucAck = IIC_WaitAck(); // 检测设备的ACK应答
IIC_Stop(); // 发送停止信号
return ucAck;
}
/*********************************************************************
* LOCAL FUNCTIONS
*/
/**
@brief SDA输出配置
@param 无
@return 无
*/
static void SDA_OUT_MODE(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
}
/**
@brief SDA输入配置
@param 无
@return 无
*/
static void SDA_IN_MODE(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
}
/****************************************************END OF FILE****************************************************/
2.2 board_i2c.h
#ifndef _BOARD_I2C_H_
#define _BOARD_I2C_H_
/*********************************************************************
* INCLUDES
*/
#include 'stm32f10x.h'
/*********************************************************************
* DEFINITIONS
*/
// I2C_SCL时钟
#define IIC_SCL_CLK RCC_APB2Periph_GPIOB // GPIO端口时钟
#define IIC_SCL_PORT GPIOB // GPIO端口
#define IIC_SCL_PIN GPIO_Pin_6 // GPIO引脚
// I2C_SDA时钟
#define IIC_SDA_CLK RCC_APB2Periph_GPIOB // GPIO端口时钟
#define IIC_SDA_PORT GPIOB // GPIO端口
#define IIC_SDA_PIN GPIO_Pin_5 // GPIO引脚
/*********************************************************************
* MACROS
*/
#define IIC_SCL_0() GPIO_ResetBits(IIC_SCL_PORT, IIC_SCL_PIN)
#define IIC_SCL_1() GPIO_SetBits(IIC_SCL_PORT, IIC_SCL_PIN)
#define IIC_SDA_0() GPIO_ResetBits(IIC_SDA_PORT, IIC_SDA_PIN)
#define IIC_SDA_1() GPIO_SetBits(IIC_SDA_PORT, IIC_SDA_PIN)
#define IIC_SDA_READ() GPIO_ReadInputDataBit(IIC_SDA_PORT, IIC_SDA_PIN)
/*********************************************************************
* API FUNCTIONS
*/
void IIC_Init(void);
void IIC_Start(void);
void IIC_Stop(void);
void IIC_SendByte(uint8_t ucByte);
uint8_t IIC_ReadByte(void);
uint8_t IIC_WaitAck(void);
void IIC_Ack(void);
void IIC_NAck(void);
uint8_t IIC_CheckDevice(uint8_t address);
上一篇:STM32F103学习笔记(2)——收音机模块TEA5767使用
下一篇:OSW-MMOS直驱方向盘DIY过程记录2-PWM+DIR模式
推荐阅读最新更新时间:2026-03-17 10:54
- DC757A-A,使用 LTC4302CMS-1 可寻址 2 线总线缓冲器和电源电平转换的演示板
- 使用 Microchip Technology 的 MIC2871YMK 的参考设计
- DVK-SFJK-1-GEVK,基于AX-SFJK收发器的RCZ3的Sigfox AT开发套件
- 汽车后视镜控制设计
- AM2G-4805DH30Z ±5V 2 瓦 DC/DC 转换器的典型应用
- DC1067A-A,LTC2450IDC 演示板,16 位高性能,Delta Sigma 模数转换器
- AM2G-2407DH30Z ±7.2V 2 瓦 DC/DC 转换器的典型应用
- 使用 Cypress Semiconductor 的 S6AP413A29GN1C000 的参考设计
- 升压变压器设计中的寄生电容效应
- snapVCC:3.3/5 V 超高效稳压器,可直接安装在您的 9 V 电池上(含原理图、PCB等)



基于 X-Cube-FreeRTOS_Heap4 和 CubeMX 生成 UCPD 项目介绍
基于开发板frdmmcxn947利用lwip_httpsrv_freertos程序开发
现代雷达系统的信号设计
BFR340T






京公网安备 11010802033920号