(限于本人水平,此项目中中还存在不足,欢迎大家指正探讨)
多功能LED设计,拥有自动和手动两种模式
1)自动模式:可以通过人体红外传感器检测是否有人,采用光敏电阻构成的电路检测环境光的强度,从而自动实现灯的开启和关闭,也可以根据环境亮度调节灯的亮度;
2)WiFi模式:可以使用WIFI连接手机,通过手机APP手动控制不同灯的开启和关闭,并可控制LED灯的亮度
单片机选用stm32f103c8t6;APP使用Android stutio环境编写;OLED为7脚,SPI
stm32程序、电路图、PCB、手机APP程序
程序源码:https://download.csdn.net/download/MaZhongkai1994/78057051
硬件电路构成:USB供电接口,AMS1117稳压电路,stm32f103c8t6单片机最小系统,WiFi模块,按键选择,光敏电阻分压电路,OLED接口等。
上图为模式选择界面,可通过按键进行模式选择
switch(KEY_Scan(0)) //按键判断
{
case KEY0_PRES: //确认按键
if(!confirm_flag) //如果confirm = 0,按键按下后进行"确定",将此标志置1
confirm_flag=1;
else //如果confirm = 1,按键按下后进行"返回",将此标志清零
confirm_flag=0;
OLED_Clear();break; //OLED清除
case KEY1_PRES: //自动模式选择按键
if(!confirm_flag) //确认按键(标志位)未按下前,可进行模式选择
{
mode=0; //KEY1用于选择自动模式,设置mode=0
OLED_Clear();
OLED_ShowChar_16X16(5,1,'>'); //显示选择标号
};break;
case KEY2_PRES: //WiFi模式选择按键
if(!confirm_flag) //确认按键(标志位)未按下前,可进行模式选择
{
mode=1; //KEY1用于选择WiFi模式,设置mode=1
OLED_Clear();
OLED_ShowChar_16X16(5,4,'>');
};break;
default:break;
}
完成模式选择后,则进入相应模式,显示相关参数
1)WiFi模式下,通过串口接收手机APP发送的控制命令,判断接收到的命令并执行
接收到开灯命令后,以PWM=30的亮度打开LED
if(mode) //如果mode=1 为WiFi模式,显示相应的参数
{ //显示“WiFi模式”字样
OLED_ShowChar_16X16(25,0,'W');
OLED_ShowChar_16X16(35,0,'I');
OLED_ShowChar_16X16(45,0,'F');
OLED_ShowChar_16X16(55,0,'I');
OLED_ShowCHinese(65,0,7);
OLED_ShowCHinese(81,0,8);
OLED_ShowCHinese(5,3,16);
OLED_ShowCHinese(21,3,17);
OLED_ShowChar_16X16(37,3,':');
switch(USART_RX_Temp[0]) //判断从串口接收到的控制命令
{
case 'K': //开灯命令
PWM_OUT=30; //以30的亮度打开LED
WiFi_Flag=1;
OLED_ShowCHinese(47,3,20);
OLED_ShowCHinese(63,3,22);break;
case 'G': //关灯命令
WiFi_Flag=0;
OLED_ShowCHinese(47,3,21);
OLED_ShowCHinese(63,3,22);break;
case 'Z': //PWM+命令 用于调节LED的亮度
if(PWM_OUT<60) //PWM_OUT值小于最大值,PWM_OUT每次+10
PWM_OUT+=10;
break;
case 'F': //PWM-命令 用于调节LED的亮度
if(PWM_OUT>0) // //PWM_OUT值大于0,PWM_OUT每次-10
PWM_OUT-=10;
break;
default:break;
}
USART_RX_Temp[0]='0'; //数组要清零保证发送一条命令只执行一次
OLED_ShowCHinese(5,5,18); //亮
OLED_ShowCHinese(21,5,19); //度
OLED_ShowChar_16X16(37,5,':');
OLED_ShowNum(47,5,PWM_OUT,2,16);}
2)自动模式下 ,人体红外检测和光敏电阻共同控制LED,当人体红外模块检测到有人靠近时,并判断当前光敏电阻电压值,输出对应的PWM,根据光强控制LED亮度
没人靠近时,即使光照变暗,PWM有对应的值,LED灯也不会亮
有人靠近时,会根据现在光强控制输出PWM,LED亮后,即使再次检测到有人靠近也不会一直亮,10S后关闭,再次检测到有人靠近会再次亮起
else
{
adcx=Get_Adc_Average(ADC_Channel_1,10); //采集电压值
temp=(float)adcx*(3.3/4096);
adcx=temp*10; //将数组处理为整数
//显示“自动模式”字样
OLED_ShowCHinese(25,0,5);
OLED_ShowCHinese(41,0,6);
OLED_ShowCHinese(57,0,7);
OLED_ShowCHinese(73,0,8);
sprintf(display,"ADC=%.2f",temp); //显示电压值
OLED_ShowString(5,4,(u8 *)display);
sprintf(display,"PWM=%d",PWM_OUT); //显示PWM
OLED_ShowString(5,6,(u8 *)display);
//共五个电压区间,可输出对应亮度
if(adcx/10 >= 1 && adcx/10 < 2) //判断adc值,输出对应的PWM
{
if(adcx%10 >=0 && adcx%10 <= 6)
PWM_OUT=0;
else if(adcx%10 > 6) //电压值大于1.6V,PWM_OUT=15
PWM_OUT=15;
}
else if(adcx/10 >= 2 && adcx/10 < 3)
{
if(adcx%10 >=0 && adcx%10 < 5)
PWM_OUT=30;
else if(adcx%10 >=5)
PWM_OUT=45;
}
else if(adcx/10 >=3)
PWM_OUT=60;
OLED_ShowCHinese(5,2,9);
OLED_ShowCHinese(21,2,10);
OLED_ShowChar_16X16(37,2,':');if(Log_OUT)
{
if(!Log_Flag) //已经检测到有人靠近,即使再次靠近也不会重新计时
{
count1=0;
Log_Flag=1;
}
OLED_ShowCHinese(47,2,12);
OLED_ShowCHinese(63,2,13);
OLED_ShowCHinese(79,2,14);
OLED_ShowCHinese(95,2,15);
}
else
{
OLED_ShowCHinese(47,2,11);
OLED_ShowCHinese(63,2,13);
OLED_ShowCHinese(79,2,14);
OLED_ShowCHinese(95,2,15);
}
}
ESP8266-12E,先通过串口调试上位机设置对应的 模式,需要勾选发送新行
AT+RST 重启模块
AT+UART=115200,8,1,0,0 设置串口配置
AT +CWMODE=2 选择WiFi应用为AP模式
AT+CWSAP=“ATK_ESP8266”,"12345678",1,4 设置AP模式下参数
AT+CIPMUX=1 启动多路连接
AT+CIFSR 获取本地IP,用于APP
WiFi初始化函数,单片机上电后须进行部分设置初始化
//WiFi初始化程序
void WIFI_Init(void)
{
printf("AT+CWMODE=2\r\n"); //
delay_ms(1000);printf("AT+RST\r\n");
delay_ms(1000);
delay_ms(1000);printf("AT+CIPMUX=1\r\n");
delay_ms(1000);
printf("AT+CIPSERVER=1,8080\r\n");
delay_ms(1000);
}
串口中断服务函数,手机APP发送的控制的命令为+ I P D ‘K’ 格式,‘ ’中的数据为APP程序中设置的控制命令,先判断前面的数据为+ I P D,则获取数组中第九位数据作为控制命令
void USART1_IRQHandler(void)
{
u16 res;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)//接收到数据
{
res =USART_ReceiveData(USART1);
USART_RX_BUF[USART_RX_STA]=USART_ReceiveData(USART1);
if(USART_RX_BUF[0]=='+') //手机APP传输的命令为+IPD ‘K’/+IPD ‘G’ 等,
USART_RX_STA++;
else
USART_RX_STA=0;
if(USART_RX_STA==10)
{
USART_RX_STA=0;
if(USART_RX_BUF[0]=='+'&&USART_RX_BUF[1]=='I'&&USART_RX_BUF[2]=='P'&&USART_RX_BUF[3]=='D')//接收保存命令
{
USART_RX_Temp[0]=USART_RX_BUF[9]; //上面判断接收的命令若为前面模式,若是则将第九位数据传输到中间变量数组,到主函数判断}
}
}
}
定时器中断服务函数
1)定时器3每10ms中断一次,控制LED自动模式下有人靠近后的10S灭灯标志位( Log_Flag),和控制标志(control_flag)位,主函数中的程序通过控制标志位控制每10ms执行一次
2)定时器2控制输出LED亮度
void TIM3_IRQHandler(void) //TIM3中断
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update)!=RESET) //检查指定的TIM中断发生与否:TIM 中断源
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除TIMx的中断待处理位:TIM 中断源
count1++;
if(count1==1000)
{
count1=0;
Log_Flag=0;
}
control_flag=1;
}
}void TIM2_IRQHandler(void) //TIM2中断
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update)!=RESET) //检查指定的TIM中断发生与否:TIM 中断源
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除TIMx的中断待处理位:TIM 中断源
if(count--)
{
if(count>=PWM_OUT)
{
LED0=1;
}
else
{
if(Log_Flag || WiFi_Flag)
LED0=0;
else if(!Log_Flag || !WiFi_Flag)
LED0=1;
}
}
else
count=60;
}
}
第一次使用Android stutio写程序,还不是很熟悉,Android stutio软件的快速使用以及APP的例程下次发文