news 2026/7/16 17:34:24

蓝桥杯单片机备赛指南第十三讲:IIC 总线与PCF8591 AD DA 转换

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
蓝桥杯单片机备赛指南第十三讲:IIC 总线与PCF8591 AD DA 转换

**

蓝桥杯单片机备赛指南第十三讲:IIC 总线与PCF8591 AD DA 转换

**

1. IIC 总线与PCF8591 硬件原理

1.1 IIC 通信协议(软件模拟)

IIC (Inter-Integrated Circuit) 是一种双线串行总线。

  • SCL (P2.0):时钟线。

  • SDA (P2.1):数据线。

时序核心(死记硬背)

  • 起始(Start):SCL 高期间,SDA 下降沿。

  • 停止(Stop):SCL 高期间,SDA 上升沿。

  • 应答(ACK):发送8 位后,第9 个时钟周期SDA 被拉低。

1.2 PCF8591 芯片详解

  • 设备地址:写地址0x90,读地址0x91

  • 控制字(Control Byte)

    • 通道选择:Bit 0-1 (00=AIN0, 01=AIN1, 10=AIN2, 11=AIN3)。

    • DA 使能:Bit 6 (1=开启模拟输出)。

    • 常用控制字

      • 0x01: 读光敏电阻(AIN1)。

      • 0x03: 读电位器Rb2 (AIN3)。

      • 0x40: 仅启用DAC 输出。


2. 进阶底层驱动模块

2.1 基础外设驱动(LED.c更新版)

重点:增加了BeepRelay,且所有函数均采用static变量+ 位运算,确保互不干扰。

#include"LED.h"// LED 单灯控制 (非破坏性)voidLED_Disp(unsignedcharaddr,bit enable){staticunsignedcharTemp=0x00;staticunsignedcharTemp_Old=0xFF;if(enable)Temp|=(0x01<<addr);elseTemp&=~(0x01<<addr);if(Temp!=Temp_Old){P0=~Temp;// 共阳极,取反输出P2=P2&0x1F|0x80;// 打开 Y4 (LED)P2&=0x1F;// 锁存Temp_Old=Temp;}}// 蜂鸣器控制 (非破坏性)voidBeep(bit enable){staticunsignedcharTemp=0x00;// 0x00 表示初始关闭状态 (假设 ULN2003 输入0为关)staticunsignedcharTemp_Old=0xFF;// 蜂鸣器通常接在 P0.6 (0x40)if(enable)Temp|=0x40;// 置 1 开启elseTemp&=~0x40;// 置 0 关闭if(Temp!=Temp_Old){P0=Temp;// 直接输出 (ULN2003 驱动)P2=P2&0x1F|0xA0;// 打开 Y5 (蜂鸣器/继电器)P2&=0x1F;Temp_Old=Temp;}}// 继电器控制 (非破坏性)voidRelay(bit flag){staticunsignedchartemp=0x00;staticunsignedchartemp_old=0xff;// 继电器通常接在 P0.4 (0x10)if(flag)temp|=0x10;elsetemp&=~0x10;if(temp!=temp_old){P0=temp;P2=P2&0x1F|0xA0;// 打开 Y5P2&=0x1F;temp_old=temp;}}

2.2 IIC 与PCF8591 读写(iic.c补全)

官方提供的代码包通常只有基础时序,必须熟练默写以下两个函数。

#include"iic.h"#include"intrins.h"// ... (I2CStart, I2CStop, I2CSendByte 等基础时序略,参考官方文件) ...// === 1. PCF8591 A/D 读取函数 ===// addr: 通道号 (0x01 光敏, 0x03 电位器)unsignedcharAd_Read(unsignedcharaddr){unsignedchartemp;I2CStart();I2CSendByte(0x90);// 写设备地址I2CWaitAck();I2CSendByte(addr);// 写控制字 (选择通道)I2CWaitAck();I2CStart();// 重新起始I2CSendByte(0x91);// 读设备地址I2CWaitAck();temp=I2CReceiveByte();// 读取数据I2CSendAck(1);// 发送非应答 (1),结束读取I2CStop();returntemp;}// === 2. PCF8591 D/A 写入函数 ===// dat: 输出电压对应的数字量 (0~255)voidDa_Write(unsignedchardat){I2CStart();I2CSendByte(0x90);// 写设备地址I2CWaitAck();I2CSendByte(0x40);// 写控制字 (0x40 = 启用 DAC)I2CWaitAck();I2CSendByte(dat);// 发送 DAC 数据I2CWaitAck();I2CStop();}

3. 功能设计要求(电压采集装置)

基于**《蓝桥杯模块训练- PCF8591.pdf》**原题整理。

3.1 数码管显示

系统包含两个界面,通过S4 切换。

  1. 电压显示界面(界面U)

    • 内容:显示电位器RB2 (AIN3) 的实时电压。

    • 格式U 3.41(保留两位小数)。

    • 细节:提示符’U’ 在第1 位,数据在6-8 位,中间熄灭。

  2. 电压输出界面(界面F)

    • 内容:显示当前DAC 输出端的电压值。

    • 格式F 2.50

    • 细节:提示符’F’ 在第1 位。

