stm32的hal库软件模拟iic通信学习(以M24C02/AT24C02为例) 从数据手册到配置到代码看这一个就够啦

本文记录了使用蓝桥杯嵌入式的STM32G431开发板与M24C02芯片进行IIC通信的过程。从引脚配置开始,介绍了如何使用软件IIC通信,包括芯片规范、起始与终止代码、ACK代码、读写数据代码等,还涉及M24C02芯片存储的描述与控制,最后给出总源代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于iic的概念我就不多说了,csdn很多资料。

我将讲述英语不会的情况下如何查看英文的手册

从原理到代码一步一步记录如何与芯片进行通信。

在阅读本篇文章时,请去学习iic的通信规范,不然比较难懂

开篇:

不废话,电脑安装一个有道词典并且启动就行

首先:

我用的是蓝桥杯嵌入式的stm32g431开发板,使用的M24C02芯片,接线图如下

可以看出,

PB6   接的是     SCL

PB7   接的是     SDA

并且还外接了两个上拉电阻,在通信时起到上拉的作用

这两个引脚并没有硬件iic功能,所以只能软件iic通信。

由于iic支持一主多从,图中还有一个MCP4017芯片,这个芯片不做讲解,没有影响。

引脚配置

现在知道了两个引脚了,那就配置两个引脚

打开cubemx

找到pb6,pb7,设置为gpio_output模式,即引脚输出模式

选择好后,进入system core->gpio

点开pb6,和pb7,配置成如下的代码

释义:

GPIO output level:High
引脚默认输出电平,这里选择high,在开漏模式下属于高阻态,电平取决于外部电路


GPIO mode:Output Open Drain
引脚的输出模式,这里是开漏输出,只有高阻态和下拉


GPIO Pull-up/Pull-down:No pull-up and no pull-down
这个是是否配置上拉,我选择的是无上下拉,如果上面的原理图中没有上拉电阻,那这里就要配置成上拉电阻,即GPIO Pull-up/Pull-down:pull-up


Maximum output speed:Low
输出速度,默认,慢
Fast Mode:Disable
快速模式,默认,不启动

User Label:

用户重命名,默认空,不动。

pb6和pb7都按这个配置配置完后生成代码

驱动部分

芯片的规范

首先在工程中配置好两个空白的myiic.c和.h文件

不会的看这个链接
http://t.csdnimg.cn/6lkJx
 

之后会参考数据手册,

m24c02数据手册获取

链接:https://pan.baidu.com/s/1hE7OGJWPdsbPWSUG9vwXYg 
提取码:8888

打开数据手册,看第一页

没什么好看的,就是参数介绍,继续往下看

目录,非常明显,我们需要参考的地方就在红色的框框里面

图中标记的数据大概就是SDA或者SCL电平保持的时间不能低于多少时间,因为我们使用软件iic模拟,所以基本上不会出现时间过短导致传输失败,不做过多解释,往下一大半

这里讲了大概的引脚规范,其中提到了芯片的两个引脚是开漏输出模式。与我们的stm32的两个引脚配置的引脚是开漏输出相呼应,并且建议使用上拉电阻,对应了iic的协议规范。

这里提到了本芯片的iic寻址是的7位地址,而且是高位起始,意思是数据从高位开始往地位发送,并且第八位是命令位,代表读或者写。

通过查看原理图和手册,E1,E2,E3都接地,即0.

所以本芯片的ip地址是1010000(),最后一位是命令位

这个就很重要了,讲述了iic通信中的各组标志。
起始信号:SCL为高电平期间,SDA信号线由高电平向低电平的变化表示起始信号;
终止信号:SCL为高电平期间,SDA由低电平向高电平的变化表示终止信号。

即在SCL拉高时
SDA:由低到高 – 起始信号
SDA:由高到低 – 终止信号

起始与终止的代码撰写

回到开头的引脚原理图部分

进行启动和停止代码的描写

首先,我们将pb6和pb7进行封装

打开myiic.h

#ifndef _MY_IIC_H
#define _MY_IIC_H
//scl的端口
#define MYSCL_PORT  GPIOB
#define MYSCL_PIN   GPIO_PIN_6
//sda的端口
#define MYSDA_PORT  GPIOB
#define MYSDA_PIN   GPIO_PIN_7






