基于STM32单片机WIFI无线APP控灯亮度灭设计

发布于:2025-06-25 ⋅ 阅读:(24) ⋅ 点赞:(0)

基于STM32单片机控灯设计

(程序+原理图+设计报告)

功能介绍

具体功能:

本设计由STM32F103C8T6单片机核心电路+两位白色高亮LED灯电路+WIFI模块ESP8266电路+电源电路组成。

1、stm32实时监测wifi数据,解析数据后通过pwm控制led的亮灭及亮度程度。

2、手机发送指令:

OPEN1,第一个灯亮;OPEN2,第二个灯亮;

CLOSE1,第一个灯灭;CLOSE2,第二个灯灭;

LED1-1,第一个等处于1档,LED1-2,第1个等处于2档,LED1-3,第一个等处于3档。

LED2-1,第2个等处于1档,LED2-2,第2个等处于2档,LED2-3,第2个等处于3档,

OPENALL:全亮

CLOSEALL:全灭!

添加图片注释,不超过 140 字(可选)

程序

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "timer.h"
#include "key.h"
#include "usart.h"	
#include <string.h>



unsigned char led1Count=0;	//led 对比pwm值计数
unsigned char led2Count=0;
unsigned char PWML_LED1=10;//led PWM 范围0-10
unsigned char PWML_LED2=10;

unsigned char BufTab[10]; //wifi数据暂存
unsigned char Count;	   //串口数据计数
unsigned char UartBusy=0;  //判断忙碌
unsigned char ReadFlag=0;//读取标志
unsigned char sendDataFlag=0;	//发送数据标志
u8 rebackFalg= 0; //数据返回标志
u8 MesCount=0;	//发送内容计数
unsigned char i ;
int main(void)
 {	
	delay_init();	    	 //延时函数初始化
	NVIC_Configuration();//设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	LED_Init();		  	//初始化与LED连接的硬件接?
//	KEY_Init();
	uart_init(9600);
	TIM3_Int_Init(499,7199);//10Khz的计数频率,计数到500为50ms 
	i=50;
	while(i--) delay_ms(100);
	printf("AT+CIPMUX=1\r\n");		   //允许链接
	i=10;
	while(i--) delay_ms(100);
	printf("AT+CIPSERVER=1,8080\r\n");	   //创建端口号8080
	
	while(1)
	{  
		if(ReadFlag== 1)		//读取串口数据标志
		{
			Count=0;					//传授接收变量清零
			UartBusy=0;
			ReadFlag=0;				//读取标识清零

			if((strstr((const char *)BufTab,"PEN1")!=NULL)||(strstr((const char * )BufTab,"ED1-3")!=NULL))	 //接收到LPEN1 LED1-3
			{
			 	PWML_LED1=10;rebackFalg=1;//设置pwm 发送标志置位
			}
			else if(strstr((const char * )BufTab,(const char * )"LOSE1")!=NULL)	  //接收到CLOSE1
			{
			 	PWML_LED1=0;rebackFalg=1;//设置pwm 发送标志置位
			}
			else if(strstr((const char *)BufTab,"ED1-1")!=NULL)	   //接收到LED1-1
			{
			 	PWML_LED1=3;rebackFalg=1;//设置pwm 发送标志置位
			}
			else if(strstr((const char *)BufTab,"ED1-2")!=NULL)	  //接收到LED1-2
			{
			 	PWML_LED1=6;rebackFalg=1;//设置pwm 发送标志置位
			}
			else if((strstr((const char *)BufTab,"PEN2")!=NULL)||(strstr((const char *)BufTab,"ED2-3")!=NULL))	 //接收到	OPEN2
			{
			 	PWML_LED2=10;rebackFalg=1;//设置pwm 发送标志置位
			}
			else if(strstr((const char *)BufTab,"LOSE2")!=NULL)	  //接收到LLOSE2
			{
			 	PWML_LED2=0;rebackFalg=1;//设置pwm 发送标志置位
			}
			else if(strstr((const char *)BufTab,"ED2-1")!=NULL)	   //接收到LED2-1
			{
			 	PWML_LED2=3;rebackFalg=1;//设置pwm 发送标志置位
			}
			else if(strstr((const char *)BufTab,"ED2-2")!=NULL)	 //接收到LED2-2
			{
			 	PWML_LED2=6;rebackFalg=1;//设置pwm 发送标志置位
			}
			}
			else if(strstr((const char *)BufTab,"PENALL")!=NULL)	 //接收OENALL
			{
			 	PWML_LED1=10;PWML_LED2=10;rebackFalg=1;		//设置pwm 发送标志置位
			}
			else if(strstr((const char *)BufTab,"LOSEALL")!=NULL)	  //接收到CLOSEALL
			{
			 	PWML_LED1=0;PWML_LED2=0; rebackFalg=1;
			}
			for(i=0;i<10;i++)	   //清空wifi数据数组
			{
				BufTab[i]='0';
			}

		if((sendDataFlag == 1)&&(rebackFalg != 0))//接收到数后返回ok			
		{
			if(MesCount == 0)			//发送信息计数
			{
				MesCount =1;
				printf("AT+CIPSEND=0,2\r\n");		//发送固定字节数据的at命令
			}
			else
			{				
				if(rebackFalg ==1)		//返回标志置位
				{printf("OK");}					//发送ok
				MesCount = 0;				   //发送信息计数
				rebackFalg = 0;
			}
			sendDataFlag =	0;		//定时发送数据清空
		}			
		
			led1Count++;		//led 对比pwm值计数
			led2Count++;		//led 对比pwm值计数
			if(led1Count<PWML_LED1)	   //led1 PWM对比
			{
				LED1=0;			  //开灯
			}
			else if((led1Count>=PWML_LED1)&&(led1Count<=10))	 //led1 PWM对比
			{
			 	LED1=1;			//关灯
			}
			else
			{
				led1Count=0;  //一个周期结束
			}
		
			if(led2Count<PWML_LED2)	   //led2 PWM对比
			{
				LED2=0;			   //开灯
			}
			else if((led2Count>=PWML_LED2)&&(led2Count<=10))	 //led2 PWM对比
			{
			 	LED2=1;			//关灯
			}
			else
			{
				led2Count=0;  //一个周期结束
			}				
	}
}
 #include "delay.h"
