十一届蓝桥杯嵌入式模拟赛题(二)

在这里插入图片描述
分析
该题目总体上觉得中等偏下一点,但是在处理按键B1和按键B2时有一定技巧,具体分析见下文。还有一个地方就是RTC时钟,由于看到按下B1键要使RTC暂停。如果用RTC时钟来写,我就不知道怎样让RTC暂停,因此我选择采用SysTick产生中断来控制RTC时钟。其次就是循环选择时,分,秒这个功能,这个是通过设置标志位来实现的。
代码
1、main.c

#include "stm32f10x.h"
#include "stm32f10x_it.h"
#include "lcd.h"
#include "i2c.h"
#include "key.h"
#include "lcd_window.h"
#include "usart.h" 
#include "led.h" 
u8  k1,k2;//k1为时间修改次数,k2为闹钟修改次数
u8  Hour=11,Min=59,Sec=55;//时钟
u8  Hour_A=12,Min_A=0,Sec_A=0;//闹钟时间
u32 Sysclock=11*3600+59*60+55;
u8  K1_Flag,K2_Flag;
u8  RTC_Flag,Ala_Flag; //0代表选择选中了时,1是分,2,是秒
u8  K1_Sum,K2_Sum,K3_Sum,K4_Sum;
u8  Setting_Mode;//0显示主页面,1显示时钟设置页面,2显示闹钟设置页面
u8  LED_Flag;
int main(void)
{
    
    
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
SysTick_Config(SystemCoreClock/1000);
STM3210B_LCD_Init();
LCD_Clear(Blue);
LCD_SetTextColor(White);
LCD_SetBackColor(Blue);
i2c_init();
KEY_Init();
usart_Init();
LED_Init();
k1=x24c02_read(0x10);
delay_ms(10);
k2=x24c02_read(0x20);
delay_ms(10);
Hour_A=x24c02_read(0x30);
delay_ms(10);
Min_A=x24c02_read(0x40);
delay_ms(10);
Sec_A=x24c02_read(0x50);
while(1)
{
    
    
KEY_Control();
Lcd_Window();
LED_Show();
}

}


在创建工程完毕后,我会先把lcd的配置文件添加到工程里来测试板子和工程是否有问题,接下就是配置系统时钟和延时函数。
2、key.c

#include "key.h"
#include "stm32f10x.h"
#include "stm32f10x_it.h"
#include "lcd.h"
#include "i2c.h"
#include "usart.h"
#include "stdio.h"
extern u8  K1_Sum,K2_Sum,K3_Sum,K4_Sum;
extern u8  Setting_Mode;
extern u8  K1_Flag,K2_Flag;
extern u8  RTC_Flag,Ala_Flag;
extern u8  Hour,Min,Sec;//时钟
extern u8  Hour_A,Min_A,Sec_A;//闹钟时间
extern u32 Sysclock;
extern u8  k1,k2;
void KEY_Init(void)
{
    
    
GPIO_InitTypeDef   GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  /* Configure PA.00 pin as input floating */
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_8;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
 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);
}

void  KEY_Control(void)
{
    
    u8 str[30];
if(KEY1==0)
{
    
    
delay_ms(10);//消抖
if(KEY1==0)
{
    
    
 K1_Sum++;
 if(K1_Sum==1)
 {
    
    
  if(Setting_Mode==0)//这里B2键还没按下,即是主页面,然后按下B1进入时钟设置页面
  {
    
    
  K1_Flag=1;  //这个标志位很重要,说明是B1先按,再是B2按下
  }
 if(K1_Flag)
 {
    
    
 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); 
 K2_Flag=0;
 switch(Setting_Mode)
 {
    
    
 case 0:  Setting_Mode=1;	
 		  break;
 case 1:  Setting_Mode=0;
 		  k1++;
		  x24c02_write(0x10,k1);
		  delay_ms(10);
		  sprintf((char*)str,"New RTC:%.2d:%.2d:%.2d\\r\\n",Hour,Min,Sec);//当再次回到主页面时,说明修改完成,则相串口发送信息
          usart_Sendata(str);
 		  break;
 default: break;
 }
 }
 if(K1_Flag==0&&Setting_Mode==2)//这里是选择闹钟的时,分,秒的标志位设置
 {
    
    
  Ala_Flag++;
  if(Ala_Flag>2)
  {
    
    
  Ala_Flag=0;
  }
 }
}
}
}
else
{
    
    
 K1_Sum=0;
}

