蓝桥杯CT107D单片机进阶实战:双通道电压采样与动态显示全解析

在蓝桥杯单片机竞赛的备战过程中,掌握多通道模拟信号采集技术是突破硬件编程瓶颈的关键一环。CT107D开发板搭载的PCF8591芯片为参赛选手提供了便捷的A/D转换解决方案,而如何同时采集光敏电阻和可调电阻的电压值并实现动态显示,则是检验I2C通信与数据处理能力的经典案例。本文将手把手带你从零搭建完整工程,深入解析每个技术细节。

1. 硬件架构与原理剖析

1.1 PCF8591芯片工作机理

PCF8591作为一款集成了4路模拟输入、1路模拟输出的8位A/D-D/A转换器,其核心特性包括:

  • 4路模拟输入:支持单端或差分输入模式,本文案例使用AIN1和AIN3两个独立通道
  • 8位分辨率:对应0-255的数字量输出范围,量化精度约为19.5mV(5V基准时)
  • I2C接口:标准400kHz快速模式兼容,设备地址固定为0x90(写)/0x91(读)

实际应用中需注意:PCF8591的转换速度约11ms/次,连续采样时需要适当加入延时

1.2 电路连接关键点

CT107D开发板的硬件连接需要特别注意以下接口:

元件 连接位置 参数特性
光敏电阻RD1 PCF8591 AIN1 光照越强阻值越小(2-20kΩ)
可调电阻RB2 PCF8591 AIN3 10kΩ线性可调
基准电压 PCF8591 VREF 默认接开发板5V电源
// 硬件初始化验证代码
void Hardware_Check() {
    PCF8591_Init();  // I2C初始化
    LED_Init();      // 调试指示灯初始化
    SEG_Init();      // 数码管初始化
}

2. 工程搭建与驱动移植

2.1 I2C驱动文件移植

蓝桥杯官方提供的I2C驱动通常包含以下关键函数:

// I2C基础操作函数
void IIC_Start(void);
void IIC_Stop(void);
void IIC_SendByte(unsigned char dat);
unsigned char IIC_RecByte(void);
void IIC_SendAck(bit ackbit);
bit IIC_WaitAck(void);

移植步骤:

  1. iic.hiic.c添加到工程目录
  2. 检查头文件包含路径是否正确
  3. 验证延时函数与硬件匹配(STC15系列需要调整延时)

2.2 工程结构规划

推荐采用模块化编程结构:

Project/
├── Main.c            // 主循环与调度
├── PCF8591.c         // A/D转换处理
├── Display.c         // 数码管显示
├── iic.c             // I2C底层驱动
└── Includes.h        // 全局定义与声明

3. 核心代码实现解析

3.1 多通道采样逻辑

PCF8591的通道切换需要遵循特定时序:

  1. 发送控制字节选择通道
  2. 启动转换后等待足够时间
  3. 读取转换结果
unsigned char Read_PCF8591(unsigned char channel) {
    unsigned char result;
    
    IIC_Start();
    IIC_SendByte(0x90);       // 设备地址+写模式
    IIC_WaitAck();
    IIC_SendByte(0x40 | channel); // 启用A/D转换+通道选择
    IIC_WaitAck();
    IIC_Stop();
    
    Delay_ms(15);             // 等待转换完成
    
    IIC_Start();
    IIC_SendByte(0x91);       // 设备地址+读模式
    IIC_WaitAck();
    result = IIC_RecByte();   // 读取转换结果
    IIC_SendAck(1);           // 非应答终止传输
    IIC_Stop();
    
    return result;
}

3.2 电压换算算法

8位ADC的电压换算公式:

实际电压 = 采样值 × (基准电压 / 255)

考虑到数码管显示需要保留两位小数,可采用整数运算优化:

void Process_Voltage(void) {
    // 读取原始采样值
    adc1_raw = Read_PCF8591(1);
    adc3_raw = Read_PCF8591(3);
    
    // 电压换算(放大100倍避免浮点运算)
    adc1_volt = adc1_raw * 500 / 255;  // 等效于 (adc1_raw*5.0/255)*100
    adc3_volt = adc3_raw * 500 / 255;
    
    // 分离各位数字
    disp_buf[0] = adc1_volt / 100;       // 十位
    disp_buf[1] = (adc1_volt / 10) % 10; // 个位
    disp_buf[2] = adc1_volt % 10;        // 十分位
    disp_buf[3] = adc3_volt / 100;
    disp_buf[4] = (adc3_volt / 10) % 10;
    disp_buf[5] = adc3_volt % 10;
}

4. 动态显示优化技巧

4.1 数码管刷新策略

采用定时中断实现稳定刷新:

// 定时器0初始化(1ms中断)
void Timer0_Init() {
    AUXR |= 0x80;       // 1T模式
    TMOD &= 0xF0;
    TL0 = 0xCD;
    TH0 = 0xD4;
    TR0 = 1;
    ET0 = 1;
    EA = 1;
}

// 中断服务程序
void Timer0_ISR() interrupt 1 {
    static unsigned char pos = 0;
    
    SEG_OFF_ALL();      // 关闭所有位选
    SEG_Set(pos, disp_buf[pos]); // 显示当前位
    pos = (pos + 1) % 6; // 循环6位数码管
}

4.2 显示效果优化

针对不同环境光照条件,可增加自动亮度调节:

void Auto_Brightness() {
    unsigned char light = Read_PCF8591(1);
    if(light > 200) SEG_Brightness(3);  // 强光环境高亮度
    else if(light > 100) SEG_Brightness(2);
    else SEG_Brightness(1);             // 弱光环境低亮度
}

5. 调试常见问题解决方案

5.1 采样值不稳定

可能原因及对策:

  1. 电源噪声:在VREF引脚增加0.1μF去耦电容
  2. 信号干扰:缩短传感器引线长度,必要时加屏蔽
  3. I2C时序问题:用逻辑分析仪捕获波形验证时序参数

5.2 数码管显示异常

典型故障排查流程:

观察现象 → 检查位选信号 → 验证段码数据 → 测量驱动电压 → 排查程序逻辑

关键测试点:

  • 锁存器使能信号(LE)是否正常
  • 段码数据与预期编码表是否一致
  • 动态刷新频率是否在100-500Hz范围内

6. 进阶功能扩展

6.1 数据滤波处理

采用滑动平均滤波提升稳定性:

#define FILTER_LEN 8
unsigned char filter_buf[FILTER_LEN];
unsigned char filter_index = 0;

unsigned char Moving_Average(unsigned char new_val) {
    static unsigned int sum = 0;
    
    sum -= filter_buf[filter_index];
    sum += new_val;
    filter_buf[filter_index] = new_val;
    filter_index = (filter_index + 1) % FILTER_LEN;
    
    return (unsigned char)(sum / FILTER_LEN);
}

6.2 阈值报警功能

增加光强阈值检测:

void Check_Light_Threshold() {
    if(adc1_volt < light_threshold) {
        BUZZER_ON();
        LED_Alert_Blink();
    } else {
        BUZZER_OFF();
        LED_Normal();
    }
}

在项目开发过程中,我发现合理使用状态机架构能显著提升代码可维护性。将采样、处理、显示等任务分配到不同定时周期执行,既保证了实时性又避免了函数阻塞。例如设置10ms采样周期、5ms显示刷新周期,通过标志位触发各任务执行。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