#include "sys.h"
// 	 
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_UCOS
#include "includes.h"					//ucos 使用	  
#endif

static u8  fac_us=0;//us延时倍乘数
static u16 fac_ms=0;//ms延时倍乘数
#ifdef OS_CRITICAL_METHOD 	//如果OS_CRITICAL_METHOD定义了,说明使用ucosII了.
//systick中断服务函数,使用ucos时用到
void SysTick_Handler(void)
{				   
	OSIntEnter();		//进入中断
    OSTimeTick();       //调用ucos的时钟服务程序               
    OSIntExit();        //触发任务切换软中断
}
#endif
********//完整资料
 	***//***公众号:木子单片机********/	
//初始化延迟函数
//当使用ucos的时候,此函数会初始化ucos的时钟节拍
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
void delay_init()	 
{

#ifdef OS_CRITICAL_METHOD 	//如果OS_CRITICAL_METHOD定义了,说明使用ucosII了.
	u32 reload;
#endif
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);	//选择外部时钟  HCLK/8
	fac_us=SystemCoreClock/8000000;	//为系统时钟的1/8  
	 
#ifdef OS_CRITICAL_METHOD 	//如果OS_CRITICAL_METHOD定义了,说明使用ucosII了.
	reload=SystemCoreClock/8000000;		//每秒钟的计数次数 单位为K	   
	reload*=1000000/OS_TICKS_PER_SEC;//根据OS_TICKS_PER_SEC设定溢出时间
							//reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右	
	fac_ms=1000/OS_TICKS_PER_SEC;//代表ucos可以延时的最少单位	   
	SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;   	//开启SYSTICK中断
	SysTick->LOAD=reload; 	//每1/OS_TICKS_PER_SEC秒中断一次	
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;   	//开启SYSTICK    
#else
	fac_ms=(u16)fac_us*1000;//非ucos下,代表每个ms需要的systick时钟数   
#endif
}								    

