一.MCP4017

1.啥是MCP4017

老式收音机音量旋钮就是电位器:

  • 拧到最左边 → 音量最小(0)

  • 拧到中间 → 音量适中(50)

  • 拧到最右边 → 音量最大(100)

MCP4017 就是把这个机械旋钮变成了电子的!

MCP4017 = 电子音量旋钮
        = 数字电位器
        = 用代码控制的电阻

2.MCP4017特点

  1. 有128个档位(像音量旋钮有128个刻度)

    • 0 → 电阻最小(像音量最小)

    • 127 → 电阻最大(像音量最大)

  2. 用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都加!

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