STM32单片机光照检测智能调光系统

本设计包含proteus仿真+程序代码+设计报告+讲解视频

一、开发环境

仿真图:proteus 8.17

程序编译器:keil 5

编程语言:C语言

设计编号:C0136

二、主要功能

  1. 采用STM32F103系列单片机作为控制核心,实现光照检测与LED亮度调节;

  2. 仿真环境光照检测范围为0~999lx,显示分辨率不低于10lx;

  3. LED台灯亮度可在10%~100%范围内调节,至少具有5档亮度等级;

  4. 具有自动调光与手动调光两种工作模式,通过按键切换;

  5. 自动模式下,当环境光变化时,系统响应时间不大于2s;

  6. 采用OLED显示当前光照值、工作模式和亮度等级;

  7. 使用Proteus仿真实现亮度自动调节功能。

img

资料下载链接:

KEY_C0136 STM32智能台灯控制OLED显示设计

链接: https://pan.baidu.com/s/14liAWxV4vjPOY_2gfqGDkw?pwd=pc1q

提取码: pc1q

以下为本设计资料展示:

三、仿真设计

打开仿真工程,双击proteus中的单片机,选择hex文件路径,然后开始仿真。

img

img

四、程序代码

程序是用keil5 mdk版本打开的,如果打开有问题,核实下keil的版本。程序有注释可以结合讲解视频理解。

// 函数声明
void Hardware_Init(void);
void Display_Init(void);
void Refresh_Data(void);

// 全局变量
u8 humi, fan_adj;          // 湿度、风扇调节(未使用)
u8 set_sta = 0;            // 设置状态标志(0:正常显示,1:设置模式)
u8 key_ctrl = 0;           // 按键控制标志,用于刷新显示

float mq2_vol, smog_th = 100.0;   // MQ2烟雾传感器电压、烟雾阈值(未使用)
u8 temp_th = 30;                  // 温度阈值(未使用)

uint32_t light_vol;               // 光照强度值(Lux)
uint8_t work_mode = 0;            // 工作模式:0-自动模式,1-手动模式
uint8_t light_level = 1;          // 亮度等级 1~5

uint8_t Fan_Status = 0;           // 风扇状态(未使用)
uint8_t Beep_Status;              // 蜂鸣器状态(未使用)
uint8_t Fire_Status = 0;          // 火焰检测状态(未使用)
uint8_t relay_Status = 0;         // 继电器状态(未使用)
uint8_t Status_Change;            // 状态变化标志,用于刷新显示

float temp;                       // 温度值(未使用)

/*
************************************************************
*	函数名称:	main
*	函数功能:	主函数,程序入口
*	入口参数:	无
*	返回参数:	0
*	说明:		循环检测光照、控制风扇亮度等级、刷新显示
************************************************************
*/
int main(void)
{
	unsigned short timeCount = 0;	// 发送间隔变量(用于定时任务,约2.5秒)

	Hardware_Init();				// 初始化外围硬件
	Display_Init();					// 初始化OLED显示界面
	Led_Set(LED_OFF);				// 关闭LED(指示灯)
	
	SystemCoreClockUpdate();		// 更新系统核心时钟变量

	// 通过串口1打印系统时钟频率
	UsartPrintf(USART_DEBUG, "system_clock:%lu Hz (%.2f MHz)\r\n", SystemCoreClock, SystemCoreClock / 1000000.0);


	while(1)
	{
		// 定时任务:每50次循环(约500ms,因为循环内DelayMs(10))执行一次
		if(++timeCount >= 50)		// 发送间隔2.5s 
		{
			timeCount = 0;

			// 读取光照强度(Lux)
			light_vol = light_intensity();
		    UsartPrintf(USART_DEBUG, "light----%d--\r\n", light_vol);
			
			// 如果是自动模式(work_mode==0),根据光照强度自动计算亮度等级
			if(work_mode == 0)
				light_level = light_level_intensity();  // 自动调节亮度等级
			UsartPrintf(USART_DEBUG, " light_level = %d\r\n", light_level);
		 	
			// 如果状态发生变化,重新初始化显示界面
			if(Status_Change){
				Status_Change = 0;
				Display_Init();
			}
		}

		// 处理设置模式下的显示清除
		if(set_sta){
			if(key_ctrl){
				OLED_Clear();
				key_ctrl = 0;
			    UsartPrintf(USART_DEBUG, "OLED_Clear\r\n");
			}
		} else {
			// 非设置模式下,按键触发重新初始化显示
			if(key_ctrl){
				Display_Init();
				key_ctrl = 0;
				UsartPrintf(USART_DEBUG, "Display_Init\r\n");
			}		
		}
		
		// 刷新显示数据(光照值、工作模式、亮度等级等)
		Refresh_Data();

		// 根据亮度等级设置PWM占空比控制灯光
		if(light_level == 1){
			Fan_Set(PWM_L1);
		} else if(light_level == 2){
			Fan_Set(PWM_L2);
		} else if(light_level == 3){
			Fan_Set(PWM_L3);
		} else if(light_level == 4){
			Fan_Set(PWM_L4);
		} else if(light_level == 5){
			Fan_Set(PWM_L5);
		}
		
		DelayMs(10);	// 延时10ms,主循环周期约10ms
	}
}

