蓝桥杯嵌入式-温湿度监控设备

#注意点总结
1,针对系统的代码,子函数按功能划分:实时数据刷新函数(接收电压值和接收方波信号),LCD页面显示函数(设置界面和实时数据显示界面),Key操作函数,E2写入和读取函数,LED报警函数,串口操作函数,数据储存函数;
2,注意,u16和u8的使用,u8的数据最大支持(256-1),u16最大支持(65536-1)
3,E2写入和读取时需注意:写入的为u8类型数据,若为其他类型,需强制转换,但要保证数据大小读取和写入前后不变,可以和放大或缩小数据一起使用。
4,解决LCD两个页面的冲突问题:当个高亮设置界面最后一行时,设置界面第一行会高亮,并且此时回到实时数据显示界面,也会高亮,应该分别在两页面的第一行写上代码字体颜色。
5,解决RTC计时会先出现24:00:00,后又出现00:00:00,造成重复,可以在RTC中断函数里设置

	if(time == 24 * 3600) 
		{
			RTC_SetCounter(1);//避免出现一次24:00:00后,又出现一次00:00:00
		}
//		if(time==23*3600+59*60+59)//这种写法可以出现00:00:00
//		{
//			RTC_SetCounter(0);
//		}

6,之前自己习惯使用滴答定时器来进行设标志位(没有功能划分思想,原意是按部件拆分思想,发现部件独立,无法串联),在主函数中读取标志位进行操作,出现的问题是造成程序堵塞,后改为定时器定时,程序稳定(也是有功能划分的功劳),滴答定时器只用于简单的1ms计时。
7,学习了LED的寄存器操作方法:简单,易懂
(1)在LED初始化中首先需要对灯全灭:

  GPIOC->ODR|=0XFF00;
  GPIOD->ODR|=(1<<2);
  GPIOD->ODR&=~(1<<2);

(2)设置LED变量

u32 LED_MODE=0XFFFF;

(3)闪烁,点亮,熄灭LED1

	LED_MODE^=(1<<8);//闪烁
	LED_MODE&=~(1<<8);//点亮
	LED_MODE|=(1<<8);//熄灭
	GPIOC->ODR=LED_MODE;
	GPIOD->ODR|=(1<<2);
	GPIOD->ODR&=~(1<<2);

8,关于PWM捕捉,使用的是系统自带的通道一和通道二捕捉(直连和非直连),优点是中断函数简单容易理解,缺点是只能捕捉一路。
<捕捉讲解>
9.按数据采样间隔采集数据:定时器中根据 采样间隔 设置 采集标志位 置一
#黏贴代码
##main.c

#include"stm32f10x.h"
#include"led.h"
#include"key.h"
#include"timer.h"
#include"adc.h"
#include"pwm.h"
#include"i2c.h"
#include"e2prom.h"
#include"lcd.h"
#include"stdio.h"
#include"rtc.h"
#include"capture.h"
#include"usart2.h"
//变量声明区//
u32 delaytime;
u32 LED_MODE=0XFFFF;
extern u8 flag200ms;
u8 string[20];

//界面显示//
u8 SetFlag=0;//界面切换
u8 ChooseFlag=1;//高亮切换

//实时显示//
float AdcVal;//接收电压值
float TH;//转化成的温度
float Fre=1.0;//信号发出频率
float RH;//转化成的湿度
extern u32 Frequence;
u32 time=0;
u8 HH=0;
u8 MM=0;
u8 SS=0;

//参数设置//
int TH_Limit=40;//温度上限,有正负
u8 RH_Limit=80;//湿度上限
u8 SampleTime=1;//采样间隔
                //测试信号:Fre
//缓冲区//
int TH_LimitBuf=40;
u8 RH_LimitBuf=80;
u8 SampleTimeBuf=1;
float FreBuf;

//串口//
u8 RxdCnt=0;
u8 RxdOver=0;
u8 RxdBuf[20];
float TH_Buf;//实时温度储存在数组里的变量
float RH_Buf;//实时湿度储存在数组里的变量
u32 HH_Buf;//小时储存在数组里的变量
u32 MM_Buf;//分钟储存在数组里的变量
u32 SS_Buf;//毫秒储存在数组里的变量


//采样相关变量
int Record[70][5];
u16 RecordCnt = 0;
extern u8 RecordFlag ;



