硬件实现I2C案例(HAL库实现)

引言

        前面陆陆续续利用寄存器方式实现了软件模拟I2C、硬件实现I2C的案例。接下来,我们使用HAL库的方式实现以下硬件I2C案例。当然了,本次案例可能复用前面寄存器实现的硬件I2C案例中实现的某些代码块,所以建议看这之前可以先看看前面寄存器实现的案例介绍。


一、需求描述

二、硬件电路设计

       本次案例属于是前面寄存器实现的硬件I2C案例的另一种实现方式,故需求和硬件设计不变,不清楚的可参考下面文章:

硬件实现I2C案例(寄存器实现)_iic硬件电路-优快云博客https://blog.youkuaiyun.com/2301_79475128/article/details/145492167?spm=1001.2014.3001.5501

三、软件设计

接下来,我们首先进入STM32CubeMX中创建工程并进行相应的配置。

3.1 STM32CubeMX中的配置

进入STM32CubeMX后,左键单击【ACCESS TO MCU SELECTOR】,找到使用的STM32芯片类型,接着双击创建新工程。

新工程创建好后,就会进入下图界面

3.1.1 选择Debug

首先开始配置调试工具,进入【System Core】的【SYS】,然后选择【Serial Wire】穿行单线调试即可。

3.1.2 配置RCC时钟

同样,进入【System Core】的【RCC】中,先配置外部时钟源,如下图HSE和LSE对应的均选择石英晶体震荡源【Crystal/Ceramic Resonator】即可。

然后,在此基础上,继续进入【Clock Configuration】,配置内部系统时钟,如下图配置即可。

3.1.3 配置串口

本次案例中串口的作用是将数据输出到串口助手上,因此直接利用串口重定向printf即可,在STM32CubeMX中的配置如下图(使用USART1)

3.1.4 配置I2C

前面硬件电路设计中,我们使用的I2C外设为I2C2,所以这里配置使用的也是I2C2,配置参考如下图

3.1.5 工程管理配置

最后,进入【Project Manager】,设置工程名称、路径、工具链等,然后勾选相关项即可。配置参考下图

最后,点击【GENERATE CODE】生成代码,接着在keil中打开工程即可。

 3.2 Keil中的配置

进入keil工程进行相关的配置。

3.2.1 魔法棒配置

3.2.2 品的配置

【品】中是用来添加文件或目录组的。原本是不需要再【品】中配置的,但是本案例需要使用M24C02与32进行I2C通讯,所以和前面一样需要M24C02相关代码文件,这里方便起见,直接复用前面的M24C02的头源文件。

所以这里需要将俩文件添加到相关目录中即可。参考下图即可

这样,keil中的配置就OK了。

3.3 代码完善

进入VSCode,打开对应工程完善代码。

3.3.1 串口部分

串口我们之间重定向printf,因此首先在usart.h中引入stdio头文件,然后在usart.c文件中重写fputc函数即可。

3.3.2 I2C部分

先看看相关文件内容

I2C部分通过软件中的配置产生,代码自动生成,我们不用新增代码,相关函数HAL库已经存在,后面只需直接调用即可。

3.3.3 M24C02部分

HAL库已经对不同I2C通讯设备使用的函数进行包装,所以关于存储器(Mem)使用的函数也可以直接调用,所以我们对M24C02部分的函数实现使用HAL库函数进行替换即可。

注:这里笔者希望大家多主动理解相关HAL库函数代码,故这里不再赘述下面代码涉及到的相关函数,相信对大家来说比较容易。

1、m24c02.h

#ifndef __M24C02_H
#define __M24C02_H

#include "i2c.h"

// 宏定义
#define W_ADDR (0xA0)
#define R_ADDR (0xA1)

// 初始化
void M24C02_Init(void);

// 写入一个字节的数据
void M24C02_Writebyte(uint8_t innerAddr, uint8_t byte);

// 读取一个字节的数据
uint8_t M24C02_Readbyte(uint8_t innerAddr);

