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

本文主要是介绍嵌入式|蓝桥杯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 MCP4018_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)
{//rank1HAL_ADC_Start(&hadc1);volt_mcp = HAL_ADC_GetValue(&hadc1)/4095.0f*3.3f;//rank2HAL_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和采样速度。

这篇关于嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记11:数字电位器MCP4017的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/851931

相关文章

基于Python开发Windows屏幕控制工具

《基于Python开发Windows屏幕控制工具》在数字化办公时代,屏幕管理已成为提升工作效率和保护眼睛健康的重要环节,本文将分享一个基于Python和PySide6开发的Windows屏幕控制工具,... 目录概述功能亮点界面展示实现步骤详解1. 环境准备2. 亮度控制模块3. 息屏功能实现4. 息屏时间

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部

使用Python开发一个现代化屏幕取色器

《使用Python开发一个现代化屏幕取色器》在UI设计、网页开发等场景中,颜色拾取是高频需求,:本文主要介绍如何使用Python开发一个现代化屏幕取色器,有需要的小伙伴可以参考一下... 目录一、项目概述二、核心功能解析2.1 实时颜色追踪2.2 智能颜色显示三、效果展示四、实现步骤详解4.1 环境配置4.

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

Python使用smtplib库开发一个邮件自动发送工具

《Python使用smtplib库开发一个邮件自动发送工具》在现代软件开发中,自动化邮件发送是一个非常实用的功能,无论是系统通知、营销邮件、还是日常工作报告,Python的smtplib库都能帮助我们... 目录代码实现与知识点解析1. 导入必要的库2. 配置邮件服务器参数3. 创建邮件发送类4. 实现邮件

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

基于Python开发一个有趣的工作时长计算器

《基于Python开发一个有趣的工作时长计算器》随着远程办公和弹性工作制的兴起,个人及团队对于工作时长的准确统计需求日益增长,本文将使用Python和PyQt5打造一个工作时长计算器,感兴趣的小伙伴可... 目录概述功能介绍界面展示php软件使用步骤说明代码详解1.窗口初始化与布局2.工作时长计算核心逻辑3

python web 开发之Flask中间件与请求处理钩子的最佳实践

《pythonweb开发之Flask中间件与请求处理钩子的最佳实践》Flask作为轻量级Web框架,提供了灵活的请求处理机制,中间件和请求钩子允许开发者在请求处理的不同阶段插入自定义逻辑,实现诸如... 目录Flask中间件与请求处理钩子完全指南1. 引言2. 请求处理生命周期概述3. 请求钩子详解3.1

如何基于Python开发一个微信自动化工具

《如何基于Python开发一个微信自动化工具》在当今数字化办公场景中,自动化工具已成为提升工作效率的利器,本文将深入剖析一个基于Python的微信自动化工具开发全过程,有需要的小伙伴可以了解下... 目录概述功能全景1. 核心功能模块2. 特色功能效果展示1. 主界面概览2. 定时任务配置3. 操作日志演示

JavaScript实战:智能密码生成器开发指南

本文通过JavaScript实战开发智能密码生成器,详解如何运用crypto.getRandomValues实现加密级随机密码生成,包含多字符组合、安全强度可视化、易混淆字符排除等企业级功能。学习密码强度检测算法与信息熵计算原理,获取可直接嵌入项目的完整代码,提升Web应用的安全开发能力 目录