#ifdef OS_CRITICAL_METHOD	//使用了ucos
//延时nus
//nus为要延时的us数.		    								   
void delay_us(u32 nus)
{		
	u32 ticks;
	u32 told,tnow,tcnt=0;
	u32 reload=SysTick->LOAD;	//LOAD的值	    	 
	ticks=nus*fac_us; 			//需要的节拍数	  		 
	tcnt=0;
	told=SysTick->VAL;        	//刚进入时的计数器值
	while(1)
	{
		tnow=SysTick->VAL;	
		if(tnow!=told)
		{	    
			if(tnow<told)tcnt+=told-tnow;//这里注意一下SYSTICK是一个递减的计数器就可以了.
			else tcnt+=reload-tnow+told;	    
			told=tnow;
			if(tcnt>=ticks)break;//时间超过/等于要延迟的时间,则退出.
		}  
	}; 									    
}
//延时nms
//nms:要延时的ms数
void delay_ms(u16 nms)
{	
	if(OSRunning==TRUE)//如果os已经在跑了	    
	{		  
		if(nms>=fac_ms)//延时的时间大于ucos的最少时间周期 
		{
   			OSTimeDly(nms/fac_ms);//ucos延时
		}
		nms%=fac_ms;				//ucos已经无法提供这么小的延时了,采用普通方式延时    
	}
	delay_us((u32)(nms*1000));	//普通方式延时,此时ucos无法启动调度.
}
#else//不用ucos时
//延时nus
//nus为要延时的us数.		    								   
void delay_us(u32 nus)
{		
	u32 temp;	    	 
	SysTick->LOAD=nus*fac_us; //时间加载	  		 
	SysTick->VAL=0x00;        //清空计数器
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;          //开始倒数	 
	do
	{
		temp=SysTick->CTRL;
	}
	while(temp&0x01&&!(temp&(1<<16)));//等待时间到达   
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;       //关闭计数器
	SysTick->VAL =0X00;       //清空计数器	 
}
//延时nms
//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms
//对72M条件下,nms<=1864 
void delay_ms(u16 nms)
{	 		  	  
	u32 temp;		   
	SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)
	SysTick->VAL =0x00;           //清空计数器
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;          //开始倒数  
	do
	{
		temp=SysTick->CTRL;
	}
	while(temp&0x01&&!(temp&(1<<16)));//等待时间到达   
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;       //关闭计数器
	SysTick->VAL =0X00;       //清空计数器	  	    
} 
#endif


#include "sys.h"
#include "usart.h"	
#include "led.h"

 

//
//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 

}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
_sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
    USART1->DR = (u8) ch;      
	return ch;
}
#endif 

/*使用microLib的方法*/
 /* 
int fputc(int ch, FILE *f)
{
	USART_SendData(USART1, (uint8_t) ch);

	while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {}	
   
    return ch;
}
int GetKey (void)  { 

    while (!(USART1->SR & USART_FLAG_RXNE));

    return ((int)(USART1->DR & 0x1FF));
}
*/
  
u8 uartFlag = 0;

//初始化IO 串口1 
//bound:波特率
void uart_init(u32 bound){
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
 	USART_DeInit(USART1);  //复位串口1
	 //USART1_TX   PA.9
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
    GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9
   
    //USART1_RX	  PA.10
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PA10

   //Usart1 NVIC 配置

    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
  
   //USART 初始化设置

	USART_InitStructure.USART_BaudRate = bound;//一般设置为9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式

    USART_Init(USART1, &USART_InitStructure); //初始化串口
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断
    USART_Cmd(USART1, ENABLE);                    //使能串口 

}


void USART1_IRQHandler(void)                	//串口1中断服务程序
	{
	u8 Res;
#ifdef OS_TICKS_PER_SEC	 	//如果时钟节拍数定义了,说明要使用ucosII了.
	OSIntEnter();    
#endif
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //
	{
		Res =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到数据
		Count++;
		if(Count>20)
		{
			Count=0;
		}
		BufTab[Count]=Res;	//存储串口数据
		UartBusy=0;
	} 
#ifdef OS_TICKS_PER_SEC	 	//如果时钟节拍数定义了,说明要使用ucosII了.
	OSIntExit();  											 
#endif
} 
































硬件设计

使用元器件:

单片机:STM32F103;

极性电容:10uF;

LED灯:高亮;电阻:10K;

ESP8266/WIFI模块:WIFI_ESP8266;

STM32核心板:STM32_CORE;

2.54单排座:3pin;

2.54单排座:4pin;

2.54单排座:20pin;

覆铜板或万用板;

普通USB线_大头;

添加图片注释,不超过 140 字(可选)

流程图:

添加图片注释,不超过 140 字(可选)

设计资料

01原理图

本系统原理图采用Altium Designer19设计,具体如图!

添加图片注释,不超过 140 字(可选)

02程序

本设计使用软件keil4和Keil5 MDK两个版本编程设计!具体如图!

添加图片注释,不超过 140 字(可选)

03设计报告

九千字设计报告,具体如下!

添加图片注释,不超过 140 字(可选)

04设计资料

全部资料包括程序(含注释)、AD原理图、任务书、开题报告、结构框图、设计报告、流程图、元件清单、实物图等。具体内容如下,全网最全! !

添加图片注释,不超过 140 字(可选)

点赞分享一起学习成长。


网站公告

今日签到

点亮在社区的每一天
去签到