//函数声明区//
void delay_ms(u32 times);
void KeyAction(int code);
void RefreshData(void);
void WriteE2Data(void);
void ReadE2Data(void);
void ShowReal(void);
void ShowSet(void);
void UsartAction(void);
void RecordAction(void);
void LED_Thr(void);
int main()
{
	SysTick_Config(SystemCoreClock/1000);
	STM3210B_LCD_Init();
	RTC_Init(23,59,55);
	USART2_Init();
	Capture_Init();
	LED_Init();
	Key_Init();
	ADC1_Init();
	i2c_init();
	TIM4_Init(2000,72);//2ms定时器

	LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(White);

	ReadE2Data();
	TH_Limit=TH_LimitBuf;
	RH_Limit=RH_LimitBuf;
	SampleTime=SampleTimeBuf;
	Fre=FreBuf;
	PWM_Init(Fre*1000,50);

	while(1)
	{
		KeyDriver();
		if(flag200ms==1)
		{
			RefreshData();
			if(SetFlag==1)
			{
				ShowSet();
			}
			else
			{
				ShowReal();
			}
			flag200ms=0;
			LED_Thr();//实时值与阈值比较,注意不要让设置值即时生效,和Buf比较
		}
		if(RxdOver)
		{
			UsartAction();
			RxdOver=0;
		}
		if(RecordFlag)
		{
			RecordAction();
			RecordFlag=0;
		}	
	}
}
void LED_Thr(void)
{
	if(TH>TH_LimitBuf)
	{
		LED_MODE^=(1<<8);
	}
	else
	{
		LED_MODE|=(1<<8);
	}
	if(RH>RH_LimitBuf)
	{
		LED_MODE^=(1<<9);
	}
	else
	{
		LED_MODE|=(1<<9);
	}

	GPIOC->ODR=LED_MODE;
	GPIOD->ODR|=(1<<2);
	GPIOD->ODR&=~(1<<2);
}
void RecordAction(void)
{
	Record[RecordCnt][0]=TH;//实时温度
    Record[RecordCnt][1]=RH;
	Record[RecordCnt][2]=HH;
	Record[RecordCnt][3]=MM;
	Record[RecordCnt][4]=SS;
	RecordCnt++;
	if(RecordCnt>60)					 
	{
		RecordCnt=0;
	}

	LED_MODE^=(1<<10);
	GPIOC->ODR=LED_MODE;
	GPIOD->ODR|=(1<<2);
	GPIOD->ODR&=~(1<<2);
}
void UsartAction(void)
{
	u8 i=0;
	u8 usart_str[50];
	if(RxdBuf[0]=='C')
	{
		HH_Buf=Record[RecordCnt-1][2];
		MM_Buf=Record[RecordCnt-1][3];
		SS_Buf=Record[RecordCnt-1][4];
		sprintf((char*)usart_str,"TH_Limit:%dC,RH_Limit:%d%%,TIME:%.2d:%.2d:%.2d\r\n",TH_Limit,RH_Limit,HH_Buf,MM_Buf,SS_Buf);
		USART2_SendString(usart_str);
	}
	else if(RxdBuf[0]=='T')
	{
		for(i=0;i<RecordCnt;i++)
		{
			TH_Buf=Record[i][0];
			RH_Buf=Record[i][1];
			HH_Buf=Record[i][2];
			MM_Buf=Record[i][3];
			SS_Buf=Record[i][4];
			sprintf((char*)usart_str,"TH:%.0fC RH:%.0f%% TIME:%.2d:%.2d:%.2d\r\n",TH_Buf,RH_Buf,HH_Buf,MM_Buf,SS_Buf);
			USART2_SendString(usart_str);
		}
	}
	//别忘了这两个
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//接收的数据处理完毕后打开接收中断
	for(i=0; i<20; i++)//清空缓冲区
		RxdBuf[i] = 0;
}
void ShowReal(void)
{
	LCD_SetTextColor(White);//注意这里加上是最后一行高亮,实时数据显示不高亮
	LCD_DisplayStringLine(Line1,(u8*)"     Real Data    ");//左5
	sprintf((char*)string,"  TH : %.0fC  ",TH);
	LCD_DisplayStringLine(Line3,string);
	sprintf((char*)string,"  RH : %.0f%%  ",RH);//注意百分号的书写方式
	LCD_DisplayStringLine(Line5,string);
	sprintf((char*)string,"  TIME : %.2d:%.2d:%.2d ",HH,MM,SS);
	LCD_DisplayStringLine(Line7,string);
	sprintf((char*)string,"  RecordCnt : %d  ",RecordCnt);
	LCD_DisplayStringLine(Line9,string);	
}
void ShowSet(void)
{
	LCD_SetTextColor(White);//注意这里加上是最后一行高亮,第一行不高亮
	LCD_DisplayStringLine(Line1,(u8*)"     Set Data    ");//左5
	if(ChooseFlag==1)
	{
		LCD_SetTextColor(Green);
	}
	else
	{
		LCD_SetTextColor(White);
	}
	sprintf((char*)string,"  TH_Limit : %dC  ",TH_Limit);
	LCD_DisplayStringLine(Line3,string);
	if(ChooseFlag==2)
	{
		LCD_SetTextColor(Green);
	}
	else
	{
		LCD_SetTextColor(White);
	}
	sprintf((char*)string,"  RH_Limit : %d%%  ",RH_Limit);
	LCD_DisplayStringLine(Line5,string);
	if(ChooseFlag==3)
	{
		LCD_SetTextColor(Green);
	}
	else
	{
		LCD_SetTextColor(White);
	}
	sprintf((char*)string,"  SampleTime : %ds ",SampleTime);
	LCD_DisplayStringLine(Line7,string);
	if(ChooseFlag==4)
	{
		LCD_SetTextColor(Green);
	}
	else
	{
		LCD_SetTextColor(White);
	}
	sprintf((char*)string,"  TestFre : %.1fKhz  ",Fre);
	LCD_DisplayStringLine(Line9,string);	
}

