Phase 1 实现了 ADC + I2C + UART 三种外设的集成,构建了一个基础的环境监测系统。
multi_sensor_project/
├── CMakeLists.txt # 构建配置
├── prj.conf # 内核配置
├── boards/
│ └── nrf54l15dk_nrf54l15_cpuapp.overlay # 设备树覆盖
└── src/
├── main.c # 主程序
├── sensor/
│ ├── adc_sensor.c/h # ADC 传感器模块
│ └── i2c_sensor.c/h # I2C 传感器模块
└── communication/
└── uart_log.c/h # UART 日志模块
功能: 采集模拟传感器数据(光照、电位器)
关键实现:
// 初始化
int adc_sensor_init(void) {
// 检查设备就绪
if (!adc_is_ready_dt(&adc_channels[i])) return -ENODEV;
// 配置通道
err = adc_channel_setup_dt(&adc_channels[i]);
}
// 读取
int adc_sensor_read(struct adc_sensor_data *data) {
// 初始化序列
adc_sequence_init_dt(&adc_channels[0], &sequence);
// 读取数据
err = adc_read_dt(&adc_channels[0], &sequence);
}
设备树配置:
&adc {
channel@0 {
reg = <0>;
zephyr,gain = "ADC_GAIN_1";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,input-positive = <NRF_SAADC_AIN0>;
zephyr,resolution = <12>;
};
};
功能: 读取 SHT30 温湿度传感器
关键实现:
// 发送测量命令
uint8_t cmd[2] = { 0x24, 0x00 }; // 高精度模式
i2c_write_dt(&sht30_dev, cmd, sizeof(cmd));
// 等待测量完成
k_sleep(K_MSEC(20));
// 读取数据(6字节:温度+湿度+CRC)
i2c_read_dt(&sht30_dev, buf, sizeof(buf));
// CRC 校验
if (sht30_crc8(&buf[0], 2) != buf[2]) {
LOG_WRN("CRC mismatch");
}
// 转换为物理量
data->temp_celsius = -4500 + (17500 * raw_temp / 65535);
data->hum_percent = 10000 * raw_hum / 65535;
I2C 时序:
主机发送: [START] [ADDR+W] [CMD_MSB] [CMD_LSB] [STOP]
等待: 20ms
主机读取: [START] [ADDR+R] [DATA0]...[DATA5] [STOP]
功能: 格式化输出传感器数据
关键实现:
// JSON 格式输出
void uart_log_sensor_data(const struct sensor_log_data *data) {
printk("{\n");
printk(" \"temperature\": %d.%02d,\n", temp/100, temp%100);
printk(" \"humidity\": %d.%02d,\n", hum/100, hum%100);
printk(" \"light\": %u\n", light);
printk("}\n");
}
问题: ADC 和 I2C 采样速度不同,需要同步数据。
解决方案: 使用时间戳标记每次采样,主循环统一处理。
struct sensor_log_data {
int16_t temp_celsius;
int16_t hum_percent;
uint8_t light_percent;
uint32_t timestamp; // 统一时间戳
};
问题: 某个传感器失败不应影响其他功能。
解决方案: 模块化错误处理,失败后继续执行。
err = adc_sensor_read(&adc_data);
if (err < 0) {
LOG_WARN("ADC read failed: %d", err);
// 继续执行,不返回
}
err = i2c_sensor_read(&i2c_data);
if (err < 0) {
LOG_WARN("I2C read failed: %d", err);
// 继续执行
}
问题: 外设初始化顺序可能影响系统稳定性。
解决方案: 按依赖关系初始化,日志模块最先。
// 1. UART(用于输出初始化日志)
uart_log_init();
// 2. ADC(无依赖)
adc_sensor_init();
// 3. I2C(可能需要更长时间)
i2c_sensor_init();
CONFIG_ADC=y # ADC 驱动
CONFIG_I2C=y # I2C 驱动
CONFIG_GPIO=y # GPIO 驱动
CONFIG_LOG=y # 日志系统
CONFIG_CBPRINTF_FP_SUPPORT=y # 浮点打印
cd /home/wangpei/ncs-sdk
west build -p -b nrf54l15dk/nrf54l15/cpuapp multi_sensor_project
[INF] Multi-Sensor Project - Phase 1 Starting
[INF] All modules initialized successfully!
{
"timestamp": 2000,
"temperature": 25.50,
"humidity": 45.00,
"light": 75,
"potentiometer": 30
}
| Phase | 功能 | 状态 |
|---|---|---|
| Phase 1 | ADC + I2C + UART | ✅ 完成 |
| Phase 2 | PWM 风扇控制 | ⏳ 待实现 |
| Phase 3 | BLE NUS 广播 | ⏳ 待实现 |
| Phase 4 | 低功耗优化 | ⏳ 待实现 |
小白 🤖 2026-03-14