蓝桥杯嵌入式开发经验分享(第八届模拟题——“温湿度监控设备”)

作者:马一飞                                                         QQ:791729359       

在学习过程中有什么问题可以联系

 

 

一、题目

                                            “温湿度监控设备”设计任务书

1、功能简述

        “温湿度监控设备”通过采集传感器输出电压信号和信号频率得到环境温湿度数据, 并能够根据设定的温湿度阈值执行相应动作,系统框图如图 1 所示:
                                          蓝桥杯嵌入式开发经验分享(第八届模拟题——“温湿度监控设备”)_第1张图片

                                                                                                    图1  系统框图

2、设计任务及要求

(1). 温度测量功能
        通过竞赛板上电位器 R37 输出电压模拟温度传感器输出信号, 温度测量范围为-20℃~60℃, 电压温度关系为如下式所示:
         T = k*VR37 + b, 其中 T 代表环境温度, VR37为电位器输出信号, k、 b 为常数, 0V时对应温度为-20℃, 3.3V 对应 60℃。

(2).湿度测量功能

        通过竞赛板 PA7 引脚检测输入信号频率相对湿度测量范围为 10%~90%, 频率湿度关系如下式所示:
                       H = m*F + n, 其中 H 代表环境湿度, F 为传感器输入到设备信号频率, m、 n 为常数, 1KHz 对应相对湿度为 10%, 10KHz 对应 90%。

(3).测试信号

        通过竞赛板 PA1 引脚输出频率 1KHz 到 10KHz 方波, 模拟湿度传感器输出信号。

(4).参数设置与数据记录功能

        可以通过按键设定温、 湿度上限数据采样间隔温湿度数据记录间隔可设置为 1 - 5秒, 要求至少保存 60 组数据, 数据不需要写入 FLASH 或 E2PROM 存储器。

(5).RTC功能

        通过单片机片内 RTC 设计实现实时时钟功能。