3.2 按键逻辑

  • S4 (界面切换):在U(显示) 和F(输出) 界面间循环。

  • S5 (模式切换):切换DAC 的输出模式。

    • 模式1 (跟随):输出电压= RB2 输入电压。

    • 模式2 (固定):输出电压固定为2.0V。

  • S6 (LED 开关):开启或关闭LED 指示功能。关闭时所有LED 熄灭。

3.3 LED 指示逻辑(修正版)

根据PDF 任务书要求:

  1. L1:指示当前在电压显示界面

  2. L2:指示当前在电压输出界面

  3. L3:当测量电压V>=3.5VV >= 3.5VV>=3.5V2.5V>V>=1.5V2.5V>V >= 1.5V2.5V>V>=1.5V时点亮。

  4. L4:DAC 输出固定电压(2.0V)时,L4 熄灭,DAC 输出电压跟 随 RB2 电位器输出电压变化时,L4 点亮。

  • S6 限制:若S6 关闭了指示功能,L1-L4 必须全部熄灭。

4. 核心代码解答(main.c)

#include<STC15F2K60S2.H>#include"Init.h"#include"Key.h"#include"LED.h"#include"Seg.h"#include"iic.h"// === 变量声明 ===typedefunsignedcharu8;typedefunsignedintu16;u8 Key_Slow_Down=0;u16 Seg_Slow_Down=0;u8 LED_Seg_Pos=0;// 数码管/LED 扫描指针// 显存与状态u8 Seg_Buf[8]={10,10,10,10,10,10,10,10};u8 Seg_Point[8]={0,0,0,0,0,0,0,0};u8 LED_Buf[8]={0,0,0,0,0,0,0,0};// LED 状态缓存 (1亮 0灭)u8 Key_Val,Key_Old,Key_Down,Key_Up;// 业务标志位bit Seg_Mode=0;// 0:电压显示界面(U), 1:电压输出界面(F)bit Mode1_Flag=0;// DAC模式: 0=固定2.0V, 1=跟随RB2bit LED_Flag=1;// LED总开关: 1=开, 0=关 (默认开)bit Seg_Flag=1;// 数码管总开关 (题目未要求按键控制,保持常开)floatVoltage=0;// 测量电压 (RB2)floatOutput_Voltage=2.0;// DAC 输出电压// === 按键逻辑 ===voidKey_Proc(){if(Key_Slow_Down)return;Key_Slow_Down=1;Key_Val=Key_Read();Key_Down=Key_Val&(Key_Val^Key_Old);Key_Old=Key_Val;switch(Key_Down){case4:// S4: 界面切换Seg_Mode^=1;break;case5:// S5: DAC 输出模式切换Mode1_Flag^=1;break;case6:// S6: LED 功能开关LED_Flag^=1;break;}}// === 数据处理与显示 ===voidSeg_Proc(){u8 i;if(Seg_Slow_Down)return;Seg_Slow_Down=1;// 1. 读取 A/D (RB2 -> AIN3)// 算法: Val / 255.0 * 5.0 => Val / 51.0Voltage=Ad_Read(0x03)/51.0;// 2. 处理 D/A 输出if(Mode1_Flag)Output_Voltage=Voltage;// 跟随模式elseOutput_Voltage=2.0;// 固定模式Da_Write((u8)(Output_Voltage*51.0));// 写入 DAC// 3. 数码管显示更新if(Seg_Flag){// 熄灭无关位Seg_Buf[1]=Seg_Buf[2]=Seg_Buf[3]=Seg_Buf[4]=10;// 设置小数点 (第5位点亮,对应 xxx.xx)for(i=0;i<8;i++)Seg_Point[i]=0;Seg_Point[5]=1;if(Seg_Mode==0)// 界面 U: 显示测量电压{Seg_Buf[0]=17;// 'U' (假设字模 17)Seg_Buf[5]=(u8)Voltage;// 个位Seg_Buf[6]=(u8)(Voltage*10)%10;// 十分位Seg_Buf[7]=(u16)(Voltage*100)%10;// 百分位}else// 界面 F: 显示输出电压{Seg_Buf[0]=16;// 'F' (假设字模 16)Seg_Buf[5]=(u8)Output_Voltage;Seg_Buf[6]=(u8)(Output_Voltage*10)%10;Seg_Buf[7]=(u16)(Output_Voltage*100)%10;}}else{for(i=0;i<8;i++)Seg_Buf[i]=10;}}// === LED 逻辑控制 ===voidLED_Proc(){u8 i;if(LED_Flag)// 总开关打开{// L1/L2: 界面指示 (互斥)LED_Buf[0]=!Seg_Mode;// Mode=0(U) -> L1亮LED_Buf[1]=Seg_Mode;// Mode=1(F) -> L2亮// L3/L4/L5: 电压范围指示 (基于测量电压 Voltage)LED_Buf[2]=(Voltage<1.5);LED_Buf[3]=(Voltage>=1.5&&Voltage<2.5);LED_Buf[4]=(Voltage>=2.5);// L6-L8: 熄灭LED_Buf[5]=LED_Buf[6]=LED_Buf[7]=0;}else// 总开关关闭{for(i=0;i<8;i++)LED_Buf[i]=0;}}// === 定时器中断 (驱动层) ===voidTimer0_Server()interrupt1{// ... 重装载代码 (1ms) ...if(++Key_Slow_Down==10)Key_Slow_Down=0;if(++Seg_Slow_Down==200)Seg_Slow_Down=0;// 硬件扫描if(++LED_Seg_Pos==8)LED_Seg_Pos=0;// 驱动数码管Seg_Disp(LED_Seg_Pos,Seg_Buf[LED_Seg_Pos],Seg_Point[LED_Seg_Pos]);// 驱动 LED (调用更新后的非破坏性驱动)LED_Disp(LED_Seg_Pos,LED_Buf[LED_Seg_Pos]);}voidmain(){// System_Init(); // 需包含初始化// Timer0_Init(); // 需包含定时器初始化while(1){Key_Proc();Seg_Proc();LED_Proc();}}

