嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记11:数字电位器MCP4017

系列文章目录

嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记01:赛事介绍与硬件平台

嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记02:开发环境安装

嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记03:G4时钟结构

嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记04:从零开始创建工程模板并开始点灯

嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记05:Systick滴答定时器

嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记06:按键输入

嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记07:ADC模数转换

嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记08:LCD液晶屏

嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记09:EEPROM

嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记10:USART串口通讯

嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记11:数字电位器MCP4017


目录

系列文章目录

前言

一、电路原理

二、程序设计

三、ADC采样分压电压


前言

数字电位器MCP4017本质是一个IC器件,也就是说它是一个集成芯片,而板子上的蓝色旋转电位器R37、R38本质是一个电阻。数字电位器本质是一个芯片,但是内部有一个电阻网络,通过很多模拟开关来给电阻网络切换不同的阻值,我们是通过之前介绍过的I2C总线来给芯片发送数据,告诉芯片我要打开哪些模拟开关,从而控制它的阻值。

一、电路原理

首先我们看一下MCP4017,首先1号管脚接3.3V,2号管脚接GND,3、4管脚是I2C的通讯线,最重要的是5、6,数字电位器W、B两个管脚,5脚相当于是一个可变电阻的一端,另一端是悬空的,6脚相当于是可变电阻的滑片。

我们假设W滑到最左边,则5、6之间的电阻R_{WB}就等于AB之间整个电阻的总值R_{AB},如果滑到AB的中点,那么R_{WB}=\frac{1}{2}R_{AB},如果滑到B端,那么R_{WB}就约等于0。需要注意的是,芯片内部并不是这样的结构,而是一堆模拟开关实现了这样的功能。因为模拟开关本身是有阻值的,所以也会存在一些误差。

这个电位器的型号是104ELT(原理图可见),也就是说最多有10*10^4欧姆的电阻可调,即100kΩ

那么我们看电路图,W端接了一个10k的电阻接到3.3V,B端接地,很容易看出这是一个分压电路,那么我们很容易可以算出W端的电位:V=3.3\cdot \frac{R_{WB}}{R_{WB}+10}。而这个分压的电压V是接到了单片机的PB14这个口,PB14在STM32上也是一个ADC的输入口,所以我们可以通过ADC来采集这个电压的分压情况,从而可以知道WB之间的阻值变化。当然我们也可以设置好一个阻值,然后通过ADC来确认它的电压。

通过对这个电路的分析我们可知,我们实际上就是通过一个10k的电阻与一个数字电位器分压来得到PB14口的模拟输入。

那么我们接下来简单了解一下MCP4017这个芯片。可以看到它是一个7bit的支持IIC总线的数字电位器,并且拥有可变内存。SC70是它的封装。401系列还有4018、4019,其中4018一般用于分压器,4017、4019一般用于可变电阻,具体的我们就不去了解了。

  • 7bit是指它的电阻网络有7个位可以配置,也就是可以配置一共127个不同的阻值。因为总阻值是100kΩ,那么我们就可以把100k分成127个档
  • 抽头的电阻是100Ω,也就是说如果把WB短接,那也有100Ω的阻值(几乎可忽略)。
  • 低温漂:可变电阻的温漂是50ppm(百万分之50)。
  • 用IIC协议来读写。
  • 掉电时WB的电压不能超过1.5V。
  • 不编任何程序的话,它默认上电就是中间电压(50kΩ)。
  • 低功耗(2.5微安)
  • 电压工作范围:2.7V-5.5V。

还有一点就是芯片的存储形式是RAM,也就是说每次掉电都会清空,这就是为什么要规定默认上电时要中间电压。

除此之外比较重要的就是MCP4017的器件地址:0101111,还有一个R/W位,如果是写入的话,R/W就是0,加上器件地址就是01011110,即0x5e,如果是读就是0x5f

我们再看一下内部的电阻网络是怎么构成的。可以看到电阻网络还是挺简单的,我们甚至可以自己用电阻加模拟开关来构成一个类似的电路,当然,芯片帮我们集成好了用起来更方便。

可以看到每个Rs的电阻上都加了一个开关,每个开关上都有一个数,也就是说我们每往上增加一个数,就会增加一个Rs的电阻。Rs一共有127个,加起来等于100kΩ,这样我们可以算出Rs的值应该是0.7874kΩ。比方说:如果控制字节是0x7F,那么电阻就是100kΩ,如果控制字节是0x3F,就是中间位,即50kΩ,如果控制字节是0x00,那么电阻就是0(实际上是100Ω)。