#endif

然后加入4个函数用来封装SDA与SCL的控制

#ifndef _MY_IIC_H
#define _MY_IIC_H
//scl的端口
#define MYSCL_PORT  GPIOB
#define MYSCL_PIN   GPIO_PIN_6
//sda的端口
#define MYSDA_PORT  GPIOB
#define MYSDA_PIN   GPIO_PIN_7


void            MYIIC_W_SCL(unsigned char x);//控制scl电平
void            MYIIC_W_SDA(unsigned char x);//控制sda电平
unsigned char   MYIIC_R_SDA(void);//读取sda电平
void            delay_us(unsigned int delay);//微妙级延迟


#endif

对应的.c代码是:

#include "myiic.h"


#define WAIT_TIME 50
static void delay1(unsigned int n)
{
    uint32_t i;
    for ( i = 0; i < n; ++i);
}

void MYIIC_W_SCL(unsigned char x)
{
    HAL_GPIO_WritePin(MYSCL_PORT, MYSCL_PIN,(GPIO_PinState)x);
    delay1(WAIT_TIME);
    
}
void MYIIC_W_SDA(unsigned char x)
{
    HAL_GPIO_WritePin(MYSDA_PORT, MYSDA_PIN,(GPIO_PinState)x);
    delay1(WAIT_TIME);
}

unsigned char MYIIC_R_SDA(void)
{
    unsigned char u8;
    
    u8 = HAL_GPIO_ReadPin(MYSDA_PORT, MYSDA_PIN);
    delay1(WAIT_TIME);
    return u8; 
    
}

其中有一个小tip,当引脚配置为开漏输出时,在高阻态的情况下是可以读取引脚的真实电平的,所以这里读取SDA电平直接readpin就行

为了降低篇幅,之后的代码就不放出.h中的函数声明,下面出现的函数都可以在头文件中声明。

好了,引脚控制有了,可以开始起始与终止的代码

起始位:
参考数据手册

即:在SCL为高电平期间将SDA拉低,随后SCL拉低

void MYIIC_Start(void)
{
    MYIIC_W_SDA(1); // 一定要先拉高SDA再拉高SCL
    MYIIC_W_SCL(1);
    
    MYIIC_W_SDA(0);//在SCL拉高的时候拉低SDA
    MYIIC_W_SCL(0);//随后拉低SCL
   
}
终止位:
参考数据手册

即SCL为高电平期间,SDA由低电平向高电平的变化表示终止信号。

void MYIIC_Stop(void)
{
    MYIIC_W_SCL(0);//先拉低SCL,控制
    MYIIC_W_SDA(0);//拉低SDA
    
    MYIIC_W_SCL(1);//拉高SCL
    MYIIC_W_SDA(1);//拉高的SCL期间拉高SDA。将iic总线释放,表示stop信号

}

发送ACK与接收ACK代码的撰写

接收ACK

即无论前面做了啥,只要发送了8位的数据且是有效的,芯片就会在下一个SCL拉高前将SDA拉低,表示ACK(收到)

//代码比较复杂,加了循环是为了防止在数据传输出错后不会卡在等待ack的循环里面
unsigned char MYIIC_WaitAck(void)
{
    unsigned short cErrTime = 10;//设置错误循环为10次
    MYIIC_W_SDA(1);//拉高SDA,即释放SDA的控制
    MYIIC_W_SCL(1);//拉高SCL
    while(MYIIC_R_SDA())//读取SDA,如果为0,则跳出循环
    {
        cErrTime--;
        if (0 == cErrTime)//错误处理
        {
            MYIIC_Stop();
            return ERROR;
        }
    }
    MYIIC_W_SCL(0);//读取完毕,重新拉低SCL
    return SUCCESS;//代码执行到这里说明接收ACK成功,返回success,即0
}
发送ACK(在进行读操作时需要)

这里数据手册没讲

我们根据逻辑来

当接收了芯片发来的8位数据时,如果还需要继续接收下一位地址,我们则需要发送ACK(0)给芯片,芯片就会自动发送下一个地址的数据。否则发送非ACK(1)。