if(KEY2==0)
{
    
    
delay_ms(10);
if(KEY2==0)
{
    
    
 
K2_Sum++;
if(K2_Sum==1)
{
    
    
if(Setting_Mode==0)//B2先按下,再是B1的选则
{
    
    
K2_Flag=1;//这个很重要
}
if(K2_Flag)
{
    
    
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); 
K1_Flag=0;
switch(Setting_Mode)
{
    
    
case 0: Setting_Mode=2;
		break;
case 2: Setting_Mode=0;
		k2++;
		x24c02_write(0x20,k1);
		delay_ms(10);
		sprintf((char*)str,"New Alarm:%.2d:%.2d:%.2d\\r\\n",Hour_A,Min_A,Sec_A);//当再次按下B2说明已经修改完成,则串口发送信息
        usart_Sendata(str);
		break;
default:break;
}
}
if(K2_Flag==0&&Setting_Mode==1)
{
    
    
RTC_Flag++;
if(RTC_Flag>2)
{
    
    
RTC_Flag=0;
}
}
}
}
}
else
{
    
    
K2_Sum=0;
}
if(KEY3==0)
{
    
    
delay_ms(10);
if(KEY3==0)
{
    
    
K3_Sum++;
if(K3_Sum==1)
{
    
    
if(Setting_Mode==1)
{
    
    
 switch(RTC_Flag)
 {
    
    
 case 0:  Hour++;
 		  if(Hour>23) 
		  {
    
    
		  Hour=0;
		  }
		  break;
 case 1: Min++;
 		  if(Min>59) 
		  {
    
    
		  Min=0;
		  }
		  break;
case 2:  Sec++;
 		  if(Sec>59) 
		  {
    
    
		  Sec=0;
		  }
		  break;
default:break;
 }
Sysclock=Hour*3600+Min*60+Sec;
}
if(Setting_Mode==2)
{
    
    
switch(Ala_Flag)
{
    
    
case 0: Hour_A++;
		if(Hour_A>23)
		{
    
    
		Hour_A=0;
		}
		x24c02_write(0x30,Hour_A);
		delay_ms(10);
		break;
case 1:Min_A++;
	   if(Min_A>59)
	   {
    
    
	   Min_A=0;
	   }
	   x24c02_write(0x40,Min_A);
		delay_ms(10);
	   break;
case 2:Sec_A++;
	   if(Sec_A>59)
	   {
    
    
	   Sec_A=0;
	   }
	   x24c02_write(0x50,Sec_A);
	   delay_ms(10);
	   break;
default:break;
}
}
}
if(K3_Sum>20)
{
    
    
 if(Setting_Mode==1)
{
    
    
 switch(RTC_Flag)
 {
    
    
 case 0:  Hour++;
 		  if(Hour>23) 
		  {
    
    
		  Hour=0;
		  }
		  break;
 case 1: Min++;
 		  if(Min>59) 
		  {
    
    
		  Min=0;
		  }
		  break;
case 2:  Sec++;
 		  if(Sec>59) 
		  {
    
    
		  Sec=0;
		  }
		  break;
default:break;
 }
 Sysclock=Hour*3600+Min*60+Sec;
 }
if(Setting_Mode==2)
{
    
    
switch(Ala_Flag)
{
    
    
case 0: Hour_A++;
		if(Hour_A>23)
		{
    
    
		Hour_A=0;
		}
		x24c02_write(0x30,Hour_A);
		delay_ms(10);
		break;
case 1:Min_A++;
	   if(Min_A>59)
	   {
    
    
	   Min_A=0;
	   }
	   x24c02_write(0x40,Min_A);
		delay_ms(10);
	   break;
case 2:Sec_A++;
	   if(Sec_A>59)
	   {
    
    
	   Sec_A=0;
	   }
	   x24c02_write(0x50,Sec_A);
	   delay_ms(10);
	   break;
default:break;
}
}
}
}
}