// 连续写入多个字节的数据(页写)
void M24C02_Writebytes(uint8_t innerAddr, uint8_t * bytes, uint8_t size);

// 连续读取多个字节的数据
void M24C02_Readbytes(uint8_t innerAddr, uint8_t * buffer, uint8_t size);

#endif

2、m24c02.c

#include "m24c02.h"

// 初始化
void M24C02_Init(void)
{
    MX_I2C2_Init();
}

// 主机写入一个字节的数据
void M24C02_Writebyte(uint8_t innerAddr, uint8_t byte)
{
    HAL_I2C_Mem_Write(&hi2c2, W_ADDR, innerAddr, I2C_MEMADD_SIZE_8BIT, &byte, 1, 1000);
    
    // 写入周期
    HAL_Delay(5);
}

// 读取一个字节的数据
uint8_t M24C02_Readbyte(uint8_t innerAddr)
{
    uint8_t data;
    HAL_I2C_Mem_Read(&hi2c2, R_ADDR, innerAddr, I2C_MEMADD_SIZE_8BIT, &data, 1, 1000);
    return data;
}

// 连续写入多个字节的数据(页写)
void M24C02_Writebytes(uint8_t innerAddr, uint8_t *bytes, uint8_t size)
{
    HAL_I2C_Mem_Write(&hi2c2, W_ADDR, innerAddr, I2C_MEMADD_SIZE_8BIT, bytes, size, 1000);
    
    // 写入周期
    HAL_Delay(5);
}

// 连续读取多个字节的数据
void M24C02_Readbytes(uint8_t innerAddr, uint8_t *buffer, uint8_t size)
{
    HAL_I2C_Mem_Read(&hi2c2, R_ADDR, innerAddr, I2C_MEMADD_SIZE_8BIT, buffer, size, 1000);
}

3.3.4 main部分

各功能已经写好,直接在main.c中编写测试代码即可。

1、引入头文件

(1)使用memset()函数,将字符数组缓冲区进行清零操作,故引入string,h

(2)使用M24C02与STM32进行通讯,故引入M24C02头文件

2、测试代码

直接使用前面案例使用的测试代码即可,因为测试代码使用的函数就是m24c02.c中实现的函数,而本次对其中的函数名没有做修改,所以可以直接复用测试代码。

/* USER CODE BEGIN 2 */

  printf("use HAL to hardware I2C will start...\n");

  // 2. 向m24c02中写入单字符
  M24C02_Writebyte(0x00, 'a');
  M24C02_Writebyte(0x01, 'b');
  M24C02_Writebyte(0x02, 'c');

  // 3. 向m24c02读取数据
  uint8_t byte1 = M24C02_Readbyte(0x00);
  uint8_t byte2 = M24C02_Readbyte(0x01);
  uint8_t byte3 = M24C02_Readbyte(0x02);

  // 4. 串口输出打印
  printf("byte1 = %c\t byte2 = %c\t byte3 = %c\n", byte1, byte2, byte3);

  // 5. 向m24c02写入字符串
  M24C02_Writebytes(0x00, "123456", 6);

  // 6. 向m24c02读取数据
  uint8_t buffer[100] = {0};
  M24C02_Readbytes(0x00, buffer, 6);

  // 7. 串口输出打印
  printf("buffer = %s\n", buffer);

  // 8. 测试页写超过数据范围
  // 缓冲区清零
  memset(buffer, 0, sizeof(buffer));

  M24C02_Writebytes(0x00, "1234567890abcdefghijk", 21);
  M24C02_Readbytes(0x00, buffer, 21);
  printf("test -> buffer = %s\n", buffer);

  /* USER CODE END 2 */

3.4 测试

编译烧录看看现象

如上图,烧录完成后串口助手上输出的数据,与测试代码实现的一致,即测试成功!


以上便是本次文章的所有内容,欢迎各位朋友在评论区讨论,本人也是一名初学小白,愿大家共同努力,一起进步吧!

鉴于笔者能力有限,难免出现一些纰漏和不足,望大家在评论区批评指正,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值