(6).按键功能定义

        设备上电后, 通过 LCD 显示实时温、 湿度数据和数据记录次数, 显示格式如图 2 所示:

                                                                          蓝桥杯嵌入式开发经验分享(第八届模拟题——“温湿度监控设备”)_第2张图片

                                                                          图 2. LCD 显示界面参考图(实时数据显示)

        B1 按键:“功能” 按键, 按下后进入功能设定界面(如图 3 所示), 再次按下 B1 按键时退出设置界面, 保存用户设定的结        果到 E2PROM, 并返回图 2 所示的实时数据显示界面。
                                                                          蓝桥杯嵌入式开发经验分享(第八届模拟题——“温湿度监控设备”)_第3张图片

                                                                          图 3. LCD 显示界面参考图(阈值设置界面

        B2 按键:“切换” 按键, 切换选择 4 个待修改的运行参数, 被选中的参数突出显示(如图 2“湿度上限”)。

        B3 按键:“” 按键, 当前选择的参数是温度时, 参数加 1℃; 选择采样间隔时, 参数加 1 秒; 选择参数为湿度时, 参数         加 5%; 选择测试信号时, 测试信号频率加 500Hz
        B4 按键:“” 按键, 当前选择的参数是温度时, 参数减 1℃; 选择采样间隔时, 参数减 1 秒, 选择参数为湿度时, 参数减 5%; 选择测试信号时, 测试信号频率减 500Hz

        备注:“加”、 减按键应根据当前调整的参数属性, 设计合理的边界值

(7).串口功能

        设备通过串口完成阈值和数据查询功能, 使用 STM32 USART2 完成上述串口功能, 波特率设置为 9600。
        ①.  阈值查询

                通过 PC 机给设备发送字符‘C’, 设备返回包含当前温湿度阈值当前时间的字符串, 格式可自定义。

        ②. 数据查询

                通过 PC 机给设备发送字符‘T’, 设备返回包含当前采集到的所有温、 湿度数据的字符串, 每条温、 湿度数据应包含该                 条数据的记录时间, 格式可自定义。

(8).报警指示功能

         当前温度值超过温度上限时, 指示灯 L1 闪烁报警;

         当前温度值超过湿度上限时, 指示灯 L2 闪烁报警;

         每次数据采集时, 指示灯 L3 亮、 灭的状态反转

 

二、模块化分析及代码实现

由于驱动上每次编写的代码都是一样的,就不重复讲解了,我们主要是讲解各部分的逻辑

1、初始化部分

iic进行初始化;同时要读取保存在eeprom的湿度比较值、温度比较值、记录间隔、测试方波的频率;初始化PWM输出;PWM捕获;RTC时钟初始化并设置初始时间;串口初始化并设置波特率为9600;LED初始化;按键初始化

注:在进行EEPROM读取时,中间最好做一小段延时操作,确保iic通信读取出来的数值正确。

SysTick_Config(SystemCoreClock/1000);
i2c_init();
TH_compare = _24c02_Read(0x11);
Delay_Ms(5);
RH_cpmpare = _24c02_Read(0x22); 
Delay_Ms(5);
Remember_Delay = _24c02_Read(0x33); 
Delay_Ms(5);
Ceshi_Fre = _24c02_Read(0x44) * 100; 
Delay_Ms(5);
ADC1_Init();
TIM2_Ch2_PWM_Init(Ceshi_Fre,1);
TIM3_Ch2_CAPTURE_Init();
RTC_Init(23,59,55);
USART2_Init(9600);
LED_Init();
KEY_Init();

2、数据采集部分

当定时器定时到我们设定的记录时间时,就对数据进行采集,并且L3进行反转

////////////////  Remember  /////////////////
if(Remember_Flag)
{
	LED_MODE ^= (1<<10);
	TH_Remember[Remember_sum] = Temperature;
	RH_Remember[Remember_sum] = RH;
	Remember_sum++;
	if(Remember_sum >= 60) Remember_sum = 0;
	Remember_number++;
	Remember_Flag = 0;
}

3、ADC获取部分

我们设定,每到一定的定时时间,就采集一次电位器的AD值,同时计算程电压,通过公式换算成温度值

//////////////// ADC ////////////////////////
if(ADC_Flag)
{
	ADC_Val = Get_Adc() * 3.3 / 4096;
	Temperature = (80 * ADC_Val / 3.3) - 20;
	ADC_Flag = 0;
}

4、RTC部分

每过一秒,我们都计算获取一次RTC的值并计算出当前的时间并显示

//////////////   RTC   ////////////////////
if(RTC_Flag)
{
	TimeVal = RTC_GetCounter();   //获取RTC寄存器值
	hour = TimeVal / 3600;     //时
	min  = TimeVal % 3600 / 60;//分
	sec  = TimeVal % 3600 % 60;//秒
	RTC_Flag = 0;// RTC标志位清空
}

5、捕获部分

成功的捕获到一次方波信号时,我们应该使用捕获到的方波周期,使用公式去计算湿度值,同时重新使能下一次的捕获

/////////////   CAPTURE   ////////////////
if(TIM3_Ch2_CAPTURE_MODE == 2)
{
	RH = 1000000 / TIM_Ch2_CAPTURE_HL; 
	RH = 80 * (RH / 1000 - 1) / 9 + 10;//计算湿度值
	TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE);//使能捕获
	TIM3_Ch2_CAPTURE_MODE = 0; //标志位清0,准备重新捕获
}

6、串口通信部分

按照题目的要求,我们需要开启串口的接收和发送,同时还要对接收的数据进行处理判断接收到的信息,并且根据题目向串口返回所需要的数据。在发送完成后吧发送缓冲区清空,同时使能串口一遍下一次的接收。