else
{
    
    
K3_Sum=0;
}
if(KEY4==0)
{
    
    
delay_ms(10);
if(KEY4==0)
{
    
    
K4_Sum++;
if(K4_Sum==1)
{
    
    
if(Setting_Mode==1)
{
    
    
 switch(RTC_Flag)
 {
    
    
 case 0:  if(Hour>0)
         {
    
    
	    	Hour--;
		 }
 		  if(Hour<=0) 
		  {
    
    
		  Hour=0;
		  }
		  break;
 case 1: if(Min>0)
        {
    
    
		Min--;
		}
 		  if(Min<=0) 
		  {
    
    
		  Min=0;
		  }
		  break;
case 2:  if(Sec>0)
        {
    
    
		Sec--;
		}
 		  if(Sec<=0) 
		  {
    
    
		  Sec=0;
		  }
		  break;
default:break;
 }
Sysclock=Hour*3600+Min*60+Sec;
}
if(Setting_Mode==2)
{
    
    
switch(Ala_Flag)
{
    
    
case 0: if(Hour_A>0)
        {
    
    
		Hour_A--;
		}
		if(Hour_A<=0)
		{
    
    
		Hour_A=0;
		}
		x24c02_write(0x30,Hour_A);
		delay_ms(10);
		break;
case 1:if(Min_A>0)
        {
    
    
		Min_A--;
		}
	   if(Min_A<=0)
	   {
    
    
	   Min_A=0;
	   }
	   x24c02_write(0x40,Min_A);
	   delay_ms(10);
	   break;
case 2:	if(Sec_A>0)
        {
    
    
		Sec_A--;
		}
	   if(Sec_A<=0)
	   {
    
    
	   Sec_A=0;
	   }
	   x24c02_write(0x50,Sec_A);
	   delay_ms(10);
	   break;
default:break;
}
}
}
if(K4_Sum>20)
{
    
    
 if(Setting_Mode==1)
{
    
    
 switch(RTC_Flag)
 {
    
    
 case 0:  if(Hour>0)
        {
    
    
		Hour--;
		}
 		  if(Hour<=0) 
		  {
    
    
		  Hour=0;
		  }
		  break;
 case 1:  if(Min>0)
        {
    
    
		Min--;
		}
 		  if(Min<=0) 
		  {
    
    
		  Min=0;
		  }
		  break;
case 2:   if(Sec>0)
        {
    
    
		Sec--;
		}
 		  if(Sec<=0) 
		  {
    
    
		  Sec=0;
		  }
		  break;
default:break;
 }
 Sysclock=Hour*3600+Min*60+Sec;
 }
if(Setting_Mode==2)
{
    
    
switch(Ala_Flag)
{
    
    
case 0: if(Hour_A>0)
        {
    
    
		Hour_A--;
		}
		if(Hour_A<=0)
		{
    
    
		Hour_A=0;
		}
		x24c02_write(0x30,Hour_A);
		delay_ms(10);
		break;
case 1:if(Min_A>0)
        {
    
    
		Min_A--;
		}
	   if(Min_A<=0)
	   {
    
    
	   Min_A=0;
	   }
	   x24c02_write(0x40,Min_A);
		delay_ms(10);
	   break;
case 2:if(Sec_A>0)
        {
    
    
		Sec_A--;
		}
	   if(Sec_A<=0)
	   {
    
    
	   Sec_A=0;
	   }
	   x24c02_write(0x50,Sec_A);
	   delay_ms(10);
	   break;
default:break;
}
}
}
}
}
else
{
    
    
K4_Sum=0;
}

}

