基于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 字(可选)
点赞分享一起学习成长。