/////////////  USART2  ////////////////////
if(RXOVER)
{
	for(i=0;i<20;i++)//清空接收缓冲区
	{
		string[i] = 0;
	}
	if(RX_BUF[0] == 'C') //判断接收字符
	{
		sprintf((char*)string,"TH_C:%dC Time:%.2d:%.2d:%.2d\r\n",TH_compare,hour,min,sec);
	}
	if(RX_BUF[0] == 'T') //判断接收字符
	{
		sprintf((char*)string,"TH:%dC-RH:%d%%\r\n",Temperature,RH);
	}
	USART2_SendString(string); //发送数据
	for(i=0;i<20;i++)  //清空接收缓冲区
	{
		RX_BUF[i] = 0;
	}
	USART_ITConfig( USART2, USART_IT_RXNE,ENABLE);//使能接收中断
	RXOVER = 0;//接收标志位清空
}

7、按键处理部分

每间隔50ms都读取一次按键,如果有按键按下,就执行按键操作,每一个按键的功能都需要根据题目的要求去设定。同时还有一点是需要注意的,key2、key3、key4在界面一的时候是无法进行操作的,这点在程序上是需要注意的一件事情。

////////////   KEY   //////////////////
if(KEY_Flag)
{
	KEY_Read();//按键操作
	KEY_Flag = 0;//按键标志位清0
}
void KEY_Read(void)
{
	static u16 key1_sum,key2_sum,key3_sum,key4_sum;
	//KEY1
	if(KEY1 == 0)
	{
		key1_sum++;
		if(key1_sum == 1)
	    {
		    Set_Flag ^= 1;
		    if(!Set_Flag)
	        {
		    	_24c02_Write(0x11,TH_compare);
		    	Delay_Ms(4);
		    	_24c02_Write(0x22,RH_cpmpare);
		    	Delay_Ms(4);
		    	_24c02_Write(0x33,Remember_Delay);
		    	Delay_Ms(4);
		    	_24c02_Write(0x44,Ceshi_Fre / 100);
		    	Delay_Ms(4);
		    }
	        LCD_ClearLine(Line0);
	        LCD_ClearLine(Line1);
		    LCD_ClearLine(Line2);
		    LCD_ClearLine(Line3);
	        LCD_ClearLine(Line4);
	    	LCD_ClearLine(Line5);
		    LCD_ClearLine(Line6);
	    	LCD_ClearLine(Line7);
		    LCD_ClearLine(Line8);
		    LCD_ClearLine(Line9);
	    }
    }else
	{
		key1_sum  = 0;
	}
	//KEY2
	if((KEY2 == 0) && Set_Flag)
	{
		key2_sum++;
		if(key2_sum == 1)
		{
			Select_Flag++;
			if(Select_Flag > 4) Select_Flag = 1;
		}
	}else
	{
		key2_sum  = 0;
	}
	//KEY3
	if((KEY3 == 0) && Set_Flag)
	{
		key3_sum++;
		if(key3_sum == 1)
		{
			switch(Select_Flag)
			{
				case 1: TH_compare++;
						if(TH_compare > 60) TH_compare = 60;
						break;
				case 2: RH_cpmpare += 5;
						if(RH_cpmpare > 90) RH_cpmpare = 90;
						break;
				case 3: Remember_Delay++;
						if(Remember_Delay > 5) Remember_Delay = 5;
						break;
				case 4: Ceshi_Fre += 500;
						if(Ceshi_Fre > 10000) Ceshi_Fre = 10000;
						TIM2_Ch2_PWM_Init(Ceshi_Fre,0);
						break;
			}
		}
	}else
	{
		key3_sum  = 0;
	}
	//KEY4
	if((KEY4 == 0) && Set_Flag)
	{
		key4_sum++;
		if(key4_sum == 1)
		{
			switch(Select_Flag)
			{
				case 1: TH_compare--;
				        if(TH_compare < -20) TH_compare = -20;
				        break;
				case 2: RH_cpmpare -= 5;
						if(RH_cpmpare < 10) RH_cpmpare = 10;
						break;
				case 3: Remember_Delay--;
						if(Remember_Delay < 1) Remember_Delay = 1;
						break;
				case 4: Ceshi_Fre -= 500;
						if(Ceshi_Fre < 1000) Ceshi_Fre = 1000;
						TIM2_Ch2_PWM_Init(Ceshi_Fre,0);
						break;
			}
		}
	}else
	{
	    key4_sum  = 0;
	}
}