3、usart.c

#include "usart.h"
#include "stm32f10x.h"
#include "stdio.h"
extern u8  usart_Flag1,usart_Flag2;
extern u8  Hour,Min,Sec;//时钟
extern u8  Hour_A,Min_A,Sec_A;//闹钟时间
void usart_Init(void)
{
    
    
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable GPIO clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB| RCC_APB2Periph_AFIO, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
   /* Configure USARTy Rx as input floating */
  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);
  /* Configure USARTy Tx as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  
  USART_InitStructure.USART_BaudRate = 9600;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  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;

  /* Configure USARTy */
  USART_Init(USART2, &USART_InitStructure);
   /* Enable USARTy Receive and Transmit interrupts */
  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);

   /* Enable the USARTy */
  USART_Cmd(USART2, ENABLE);
   /* Enable the USARTy Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
  NVIC_Init(&NVIC_InitStructure);
}

void  usart_Sendata(uint8_t *str)
{
    
    
u8 index=0;
do	  
{
    
    
USART_SendData(USART2,str[index]);
while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);
index++;
}while(str[index]!=0);
}

4.led.c

#include "led.h"
#include "stm32f10x.h"
#include "stm32f10x_it.h"
extern  u8 Setting_Mode;
extern  u8 LED_Flag;
void  LED_Init(void)
{
    
    
 GPIO_InitTypeDef   GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD, ENABLE);
/* Configure PA.00 pin as input floating */
 GPIO_InitStructure.GPIO_Pin = LED1|LED2|LED3|LED4|LED5|LED6|LED7|LED8;
 GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;
 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
 GPIO_Init(GPIOC, &GPIO_InitStructure);
 GPIO_InitStructure.GPIO_Pin =GPIO_Pin_2;
 GPIO_Init(GPIOD, &GPIO_InitStructure);

}