二、程序设计

我们可以利用I2C总线控制数字电位器芯片的电阻值,与R17的10kΩ形成分压,这样PB14的电位就会发生相应的变化,再用ADC来进行读取。

这里我们先看一下怎么编程STM32来改变MCP4017的阻值。

程序流程:

  • 复制i2c的底层驱动文件到“编程工程”并改名
  • 在main.c调用i2c的IO初始化代码并包含头文件
  • 在i2c.c文件里编程:读写MCP4017函数,并在i2c.h中声明
  • 在main.c调用MCP4017_Write和MCP4017_Read完成程序

其中重点是MCP4017读写函数的编写,其他的部分我们在EEPROM里面已经做过了就不赘述了。我们这里主要看一下怎么编写MCP4017读写函数。下图是厂商芯片资料给的如何写一个字节数据的示例。

主器件就是我们的STM32,首先要发一个Start起始命令,然后发送从器件的地址+一个R/W位,因为是写数据,所以R/W位是0,所以是0x5E。然后等待应答。完成后,我们要送一个数据给MCP4017,送的数据就是我们要控制它的电阻的大小,它是一个7bit的控制字,就是0-0x7F的控制范围。主设备把这个字节发送过去,第一位用不到所以丢弃。然后等待应答。最后主器件再发一个终止命令STOP。

根据这个图我们很容易就可以写出MCP4017_Write()函数:

void MCP4017_Write(u8 val)
{
    I2CStart();
    I2CSendByte(0x5E);
    I2CWaitAck();

    I2CSendByte(val);
    I2CWaitAck();
    I2CStop();
}

读取函数我们一般用不到,因为我们只需要写入控制它的阻值就行了,并不需要读取现在阻值多少。比赛的时候也几乎很少遇到,但是最好还是学一下,也可以通过读取函数来判断是否成功写入,防止数据干扰。比方说可以写完之后读取一下,判断写的对不对,如果不对就再写一次。但是比赛中不需要这样。

u8 MCP4017_Read(void)
{
    u8 val;

    I2CStart();
    I2CSendByte(0x5F);
    I2CWaitAck();

    val=I2CReceiveByte();
    I2CSendNotAck();
    I2CStop();

    return val;
}

 还有一点就是,MCP4017两次写入之间是不需要延时的,不同于EEPROM。

三、ADC采样分压电压

MCP4017的W端接了一个PB14的管脚,并接在了ADC1的输入口上,所以我们可以用PB14来采样分压电压。

进入CubeMX开始配置引脚。可以看到PB14可以设置为ADC1的5通道,与PB12共用一个ADC,但是通道不同。我们把它设置为单端模式直接采集电压就行了。如果这部分内容还不清楚的话可以翻到之前的内容看一下ADC的讲解。

我们需要注意的是,ADC1现在有两个通道,那我们怎么告诉STM32现在要采集哪个通道呢?这边就有一个内容要在CubeMX上配置的,在ADC1的Configuration中有一个Number of Conversion也就是ADC转换的数量,这里要改成2。改完后下面有个Rank就自动变成2个了,并自动打开Scan conversion mode扫描转换模式,它会先转换一个通道的输入后再去转换另一个通道,转化的顺序就是由Rank决定,Rank1就是第一个被转换的通道,我们可以在Rank里面选择,并且这里我们可以调整它的采样速度Sampling Time(采样时间)。注意,多通道采集的时候,采样速度最好不要太快,否则会容易出错,所以我们可以把采样速度调的慢一点,这里我们调640.5个周期。

再把Rank1设置为通道5,Rank2设置为通道11。

生成代码,我们可以看到ADC1的初始化定义里面已经有了要转换的通道数量为2,和不同Rank对应的通道。

我们已经有了之前的ADC的程序,现在在此基础上增加ADC1通道5的内容。(如果没有的话就自己写一下,配置ADC的教程在前面有,写完记得初始化一下,有的时候程序写完了发现运行不对有可能就是忘了初始化)

我们定义一个变量volt_mcp来表示通过mcp采集到的电压值。