8、LED显示部分

依据题目的要求,温度值超过湿度上限,L1会进行报警;当湿度值超过湿度上限,L2会进行报警;

////////////   LED   //////////////////
if(LED_Flag)
{
	if(Temperature > TH_compare)//温度值超过温度上限
	{
		LED_MODE ^= (1<<8);
	}else
	{
		LED_MODE |= (1<<8);
	}
	if(RH > RH_cpmpare) //湿度值超过湿度上限
	{
		LED_MODE ^= (1<<9);
	}else
	{
		LED_MODE |= (1<<9);
	}
	GPIOC-> ODR = LED_MODE; //LED显示
	GPIOD-> ODR |= (1<<2);  //LED显示
	GPIOD-> ODR &=~(1<<2);  //LED显示
	LED_Flag = 0;//LED显示标志位清0
}

9、LED显示部分

LCD显示部分,在这一部分我们要做好界面的判断,通过Set_Flag标志位来判断当前在主界面还是在设置界面,在主界面时主要是显示信息显示当前的温湿度,以及时间信息,与储存信息。 当然,温度的显示还要注意正负的判断,在显示时要做相应的处理。

在设置模式时要注意的是做好显示颜色的切换,当前设置的是什么参数,那么哪一行就要显示绿色,在LCD驱动里有文字颜色变化的函数,我们直接调用选择不同的颜色即可。

///////////   Display   ////////////////
if(Display_Flag)
{
	if(!Set_Flag)
	{
		LCD_SetTextColor(White);
		LCD_DisplayStringLine(Line1, (u8*)"     Real Data     ");
		if(Temperature >= 0)
		{
			sprintf((char*)string," TH : %dC           ",Temperature);
		}else
		{
			sprintf((char*)string," TH :-%dC           ",-Temperature);
		}
		LCD_DisplayStringLine(Line3, string);
		sprintf((char*)string," RH : %d%%           ",RH);
		LCD_DisplayStringLine(Line5, string);
		sprintf((char*)string," Time : %.2d:%.2d:%.2d  ",hour,min,sec);
		LCD_DisplayStringLine(Line7, string);
		sprintf((char*)string,"       Remember:%d   ",Remember_number);
		LCD_DisplayStringLine(Line9, string);
	}else
	{
		LCD_SetTextColor(White);
		LCD_DisplayStringLine(Line1, (u8*)"      Set          ");
		if(Select_Flag == 1)
		{
			LCD_SetTextColor(Green);
		}else
		{
			LCD_SetTextColor(White);
		}
		if(TH_compare >= 0)
		{
			sprintf((char*)string," TH_compare: %dC        ",TH_compare);
		}else
		{
			sprintf((char*)string," TH_compare:-%dC           ",-TH_compare);
		}
		LCD_DisplayStringLine(Line3, string);
		if(Select_Flag == 2)
		{
			LCD_SetTextColor(Green);
		}else
		{
			LCD_SetTextColor(White);
		}
		sprintf((char*)string," RH_compare: %d%%           ",RH_cpmpare);
		LCD_DisplayStringLine(Line5, string);
		if(Select_Flag == 3)
		{
			LCD_SetTextColor(Green);
		}else
		{
			LCD_SetTextColor(White);
		}
		sprintf((char*)string," Remember: %dS         ",Remember_Delay);
		LCD_DisplayStringLine(Line7, string);
		if(Select_Flag == 4)
		{
			LCD_SetTextColor(Green);
		}else
		{
			LCD_SetTextColor(White);
		}
		sprintf((char*)string," PWM_Fre: %.1fkHZ            ",(double)Ceshi_Fre / 1000);
		LCD_DisplayStringLine(Line9, string);
	}	
	Display_Flag = 0;
}

10、滴答定时器定时部分以及中断部分