void MYIIC_SentAck(unsigned char bit)
{
    if(bit == 0)//判断要ACK还是非ACK
    MYIIC_W_SDA(0);
    else
    MYIIC_W_SDA(1);

    MYIIC_W_SCL(1);//拉高SCL,从机读取SDA判断是否ACK
    MYIIC_W_SCL(0);//拉低SCL
}

以下内容编排中,待定

写数据的的撰写

指定地址写

读数据的的撰写

当前地址读
指定地址读
指定地址多次读

应用层的理解与代码

M24C02关于存储的描述与控制

芯片信息
芯片控制参数
芯片控制代码

总源代码

### 回答1: CubeMX是一款由ST公司出品的集成开发环境,可用于STM32微控制器的快速配置代码生成。该软件非常适合初学者和专家使用,支持Hal使用手册。 Hal是ST公司提供的硬件抽象层,封装了处理器与外设之间的通信底层操作。在使用CubeMX进行STM32代码编写时,常常需要使用Hal,因此掌握Hal的使用非常重要。 在使用Hal之前,需首先引入相关头文件,并初始化要使用的硬件外设。然后使用Hal提供的API函数进行操作,如读写外设的寄存器,发送/接收数据等。 具体来说,通过CubeMX配置工程后生成的代码中,可以看到各个外设的配置信息以及对应的HalAPI函数的调用。此外,还有一些示程序可供参考,有助于深入了解Hal的使用。 需要注意的是,Hal使用中对硬件性能的需求较高,因此在编写代码时需要小心优化,并避免出现死循环或其它性能问题。除此之外,推荐使用官方的文档和手册,以保证精准的使用。 ### 回答2: CubeMX是一个用于生成基于HAL的嵌入式软件的集成开发环境,它简化了HAL的使用。 HAL(Hardware Abstraction Layer)是针对不同的嵌入式芯片硬件架构设计的一套API接口,使开发人员能够驱动芯片硬件。因此,CubeMX HAL使用手册主要有以下方面的内容: 首先,手册介绍了CubeMX的安装、基本结构和用户界面。 这包括如何创建一个新项目,如何添加芯片型号和,以及如何定义各种芯片和外设的配置参数。 其次,手册详细介绍了HAL的各种功能和API接口,以及如何使用它们来控制芯片硬件。 在这部分中,了解如何配置GPIO、UART、DMA等外设并进行数据传输、时钟配置、电源管理以及中断等常见操作。 最后,手册包括一些示和模板代码,以帮助新手熟悉HAL的使用和应用。这使得读者可以更加深入地理解HAL如何实现各种应用程序需求。 同时,手册还包含了一些调试技巧和建议,以帮助开发人员在调试时快速找到和解决问题。 总之,CubeMX HAL使用手册是掌握HAL一个重要参考资料,它能够有效地帮助开发人员节省时间,减少犯错,从而更好地利用HAL来实现自己的应用程序需求。 ### 回答3: CubeMX是一个自动生成代码配置工具,开发人员可以通过它快速配置STM32微控制器的外设并生成代码HAL则是由STM32提供的基于C语言的封装,用于操作微控制器的外设。 CubeMX和HAL都是STM32开发中非常重要的工具和。CubeMX作为一个自动生成代码配置工具,可以帮助开发人员快速完成项目的初始化和配置,节省了人工编写代码的时间和精力。HAL则是对STM32原有的封装,让开发人员更加容易地使用外设,也提供了强大的功能和灵活性。 使用CubeMX和HAL的方法如下: 1. 在CubeMX中选择STM32微控制器型号及其外设,进行配置。 2. 生成初始化代码并导出到工程中。 3. 在工程中添加HAL依赖文件及其头文件。 4. 在代码中使用HAL提供的函数进行外设的初始化和操作。 需要注意的是,使用CubeMX和HAL并不能代替开发人员对STM32微控制器和其外设的深入了解。当需要进行更深层次的调试和优化时,开发人员仍需要熟悉硬件结构和寄存器操作,并编写自己的代码。同时,在使用过程中还要仔细阅读HAL的使用手册,掌握其函数的参数和使用方法,以便更加高效地使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值