06 ADC与I2C应用

上一篇:05 LCD驱动编写
下一篇:07 波形捕获与PWM输出

作者:桂信科黄鹏老师。note部分是我添加的内容

主要内容

1.ADC 配置,多通道采样
2.I2C驱动代码移植
3.AT24C02 E2PROM应用
4.MCP4017 数字电位器应用

一、模拟输入原理图分析

开发板上一共有三部分电路实现模拟输入。嵌入式中的ADC全名Analog-to-Digital Converter,即模拟-数字转换器,相当于嵌入到单片机里的“电压表”。

IO口 模拟输入通道 功能
PB15 ADC2_IN15 R37可调电阻调压
PB12 ADC1_IN11 R38可调电阻调压
PB14 ADC1_IN5 U3数字电阻调压

Pasted image 20240131113444.png Pasted image 20240131113449.png

二、CubeMX配置多通道ADC

IN5和IN11都设置为单端输入
Pasted image 20240131115947.png
由于有两个通道,所以ADC的转换通道数量设置为2
Rank1 中通道设置为 Channel 5
采样周期设置为247.5 Cycles
Rank2 中通道设置为 Channel 11
采样周期设置为247.5 Cycles
注意:采样周期不能设置太小,否则会导致数据错误。

Note

单通道的ADC2_IN15则无需配置,勾上IN15 Single-ended即可。

Pasted image 20240131162752.png

三、ADC数据读取代码

g_dR37_V,g_dR10_V, g_dR38_V三个变量为三个电阻的分压电压值,可以将这个数值在LCD上显示处理,显示方法参考上一次课的LCD应用内容。

void getAdc(void)
{
	uint32_t adc;
	
	HAL_ADC_Start(&hadc2);
	HAL_ADC_PollForConversion(&hadc2,2);
	adc = HAL_ADC_GetValue(&hadc2);
	g_dR37_V =  adc*3.3/4096;
	HAL_ADC_Stop(&hadc2);
	
	HAL_ADC_Start(&hadc1);
	HAL_ADC_PollForConversion(&hadc1,2);
	adc = HAL_ADC_GetValue(&hadc1);
	g_dR10_V =  adc*3.3/4096;
	
	HAL_ADC_Start(&hadc1);
	HAL_ADC_PollForConversion(&hadc1,2);
	adc = HAL_ADC_GetValue(&hadc1);
	g_dR38_V =  adc*3.3/4096;
	
	HAL_ADC_Stop(&hadc1);
}

四、I2C原理图分析

I2C通信应用于AT24C02数据存储和MCP4017T数字电位器,在PB6和PB7上只能用软件I2C,硬件I2C的引脚是PB7和PB8。
Pasted image 20240125131754.png

五、CubeMX配置模拟I2C引脚

参照02 CubeMX配置引脚#四、I2C引脚完成该步骤。

六、I2C代码移植

组委会提供的 i2c_hal.c 和 i2c_hal.h 可以直接使用,无需做任何更改,并且驱动代码中使用寄存器方式进行配置,与CubeMX中设置的User Label无关。
Pasted image 20240131165756.png

七、AT24C02代码编写

AT24C02的代码需要自己编写,编写代码时需要参考数据手册。只需要写两个函数,一个是读数据函数,一个是写数据函数。

设备地址:数据手册P11页 Figure 7
结合原理图可知:读地址为 0xA1,写地址为 0xA0
Pasted image 20240131170035.png

7.1 读数据函数

参考P12 Figure 11

//根据Random Read写函数
I2CStart();//IIC开始
I2CSendByte(AT_W_ADDR);//发送写地址
I2CWaitAck();//等待ACK
I2CSendByte(address);//发送数据地址
I2CWaitAck();//等待ACK
I2CStart();//IIC开始
I2CSendByte(AT_R_ADDR);//发送读地址
I2CWaitAck();//等待ACK
_bydata = I2CReceiveByte();//读取数据
I2CSendNotAck();//发送NO_ACK
I2CStop();//IIC停止

Pasted image 20240131170237.png

7.2 写数据函数

参考P12 Figure 11

//根据Byte Write写函数
I2CStart();//IIC开始
I2CSendByte(AT_W_ADDR);//发送写地址
I2CWaitAck();//等待ACK
I2CSendByte(address);//发送数据地址
I2CWaitAck();//等待ACK
I2CSendByte(_bydata);//发送数据
I2CWaitAck();//等待ACK
I2CStop();//IIC停止

Pasted image 20240131170845.png

7.3 AT24C02应用测试
  g_byVal1 = AT24c02_read(0);
  AT24c02_write(0, ++g_byVal1);
  HAL_Delay(5);
  g_byVal2 = AT24c02_read(1);

  AT24c02_write(1, ++g_byVal2);
  HAL_Delay(5);
  g_byVal3 = AT24c02_read(2);
  AT24c02_write(2, ++g_byVal3);

八、MCP4017T数字电位器代码编写

驱动方式与AT24C02差不多,同时,编写代码需要参考其数据手册。只需要写两个函数,一个是读电阻值,一个写电阻值。

如原理图和数据手册的功能框图所示,MCP4017的W和B之间相当于数码可调电阻,它与R17串联在一起,测量的是PB14的电压。
Pasted image 20240131173057.png
Pasted image 20240131173103.png

由数据手册的P41 、P42所得,MCP4017默认电阻为100kΩ(典型值),档位有0~127个。0表示0欧,127表示100kΩ(相当于要打开的开关位置),所以得出“分辨率”(电阻Rs的阻值)为:100k/127 = 787.4欧姆。
Pasted image 20240131173508.png Pasted image 20240131173521.png

设备地址参考 P36 Figure 5-9
由该图可知,设备读地址为:0x5F;设置写地址为:0x5E。
Pasted image 20240131174018.png

8.1 读电阻数据函数

参考 P40  Read 1 Byte 时序

步骤:
1)IIC开始               I2CStart();
2)发送读地址             I2CSendByte(MCP_R_ADDR);
3)等待ACK               I2CWaitAck();
4) 读取电阻数据           _byResData = I2CReceiveByte();
5)NoACK                 I2CSendNotAck();
6)IIC停止               I2CStop();

Pasted image 20240131174402.png

8.2 写电阻数据函数

参考 P40  Write 1 Byte 时序

步骤:
1)IIC开始               I2CStart();
2)发送写地址             I2CSendByte(MCP_W_ADDR);
3)等待ACK               I2CWaitAck();
4) 发送电阻数据           I2CSendByte(_byResData);
5)等待ACK               I2CWaitAck();
6)IIC停止               I2CStop();

Pasted image 20240131174611.png

上一篇:05 LCD驱动编写
下一篇:07 波形捕获与PWM输出