中断的话基本上就是每次都差不多的了,而滴答定时器定时部分对于每个模块的定时时间根据自己的喜好来进行调节,最重要的一点是出来的结果要看起来相对比较流畅,定时时间过短,会导致cpu资源占用过多;定时时间过短,会导致出来的结果看起来会反应迟钝的感觉。

extern u8 ADC_Flag;
extern u8 RTC_Flag;
u8 TIM3_Ch2_CAPTURE_MODE = 0;
u32 TIM_Ch2_CAPTURE_HL = 0;
u8 RXCUNT = 0;
u8 RXOVER = 0;
u8 RX_BUF[20];
extern u8 LED_Flag;
extern u8 KEY_Flag;
extern u8 Display_Flag;
extern u8 Remember_Flag;
extern u8 Remember_Delay;
void SysTick_Handler(void)
{
	static u8 key_sum = 0;
	static u8 adc_sum = 0;
	static u8 display_sum = 0;
	static u16 remember_sum;
	static u8 led_sum = 0;
	TimingDelay--;
	remember_sum++;
	if(++led_sum == 200)
	{
		led_sum = 0;
		LED_Flag = 1;
	}
	if(++adc_sum == 150)
	{
		adc_sum = 0;
		ADC_Flag = 1;
	}
	if(++key_sum == 50)
	{
		key_sum = 0;
		KEY_Flag = 1;
    }
	if(++display_sum == 100)
	{
		display_sum = 0;
		Display_Flag = 1;
	}
	if(remember_sum / 1000 == Remember_Delay)
	{
		remember_sum = 0;
		Remember_Flag = 1;
	}
		
}

void RTC_IRQHandler(void)
{
	if(RTC_GetITStatus(RTC_IT_SEC) == 1)
	{
		RTC_ClearITPendingBit(RTC_IT_SEC);
		RTC_Flag = 1;
		if(RTC_GetCounter() == (24 * 3600))
		{
			RTC_SetCounter(0x0);
			RTC_WaitForLastTask();
		}
    }
}

void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3, TIM_IT_CC2) == 1 )
	{
		TIM_ClearITPendingBit(TIM3,TIM_IT_CC2);
		switch(TIM3_Ch2_CAPTURE_MODE)
		{
			case 0: TIM_Ch2_CAPTURE_HL = 0;
					TIM3_Ch2_CAPTURE_MODE = 1;
					TIM_SetCounter(TIM3,0x0);
					break;
			case 1: TIM_Ch2_CAPTURE_HL = TIM_GetCounter(TIM3);
					TIM3_Ch2_CAPTURE_MODE = 2;
					TIM_ITConfig(TIM3, TIM_IT_CC2, DISABLE);
					break;
		}
	}
}

void USART2_IRQHandler(void)
{
	u16 temp;
	if(USART_GetITStatus(USART2,USART_IT_RXNE) == 1)
	{
		USART_ClearITPendingBit( USART2, USART_IT_RXNE);
		temp = USART_ReceiveData(USART2);
		if(temp == '\n')
		{
			RXCUNT = 0;
			RXOVER = 1;
			USART_ITConfig( USART2, USART_IT_RXNE,DISABLE);
		}else
		{
			RX_BUF[RXCUNT] = temp;
			RXCUNT++;
		}
	}
}

 

三、通用初始化部分

#include "IO.h"
extern u16 LED_MODE;
u8 Set_Flag = 0;
u8 Select_Flag = 1;
int TH_compare = 40;
u8 RH_cpmpare = 80;
u8 Remember_Delay = 1;
u16 Ceshi_Fre = 1000;