/*
************************************************************
*	函数名称:	Hardware_Init
*	函数功能:	硬件初始化
*	入口参数:	无
*	返回参数:	无
*	说明:		初始化单片机外设及外接模块:中断分组、延时、串口、
*				、LED、ADC、OLED、按键
************************************************************
*/
void Hardware_Init(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	// 中断控制器分组设置(2位抢占优先级,2位子优先级)

	Delay_Init();									// SysTick 延时初始化
	
	Usart1_Init(115200);							// 串口1初始化,波特率115200,用于打印调试信息
	Usart2_Init(115200);							// 串口2初始化,备用

   Led_Init();                                     // LED指示灯初始化
	AD_Init();                                      // ADC初始化(用于光照、烟雾等模拟量采集)

	OLED_Init();			// OLED显示屏初始化

    Fan_Init();             // PWM初始化 控制灯光
	UsartPrintf(USART_DEBUG, " Hardware init OK\r\n");
	OLED_Clear(); 
	OLED_ShowString(0,0,"Hardware init OK",16); 
	DelayMs(1000);
	Key_Init();             // 按键初始化
}

/*
************************************************************
*	函数名称:	Display_Init
*	函数功能:	初始化OLED显示界面(绘制静态文字)
*	入口参数:	无
*	返回参数:	无
*	说明:		清屏后显示中文标签:
*				第0行:"光照:"
*				第3行:"工作模式:"
*				第6行:"亮度等级:"
************************************************************
*/
void Display_Init(void)
{
	OLED_Clear();
	
	// 第0行:显示"光照:"(中文字符,索引10,11,12,0)
	OLED_ShowCHinese(0,0,10);   // "光"
	OLED_ShowCHinese(18,0,11);   // "照"
	OLED_ShowCHinese(18*2,0,12); // ":"
	OLED_ShowCHinese(18*3,0,0);  // ":"0是冒号)
	
	// 第3行:显示"工作模式:"
	OLED_ShowCHinese(0,3,13);    // "工"
	OLED_ShowCHinese(18*1,3,14); // "作"
	OLED_ShowCHinese(18*2,3,15); // "模"
	OLED_ShowCHinese(18*3,3,16); // "式"
	OLED_ShowCHinese(18*4,3,0);  // ":"
	
	// 第6行:显示"亮度等级:"
	OLED_ShowCHinese(0,6,17);    // "亮"
	OLED_ShowCHinese(18*1,6,18); // "度"
	OLED_ShowCHinese(18*2,6,19); // "等"
	OLED_ShowCHinese(18*3,6,20); // "级"
	OLED_ShowCHinese(18*4,6,0);  // ":"
}

/*
************************************************************
*	函数名称:	Refresh_Data
*	函数功能:	刷新OLED上的动态数据(光照值、工作模式文字、亮度等级)
*	入口参数:	无
*	返回参数:	无
*	说明:		根据Status_Change标志决定是否清屏,仅在非设置模式(set_sta==0)
*				且非状态变化时更新显示数值。工作模式显示"自动"/"手动"。
************************************************************
*/
void Refresh_Data(void)
{
    static u8 last_status = 0;  // 记录上一次的Status_Change状态,用于检测上升沿
	
    char buf[20];               // 临时字符串缓冲区
    
    // 如果状态发生变化,且上一次状态为0(即刚变为1),则清屏
    if(Status_Change) {
        if(last_status == 0) {
            OLED_Clear();
        }
    } else {
        // 非设置模式下才更新显示数值
        if(set_sta == 0){
            memset(buf, 0, sizeof(buf));
            // 显示光照强度值,单位Lux
            sprintf(buf, "%dLux", light_vol);
            OLED_ShowString(18*4, 0, (u8*)buf, 16);   // 从第4个中文字符位置开始显示
            
            // 显示工作模式:自动模式显示"自动",手动模式显示"手动"
            if(work_mode == 0){   // 0是自动模式
                OLED_ShowCHinese(18*5, 3, 21);  // "自"
                OLED_ShowCHinese(18*6, 3, 23);  // "动"
            } else {
                OLED_ShowCHinese(18*5, 3, 22);  // "手"
                OLED_ShowCHinese(18*6, 3, 23);  // "动"
            }
            
            // 显示亮度等级
            memset(buf, 0, sizeof(buf));
            sprintf(buf, "%d", light_level);
            OLED_ShowString(18*5, 6, (u8*)buf, 16); // 从第5个中文字符位置显示等级数字
        }
    }
    
    last_status = Status_Change;  // 更新状态记录,用于下次判断边沿
}

img

程序流程图:

img

五、设计说明书

8265字,内容包括硬件设计、软件设计、结论等。

img

六、资料清单&下载链接

img

资料下载链接:

链接: https://pan.baidu.com/s/14liAWxV4vjPOY_2gfqGDkw?pwd=pc1q

提取码: pc1q
imgimg

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