void LED_Show(void)
{
    
    
GPIOC->ODR=0xffff;
if(Setting_Mode==0)
{
    
    
if(LED_Flag==1)
{
    
    
GPIO_ResetBits(GPIOC,LED1);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
else
{
    
    
GPIO_SetBits(GPIOC,LED1);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
}
if(Setting_Mode==1)
{
    
    
GPIO_ResetBits(GPIOC,LED2);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
if(Setting_Mode==2)
{
    
    
GPIO_ResetBits(GPIOC,LED3);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}


}


5、stm32f10x_it.c里的 void SysTick_Handler(void)函数

void SysTick_Handler(void)
{
    
    
static u32 RTC_Sum;
static u32 LED_Sum;
delayTime--;
if(Setting_Mode==0)
{
    
    
if(++RTC_Sum==1000)//1s,RTC时钟
 {
    
    
  RTC_Sum=0;
  Sysclock++;
  if(Sysclock==23*3600+59*60+59)
  {
    
    
  Sysclock=0;
  } 
 }
}
if(++LED_Sum==1000)//1s让LED1亮灭
{
    
    
 LED_Sum=0;
 LED_Flag^=1;
}
}

6.lcd_window.c

#include "lcd_window.h"
#include "stm32f10x.h"
#include "lcd.h"
#include "stdio.h"
#include "i2c.h"
#include "stm32f10x_it.h"
extern u8  Hour,Min,Sec;
extern u32 Sysclock;
extern u8  Hour_A,Min_A,Sec_A;//闹钟时间
extern u8  RTC_Flag,Ala_Flag; //0代表选择选中了时,1是分,2,是秒
extern u8  Setting_Mode;//0显示主页面,1显示时钟设置页面,2显示闹钟设置页面
void Lcd_Window(void)
{
    
    u8 str[20];
Hour=Sysclock/3600;
Min=Sysclock%3600/60;
Sec=Sysclock%3600%60;
if(Setting_Mode==0)
 {
    
    
 LCD_SetTextColor(White);
 sprintf((char*)str,"    MAIN    ");
 LCD_DisplayStringLine(Line1,str);
 sprintf((char*)str,"    RTC:%.2d:%.2d:%.2d   ",Hour,Min,Sec);
 LCD_DisplayStringLine(Line4,str);
 }
if(Setting_Mode==1)
{
    
     
 LCD_SetTextColor(White);
 sprintf((char*)str,"    RTC-SETTING     ");
 LCD_DisplayStringLine(Line1,str);
 sprintf((char*)str,"  RTC:");
 LCD_DisplayStringLine(Line4,str);
 if(RTC_Flag==0)
 {
    
    
 LCD_SetTextColor(Red);
 }
 else
 {
    
    
 LCD_SetTextColor(White);
 }
 LCD_DisplayChar(Line4,215,Hour/10+0x30);
 LCD_DisplayChar(Line4,200,Hour%10+0x30);
 LCD_SetTextColor(White);
 LCD_DisplayChar(Line4,185,':');
 if(RTC_Flag==1)
 {
    
    
 LCD_SetTextColor(Red);
 }
 else
 {
    
    
 LCD_SetTextColor(White);
 }
 LCD_DisplayChar(Line4,170,Min/10+0x30);
 LCD_DisplayChar(Line4,155,Min%10+0x30);
 LCD_SetTextColor(White);
 LCD_DisplayChar(Line4,140,':');
 if(RTC_Flag==2)
 {
    
    
 LCD_SetTextColor(Red);
 }
 else
 {
    
    
 LCD_SetTextColor(White);
 }
 LCD_DisplayChar(Line4,125,Sec/10+0x30);
 LCD_DisplayChar(Line4,110,Sec%10+0x30);
 //LCD_SetTextColor(White);
}
if(Setting_Mode==2)
{
    
    
 LCD_SetTextColor(White);
 sprintf((char*)str,"    ALARM-SETTING     ");
 LCD_DisplayStringLine(Line1,str);
 sprintf((char*)str,"Alarm:");
 LCD_DisplayStringLine(Line4,str);
if(Ala_Flag==0)
 {
    
    
 LCD_SetTextColor(Red);
 }
 else
 {
    
    
 LCD_SetTextColor(White);
 }
 LCD_DisplayChar(Line4,215,Hour_A/10+0x30);
 LCD_DisplayChar(Line4,200,Hour_A%10+0x30);
 LCD_SetTextColor(White);
 LCD_DisplayChar(Line4,185,':');
 if(Ala_Flag==1)
 {
    
    
 LCD_SetTextColor(Red);
 }
 else
 {
    
    
 LCD_SetTextColor(White);
 }
 LCD_DisplayChar(Line4,170,Min_A/10+0x30);
 LCD_DisplayChar(Line4,155,Min_A%10+0x30);
 LCD_SetTextColor(White);
 LCD_DisplayChar(Line4,140,':');
 if(Ala_Flag==2)
 {
    
    
 LCD_SetTextColor(Red);
 }
 else
 {
    
    
 LCD_SetTextColor(White);
 }
 LCD_DisplayChar(Line4,125,Sec_A/10+0x30);
 LCD_DisplayChar(Line4,110,Sec_A%10+0x30);

}


}

说明
可能是我自己理解有问题,题目里面要求设置报警时间,和时钟时间,但是没要求当时钟时间达到报警时间时会发出警报的功能,如蜂鸣器报警。以上是本人的拙见,若有误还望见谅!

总结
在做题时,本人觉得应该要善于设置标志位作为条件控制,这样可以使问题分解,易于理解,逻辑性更强。

猜你喜欢

转载自blog.csdn.net/fsvff/article/details/105606567