///////////////////   24c02   //////////////////
void _24c02_Write(u8 address,u8 data)
{
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(address);
	I2CWaitAck();
	I2CSendByte(data);
	I2CWaitAck();
	I2CStop();
}
u8 _24c02_Read(u8 address)
{
	u8 temp;
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(address);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0xa1);
	I2CWaitAck();
	temp = I2CReceiveByte();
	I2CWaitAck();
	I2CStop();
	return temp;
}
////////////////////   ADC   //////////////////////
void ADC1_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_ADC1, ENABLE);
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	ADC_InitStructure.ADC_NbrOfChannel = 1;
	ADC_Init( ADC1, &ADC_InitStructure);
	
	ADC_Cmd( ADC1, ENABLE);
	
	ADC_ResetCalibration(ADC1);
	while(ADC_GetResetCalibrationStatus(ADC1));
		
	ADC_StartCalibration(ADC1);
	while(ADC_GetCalibrationStatus(ADC1));
}
u16 Get_Adc(void)
{
	u16 temp;
	ADC_RegularChannelConfig(ADC1,ADC_Channel_8, 1,ADC_SampleTime_239Cycles5);
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
	while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == 0);
	temp = ADC_GetConversionValue(ADC1);
	ADC_SoftwareStartConvCmd(ADC1, DISABLE);
	return temp;
}
/////////////////////  PA1_PWM_Out  ////////////////////////
void TIM2_Ch2_PWM_Init(u16 fre,u8 status)
{
	u16 TIM2_Val;
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	if(status)
	{
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_Init(GPIOA, &GPIO_InitStructure);
	}
	TIM2_Val = 1000000 / fre;
	TIM_TimeBaseInitStructure.TIM_Period = TIM2_Val - 1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 71;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = 0x0;
	TIM_TimeBaseInitStructure.TIM_CounterMode = 0x0;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = (TIM2_Val - 2) * 0.5;
	TIM_OC2Init(TIM2, &TIM_OCInitStructure);
	if(status)
	{
		TIM_Cmd( TIM2, ENABLE);
	}
}
///////////////////////   RTC   ///////////////////////////
void RTC_Init(u8 HH,u8 MM,u8 SS)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP | RCC_APB1Periph_PWR, ENABLE);
	
	NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	PWR_BackupAccessCmd(ENABLE);
	BKP_DeInit();
	RCC_LSICmd(ENABLE);
	while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == 0);
	RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
	RCC_RTCCLKCmd(ENABLE);
	
	RTC_ITConfig(RTC_IT_SEC, ENABLE);
	RTC_WaitForLastTask();
	
	RTC_WaitForSynchro();
	RTC_WaitForLastTask();
	
	RTC_SetPrescaler(40000 - 1);
	RTC_WaitForLastTask();
	
	RTC_SetCounter(HH * 3600 + MM * 60 + SS);
	RTC_WaitForLastTask();
	
}
////////////////////////   CAPTURE  ////////////////////////
void TIM3_Ch2_CAPTURE_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_ICInitTypeDef TIM_ICInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_TimeBaseInitStructure.TIM_Period = 0xffff;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 71;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = 0x0;
	TIM_TimeBaseInitStructure.TIM_CounterMode = 0x0;
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
	
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
	TIM_ICInitStructure.TIM_ICFilter = 0x0;
	TIM_ICInit(TIM3,&TIM_ICInitStructure);
		
	TIM_Cmd(TIM3,ENABLE);
	TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE);
}
/////////////////////  USART2  ///////////////////////////
void USART2_Init(u32 bound)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	USART_InitStructure.USART_BaudRate = bound;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_Init(USART2, &USART_InitStructure);
		
	USART_Cmd(USART2,ENABLE);
	USART_ITConfig( USART2, USART_IT_RXNE,ENABLE);
}
void USART2_SendString(u8 *str)
{
	u8 index = 0;
	do
	{
		USART_SendData(USART2,str[index]);
		while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == 0);
		index++;
	}while(str[index] != 0);
}
///////////////////////   LED   ////////////////////
void LED_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOD, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin = 0XFF00;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);
	
	GPIOC-> ODR = 0XFFFF;
	GPIOD-> ODR |= (1<<2);
	GPIOD-> ODR &=~(1<<2);
}
////////////////////////   KEY   /////////////////////
void KEY_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}

 

你可能感兴趣的:(蓝桥杯)