
简介本资源是面向嵌入式初学者与PIC单片机开发者的PIC12F675微控制器ADC功能实践例程聚焦模拟信号采集核心需求适用于温度检测、电位器读取、传感器数据采集等典型应用场景。压缩包共21个文件涵盖C源码ADC.C、汇编启动文件startup.as、编译中间产物.obj/.rlf/.lst、可执行镜像.hex、链接映射.map、符号表.sym及调试信息.sdb等完整开发链路文件直观呈现从代码编写到烧录运行的全流程便于理解编译机制与寄存器配置逻辑。资源包仅44KB轻量易用已获118人学习下载。读者可直接复现ADC初始化、通道选择、采样触发、结果读取与数值处理等关键操作代码结构清晰、注释充分特别适合对照学习PIC12F675内置10位ADC模块的寄存器配置方法与实际应用技巧。1. PIC12F675 的 ADC 功能不是“开箱即用”而是需要手动配置寄存器、校准参考电压、处理采样时序才能稳定读出有效值你手头有一份名为ADC.rar_PIC12F675的压缩包解压后看到characterbj2_pic12F675这类命名文件——这大概率是某位工程师在 2010 年前后用 MPLAB IDE v8.x PICkit2 调试 PIC12F675 时留下的工程快照核心目标很明确用片上 10 位逐次逼近型SARADC 采集模拟信号比如电位器分压、温度传感器输出再通过 GPIO 或 UART 输出对应字符characterbj2可能指“字符版 BJ2 协议”或某段 ASCII 映射逻辑。但直接烧录.hex文件常失败因为 PIC12F675 的 ADC 模块极度依赖外部条件VDD 必须稳定在 4.5–5.5V内部基准电压FVR需使能且校准ADCON0/ADCON1 寄存器必须按特定顺序写入且每次采样前需预留 ≥20μs 的采样时间TAD ≥ 2μs但实际需留余量。新手常卡在“读出来全是 0 或 0x3FF”本质是未等待 Acquisition Time 结束就启动转换或未正确配置 ANSEL 使能模拟输入引脚。本文面向嵌入式固件开发者覆盖从寄存器级配置、C 语言驱动编写、采样值滤波到实测验证的完整链路不依赖 MPLAB Code Configurator所有代码可在 HI-TECH C 或 XC8 v2.35 下编译通过。2. 配置 PIC12F675 ADC 寄存器从 ANSEL 到 ADCON1每一步都决定采样是否有效PIC12F675 的 ADC 模块虽小但寄存器交互逻辑严密。它没有自动触发或 DMA所有操作靠软件轮询完成。关键寄存器共 4 个必须按固定顺序初始化否则 ADC 不工作或返回随机值。2.1 确认模拟引脚使能与端口方向PIC12F675 有 4 个模拟输入通道AN0–AN3对应 GP0–GP3 引脚。但这些引脚默认为数字 I/O必须显式配置为模拟输入// HI-TECH C 语法XC8 兼容 ANSEL 0b00001111; // ANSEL3:0 1 启用 AN0–AN3注意ANSEL 是 4 位寄存器高 4 位无效 TRISIO 0b00001111; // GP0–GP3 设为输入TRISIO3:0 1注意ANSEL寄存器在 PIC12F675 中仅低 4 位有效写ANSEL 0x0F即可。若遗漏此步即使 ADCON0 设置正确GPx 引脚仍处于数字模式ADC 输入被钳位采样值恒为 0。2.2 设置 ADC 时钟源与转换精度ADCON1 控制参考电压和数据对齐方式。PIC12F675 支持 VDD、VREF外部、FVR固定电压参考三种参考源。characterbj2工程中常见做法是启用内部 FVR4.096V因其不受 VDD 波动影响// 启用 FVR 并设为 ADC 参考源 CMCON 0x07; // 关闭比较器否则占用 AN0–AN2 VRCON 0b11000000; // FVREN1, FVRST0, FVRR11 → 启用 FVR 且输出 4.096V ADCON1 0b10000000; // ADFM1右对齐VCFG1FVR 作 VREFVCFG10VSS 作 VREF-提示VRCON寄存器必须在ADCON1之前配置否则 FVR 未启用时设置VCFG1会导致参考电压悬空。FVR 输出精度典型值 ±1%若需更高精度需外接精密基准芯片如 TL431并设VCFG0使用 VDD。2.3 配置 ADCON0启动转换与通道选择ADCON0 是控制核心包含通道选择、转换启动、结果状态位// 初始化 ADCON0选择 AN0 通道关闭 ADC清零状态位 ADCON0 0b00000000; // 设置 TAD FOSC/8推荐值确保 TAD ≥ 2μs 4MHz // 注意PIC12F675 无 ADCS2:0 位TAD 固定为 FOSC/8故主频必须 ≤ 4MHz 才满足最小 TAD // 若用 4MHz 内部振荡器则 TAD 2μs符合 datasheet 要求2.4 完整初始化函数C 语言将上述步骤封装为可复用函数加入必要延时#include pic.h #include delays.h void ADC_Init(void) { // 1. 关闭比较器释放 AN0–AN2 CMCON 0x07; // 2. 配置 FVR4.096V VRCON 0xC0; // 0b11000000 // 3. 设置 ADC 参考与数据格式 ADCON1 0x80; // 0b10000000FVR 作 VREF, 右对齐 // 4. 配置模拟引脚与方向 ANSEL 0x0F; // AN0–AN3 使能 TRISIO 0x0F; // GP0–GP3 输入 // 5. 延时等待 FVR 稳定≥ 10μs Delay10TCYx(1); // 10 × 1μs 10μs假设 FOSC4MHz // 6. 清除 ADCON0准备后续采样 ADCON0 0x00; }参数说明Delay10TCYx(1)调用 HI-TECH C 内置延时函数10 TCY指令周期≈ 10μsFOSC4MHz。若使用 XC8改用__delay_us(10)。此处延时不可省略FVR 启用后需稳定时间否则首次采样值偏差 5%。3. 实现可靠 ADC 采样手动管理采样周期、读取结果与基础滤波PIC12F675 的 ADC 无硬件采样保持必须由软件严格控制采样时间Acquisition Time与转换时间Conversion Time。adc采样周期在此场景下指“从选通通道到读取结果”的完整流程耗时典型值为 12–14 TAD含 2 TAD 采样 10–12 TAD 转换即约 24–28μsFOSC4MHz。3.1 单通道采样函数精确控制时序以下函数实现 AN0 通道单次采样返回 10 位右对齐结果unsigned int ADC_Read_AN0(void) { unsigned int result; // 1. 选择 AN0 通道ADCS2:0 不存在故只设 CHS2:0 ADCON0 0b00000001; // CHS2:0001 → AN0GO/DONE0不启动 // 2. 延时 ≥20μs 保证采样电容充电Acquisition Time // 计算20μs / (1/FOSC) 20 × FOSC × 10^-6 → FOSC4MHz → 80 个指令周期 // 使用 Delay1KTCYx(1) ≈ 1ms太长改用循环延时 __delay_us(20); // XC8 推荐或自定义 _delay_10us(2) // 3. 启动转换GO/DONE1 ADCON0bits.GO 1; // 4. 等待转换完成GO/DONE 自动清零 while(ADCON0bits.GO); // 5. 读取结果ADRESH:ADRESL右对齐 result ((unsigned int)ADRESH 8) | ADRESL; return result; }逻辑说明__delay_us(20)是关键——它替代了传统“等待 TAD 循环”因 PIC12F675 无 ADC 时钟分频位TAD 固定故直接按微秒延时更可靠。若省略此步采样电容未充满结果偏低如理论 512 实际读 480。3.2 C 语言 ADC 值滤波函数应对adc数据漂移实测中adc数据漂移常由电源噪声、PCB 布线耦合引起。characterbj2工程采用简单但有效的滑动平均滤波窗口大小 4#define ADC_FILTER_SIZE 4 static unsigned int adc_buffer[ADC_FILTER_SIZE]; static unsigned char adc_index 0; static unsigned int adc_sum 0; unsigned int ADC_Filtered_Read(void) { unsigned int raw ADC_Read_AN0(); // 更新环形缓冲区 adc_sum - adc_buffer[adc_index]; adc_buffer[adc_index] raw; adc_sum raw; adc_index (adc_index 1) % ADC_FILTER_SIZE; // 返回平均值右移 2 位等效除以 4 return adc_sum 2; }参数说明窗口大小 4 是经验平衡点——太大响应慢按键检测延迟太小滤波弱。adc_sum用unsigned int16 位可容纳 4×10234092无溢出风险。若需更强抗干扰可叠加中值滤波先排序 4 个值取中间两数平均。3.3 主循环调用示例映射为字符输出characterbj2的核心逻辑是将 ADC 值0–1023映射为 ASCII 字符如 0–9 或 A–Zvoid main(void) { OSCCON 0x60; // 设置内部 4MHz 振荡器 ADC_Init(); while(1) { unsigned int val ADC_Filtered_Read(); char ch; // 映射0–1023 → 0–9每 102.3 步进 if (val 102) ch 0; else if (val 204) ch 1; else if (val 306) ch 2; else if (val 408) ch 3; else if (val 510) ch 4; else if (val 612) ch 5; else if (val 714) ch 6; else if (val 816) ch 7; else if (val 918) ch 8; else ch 9; // 通过 GP5UART TX 模拟或 LED 闪烁输出 ch // 此处省略具体输出实现characterbj2 通常用 GP5 模拟 UART bit-banging Delay10KTCYx(1); // 10ms 间隔 } }提示映射区间划分需根据实际传感器范围调整。若电位器非线性应改用查表法const char map[16] {0,1,...,F}; ch map[val6];。4. 排查 PIC12F675 ADC 常见故障从寄存器值验证到 PCB 布局要点当ADC.rar_PIC12F675工程烧录后无输出或数值跳变需系统性排查。以下方法按优先级排序覆盖 90% 问题。4.1 寄存器快照验证确认配置已生效使用 PICkit2 编程器连接后在 MPLAB IDE 中暂停运行查看关键寄存器值寄存器正常值异常表现原因ANSEL0x0F0x00未执行ANSEL 0x0F引脚为数字模式VRCON0xC00x00FVR 未启用参考电压为 VDD波动大ADCON10x800x00VREF 误设为 VDD且未右对齐读取高位字节错误ADCON00x01采样时0x00未写入通道选择位或 GO 位未置 1注意ADCON0的GO/DONE位在转换完成后自动清零若始终为 1说明转换未启动可能ADON0或时钟异常若始终为 0说明未执行ADCON0bits.GO 1。4.2 电源与参考电压测量规避adc/dac 电路设计中的噪声陷阱adc/dac 电路设计:规避时钟抖动与电源噪声的3个pcb布局要点在 PIC12F675 上同样适用AVDD 与 VDD 分离AVDD引脚 1必须通过 100nF 陶瓷电容直连到 VDD且该电容靠近芯片放置。若共用电源走线数字开关噪声会耦合进 ADC。模拟地AGND独立布线GP3AN3附近铺铜作为 AGND单独走线至电源地避免与数字地在芯片内短接。输入信号滤波AN0 输入端串联 1kΩ 电阻 100nF 电容RC100μs截止频率 ≈16kHz抑制高频噪声。此即adc采样电路标准做法。4.3 实测采样值诊断表用万用表测 AN0 电压对比理论值与读数定位误差类型AN0 实测电压理论 ADC 值FVR4.096V实际读数故障类型解决方案0.00V00正常—2.048V512480采样不足增加__delay_us()至 25μs2.048V512512正常—2.048V512530参考偏高检查VRCON是否误设为0xE0FVR2.048V2.048V5120通道未选通检查ADCON0的 CHS 位是否为0b000000012.048V5121023参考偏低检查 FVR 是否启用或 VDD 4.5V 导致 FVR 失效提示理论值计算公式为ADC_value (Vin / Vref) × 1023。若Vref4.096V则Vin2.048V时理论值为(2.048/4.096)×1023 511.5 ≈ 512。读数偏差 ±5 即需排查。5. 提升 ADC 精度的关键技巧利用 FVR 校准与多点线性补偿PIC12F675 的 FVRFixed Voltage Reference出厂校准值存储在0x200F地址读取后可修正参考电压偏差将adc信噪比提升 1–2 位有效分辨率。5.1 读取 FVR 校准字并计算实际 VREF校准字为 7 位表示 FVR 实际值相对于标称值4.096V的百分比// 读取校准字需在 CONFIG 位设置后执行 unsigned char cal_byte; cal_byte *0x200F; // 直接读取地址 0x200F // 校准字格式bit6:0 (Vref_actual / 4.096) × 128 // 故 Vref_actual (cal_byte / 128.0) × 4.096 float vref_actual (float)cal_byte * 4.096f / 128.0f;5.2 动态修正 ADC 结果将原始读数转换为真实电压再映射为字符float ADC_Voltage(unsigned int raw) { static float vref 4.096f; // 默认值 // 首次运行时读取校准字仅一次 static bit cal_done 0; if (!cal_done) { unsigned char cal *0x200F; vref (float)cal * 4.096f / 128.0f; cal_done 1; } return ((float)raw / 1023.0f) * vref; } // 主循环中调用 float volt ADC_Voltage(ADC_Filtered_Read()); if (volt 0.5f) ch 0; else if (volt 1.0f) ch 1; // ... 其他映射5.3 多点线性补偿表针对非线性传感器若接入热敏电阻等非线性器件可预存 16 点查表// 16 点电压→温度映射示例 const unsigned int adc_table[16] { 0, 100, 200, 300, 400, 500, 600, 700, 800, 850, 900, 930, 960, 980, 995, 1023 }; const char temp_char[16] {C,D,E,F,G,H,I,J, K,L,M,N,O,P,Q,R}; char Map_ADC_To_Char(unsigned int val) { for (unsigned char i 0; i 15; i) { if (val adc_table[i] val adc_table[i1]) { return temp_char[i]; } } return temp_char[15]; }技巧说明查表法比多项式拟合更适合资源受限的 PIC12F675仅 1.75KB Flash。adc采样矫正的本质是用已知标准点如冰水混合物 0°C、沸水 100°C标定表中值需实测填充。本文还有配套的精品资源点击获取