ITPub博客

首页 > 嵌入式/内核开发 > 嵌入式/内核开发 > [蓝桥杯嵌入式有手就行]8_I2C

[蓝桥杯嵌入式有手就行]8_I2C

原创 嵌入式/内核开发 作者:工具人呵呵 时间:2023-10-17 11:40:37 0 删除 编辑


前言

一、内部结构

1、内部框图

2、I2C通信协议

二、I2C模块分析

1、原理图

2、元件介绍

1、24C02(eeprom)

2、MCP4017(可编程电阻)

3、硬件I2C发送与接收


三、代码示例

1、cubemx配置

2、上代码

1、24C02的相关代码

2、MCP4017的相关代码

四、问题

1、PB6和PB7引脚设置

总结

前言

注:本系列基于2023年蓝桥杯实战情况就行编写,所有软件均采用2023年赛点资源包

目前已知stm32 硬件I2C在hal库下存在bug,在I2C通讯过程中,如果进入中断(任意)会导致卡死。近期没有精力去测试各个版本(资料包提供的是1.3的库,但是我的cubemx强制更新1.4,再加上keil g4包版本可能也不一样)。

因此本文基于软件I2C编写(主要是官方给了库文件),等我更新完最近的两个系列文章后,我会去试试硬件I2C,到时会更新在下文或者另出一篇。


一、内部结构

1、内部框图

在这里插入图片描述


2、I2C通信协议

I2C总线是一种双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。

器件又可以分为主设备和从设备,相当于主人和仆人的关系。在每次通讯时,必须由主设备发送起始信号,每接收一个字节的数据都需要回复一个ack应答信号,在结束后发送结束信号。参看下图。

在这里插入图片描述

在同一总线上的每一个从设备必须拥有一个独立的地址,这个地址为8位,因此理论最大连接设备数是256个。采用I2C通讯的设备必须使用开漏输出的形式,以避免多个设备同时发送。在实际使用过程中,每个器件的总线接口都有一定的等效电容,连接数量会受到总线电容负载能力限制(400pF)。

在这里插入图片描述

发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。


start:SDA(1)➡SCL(1)➡SDA(0)➡SCL(0)

stop:SCL(1)➡SDA(0)➡SCL(1)➡SDA(1)


二、I2C模块分析

1、原理图

在这里插入图片描述


2、元件介绍

1、24C02(eeprom)

在这里插入图片描述

M24C02-WMN6TP:Internally organized with 32 pages of 8 bytes each,

the 2K requires an 8-bit data  word address for random word addressing.

一共可以储存256字节,但是,不能跨页读写(换句话说,要不多次读写,要不依次全读出来挑有用的)。

器件地址:根据手册Device Addressing章节,我们可知其器件地址前4位固定为1010,后三位由A2、A1、A0硬件连接决定,最后一位读取是1,写入是0。在原理图中可见,三个引脚全部接地。因此,我们读取地址是0xa1写入地址是0xa0。

在这里插入图片描述

注意:大多数情况下,我们在发送器件地址后,还需要发送页地址来确认需要读取/写入的数据页,然后才是数据传输。如图所示:

在这里插入图片描述


当然,也可以按顺序来读写

在这里插入图片描述


2、MCP4017(可编程电阻)

地址:参看手册,我们可以知道其读地址为0x5F写地址为0x5E。

在这里插入图片描述


我们通过手册可以看到其内部由128个Rs组成一个大电阻。而我们通过指令,可以更改电阻的通断,这样就可以更改总电阻的大小。在板子上的体现就是PB14的电压变化。

在这里插入图片描述

那么,电阻如何计算?

我们继续看手册,下图是内部电阻的结构图,我们实际更改的是RW开关的数量。

在这里插入图片描述

以下是手册中给出的计算公式。

在这里插入图片描述

然而公式中有两个未知数,RAB和RW,我们继续查找手册。此处的Rw应该是为了防止N=0时短路的。

在这里插入图片描述

在上面这个表格中,我们可以发现当前器件的RAB为100kΩ。100kΩ/127=Rs=787.402Ω。

于是上式就可以改成Rwb=Rs*N+Rw。但是,Rw还是未知,我们继续查手册。

在这里插入图片描述

根据上表,我们得到Rab在100kΩ下,Rw=100Ω。

因此,计算公式就变成了:Rw=787.40*N+100。


3、硬件I2C发送与接收

软件I2C其实就是模仿硬件的形式按照I2C协议发送指定数据。这里在不确定bug是否修复了的情况下,建议还是使用软件模拟。

在这里插入图片描述

在这里插入图片描述


三、代码示例

1、cubemx配置

这里我们使用软件I2C,直接跳过。我们只需要导入这两个文件,不会的看lcd章节。

在这里插入图片描述


2、上代码

1、24C02的相关代码

void write_24c02(unsigned char value)
{
I2CStart();//发送起始信号
I2CSendByte(0xa0);//发送器件写地址
I2CWaitAck();
I2CSendByte(0);//发送页地址
I2CWaitAck();
I2CSendByte(value);//发送数据
I2CWaitAck();
I2CStop();//发送停止信号
}
unsigned char read_24c02(void)
{
unsigned char value;
I2CStart();//发送起始信号
I2CSendByte(0xa0);//发送器件写地址
I2CWaitAck();//等待应答信号
I2CSendByte(0);//发送页地址
I2CWaitAck();
I2CStart();//这个很重要
I2CSendByte(0xa1);//发送器件读地址
I2CWaitAck();
value = I2CReceiveByte();//读数据
I2CSendNotAck();
I2CStop();
return value;
}




2、MCP4017的相关代码

void write_resistor(uint8_t value)
{
I2CStart();
I2CSendByte(0x5E);
I2CWaitAck();
I2CSendByte(value);
I2CWaitAck();
I2CStop();
}
uint8_t read_resistor(void)
{
uint8_t value;
I2CStart();
I2CSendByte(0x5F);
I2CWaitAck();
value = I2CReceiveByte();
I2CSendNotAck();
I2CStop();
return value;
}



四、问题

1、PB6和PB7引脚设置

通过阅读i2c_hal.c,我们可以得到


引脚      描述

PB6      SCL,推挽高速输出,带上拉。

PB7      SDA,输入:高速上拉开漏;输出:高速无上下拉开漏输出

总结

以上就是I2C的内容,相比硬件i2c多了发送ack的命令(当然你可以魔改下官方的库文件)。上文已经将两个元件通信流程截图放上来了。比赛忘记了就翻手册,虽然到现在为止,还没考过。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70050091/viewspace-3117700/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-01-01

  • 博文量
    35
  • 访问量
    5027