因为我们定义的Rank1是采集mcp,也就是先采集mcp再采集R37,所以我们是在采集R37的程序前面添加采集mcp的程序。

u16 adc1_val,adc2_val;
float volt_r37,volt_r38,volt_mcp;
void ADC_Process(void)
{
	//rank1
	HAL_ADC_Start(&hadc1);
	volt_mcp = HAL_ADC_GetValue(&hadc1)/4095.0f*3.3f;
	//rank2
	HAL_ADC_Start(&hadc1);
	adc1_val = HAL_ADC_GetValue(&hadc1);
	volt_r37 = adc2_val/4095.0f*3.3f;
	
	HAL_ADC_Start(&hadc2);
	adc2_val = HAL_ADC_GetValue(&hadc2);
	volt_r38 = adc1_val/4095.0f*3.3f;
}

这样就完成了ADC1先采集通道5,再采集通道11的过程,需要注意的是,我们并不需要手动切换采集通道,只需要再调用一次HAL_ADC_Start()函数就可以自动切换通道了,这是因为我们之前配置了扫描转换,正因如此,我们在编写程序的时候一定要注意采样的顺序!

我们可以调用一下前面写好的MCP4017_Write(),然后写入0x3F,也就是中位点。设置好电阻后在主循环中调用ADC采样函数就可以看一下现在的分压电压了。

int main()
{
    MCP4017_Write(0x3F);
    while(1);
    {
        ADC_Process();
    }
}

我们可以写个LCD显示函数来看一下此时volt_mcp的值,这里就跳过了。显示出来的值应该是2.7左右。如果输入0x7F的话,输出应该是2.95左右。

如果之前没有现成的ADC程序的话,我们总结一下利用ADC1双通道采集的程序设计步骤:

  • 用给的“模版”生成代码
  • 设置ADC相关的GPIO为输入模式,并设置成单端模式。(PB15、PB12、PB14)
  • 设置ADC1的转换的通道数(number of conversion)为2,并设置Rank和采集速度。
  • 添加ADC相关的HAL库驱动文件
  • 包含ADC的头文件,并初始化ADC(如果是移植代码的话要初始化外设时钟)
  • 利用HAL_ADC_Start和HAL_ADC_GetValue编写程序(双通道要调用两次Start)

总结

这节课主要是学习如何使用MCP4017数字电位器,它需要通过I2C总线进行通信,利用I2C向其内部写入数据从而控制它的内部电阻大小,并且外部接了一个分压电路,并把分压电压作为ADC的输入采样,从而转化成数字量被我们读取。所以这一节的内容需要结合I2C总线和ADC这两部分内容一起来学习的。其中最重要的内容是MCP4017读写函数的编写ADC的双通道采集这两部分内容,比赛时是需要自己编写的,需要牢记。此外,还需要记得ADC的采样Rank和采样速度。

  • 28
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32G431RB是一款32位ARM Cortex-M4微控制器,它支持多种中断类型。 在STM32G431RB中,中断被分为两类:外部中断和内部中断。外部中断由外部设备触发,例如GPIO口的边沿触发。内部中断则是由内部的事件或异常触发,例如定时器溢出事件或DMA传输完成。 要使用中断功能,首先需要配置中断向量表和NVIC(Nested Vectored Interrupt Controller)。 1. 配置中断向量表: 中断向量表是存放中断处理程序入口地址的表格。在STM32G431RB中,可以通过修改链接脚本文件或使用HAL库提供的函数来配置中断向量表。 2. 配置NVIC: NVIC用于管理中断优先级和使能中断。可以使用CMSIS提供的API函数来配置NVIC。 3. 配置外部中断: 对于外部中断,首先要配置对应GPIO口的输入模式和触发方式。然后通过EXTI(External Interrupt)模块来使能外部中断,并设置触发条件。 4. 编写中断处理程序: 中断处理程序是中断发生时执行的代码块。在编写中断处理程序时,需要注意以下几点: - 使用__attribute__((interrupt))或者对应的函数前缀来声明中断处理程序。 - 在中断处理程序中尽量避免使用延时函数或阻塞操作,而是应尽量简洁并尽快完成中断处理。 - 在中断处理程序中清除中断标志位,以便使能下一次中断发生。 这是一个简要的关于在STM32G431RB上使用中断的介绍。具体的配置和编程细节可以查阅相关的参考资料或官方文档。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值