stm32/User/main.c

611 lines
17 KiB
C
Raw Permalink Normal View History

2021-10-25 14:03:59 +00:00
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "LED.h"
#include "lcd.h"
#include "image2lcd.h"
#include "dht11.h"
#include "zph01.h"
#include "time.h"
//! 屏蔽编译器对LCD显示中文字符串函数的警告
#pragma diag_suppress 870
u8 pm25_lcd[6]={0},hh06_lcd[6]={0},dht11_flag=0;
//! SWPU图标
extern const u8 gImage_swpu[];
//! 公交E图标
extern const u8 gImage_gongjiaoe[];
//! 定时器3标志,中断一次加一
extern u8 time3_flag,usart_time,time_hours,time_minutes,time_seconds;
//! 串口2数据缓存Buffer和标志,串口1噪音数据,串口2 pm2.5数据,串口3 GSM模块数据
extern u8 USART1_RX_BUF[7],USART2_RX_BUF[10],USART3_RX_BUF[75];
extern u16 USART1_RX_STA,USART2_RX_STA,USART3_RX_STA;
//! 温湿度
u8 temperature=0,humidity=0;
//! pm2.5,噪音数据的整数和小数
u8 pm25_zheng=0,pm25_xiao=0,hh06_zheng=0,hh06_xiao=0;
//! 图片显示标志
u8 Image_flag=0;
void lcd_display(void);
void data_pros(void);
void data_pm25(void);
void data_hh06(void);
//! 串口1和串口2使能,禁止函数
void disadle_uart(void);
void enadle_uart(void);
//********************************************************************//
//! 函数名:main
//! 功能:主函数
//! 输入:none
//! 输出:none
//********************************************************************//
int main(void)
{
//! flag_dht11为读取温湿度数据延时三个主周期而设置,主循环周期大于300ms
u8 CheckSum=0,j=0,flag_dht11=0;
//! GSM模块上传数据buffer
u8 send[36]={0};
//! 中断优先级配置,四个抢占优先级,四个副优先级
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//! LCD初始化
LCD_Init();
//! LED灯GPIO初始化
LED_GPIO_Config();
//! 延时1.5秒
delay_ms(1500);
//! 开启LCD显示
lcd_display();
//! 串口1初始化 噪音数据接口
uart1_init(115200);
//! 串口2初始化 pm2.5数据接口
uart2_init(9600);
//! 串口3初始化 GSM模块
uart3_init(115200);
//! 延时1秒
delay_ms(1000);
dht11_flag=1;
//! 初始化DHT11
if(DHT11_Init())
{
dht11_flag=1;
}
else
{
//! 100 纵坐标,10 横坐标
LCD_ShowString(100,10,80,24,24,"Error");
dht11_flag=0;
}
//! 定时器3初始化,定时1秒
time3_init(2000,35999);
delay_ms(500);
//! 关闭串口1,2
disadle_uart();
//! 主循环
while(1)
{
//! DHT11读取计数
flag_dht11++;
//! 点亮LED2
LED2_ON;
//! 点亮LED1
LED1_ON;
//! 温度采集周期大概900ms
if(flag_dht11==3)
{
//! 清标志
flag_dht11=0;
//! DHT11数据读取过程大于100ms
data_pros();
}
//! 只允许在这300ms开启串口,读取传感器数据
enadle_uart();
delay_ms(150);
LED1_OFF;
delay_ms(150);
disadle_uart();
//! 噪音数据读取成功标志
if(USART1_RX_STA)
{
USART1_RX_STA=0;
data_hh06();
}
if(usart_time==15)
{
usart_time=0;
Image_flag=~Image_flag;
//! 延时5ms是为了解决显示器死掉的问题,大概原因是刷新LCD的频率太高,
//! 根本原因与中断中更新屏幕内容有关,如果在主函数中正在更新屏幕,但是中断又更新,可能出现错误
delay_ms(5);
//! 在坐标(0,160)到坐标(319,239)区域填充白色
LCD_Fill(0,167,319,239,WHITE);
//! 图标刷新标志有效,并且定时器没进定时器中断
if(Image_flag && (TIM_GetITStatus(TIM3,TIM_IT_Update)!=SET))
{
delay_ms(5);
//! 显示SWPU图标
image_display(45,167,(u8*) gImage_swpu);
}
if((Image_flag==0)&&(TIM_GetITStatus(TIM3,TIM_IT_Update)!=SET))
{
//! 显示公交E图标
delay_ms(5);
image_display(45,167,(u8*) gImage_gongjiaoe);
}
delay_ms(50);
//! 实际请求网址ַ:http://xkmg9m2k.qcloud.la/weapp/usrcloud?a=255&b=1&c=18&d=15&e=1&f=12&g=50&h=3&i=0
//! 域名已在GSM模块中配置,这里仅需配置参数
if(dht11_flag==1) //get请求参数:a=255&b=1&c=18&d=15&e=1&f=12&g=50&h=3&i=0
{
send[0]='a';
send[1]='=';
send[2]=0xFF;
send[3]='&';
send[4]='b';
send[5]='=';
//! 需加48转换成对应的ASCII码,否则服务器无法读出数据
send[6]=1+48;
send[7]='&';
send[8]='c';
send[9]='=';
send[10]=temperature+48;
send[11]='&';
send[12]='d';
send[13]='=';
send[14]=humidity+48;
send[15]='&';
send[16]='e';
send[17]='=';
send[18]=pm25_zheng+48;
send[19]='&';
send[20]='f';
send[21]='=';
send[22]=pm25_xiao+48;
send[23]='&';
send[24]='g';
send[25]='=';
send[26]=hh06_zheng+48;
send[27]='&';
send[28]='h';
send[29]='=';
send[30]=hh06_xiao+48;
send[31]='&';
send[32]='i';
send[33]='=';
send[34]=0+48;
send[35]='\0';
//! 向服务器发送请求
USART_SendString(USART3,send);
}
else
{
send[0]='a';
send[1]='=';
send[2]=0xfe;
send[35]='\0';
//! 向服务器发送错误标志
USART_SendString(USART3,send);
}
enadle_uart();
}
//! 串口收到pm2.5数据
if(USART2_RX_STA)
{
USART2_RX_STA=0;
CheckSum=FucCheckSum(USART2_RX_BUF,9);
if(CheckSum==USART2_RX_BUF[8])
{
data_pm25();
}
}
//! GMS串口模块,数据为服务器返回的字符串:
//! {"a":0,"b":0,"c":0,"d":0,"e":0,"f":2,"g":12,"h":21,"i":22,"j":2}
//! a为系统状态;b为公交车状态;c为到达时间;d为车到站牌距离的整数;e为距离的小数;f为服务器时间星期几;
//! g为服务器时间日期;hij分别为服务器时间时分秒
//! 串口收到一帧服务器的回复标志,站牌每15秒向服务器发送一次请求,请求发送后需要十二三秒才能收到回复(2G网络)
//! 返回数据为字符串,长度小于75字节但是不固定
if(USART3_RX_STA)
{
u8 m=0;
u8 bus_flag=48,system_flag=48,arrivaltime=0,distance_h=0,distance_l=0,day=0,date=0,hours=0,minutes=0,seconds=0;
LED2_OFF;
USART3_RX_STA=0;
for(m=0;m<75;m++)
{
//! 系统状态
if(USART3_RX_BUF[m]=='a')
{
bus_flag=USART3_RX_BUF[m+3];
if(bus_flag-48==1)
{
GUI_Chinese_Text(188,78,"运行中",6,0x0000,0xffff);
}
else
GUI_Chinese_Text(188,78,"待发车",6,0x0000,0xffff);
}
//! 公交车状态
if(USART3_RX_BUF[m]=='b')
{
system_flag=USART3_RX_BUF[m+3];
if(system_flag-48==1)
{
LCD_Fill(114,30,122,46,WHITE);
LCD_ShowString(90,30,24,16,16,"OK!");
}
else
LCD_ShowString(90,30,32,16,16,"OFF!");
}
//! 公交车到达站台时间,单位:分钟
if(USART3_RX_BUF[m]=='c')
{
//! 区分到达时间分钟数为一位还是两位,需做不同处理
//! 分钟数为一位
if(USART3_RX_BUF[m+4]==',')
{
arrivaltime=USART3_RX_BUF[m+3]-48;
LCD_Fill(133,78,141,94,WHITE);
LCD_ShowxNum(141,78,arrivaltime,1,16,0);
//! 分钟数为两位
}
else
{
arrivaltime=(USART3_RX_BUF[m+3]-48)*10+USART3_RX_BUF[m+4]-48;
LCD_ShowxNum(133,78,arrivaltime,2,16,0);
}
}
//! 公交车到站台的距离整数,单位:米
if(USART3_RX_BUF[m]=='d')
{
if(USART3_RX_BUF[m+4]==',')
{
distance_h=USART3_RX_BUF[m+3]-48;
LCD_Fill(61,78,69,94,WHITE);
//! LCD显示区域,按像素点计算,下同
//! 69=57+4+8
LCD_ShowxNum(69,78,distance_h,1,16,0);
}else{
distance_h=(USART3_RX_BUF[m+3]-48)*10+USART3_RX_BUF[m+4]-48;
//! 61=57+4
LCD_ShowxNum(61,78,distance_h,2,16,0);
}
}
//! 公交车到站台的距离小数,单位:米
if(USART3_RX_BUF[m]=='e')
{
if(USART3_RX_BUF[m+4]==',')
{
distance_l=USART3_RX_BUF[m+3]-48;
LCD_Fill(85,78,93,94,WHITE);
//! 77=61+16
LCD_ShowxNum(77,78,distance_l,1,16,0);
}
else
{
distance_l=(USART3_RX_BUF[m+3]-48)*10+USART3_RX_BUF[m+4]-48;
//! 77=61+16
LCD_ShowxNum(77,78,distance_l,2,16,0);
}
}
//! 当前服务器时间星期几
if(USART3_RX_BUF[m]=='f')
{
day=USART3_RX_BUF[m+3]-48;
switch(day)
{
case 1:
//! 162+2*8+3=181
GUI_Chinese_Text(181,10,"星期一",6,0x0000,0xffff);
break;
case 2:
//! 162+2*8+3=181
GUI_Chinese_Text(181,10,"星期二",6,0x0000,0xffff);
break;
case 3:
//! 162+2*8+3=181
GUI_Chinese_Text(181,10,"星期三",6,0x0000,0xffff);
break;
case 4:
//! 162+2*8+3=181
GUI_Chinese_Text(181,10,"星期四",6,0x0000,0xffff);
break;
case 5:
//! 162+2*8+3=181
GUI_Chinese_Text(181,10,"星期五",6,0x0000,0xffff);
break;
case 6:
//! 162+2*8+3=181
GUI_Chinese_Text(181,10,"星期六",6,0x0000,0xffff);
break;
case 7:
//! 162+2*8+3=181
GUI_Chinese_Text(181,10,"星期日",6,0x0000,0xffff);
break;
default:
break;
}
}
//! 当前服务器时间日期
if(USART3_RX_BUF[m]=='g')
{
if(USART3_RX_BUF[m+4]==',')
{
date=USART3_RX_BUF[m+3]-48;
LCD_Fill(82,10,90,26,WHITE);
//! 90=82+8
LCD_ShowxNum(90,10,date,1,16,0);
}
else
{
date=(USART3_RX_BUF[m+3]-48)*10+USART3_RX_BUF[m+4]-48;
//! 66+16=82
LCD_ShowxNum(82,10,date,2,16,0);
}
}
//! 服务器当前时间:时
if(USART3_RX_BUF[m]=='h')
{
if(USART3_RX_BUF[m+4]==',')
{
hours=USART3_RX_BUF[m+3]-48;
time_hours=hours;
//! 98+16=114
LCD_ShowxNum(114,10,0,1,16,0);
//! 98+16+8=122
LCD_ShowxNum(122,10,hours,1,16,0);
}
else
{
hours=(USART3_RX_BUF[m+3]-48)*10+USART3_RX_BUF[m+4]-48;
time_hours=hours;
//! 98+16=114
LCD_ShowxNum(114,10,hours,2,16,0);
}
}
//! 服务器时间:分
if(USART3_RX_BUF[m]=='i')
{
if(USART3_RX_BUF[m+4]==',')
{
minutes=USART3_RX_BUF[m+3]-48;
time_minutes=minutes;
//! 130+8=138
LCD_ShowxNum(138,10,0,1,16,0);
//! 130+8+8=146
LCD_ShowxNum(146,10,minutes,1,16,0);
}
else
{
minutes=(USART3_RX_BUF[m+3]-48)*10+USART3_RX_BUF[m+4]-48;
time_minutes=minutes;
//! 130+8=138
LCD_ShowxNum(138,10,minutes,2,16,0);
}
}
//! 服务器时间:秒
if(USART3_RX_BUF[m]=='j')
{
//! 通过判断数据结束大括弧位置确定
if(USART3_RX_BUF[m+4]=='}')
{
seconds=USART3_RX_BUF[m+3]-48;
time_seconds=seconds;
//! 154+8=162
LCD_ShowxNum(162,10,0,1,16,0);
//! 154+8+8=170
LCD_ShowxNum(170,10,seconds,1,16,0);
}
else
{
seconds=(USART3_RX_BUF[m+3]-48)*10+USART3_RX_BUF[m+4]-48;
time_seconds=seconds;
//! 154+8=162
LCD_ShowxNum(162,10,seconds,2,16,0);
}
}
}
//! 清空数据buffer
for(j=0;j<=75;j++)
{
USART3_RX_BUF[j]=0;
}
}
}
}
//********************************************************************//
//! 函数名:lcd_display
//! 功能:LCD固定内容显示,初始化完成调用一次
//! 输入:none
//! 输出:none
//********************************************************************//
void lcd_display(void)
{
//! 清屏
LCD_Clear(WHITE);
//! 显示默认时间,数据依次含义:开始显示点横纵坐标;要显示的数;数的位数;区域大小;叠加方式
LCD_ShowxNum(10,10,2018,4,16,1);
//! 4*8+10=42
GUI_Chinese_Text(42,10,"",2,0x0000,0xffff);
//! 42+16=58
LCD_ShowxNum(58,10,6,1,16,1);
//! 58+8=66
GUI_Chinese_Text(66,10,"",2,0x0000,0xffff);
//! 66+16=82
LCD_ShowxNum(82,10,7,2,16,1);
//! 82+8*2=98
GUI_Chinese_Text(98,10,"",2,0x0000,0xffff);
//! 98+16=114
LCD_ShowxNum(114,10,13,2,16,1);
//! 114+2*8=130
LCD_ShowString(130,9,8,16,16,":");
//! 130+8=138
LCD_ShowxNum(138,10,47,2,16,1);
//! 138+2*8=154
LCD_ShowString(154,9,8,16,16,":");
//! 154+8=162
LCD_ShowxNum(162,10,50,2,16,1);
//! 162+2*8+3=181
GUI_Chinese_Text(181,10,"星期四",6,0x0000,0xffff);
//! 行间距4像素,第二行30=16+10+4
GUI_Chinese_Text(10,30,"系统状态",10,0x0000,0xffff);
//! 10+5*16=90
LCD_ShowString(90,30,32,16,16,"OFF!");
//! 画表格
//! (0,50)-->(239,50) 50=30+16+4
LCD_DrawLine(0,50,239,50);
//! (0,74)-->(239,74)
LCD_DrawLine(0,74,239,74);
//! (0,98)-->(239,98)
LCD_DrawLine(0,98,239,98);
//! (0,122)-->(239,122)
LCD_DrawLine(0,122,239,122);
//! (57,50)-->(57,122)
LCD_DrawLine(57,50,57,122);
//! (114,50)-->(114,122)
LCD_DrawLine(114,50,114,122);
//! (184,50)-->(184,122)
LCD_DrawLine(184,50,184,122);
//! 填充表格内容
GUI_Chinese_Text(12,54,"线路",4,0x0000,0xffff);
GUI_Chinese_Text(70,54,"距离",4,0x0000,0xffff);
GUI_Chinese_Text(133,54,"时间",4,0x0000,0xffff);
GUI_Chinese_Text(196,54,"状态",4,0x0000,0xffff);
LCD_ShowString(12,78,16,16,16,"XX");
GUI_Chinese_Text(28,78,"",2,0x0000,0xffff);
//! 93=89+4
GUI_Chinese_Text(93,78,"",2,0x0000,0xffff);
GUI_Chinese_Text(117,78,"",2,0x0000,0xffff);
GUI_Chinese_Text(149,78,"分钟",4,0x0000,0xffff);
GUI_Chinese_Text(188,78,"待发车",6,0x0000,0xffff);
//! 0~3共四像素
GUI_Chinese_Text(3,126,"气温",6,0x0000,0xffff);
//! 67=3+16*3+8*2
GUI_Chinese_Text(67,126,"",2,0x0000,0xffff);
//! 87=67+16+4
GUI_Chinese_Text(87,126,"颗粒物",8,0x0000,0xffff);
//! 199=87+4*16+6*8
LCD_ShowString(199,126,40,16,16,"ug/m3");
//! 146=126+16+4
GUI_Chinese_Text(3,146,"湿度",6,0x0000,0xffff);
//! 67=51+16
LCD_ShowString(67,146,24,16,16,"%rh");
//! 103=87+3*16-2*16
GUI_Chinese_Text(103,146,"噪音",6,0x0000,0xffff);
LCD_ShowString(191,146,16,16,16,"dB");
}
//********************************************************************//
//! 函数名:data_pros
//! 功能:温湿度数据处理
//! 输入:none
//! 输出:none
//********************************************************************//
void data_pros(void)
{
u8 temp;
u8 humi;
u8 temp_buf[3],humi_buf[3];
//! 关闭定时器,避免打断数据处理过程
TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);
//! 温湿度数据读取核心函数,模拟dht11的通信时序,要求us级精确延时
DHT11_Read_Data(&temp,&humi);
//! 打开定时器
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
temp_buf[0]=temp/10+0x30;
temp_buf[1]=temp%10+0x30;
temp_buf[2]='\0';
delay_ms(5);
//! 51=3+16*3
LCD_ShowString(51,126,16,16,16,temp_buf);
humi_buf[0]=humi/10+0x30;
humi_buf[1]=humi%10+0x30;
humi_buf[2]='\0';
delay_ms(5);
//! 51=3+6*8
LCD_ShowString(51,146,16,16,16,humi_buf);
temperature = temp;
humidity = humi;
}
//********************************************************************//
//! 函数名:data_pm25
//! 功能:pm2.5数据处理
//! 输入:none
//! 输出:none
//********************************************************************//
void data_pm25(void)
{
u8 z=0,x=0;
u32 density=0;
//! 整数部分
z=USART2_RX_BUF[3];
//! 小数部分
x=USART2_RX_BUF[4];
density=z*20*100 + x*20;
pm25_zheng=z;
pm25_xiao=x;
pm25_lcd[0]=(u8)(density/1000)+0x30;
pm25_lcd[1]=(u8)(density%1000/100)+0x30;
pm25_lcd[2]='.';
pm25_lcd[3]=(u8)(density%100/10)+0x30;
pm25_lcd[4]=(u8)(density%10)+0x30;
pm25_lcd[5]='\0';
delay_ms(5);
LCD_ShowString(151,126,40,16,16,pm25_lcd);
}
//********************************************************************//
//! 函数名:data_hh06
//! 功能:噪音数据处理
//! 输入:none
//! 输出:none
//********************************************************************//
void data_hh06(void)
{
u8 h,l;
u16 date=0;
h=USART1_RX_BUF[4];
l=USART1_RX_BUF[3];
date=((u16)(h)<<8)|(u16)(l);
hh06_zheng=(u8)(date/1000)*100+(u8)((date%1000)/100)*10+(u8)((date%100)/10);
hh06_xiao=(u8)(date%10);
hh06_lcd[0]=(u8)(date/1000)+0x30;
hh06_lcd[1]=(u8)((date%1000)/100)+0x30;
hh06_lcd[2]=(u8)((date%100)/10)+0x30;
hh06_lcd[3]='.';
hh06_lcd[4]=(u8)(date%10)+0x30;
hh06_lcd[5]='\0';
delay_ms(3);
LCD_ShowString(151,146,40,16,16,hh06_lcd);
delay_ms(3);
}
//********************************************************************//
//! 函数名:disadle_uart
//! 功能:关闭串口1,2
//! 输入:none
//! 输出:none
//********************************************************************//
void disadle_uart(void)
{
USART_Cmd(USART1,DISABLE);
USART_Cmd(USART2,DISABLE);
}
//********************************************************************//
//! 函数名:enadle_uart
//! 功能:开启串口1,2
//! 输入:none
//! 输出:none
//********************************************************************//
void enadle_uart(void)
{
USART_Cmd(USART1,ENABLE);
USART_Cmd(USART2,ENABLE);
}