| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448 |
- /*
- * ADC采集模块 - v2.3 (10次平均版本)
- *
- * 功能:使用HAL库直接采集ADC通道数据,连续10次读取求平均值
- * - NTC温度(PA5-ADC1_IN5)-> 查表转换为温度存入 dev_info.ambient_temp
- * - 光控(PA4-ADC1_IN4)
- * - 电池电压(PA7-ADC1_IN7)-> 存入 sys_info.battery_voltage
- * - 太阳能充电电压(PA6-ADC1_IN6)-> 存入 sys_info.charge_voltage
- * - 灯管电流(PB0-ADC1_IN8)
- * - 高压输出电流(PB1-ADC1_IN9)
- *
- * Version: 2.3.0
- */
- /*********************↓ include ↓************************/
- #define DBG_TAG "ADC"
- #define DBG_LVL DBG_INFO
- #include <rtdbg.h>
- #include <rtthread.h>
- #include <board.h>
- #include "stm32f4xx_hal.h"
- #include "ym310_protecl.h"
- /*********************↑ include ↑************************/
- /*********************↓ define ↓************************/
- /* ADC通道配置 */
- #define ADC_CH_NTC 5 /* PA5 - ADC1_IN5 */
- #define ADC_CH_LIGHT 4 /* PA4 - ADC1_IN4 */
- #define ADC_CH_BAT 7 /* PA7 - ADC1_IN7 */
- #define ADC_CH_PV 6 /* PA6 - ADC1_IN6 */
- #define ADC_CH_LED 8 /* PB0 - ADC1_IN8 */
- #define ADC_CH_ELE 9 /* PB1 - ADC1_IN9 */
- /* 采集周期(毫秒) */
- #define ADC_CYCLE_NTC 1000
- #define ADC_CYCLE_LIGHT 100
- #define ADC_CYCLE_BAT 500
- #define ADC_CYCLE_PV 500
- #define ADC_CYCLE_LED 500
- #define ADC_CYCLE_ELE 5
- #define ADC_BASE_CYCLE_MS 5
- /* 采样次数(求平均值) */
- #define ADC_SAMPLE_COUNT 5
- /* 电压转换系数:ADC值 * 3.3 / 4095 * 2 * 1000 = ADC值 * 1.611 */
- #define ADC_TO_MV(x) ((x) * 1611 * 11 / 2 / 1000)
- //#define ADC_TO_MV(x) ((x) * 1611 / 1000)
- #define ADC_TO_MV_BAT(x) ((x) * 1611 * 11 / 2 / 1000)
- /* NTC温度查表:-30℃到100℃,共131个点 */
- /* 索引0对应-30℃,索引130对应100℃ */
- static const uint16_t tempRes_buf[131] = {
- 3889, 3876, 3862, 3848, 3833, 3817, 3801, 3784, 3766, 3747, /* -30 ~ -21 */
- 3727, 3707, 3686, 3663, 3640, 3616, 3592, 3566, 3539, 3511, /* -20 ~ -11 */
- 3483, 3453, 3423, 3392, 3359, 3326, 3292, 3257, 3221, 3185, /* -10 ~ -1 */
- 3147, /* 0 */
- 3109, 3070, 3030, 2990, 2948, 2906, 2864, 2821, 2777, 2733, /* 1 ~ 10 */
- 2689, 2644, 2599, 2553, 2508, 2462, 2416, 2369, 2324, 2277, /* 11 ~ 20 */
- 2231, 2185, 2139, 2093, 2048, 2003, 1958, 1914, 1870, 1825, /* 21 ~ 30 */
- 1783, 1739, 1698, 1656, 1615, 1575, 1534, 1495, 1457, 1419, /* 31 ~ 40 */
- 1382, 1345, 1310, 1275, 1242, 1207, 1174, 1143, 1111, 1080, /* 41 ~ 50 */
- 1051, 1021, 993, 965, 938, 911, 886, 861, 835, 811, /* 51 ~ 60 */
- 790, 766, 744, 725, 702, 683, 663, 645, 625, 607, /* 61 ~ 70 */
- 589, 574, 556, 540, 525, 512, 497, 481, 468, 455, /* 71 ~ 80 */
- 442, 429, 419, 406, 396, 382, 372, 362, 352, 342, /* 81 ~ 90 */
- 335, 324, 314, 307, 300, 289, 282, 275, 268, 261 /* 91 ~ 100 */
- };
- /*********************↑ define ↑************************/
- extern SYS_STATUS sys_sta;
- /*********************↓ 静态变量 ↓************************/
- static ADC_HandleTypeDef s_adc_handle;
- static rt_thread_t s_adc_thread = RT_NULL;
- static rt_bool_t s_adc_running = RT_FALSE;
- /* 各通道上次采集时间 */
- static rt_tick_t s_last_ntc = 0;
- static rt_tick_t s_last_light = 0;
- static rt_tick_t s_last_bat = 0;
- static rt_tick_t s_last_pv = 0;
- static rt_tick_t s_last_led = 0;
- static rt_tick_t s_last_ele = 0;
- /*********************↑ 静态变量 ↑************************/
- /*********************↓ 函数实现 ↓************************/
- /**
- * @brief 判断是否到达采样时间
- */
- static rt_bool_t is_time_to_sample(rt_tick_t *last_tick, rt_uint32_t cycle_ms)
- {
- rt_tick_t now = rt_tick_get();
- rt_tick_t cycle_tick = rt_tick_from_millisecond(cycle_ms);
- if ((now - *last_tick) >= cycle_tick)
- {
- *last_tick = now;
- return RT_TRUE;
- }
- return RT_FALSE;
- }
- /**
- * @brief 配置ADC引脚为模拟输入模式
- */
- static void adc_pin_init(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- /* 使能GPIOA和GPIOB时钟 */
- __HAL_RCC_GPIOA_CLK_ENABLE();
- __HAL_RCC_GPIOB_CLK_ENABLE();
- /* 配置PA4, PA5, PA6, PA7为模拟输入 */
- GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
- GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- /* 配置PB0, PB1为模拟输入 */
- GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;
- HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
- //LOG_I("ADC pins configured as analog input");
- }
- /**
- * @brief 初始化ADC
- */
- static void adc_hw_init(void)
- {
- /* 使能ADC1时钟 */
- __HAL_RCC_ADC1_CLK_ENABLE();
- /* 配置ADC */
- s_adc_handle.Instance = ADC1;
- s_adc_handle.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
- s_adc_handle.Init.Resolution = ADC_RESOLUTION_12B;
- s_adc_handle.Init.ScanConvMode = DISABLE;
- s_adc_handle.Init.ContinuousConvMode = DISABLE;
- s_adc_handle.Init.DiscontinuousConvMode = DISABLE;
- s_adc_handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
- s_adc_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
- s_adc_handle.Init.NbrOfConversion = 1;
- s_adc_handle.Init.DMAContinuousRequests = DISABLE;
- s_adc_handle.Init.EOCSelection = ADC_EOC_SEQ_CONV;
- if (HAL_ADC_Init(&s_adc_handle) != HAL_OK)
- {
- LOG_E("ADC HAL init failed");
- return;
- }
- //LOG_I("ADC HAL initialized");
- }
- /**
- * @brief 读取单个ADC通道(单次读取)
- * @param channel ADC通道号 (ADC_CHANNEL_x)
- * @return ADC值(0-4095)
- */
- static uint32_t adc_read_single(uint32_t channel)
- {
- uint32_t value = 0;
- ADC_ChannelConfTypeDef sConfig = {0};
- /* 配置通道 */
- sConfig.Channel = channel;
- sConfig.Rank = 1;
- sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
- sConfig.Offset = 0;
- if (HAL_ADC_ConfigChannel(&s_adc_handle, &sConfig) != HAL_OK)
- {
- LOG_E("ADC config channel %d failed", channel);
- return 0;
- }
- /* 启动ADC转换 */
- HAL_ADC_Start(&s_adc_handle);
- /* 等待转换完成(超时100ms) */
- if (HAL_ADC_PollForConversion(&s_adc_handle, 100) == HAL_OK)
- {
- value = HAL_ADC_GetValue(&s_adc_handle);
- }
- else
- {
- LOG_E("ADC conversion timeout, channel=%d", channel);
- }
- /* 停止ADC */
- HAL_ADC_Stop(&s_adc_handle);
- return value;
- }
- /**
- * @brief 读取ADC通道(连续读取多次求平均值)
- * @param channel ADC通道号 (ADC_CHANNEL_x)
- * @return 平均ADC值(0-4095)
- */
- static uint32_t adc_read_average(uint32_t channel)
- {
- uint32_t sum = 0;
- uint32_t value;
- uint8_t i;
- for (i = 0; i < ADC_SAMPLE_COUNT; i++)
- {
- value = adc_read_single(channel);
- sum += value;
- /* 采样间隔5ms,让ADC稳定 */
- if (i < ADC_SAMPLE_COUNT - 1)
- {
- rt_thread_mdelay(5);
- }
- }
- return sum / ADC_SAMPLE_COUNT;
- }
- /**
- * @brief ADC值查表转换为温度(整数温度)
- * @param adc_value ADC采样值(0-4095)
- * @return 温度值(整数℃),超出范围返回边界值
- */
- static int8_t adc_to_temperature(uint32_t adc_value)
- {
- uint8_t i;
- /* 超出量程上限(低于-30℃) */
- if (adc_value >= tempRes_buf[0])
- {
- return -30;
- }
- /* 超出量程下限(高于100℃) */
- if (adc_value <= tempRes_buf[130])
- {
- return 100;
- }
- /* 线性查表 */
- for (i = 0; i < 130; i++)
- {
- if (adc_value >= tempRes_buf[i + 1] && adc_value <= tempRes_buf[i])
- {
- /* 线性插值,返回整数温度 */
- int32_t temp = -30 + i;
- uint32_t diff = tempRes_buf[i] - tempRes_buf[i + 1];
- if (diff > 0)
- {
- temp += (tempRes_buf[i] - adc_value) * 1 / diff;
- }
- return (int8_t)temp;
- }
- }
- return 100;
- }
- /**
- * @brief 执行一次ADC采集
- */
- static void adc_collect(void)
- {
- uint32_t value;
- int8_t temp;
- /* 1. NTC温度(PA5)- 查表转换为温度存入 dev_info.ambient_temp */
- if (is_time_to_sample(&s_last_ntc, ADC_CYCLE_NTC))
- {
- value = adc_read_average(ADC_CH_NTC);
- temp = adc_to_temperature(value);
- sensor.temp_ntc = temp * 10; /* 转换为0.1℃精度存储 */
- sensor.valid_ntc = VALID;
- //sys_sta.board_temp = temp * 10;
- LOG_D("NTC: avg=%d, temp=%d°C", value, temp);
- }
- /* 2. 光控(PA4)- 转换为百分比存入 sys_sta.light_percent */
- if (is_time_to_sample(&s_last_light, ADC_CYCLE_LIGHT))
- {
- value = adc_read_average(ADC_CH_LIGHT);
- /* ADC取值范围0-4095,计算百分比(保留一位小数,乘以10存储)*/
- /* 百分比 = (value / 4095) * 100 = value * 100 / 4095 */
- /* 保留一位小数:乘以10存储,即 (value * 1000 / 4095) */
- uint16_t percent_x10 = (uint16_t)(((uint32_t)value * 1000) / 4095);
- /* 限制范围0-1000(0.0%-100.0%)*/
- if (percent_x10 > 1000)
- percent_x10 = 1000;
- sys_sta.light_percent = percent_x10;
- LOG_D("LIGHT: avg=%d, percent=%d.%d%%",
- value, percent_x10 / 10, percent_x10 % 10);
- }
- /* 3. 电池电压(PA7)- 存入 sys_info.battery_voltage */
- if (is_time_to_sample(&s_last_bat, ADC_CYCLE_BAT))
- {
- value = adc_read_average(ADC_CH_BAT);
- sys_sta.battery_voltage = ADC_TO_MV_BAT(value);
- LOG_D("BAT: avg=%d, %dmV", value, sys_info.battery_voltage);
- }
- /* 4. 太阳能充电电压(PA6)- 存入 sys_info.charge_voltage */
- if (is_time_to_sample(&s_last_pv, ADC_CYCLE_PV))
- {
- value = adc_read_average(ADC_CH_PV);
- sys_sta.charge_voltage = ADC_TO_MV(value);
- LOG_D("PV: avg=%d, %dmV", value, sys_info.charge_voltage);
- }
- /* 5. 灯管电流(PB0)*/
- if (is_time_to_sample(&s_last_led, ADC_CYCLE_LED))
- {
- value = adc_read_average(ADC_CH_LED);
- //LOG_I("LED: avg=%d", value);
- sys_sta.lamp_current = value;
- }
- // static char times = 0;
- // times ++;
- /* 6. 高压输出电流(PB1)*/
- if (1)
- {
- value = adc_read_average(ADC_CH_ELE);
- // if(times >= 10)
- // {
- // LOG_I("ELE: avg=%d", value);
- // times = 0;
- // }
- sys_sta.hv_current = value;
- }
- }
- /**
- * @brief ADC采集线程入口
- */
- static void adc_thread_entry(void *parameter)
- {
- //LOG_I("ADC thread started (10 samples average)");
- // LOG_I(" NTC:%dms LIGHT:%dms BAT:%dms PV:%dms LED:%dms ELE:%dms",
- // ADC_CYCLE_NTC, ADC_CYCLE_LIGHT, ADC_CYCLE_BAT,
- // ADC_CYCLE_PV, ADC_CYCLE_LED, ADC_CYCLE_ELE);
- /* 初始化各通道上次采样时间 */
- rt_tick_t start_tick = rt_tick_get();
- s_last_ntc = start_tick;
- s_last_light = start_tick;
- s_last_bat = start_tick;
- s_last_pv = start_tick;
- s_last_led = start_tick;
- s_last_ele = start_tick;
- while (1)
- {
- adc_collect();
- rt_thread_mdelay(ADC_BASE_CYCLE_MS);
- }
- LOG_I("ADC thread stopped");
- }
- /**
- * @brief 启动ADC采集线程
- */
- static void adc_thread_start(void)
- {
- if (s_adc_thread != RT_NULL)
- {
- LOG_D("ADC thread already running");
- return;
- }
- /* 配置引脚 */
- adc_pin_init();
- /* 初始化ADC硬件 */
- adc_hw_init();
- /* 创建采集线程 */
- s_adc_running = RT_TRUE;
- s_adc_thread = rt_thread_create("adc_mon", adc_thread_entry, NULL,
- 1024, 20, 10);
- if (s_adc_thread == RT_NULL)
- {
- LOG_E("Failed to create ADC thread");
- s_adc_running = RT_FALSE;
- return;
- }
- rt_thread_startup(s_adc_thread);
- //LOG_I("ADC thread started");
- }
- /*********************↓ 自动初始化 ↓************************/
- static int adc_auto_init(void)
- {
- adc_thread_start();
- return 0;
- }
- INIT_APP_EXPORT(adc_auto_init);
- /*********************↑ 自动初始化 ↑************************/
- /*********************↓ MSH命令 ↓************************/
- static void cmd_adc_read(int argc, char **argv)
- {
- uint32_t val;
- int8_t temp;
- rt_kprintf("\n========== ADC VALUES (10 samples avg) ==========\n");
- val = adc_read_average(ADC_CH_NTC);
- temp = adc_to_temperature(val);
- rt_kprintf("NTC (PA5-ADC5): %d -> %d°C\n", val, temp);
- val = adc_read_average(ADC_CH_LIGHT);
- rt_kprintf("LIGHT (PA4-ADC4): %d %d.%d\n", val , sys_sta.light_percent /10 ,sys_sta.light_percent %10 );
- val = adc_read_average(ADC_CH_BAT);
- rt_kprintf("BAT (PA7-ADC7): %d (%d mV)\n", val, ADC_TO_MV_BAT(val));
- val = adc_read_average(ADC_CH_PV);
- rt_kprintf("PV (PA6-ADC6): %d (%d mV)\n", val, ADC_TO_MV(val));
- val = adc_read_average(ADC_CH_LED);
- rt_kprintf("LED (PB0-ADC8): %d\n", val);
- val = adc_read_average(ADC_CH_ELE);
- rt_kprintf("ELE (PB1-ADC9): %d\n", val);
- rt_kprintf("==================================================\n");
- rt_kprintf("sys_sta.battery_voltage = %d mV\n", sys_sta.battery_voltage);
- rt_kprintf("sys_sta.charge_voltage = %d mV\n", sys_sta.charge_voltage);
- rt_kprintf("sys_sta.ambient_temp = %d.%d°C\n",
- sensor.temp_ntc / 10, sensor.temp_ntc % 10);
- }
- MSH_CMD_EXPORT(cmd_adc_read, Read all ADC channels with 10 samples average);
- /*********************↑ MSH命令 ↑************************/
|