STM32F103学习笔记(1)——FreeRTOS下模拟I2C

发布者:电子设计艺术家最新更新时间:2025-02-21 来源: jianshu关键字:STM32F103  FreeRTOS  模拟I2C 手机看文章 扫描二维码
随时随地手机看文章

一、硬件连接

功能口引脚
SCLPB.6
SDAPB.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);

[1] [2]
关键字:STM32F103  FreeRTOS  模拟I2C 引用地址:STM32F103学习笔记(1)——FreeRTOS下模拟I2C

上一篇:STM32F103学习笔记(2)——收音机模块TEA5767使用
下一篇:OSW-MMOS直驱方向盘DIY过程记录2-PWM+DIR模式

推荐阅读最新更新时间:2026-03-17 10:54

基于FreeRTOSSTM32F103系统—队列
在FreeRTOS中,队列是实现任务之间同步、互斥和通信的一种重要方法(其他的实现方法有:任务通知、事件组、信号量、互斥量)。 任何任务都可以向队列里存放任何数据,任何任务也可以从队列里读取数据,实现不同任务之间的通信。 1 队列特性 队列的数据的操作采用先进先出的方法(FIFO,First In First Out):写数据时放到尾部,读数据时从头部读,逻辑顺序如下图所示。 使用队列传输数据时有两种方法: 拷贝:把数据、把变量的值复制进队列里 引用:把数据、把变量的地址复制进队列里 FreeRTOS中的队列一般都使用拷贝的方式传输数据,局部变量的值可以发送到队列中,后续即使函数退出、局部变量被回收,也不会
[单片机]
基于<font color='red'>FreeRTOS</font>的<font color='red'>STM32F103</font>系统—队列
STM32F103R8t6 FreeRTOS工程adc+flash模拟EEPROM源程序
STM32单片机源程序如下: #include sys.h #include delay.h #include usart.h #include led.h #include FreeRTOS.h #include task.h #include ADC.h #include 74HC595.h #include key.h #include stmflash.h //const u8 TEXT_Buffer ={ 0123456789 }; //任务优先级 #define START_TASK_PRIO 1 //任务堆栈大小 #define START_STK_SIZ
[单片机]
FreeRTOS+STM32F103串口通信错误解决方法
在调试FreeRTOS系统时,在串口中断中用队列存储数据,然后再定时器中断中用队列接收数据,并通过串口打印出来。在调试代码中编译器报错。 …OBJLED.axf: Error: L6915E: Library reports error: __use_no_semihosting was requested, but _ttywrch was referenced 在网上搜索之后,找到了一个解决方法。在usart.c文件中添加以下代码,可以解决这个问题。 //__use_no_semihosting was requested, but _ttywrch was _ttywrch(int ch) { ch = ch
[单片机]
<font color='red'>FreeRTOS</font>+<font color='red'>STM32F103</font>串口通信错误解决方法
FreeRTOS学习笔记——基础知识与移植(STM32F103
1.1 前后台系统: 早期嵌入式开发没有嵌入式操作系统的概念 ,直接操作裸机,在裸机上写程序,比如用51单片机基本就没有操作系统的概念。通常把程序分为两部分:前台系统和后台系统。 简单的小系统通常是前后台系统,这样的程序包括一个死循环和若干个中断服务程序:应用程序是一个无限循环,循环中调用API函数完成所需的操作,这个大循环就叫做后台系统。中断服务程序用于处理系统的异步事件,也就是前台系统。前台是中断级,后台是任务级。 1.2 RTOS系统: RTOS全称为:Real Time OS,就是实时操作系统,强调的是:实时性。实时操作系统又分为硬实时和软实时。硬实时要求在规定的时间内必须完成操作 ,硬
[单片机]
<font color='red'>FreeRTOS</font>学习笔记——基础知识与移植(<font color='red'>STM32F103</font>)
linux gpio模拟i2c
/* 这是我模仿其他人写的程序, 仅仅是把他改写成适合自己开发板的程序 */ #include linux/miscdevice.h #include mach/regs-gpio.h #include mach/hardware.h #include linux/fs.h #define DEVICE_NAME FINALL #define RETRY_TIMES 1 #define GPIO_SCL S3C2410_GPF3 #define GPIO_SDA S3C2410_GPF0 #define GPIO_SDA_OUTP S3C2410_GPF0_OUTP #define GPIO_S
[单片机]
STM32单片机的ADS1115通过模拟I2C驱动
注意:本部分代码需要只是ADS1115的部分程序(一些用到的数组在此没有写),模拟II2C的各程序并未给出,大家根据需要进行裁剪,代码完全开源,希望能帮到大家,也希望大家乐于分享。 调试时需特别注意I2C的通信问题,特别是应答信号的使用需要特别关注,本人的程序之前出错全是因为从机的应答信号的未使用造成。 收获:对于I2C通信协议的理解更加深刻,对ADS1115也能进行单通道的使用。I2C的开始、发送/读写、应答、结束等一定要严格按照时序操作,ADS的操作还有所欠缺,仅仅会配置单通道,对于其他配置并没有关注,最近要把多通道的和阈值的配置也写好,到时再更新 附录代码: #define CMD_Write 0x90 ////写
[单片机]
STM32单片机的ADS1115通过<font color='red'>模拟</font><font color='red'>I2C</font>驱动
基于STM32系列MCU使用软件模拟I2C步骤
一、Bit Bang 关于 Bit Bang 的解释:Use software to control serial communication at general-purpose I/O pins,简单来讲就是使用软件通过 IO 脚去实现 I2C 的时序从而使用 I2C 协议进行通信。 这样做的好处是可以突破硬件上的限制,例如芯片不具有硬件 I2C 模块,或者硬件 I2C 模块损坏,又或者使用硬件 I2C 模块时布线非常麻烦。坏处是需要写代码模拟时序,根据不同的硬件平台和不同的时钟频率,代码中的部分参数是不一样的。 二、代码分析 以下代码基于 STM32 系列 MCU 使用软件模拟 I2C 的步骤如下: 1、设置 GPI
[单片机]
基于STM32系列MCU使用软件<font color='red'>模拟</font><font color='red'>I2C</font>步骤
无人机设计中STM32库实现的模拟i2c代码
目前发现国内正儿八经机器人、无人机并且还能活跃地上网关注行业前沿动向、热爱写科普文章的研究人员原来越少。因此所有的研究回答里都没有人真正说明白无人机到底是什么,而理解无人机到底是什么才是回答这个问题的先决条件。 什么是无人机 首先,无人机就是不载人的飞行器,而说到飞行器,通常我们又可以把飞行器分为三类。 1、固定翼(fixed wing)。平时坐的波音747空客A380,还有F-16歼-15之类的都是固定翼飞机。顾名思义就是翅膀形状固定,靠流过机翼的风提供升力。动力系统包括桨和助推发动机。固定翼根据机翼尺寸的不同还有很多小的分类,在此不细说。固定翼飞行器的优点是在三类飞行器里续航时间最长、飞行效率最高、载荷最大,缺点是起飞的时
[单片机]
无人机设计中STM32库实现的<font color='red'>模拟</font><font color='red'>i2c</font>代码
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved