第8章:硬件适配层应用——ADC
本章导读
前面所有输入(按键)都是"数字"的:按下/松开,两个值。但现实世界的传感器大多输出连续变化的模拟量——光线多亮?压力多大?电压多高?
**ADC(模数转换器)**就是把"连续电压"变成"数字"的桥梁。CC2530 自带 12 位 ADC,HAL 又把它封装成了一个 API。本章先对照原理图看 GEC2530 底板的传感器都接在哪些 ADC 通道,再动手完成"按键 → ADC 采样 → 屏幕显示 + 串口发送"的完整实验。
一、先看电路:GEC2530 底板的传感器(对照原理图)
打开原理图 Sheet 5(GPIO_SENSOR),可以看到 4 类传感器:
┌────────────────────────────────────────────────┐
│ 光敏传感器:R26(10K 可调) + R28(10K) + 光敏管 CS ── R30(0Ω) ── P0_5 │
│ DHT11 温湿度:J5 接口 ── R29(0Ω) ── P0_4(数字单总线) │
│ 压力传感器:U6 MPXV5010GC6U(VOUT) ── R34(0Ω) ── P0_0 │
│ 三轴加速度:U7 MMA7455(I2C:SCL/SDI/SDO)─ R33/R35/R36(0Ω) ── P1_4/P1_7/P2_0 │
└────────────────────────────────────────────────┘| 传感器 | 型号 | 信号类型 | 接口引脚 |
|---|---|---|---|
| 光敏传感器 | 光敏二极管 CS | 模拟电压(ADC) | P0_5 |
| 温湿度传感器 | DHT11 | 数字单总线 | P0_4 |
| 压力传感器 | MPXV5010GC6U(U6) | 模拟电压(ADC) | P0_0 |
| 三轴加速度传感器 | MMA7455(U7) | 数字 I2C | P1_4 / P1_7 / P2_0 |
重点理解:
- 哪些走 ADC? 只有输出"连续电压"的传感器才需要 ADC:光敏(P0_5)和压力(P0_0)。DHT11、MMA7455 是数字接口(单总线/I2C),芯片内部自己完成了转换,直接读数据即可;
- 光敏电路怎么工作的? 光敏管 CS 的阻值随光照变化 → 与 R26/R28 分压 → P0_5 上的电压随光照变化 → ADC 把电压变成数字。调节 R26(可调电阻)可以改变采样范围;
- 与 TI 原版板子的差异(易错点):原站实验代码用
HAL_ADC_CHANNEL_7(P0_7)读光敏,那是 TI 官方板的接法;GEC2530 底板的光敏在 P0_5(通道 5)——写代码时务必按自己板子的原理图选通道。
二、HAL ADC API 简介
HAL 提供了完善的 ADC 驱动 API,定义在 hal_adc.h / hal_adc.c 中。
① 核心 API:HalAdcRead()
/*
* 在指定分辨率下读取指定 ADC 通道的值
*
* @param channel - 通道号 0 ~ 7,分别对应 CC2530 的 P0_0 ~ P0_7 引脚
* @param resolution - 采样精度(分辨率)
*/
extern uint16 HalAdcRead ( uint8 channel, uint8 resolution );一次调用,完成"选通道 + 启动采样 + 读结果"三件事——HAL 把寄存器操作全封装了。
② 分辨率参数(resolution)
#define HAL_ADC_RESOLUTION_8 0x01 // 8 位精度
#define HAL_ADC_RESOLUTION_10 0x02 // 10 位精度
#define HAL_ADC_RESOLUTION_12 0x03 // 12 位精度
#define HAL_ADC_RESOLUTION_14 0x04 // 14 位精度
分辨率越高,数字越精细(8 位范围 0~255,12 位范围 0~4095),但转换时间略长。普通传感器 8~10 位够用。
③ 通道参数(channel)
#define HAL_ADC_CHANNEL_0 0x00 // P0_0(GEC2530:压力传感器)
#define HAL_ADC_CHANNEL_1 0x01 // P0_1
#define HAL_ADC_CHANNEL_2 0x02 // P0_2
#define HAL_ADC_CHANNEL_3 0x03 // P0_3
#define HAL_ADC_CHANNEL_4 0x04 // P0_4
#define HAL_ADC_CHANNEL_5 0x05 // P0_5(GEC2530:光敏传感器)
#define HAL_ADC_CHANNEL_6 0x06 // P0_6
#define HAL_ADC_CHANNEL_7 0x07 // P0_7
通道号 = 引脚号:
HAL_ADC_CHANNEL_5就是采 P0_5 的电压。对照上面的原理图:GEC2530 底板读光敏用 CHANNEL_5,读压力用 CHANNEL_0。
④ 使用示例
用 8 位精度采光敏传感器(P0_5)的值:
uint8 adcVal;
adcVal = HalAdcRead( HAL_ADC_CHANNEL_5, HAL_ADC_RESOLUTION_8 );三、ADC 实验:按键触发采样并显示
实验目标
结合按键、LED、显示屏、串口、ADC:按下按键 → ADC 采样光敏(P0_5)→ LED 闪烁 → 采样值显示到 LCD + 发送到串口。
第 1 步:包含头文件
#include "hal_adc.h"第 2 步:在按键处理函数中添加代码
在应用层的按键处理函数 zclSampleSw_HandleKeys() 中添加:
static void zclSampleSw_HandleKeys( byte shift, byte keys ) {
UI_MainStateMachine(keys);
if ( keys & HAL_KEY_SW_1 ) { // 按下 S3
uint8 adcVal;
char adcStr[30];
/* 读取 P0_5 光敏传感器的 ADC 值(GEC2530 底板:通道5) */
adcVal = HalAdcRead( HAL_ADC_CHANNEL_5, HAL_ADC_RESOLUTION_8 );
/* 闪烁 LED(红绿蓝三色演示) */
HalLedBlink(HAL_LED_1, 10, 50, 400); // LED1
HalLedBlink(HAL_LED_2, 10, 50, 1000); // LED2
HalLedBlink(HAL_LED_3, 10, 50, 2000); // LED3
/* 格式化数据到字符串 */
sprintf(adcStr, "ADC: %d\n", adcVal);
/* 在 LCD 第 4 行显示 ADC 值 */
HalLcdWriteString(adcStr, HAL_LCD_LINE_4);
/* 通过串口发送到串口助手 */
HalUARTWrite(HAL_UART_PORT_0, (uint8 *)adcStr, osal_strlen(adcStr));
}
}代码逐行解析:
| 代码 | 做了什么 |
|---|---|
HalAdcRead(HAL_ADC_CHANNEL_5, HAL_ADC_RESOLUTION_8) | 采 P0_5 光敏电压,8 位精度,得 0~255 |
HalLedBlink(...) | 三个 LED 以不同周期闪烁,直观反馈"按键生效了" |
sprintf(adcStr, "ADC: %d\n", adcVal) | 把数值格式化成字符串 |
HalLcdWriteString(adcStr, HAL_LCD_LINE_4) | 显示到屏幕第 4 行 |
HalUARTWrite(...) | 发给串口助手 |
⚠️ 注意通道号:这里用
HAL_ADC_CHANNEL_5(P0_5),因为 GEC2530 底板的光敏接在 P0_5(原理图 Sheet 5)。如果照抄 TI 官方例程的CHANNEL_7,读到的会是红外 LED 相关引脚,数值不对。换板子先查原理图!
第 3 步:编译下载验证
- Rebuild All 编译 → 烧录到 GEC2530 开发板;
- 串口助手配置:115200 / 8 / None / 1 / None;
- 按下按键 S3,观察:
- LCD 第 4 行显示
ADC: xx; - 串口助手收到
ADC: xx(每次按键一条); - 三个 LED 依次闪烁。
- LCD 第 4 行显示

用手遮挡/照亮光敏传感器,再按按键,会发现 ADC 值明显变化——光照越强,光敏管阻值越小,P0_5 电压越低,ADC 值越小(具体方向以实际电路分压为准)。这就是"传感器 → 模拟电压 → 数字"的完整链路。
四、小结
| 问题 | 答案 |
|---|---|
| GEC2530 哪些传感器走 ADC? | 光敏(P0_5)、压力(P0_0);DHT11/加速度是数字接口 |
| 光敏传感器接在哪个通道? | P0_5 = HAL_ADC_CHANNEL_5(注意与 TI 板的 P0_7 不同) |
| ADC 核心 API? | HalAdcRead(channel, resolution) 一次搞定采样 |
| 分辨率有哪些? | 8 / 10 / 12 / 14 位(HAL_ADC_RESOLUTION_8 等) |
| 通道号怎么记? | 通道号 = 引脚号:CHANNEL_5 ↔ P0_5 |
| 实验结果怎么看? | LCD 第 4 行 + 串口助手都显示 ADC: xx,随光照变化 |
一句话总结:ADC 让协议栈"看得见"模拟世界——GEC2530 底板的光敏(P0_5)、压力(P0_0)接在 ADC 通道上,HAL 一个 HalAdcRead() 就把电压变成了数字,再配合 LCD 显示、串口发送,就是完整的"采集 → 处理 → 展示"传感器节点雏形。
课堂练习:ADC
依据第8章:GEC2530 传感器电路、HalAdcRead、通道/分辨率作答。点击选项即可作答、即时反馈对错。
传感器电路、HalAdcRead、通道与分辨率
1 GEC2530 底板上,光敏传感器接在哪个 ADC 通道?
2 GEC2530 底板哪些传感器走 ADC?
3 HalAdcRead(HAL_ADC_CHANNEL_5, HAL_ADC_RESOLUTION_8) 中的两个参数分别代表?
4 8 位分辨率下,ADC 转换结果的范围是?
5 关于 ADC 通道号,最方便的记法是?
内容来源:紫甲 IoT《ZigBee 3.0 开发指南》第三部分·第8章,经本站整理优化以便于理解,电路部分已对照 GEC2530 开发板底板原理图核对(光敏通道已由原站 P0_7 更正为 GEC2530 底板的 P0_5);原站链接