目录
前言
在智能家居设备日益普及的今天,自己动手制作一款智能台灯不仅能提升居家科技感,还能加深对嵌入式系统开发的理解。本文将详细介绍如何使用STM32最小系统开发板来打造一个简单具有自动亮度调节的智能台灯。
一、模块选择
1.STM32F103C8T6最小开发板
![](https://img-blog.csdnimg.cn/direct/7af6eacfa8504f8e963e5d8a64cf3767.png)
STM32F103C8T6是一款高性能的32位微控制器(图1-1),基于ARM Cortex-M3内核,广泛适用于需要丰富外设和低功耗的嵌入式应用。STM32F103C8T6最小系统开发板是一个功能强大、特性齐全的嵌入式开发平台,非常适合需要快速开发和原型制作的工程师和爱好者。它不仅提供了稳定的硬件基础,还通过丰富的外设接口和强大的处理能力,使得从简单的家庭自动化到复杂的工业控制系统等各种应用成为可能。
2.光敏传感器模块
![](https://img-blog.csdnimg.cn/direct/a32c57af2fce40ccbfa9c61fc6a2b90f.png)
四引脚光敏传感器模块具有四个主要引脚:VCC、GND、DO(数字输出)和AO(模拟输出)。这种配置使其能够灵活地与微控制器或其他电子系统连接,实现对环境光线亮度的精确检测和响应。
光敏传感器的工作原理是将光信号转化为电信号,这依赖于其内部的光敏元件,如光敏电阻。在四引脚模块中,VCC引脚用于连接电源正极,而GND引脚则连接到电源的负极。DO引脚是开关输出,能够根据光照强度输出高电平或低电平信号。这些电平状态可以通过微控制器进行检测,从而判断环境的光线亮暗变化。AO引脚则提供模拟电压输出,通过连接到微控制器的ADC(模数转换器),可以获取具体的光照强度数值。
二、项目开发准备
硬件准备
-
STM32F103C8T6开发板
-
光敏传感器模块
-
HW-269LED模块
-
面包板和导线
软件准备
-
STM32Keil uVision5
-
STM32F103系列标准外设库
电路连接
- 将光敏传感器的AO连接到STM32F103C8T6的某个ADC输入引脚,用于检测环境光线强度。
- 将HW-269LED的OUT连接到STM32的一个GPIO引脚,该引脚配置为PWM输出。
三、项目开发
我们要对进行PWM和LED初始化,选择要控制的GPIO引脚,并确保这些引脚的配置与硬件连接相符合。同时,对于PWM初始化,需要确保定时器的配置正确,包括时钟源、计数频率、工作模式、周期和占空比等,以确保能够生成所需的PWM波形。
还要对ADC进行初始化,将与光敏传感器连接的GPIO引脚设置为模拟输入模式,并配置适当的采样时间。对ADC进行配置,包括设置分辨率、转换速率、数据对齐方式等,然后使能ADC并开始校准。指定ADC的输入通道与光敏传感器相连,确保能够读取到传感器的信号。
程序编写
1.主函数编写
主控程序是智能调光台灯软件系统的核心,负责协调各个子模块的工作并实现整体控制逻辑。程序采用模块化设计,主要包括初始化模块、数据采集模块、数据处理模块、调光控制模块和通信模块。初始化模块配置微控制器的各项参数和外设;数据采集模块读取光敏传感器的信号;数据处理模块分析采集到的数据并作出决策;调光控制模块生成相应的PWM信号以调节LED亮度;
int main(void)
{
/*模块初始化*/
OLED_Init(); //OLED初始化
AD_Init();
PWM_Init(); //AD初始化
/*显示静态字符串*/
OLED_ShowString(1, 1, "ADValue:");
OLED_ShowString(2, 1, "Voltage:0.00V");
// PWM_SetPrescaler(720 - 1); //PWM频率Freq = 72M / (PSC + 1) / 100
// PWM_SetCompare1(0); //PWM占空比Duty = CCR / 100
while (1)
{
ADValue = AD_GetValue();
//获取AD转换的值
Voltage = (float)ADValue / 4096 * 3.3; //将AD值线性变换到0~3.3的范围,表示电压
OLED_ShowNum(1, 9, ADValue, 4); //显示AD值
OLED_ShowNum(2, 9, (uint16_t)Voltage, 1); //显示电压值的整数部分
OLED_ShowNum(2, 11, (uint16_t)(Voltage * 100) % 100, 2); //显示电压值的小数部分
TIM_SetCompare3(TIM2, ADValue /50); // 假设ADC的值范围是0-4095,·
// for(int i = 0; i < 100000; i++); // 延时,等待下一次ADC采样
Delay_ms(100);
}
2.PWM初始化
PWM调光算法是通过改变PWM信号的占空比来调节LED亮度的关键。算法根据数据处理模块计算出的目标亮度值,调整PWM信号的占空比,从而实现对LED亮度的精确控制。为了减少人眼可感知的闪烁现象,PWM频率设置在较高的水平,以保证调光过程平滑自然。
void PWM_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_InternalClockConfig(TIM2);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0; //CCR
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
TIM_Cmd(TIM2, ENABLE);
}
3.ADC初始化
光敏传感器数据采集是通过模拟-数字转换器(ADC)实现的,将光敏传感器输出的模拟信号转换为数字信号供微控制器处理。数据处理模块采用阈值判断和比例积分微分(PID)控制算法,根据环境光线强度动态调整LED的目标亮度值。此方法可以有效减少系统的响应时间,提高调光精度。
void AD_Init(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //开启ADC1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟
/*设置ADC时钟*/
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //选择时钟6分频,ADCCLK = 72MHz / 6 = 12MHz
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA0引脚初始化为模拟输入
/*规则组通道配置*/
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); //规则组序列1的位置,配置为通道0
/*ADC初始化*/
ADC_InitTypeDef ADC_InitStructure; //定义结构体变量
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //模式,选择独立模式,即单独使用ADC1
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //数据对齐,选择右对齐
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //外部触发,使用软件触发,不需要外部触发
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //连续转换,失能,每转换一次规则组序列后停止
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //扫描模式,失能,只转换规则组的序列1这一个位置
ADC_InitStructure.ADC_NbrOfChannel = 1; //通道数,为1,仅在扫描模式下,才需要指定大于1的数,在非扫描模式下,只能是1
ADC_Init(ADC1, &ADC_InitStructure); //将结构体变量交给ADC_Init,配置ADC1
/*ADC使能*/
ADC_Cmd(ADC1, ENABLE); //使能ADC1,ADC开始运行
/*ADC校准*/
ADC_ResetCalibration(ADC1); //固定流程,内部有电路会自动执行校准
while (ADC_GetResetCalibrationStatus(ADC1) == SET);
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1) == SET);
}
/**
* 函 数:获取AD转换的值
* 参 数:无
* 返 回 值:AD转换的值,范围:0~4095
*/
uint16_t AD_GetValue(void)
{
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //软件触发AD转换一次
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); //等待EOC标志位,即等待AD转换结束
return ADC_GetConversionValue(ADC1); //读数据寄存器,得到AD转换的结果
}
四、效果测试
系统的工作流程如下:当环境光线发生变化时,光敏传感器检测到光线强度的变化并将其转换为电信号,随后将信号传输至控制模块。STM32F103C8T6微控制器对信号进行处理,并根据预设的算法计算出相应的PWM(脉宽调制)信号,以调节LED光源的亮度。
效果如下所示:
实验效果
总结
本次实验成功设计并实现了一款基于STM32F103C8T6微控制器和光敏传感器的智能调光的小项目。通过对硬件选型、电路设计、软件开发和系统集成的详细阐述,本研究构建了一个能够根据环境光线自动调节亮度的台灯系统。功能测试和性能测试结果表明,该智能调光台灯具有良好的稳定性、响应速度和用户交互体验,满足了设计初衷,实现了预定的研究目标。