void WriteE2Data(void)
{
	if(TH_LimitBuf<0)
	{
		E2Write(0x00,1);
		delay_ms(5);
		E2Write(0x01,(u8)(-TH_LimitBuf));//注意E2中储存的是u8类型;
	}
	else
	{
		E2Write(0x00,0);
		delay_ms(5);
		E2Write(0x01,(u8)TH_LimitBuf);
	}
	delay_ms(5);
	E2Write(0x02,RH_LimitBuf);
	delay_ms(5);
	E2Write(0x03,SampleTimeBuf);
	delay_ms(5);
	E2Write(0x04,(u8)(FreBuf*10)); //注意转换数据类型的同时保持数值不变
	delay_ms(5);
		
}
void ReadE2Data(void)
{
//	u8 i;
//	i=E2Read(0x00);
//	delay_ms(5);
//	if(i==1)
//	{
//		TH_LimitBuf=-E2Read(0x01);
//		delay_ms(5);	
//	}
//	else
//	{
//		TH_LimitBuf=E2Read(0x01);
//		delay_ms(5);
//	}
	TH_LimitBuf = E2Read(0x01);
	delay_ms(5);
	if(E2Read(0x00))
	{
		delay_ms(5);
		TH_LimitBuf = -TH_LimitBuf;
	}
	RH_LimitBuf=E2Read(0x02);
	delay_ms(5);
    SampleTimeBuf=E2Read(0x03);
	delay_ms(5);
	FreBuf=(float)E2Read(0x04)/10;
	delay_ms(5);
		
}

void RefreshData(void)
{
	AdcVal=Get_ADC()*3.3/4096;
	TH=AdcVal*80/3.3-20;

	RH=(Frequence/1000*80+10)/9;//注意考虑百分数的整数部分
}
void delay_ms(u32 times)
{
	delaytime=times;
	while(delaytime!=0);
}
void KeyAction(int code)
{
	if(code==1)
	{
		if(SetFlag==1)
		{
			SetFlag=0;
		}
		else if(SetFlag==0)
		{
  			TH_LimitBuf=TH_Limit;
			RH_LimitBuf=RH_Limit;
			SampleTimeBuf=SampleTime;
			FreBuf=Fre;	
			PWM_Init(FreBuf*1000,50);
			WriteE2Data();
			SetFlag=1;
		}
		LCD_Clear(Blue);//清楚界面,防止有乱码产生
	}
	else if(code==2)
	{
		if(SetFlag==1)
		{
			ChooseFlag++;
			if(ChooseFlag>4)
			{
				ChooseFlag=1;
			}
		}	
	}
	else if(code==3)
	{
		if(SetFlag==1)
		{
			switch(ChooseFlag)
			{
				case 1: TH_Limit++;
						if(TH_Limit>60) TH_Limit=60;
						break;
				case 2:	RH_Limit+=5;
						if(RH_Limit>90) RH_Limit=90;
						break;
				case 3:	SampleTime++;
						if(SampleTime>5) SampleTime=5;
						break;
				case 4:	Fre+=0.5;
						if(Fre>10) Fre=10;
						break;
			}
		}
	}
	else if(code==4)
	{
		if(SetFlag==1)
		{
			switch(ChooseFlag)
			{
				case 1: TH_Limit--;
						if(TH_Limit<-20) TH_Limit=-20;
						break;
				case 2:	RH_Limit-=5;
						if(RH_Limit<10) RH_Limit=10;
						break;
				case 3:	SampleTime--;
						if(SampleTime<1) SampleTime=1;
						break;
				case 4:	Fre-=0.5;
						if(Fre<1) Fre=1;
						break;
			}
		}
	}
}
发布了7 篇原创文章 · 获赞 0 · 访问量 112

猜你喜欢

转载自blog.csdn.net/weixin_43636084/article/details/105058479