4.蓝桥杯ADC+MCP4017
·
一.MCP4017
1.啥是MCP4017
老式收音机音量旋钮就是电位器:
-
拧到最左边 → 音量最小(0)
-
拧到中间 → 音量适中(50)
-
拧到最右边 → 音量最大(100)
MCP4017 就是把这个机械旋钮变成了电子的!
MCP4017 = 电子音量旋钮
= 数字电位器
= 用代码控制的电阻
2.MCP4017特点
-
有128个档位(像音量旋钮有128个刻度)
-
0 → 电阻最小(像音量最小)
-
127 → 电阻最大(像音量最大)
-
-
用I2C通信控制(两根线控制)
-
SCL:时钟线(告诉它"注意,要发数据了")
-
SDA:数据线(发送具体数值)
-
3.MCP4017的作用
// 假设你想调节一个灯的亮度 物理电位器:手拧旋钮 → 电阻变化 → 灯变亮/暗 MCP4017: 代码写数值 → 电阻变化 → 灯变亮/暗
4.MCP4017的实际应用例子
// 用MCP4017调节LED亮度
void set_led_brightness(u8 value)
{
// value 范围 0-127
// 0: 最暗
// 127: 最亮
I2C_Write_MCP4017(value);
}
// 呼吸灯效果
for(int i = 0; i < 128; i++) {
set_led_brightness(i); // 逐渐变亮
delay(10);
}
for(int i = 127; i >= 0; i--) {
set_led_brightness(i); // 逐渐变暗
delay(10);
}
二.MCP4017硬件部分

该图展示的是一个典型的I2C总线硬件连接电路,用于嵌入式系统中实现主控芯片与外部设备之间的串行通信。电路中包含两个主要外设:M24C02-WMN6TP(EEPROM存储器)和MCP4017T-104ELT(数字电位器),它们通过I2C总线与主控芯片(如STM32)相连,使用PB6作为时钟线(SCL),PB7作为数据线(SDA)。

给他127,W输出就是100k,给他0,W输出就是0k


三.关于uwTick
if(uwTick - xxx_tick < 间隔时间)
return; // 时间没到,直接退出,不执行后面代码
xxx_tick = uwTick; // 时间到了,更新时间戳,继续执行
RTC硬件每秒自动+1,我们只需要每秒读一次就够了。
不加定时,主循环多快就读多快(比如10ms一次),99%的读取是重复值,浪费CPU。
加1000ms定时,刚好和硬件同步,读一次就有新值,效率最高。
他就是一个不阻塞的延时
四.ADC采集代码
/*************** ADC ***************/
u8 mcp_num = 0;
u32 mcp_value = 0;
u32 r37_value = 0;
u32 r38_value = 0;
float mcp_volt = 0;
float r37_volt = 0;
float r38_volt = 0;
u32 adc_tick = 0;
void ADC_proc()
{
if(uwTick - adc_tick<200)
return;
adc_tick = uwTick;
HAL_ADC_Start(&hadc1);
mcp_value = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Start(&hadc1);
r38_value = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Start(&hadc2);
r37_value = HAL_ADC_GetValue(&hadc2);
mcp_volt = 3.3 * mcp_value / 4096.0;
r38_volt = 3.3 * r38_value / 4096.0;
r37_volt = 3.3 * r37_value / 4096.0;
MCP_write(mcp_num);
}
五.长按这一块的代码要好好看看
else if(ui == adc_ui)
{
if(key_down ==1)
{
ui = pwm_ui;//没有写第二个界面的时候按按键1会卡死
LCD_Clear(Black);
}
else if(key_down ==2)
{
if(mcp_num !=127)
mcp_num = 127;
else
mcp_num = 0;
}
else if(key_up ==3)
{
mcp_num ++;
if(mcp_num>127)
mcp_num = 127;
}
else if(key_up ==4)
{
mcp_num --;
if(mcp_num>127)
mcp_num = 127;
}
else if(key_down == 3 || key_down == 4)
{
key_long_tick = uwTick;
}
if(key_value == 3 && (uwTick - key_long_tick>800))
{
mcp_num ++;
if(mcp_num>127)
mcp_num=127;
}
else if(key_value == 4 && (uwTick - key_long_tick>800))
{
mcp_num --;
if(mcp_num>127)
mcp_num=0;
}
}
0ms 按下:
key_down = 3, key_value = 3
第一块:key_down==3 为真 → 进短按,mcp_num++(第1次)
└── else if 跳过,key_long_tick 不更新(还是0)
第二块:key_value==3 为真 ✓
(uwTick - 0 > 800)? → (0-0>800)? 否(第一次可能不触发)
结果:只加了1次(短按)
20ms 还按着:
key_down = 0(已经不是按下瞬间)
key_value = 3(仍按着)
第一块:都不进
第二块:key_value==3 为真 ✓
(20 - 0 > 800)? 否
结果:没加
... 一直到800ms前:都不加
820ms 还按着:
key_value = 3 ✓
(820 - 0 > 800)? ✅ 是!
第二块执行:mcp_num++(第2次)
840ms:mcp_num++(第3次)
860ms:mcp_num++(第4次)
...
每20ms都加!
更多推荐



所有评论(0)