STM32F103C8T6 · HAL库开发 · ADC模拟采集
三杯式风速传感器由三个半球形风杯组成,以120°等分安装在垂直旋转轴上。当风吹过时,由于风杯的凹面和凸面受到的风阻力不同(凹面阻力远大于凸面),产生扭矩差驱动转轴旋转。风杯的转速与风速呈线性正比关系。
传感器内部集成了信号转换电路,将转轴的机械旋转转换为模拟电压信号输出。风速越大,转速越快,输出电压越高。STM32通过ADC采集该模拟电压,经过公式换算即可得到实际风速值(m/s)。
通过三杯旋转结构,将风速转化为转速,再经内部电路输出与风速成正比的模拟电压信号,实现实时风速测量。
AO引脚输出连续变化的模拟电压,STM32的12位ADC采集后转换为0~4095的数字量,精度高、响应快。
ADC采集值经标定公式换算为风速值,支持浮点运算,结果以m/s为单位显示在OLED屏幕上。
配合0.96寸OLED显示屏,每500ms刷新一次风速数据,直观展示当前环境风速状态。
| 引脚 | 名称 | 功能 | STM32连接 |
|---|---|---|---|
| 1 | AO | 模拟电压输出(风速信号) | PA0 (ADC1_IN0) |
| 2 | GND | 电源地 | GND |
三杯式风速传感器正面外观 — 可见三个半球形风杯及旋转轴结构
三杯式风速传感器背面外观 — 信号转换电路板及接线端子
PA0连接传感器AO模拟输出,ADC1通道0采集风速模拟电压信号
使用外部高速晶振(HSE 8MHz),通过PLL倍频9倍得到72MHz系统主频。ADC时钟由PCLK2(72MHz)8分频得到9MHz,满足ADC最高14MHz的时钟要求。FLASH等待周期设为2个。
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/* HSE 8MHz + PLLx9 = 72MHz */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
Error_Handler();
/* SYSCLK=72MHz, AHB=72MHz, APB1=36MHz, APB2=72MHz */
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
Error_Handler();
/* ADC时钟 = PCLK2/8 = 72MHz/8 = 9MHz */
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV8;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
Error_Handler();
}
配置ADC1通道0(PA0引脚),12位分辨率(0~4095),单次转换模式,软件触发启动。数据右对齐,采样时间239.5个ADC时钟周期(约26.6μs),确保采样精度。PA0配置为模拟输入模式,无上下拉电阻。
void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; // 非扫描模式
hadc1.Init.ContinuousConvMode = DISABLE; // 单次转换
hadc1.Init.DiscontinuousConvMode = DISABLE; // 禁用间断模式
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 软件触发
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 数据右对齐
hadc1.Init.NbrOfConversion = 1; // 1个转换通道
if (HAL_ADC_Init(&hadc1) != HAL_OK)
Error_Handler();
sConfig.Channel = ADC_CHANNEL_0; // 通道0 = PA0
sConfig.Rank = ADC_REGULAR_RANK_1; // 第1转换序列
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; // 239.5周期采样
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
Error_Handler();
}
/* ADC1底层初始化 — PA0配置为模拟输入 */
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(adcHandle->Instance == ADC1)
{
__HAL_RCC_ADC1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/* PA0-WKUP → ADC1_IN0 模拟输入 */
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
}
使用0.96寸OLED显示屏(128×64),通过软件模拟I2C通信。SCL接PB15,SDA接PB14。支持居中字符串显示函数OLED_CenterPrintf(),风速数据以"风速:X.Xm/s"格式居中显示在第24行。
/* OLED I2C引脚定义 */
#define SCL_Port GPIOB
#define SCL_Pin GPIO_PIN_15
#define SDA_Port GPIOB
#define SDA_Pin GPIO_PIN_14
/* 核心显示函数 */
void OLED_Init(void); // OLED初始化
void OLED_Clear(void); // 清屏
void OLED_Update(void); // 更新显存到屏幕
void OLED_CenterPrintf(int16_t Y, char *format, ...); // 居中格式化打印
系统初始化后进入主循环,使用HAL_GetTick()实现500ms定时采样。每次触发时启动ADC单次转换,读取12位ADC值并代入标定公式计算风速,最后在OLED上居中显示。非阻塞定时设计允许CPU在间隔期间执行其他任务。
uint32_t Time_Now;
float air_speed; // 风速变量
int main(void)
{
HAL_Init(); // HAL库初始化
SystemClock_Config(); // 系统时钟配置 72MHz
MX_GPIO_Init(); // GPIO初始化
MX_ADC1_Init(); // ADC1初始化
OLED_Init(); // OLED显示屏初始化
while (1)
{
if(HAL_GetTick() - Time_Now >= 500) // 500ms更新一次
{
// 单通道数据获取
HAL_ADC_Start(&hadc1);
if(HAL_ADC_PollForConversion(&hadc1, 999) == HAL_OK)
air_speed = HAL_ADC_GetValue(&hadc1)/4095.0*33.0*2.7; // 获取风速
HAL_ADC_Stop(&hadc1);
OLED_Clear(); // 清屏
OLED_CenterPrintf(24, "风速:%.1fm/s", air_speed); // 显示风速
OLED_Update(); // 更新显示
Time_Now = HAL_GetTick(); // 更新时间戳
}
}
}
ADC采集的12位原始值(0~4095)经以下公式转换为风速(m/s)。公式中各系数为传感器标定参数,根据传感器输出特性确定。
左侧为三杯式风速传感器的模拟实物,三个半球形风杯安装在120°等分的旋转臂上。拖动滑块模拟不同风速,风杯转速随风速增大而加快,同时左侧出现风流粒子动画。右侧实时显示OLED屏幕内容和风速仪表盘,所有数据均按照源程序中的标定公式 air_speed = ADC/4095.0*33.0*2.7 实时计算。