基于Stm32的WiFi多功能LED

(限于本人水平,此项目中中还存在不足,欢迎大家指正探讨)

多功能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

 调节亮度命令,每次亮度加10

                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的例程下次发文

版权声明:本文为CSDN博主「MaZhongkai1994」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/MaZhongkai1994/article/details/122709128

生成海报
点赞 0

MaZhongkai1994

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

STM32F2————配置时钟延迟不准的问题

STM32F2配置时钟问题 笔者在本科毕业设计使用STM32F207芯片,但是在配置时钟时出现了问题。 问题 我按照F1写代码的延时函数放在F2竟然不准了 换个办法 使用Systick时钟也是不准,原因是笔者代

为什么重写printf函数没有用?

以前在网上找了无数方法去重写printf函数,但发现都没效果,今天偶然发现重写printf函数可以了,原因是以前没有勾选微库(Use MicroLlB)! 这里