5. 总结速查表(Cheat Sheet)

模块关键代码/公式备注
电压计算V = Val / 51.0255对应5V,系数为51
DAC 输出Val = V * 51.0逆运算写入PCF8591
通道地址0x03(电位器),0x01(光敏)一定要看电路图确认
DAC 控制字0x40写数据前必须发送此控制字
LED 逻辑LED_Buf[0] = !Seg_Mode利用逻辑非运算实现互斥指示
非破坏驱动`P2 & 0x1F0x80`
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/16 1:24:11

Qwen3-VL辅助开发ComfyUI自定义节点工作流

Qwen3-VL辅助开发ComfyUI自定义节点工作流 在AI图像生成工具日益普及的今天&#xff0c;开发者们面临一个现实矛盾&#xff1a;一方面&#xff0c;像 ComfyUI 这样的节点式工作流系统提供了无与伦比的灵活性和可复现性&#xff1b;另一方面&#xff0c;其高度依赖手动配置、代码…

作者头像 李华
网站建设 2026/7/16 11:25:28

Qwen3-VL空间感知升级:精准判断物体遮挡与3D位置关系

Qwen3-VL空间感知升级&#xff1a;精准判断物体遮挡与3D位置关系 在自动驾驶系统试图识别前方车辆时&#xff0c;如果仅依赖“图像中有个汽车”这样的信息&#xff0c;显然远远不够——真正决定是否刹车或变道的关键是&#xff1a;“这辆车离我有多远&#xff1f;”“它是否被其…

作者头像 李华
网站建设 2026/7/16 15:14:50

AI应用架构师的技术支持:AI驱动组织优化的工具选择

AI应用架构师的技术支持&#xff1a;AI驱动组织优化的工具选择 一、引言&#xff1a;AI驱动组织优化的“落地困境” 某零售企业的CIO曾向我抱怨&#xff1a;“我们花了500万买了AI平台&#xff0c;结果一年下来只做了个客户画像demo——业务部门说‘用起来麻烦’&#xff0c;技…

作者头像 李华
网站建设 2026/7/15 11:26:02

Qwen3-VL支持多语言混合OCR,中文英文无缝切换

Qwen3-VL 支持多语言混合 OCR&#xff0c;中文英文无缝切换 在智能文档处理日益普及的今天&#xff0c;一张照片里同时出现中英文内容早已司空见惯&#xff1a;产品说明书上的技术参数夹杂着英文缩写&#xff0c;跨国合同中的条款混排双语表述&#xff0c;甚至一张餐厅菜单也可…

作者头像 李华
网站建设 2026/7/14 23:40:01

Keil5中文输入显示乱?项目应用前的基础设置

Keil5中文输入乱码&#xff1f;别急&#xff0c;一文讲透根源与实战配置你有没有遇到过这样的场景&#xff1a;在Keil Vision里写注释&#xff0c;刚打下“// 初始化GPIO”&#xff0c;再一看——变成了??GPIO&#xff1f;或者打开同事传来的工程文件&#xff0c;所有中文注释…

作者头像 李华
网站建设 2026/7/15 11:25:58

房地产营销变革:Sonic生成楼盘讲解数字人视频

房地产营销变革&#xff1a;Sonic生成楼盘讲解数字人视频 在房地产销售一线&#xff0c;你是否遇到过这样的场景&#xff1f;客户深夜打开官网想了解某个新盘的户型细节&#xff0c;却发现只有冷冰冰的文字和图片&#xff1b;售楼处高峰期人满为患&#xff0c;销售顾问连喝口水…

作者头像 李华