蓝桥杯嵌入式第十一届省赛模拟试题

  • 一、问题

蓝桥杯嵌入式第十一届省赛模拟试题蓝桥杯嵌入式第十一届省赛模拟试题
蓝桥杯嵌入式第十一届省赛模拟试题

  • 二、解答:

1.初始化相关
tx.c

#include "tx.h"

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_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOD, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = 0xff00;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

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


}

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_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
}

u8 key_status[4]={1,1,1,1};
u16 key_downtime[4]={0,0,0,0};

void KEY_Driver(void){
  u8 i;
  static u8 backup[4]={1,1,1,1};
  static u16 timethr[4]={1000,1000,1000,1000};
  for(i=0;i<4;i++){
    if(backup[i]!=key_status[i]){
	  if(backup[i]!=0){
	  	Key_action(i+1,0);
	  }
	  backup[i]=key_status[i];
	}
	if(key_downtime[i]>0) {
	  if(key_downtime[i]>timethr[i]){
	  	 Key_action(i+1,1);
		 timethr[i]+=200;
	  }
	  else
	    timethr[i]=1000;	 	
	} 
  }	 
}

void KEY_Scan(void){
  u8 i;
  static u8 key_buf[4]={0xff,0xff,0xff,0xff};
  key_buf[0]=(key_buf[0]<<1)|KEY1;
  key_buf[1]=(key_buf[1]<<1)|KEY2; 
  key_buf[2]=(key_buf[2]<<1)|KEY3; 
  key_buf[3]=(key_buf[3]<<1)|KEY4;
  for(i=0;i<4;i++){
    if(key_buf[i]==0x00) {
	  key_downtime[i]+=4; 
	  key_status[i]=0;
	}
	  
	else if(key_buf[i]==0xff){
	  key_downtime[i]=0;
	  key_status[i]=1;
	}  	  
  }
}

void Tim4_Init(u16 arr,u16 psc){
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

  NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	 
  NVIC_Init(&NVIC_InitStructure);


  TIM_TimeBaseStructure.TIM_Period = arr-1;
  TIM_TimeBaseStructure.TIM_Prescaler = psc-1;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
  TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);

  /* TIM2 enable counter */
  TIM_Cmd(TIM4, ENABLE);

}


void RTC_Init(u8 HH,u8 MM,u8 SS){
  NVIC_InitTypeDef NVIC_InitStructure;
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  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);

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);

  /* Allow access to BKP Domain */
  PWR_BackupAccessCmd(ENABLE);

  /* Reset Backup Domain */
  BKP_DeInit();

  /* Enable the LSI OSC */
  RCC_LSICmd(ENABLE);
  /* Wait till LSI is ready */
  while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
  {}
  /* Select the RTC Clock Source */
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);

  /* Enable RTC Clock */
  RCC_RTCCLKCmd(ENABLE);

  /* Wait for RTC registers synchronization */
  RTC_WaitForSynchro();

  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();

  /* Enable the RTC Second */
  RTC_ITConfig(RTC_IT_SEC, ENABLE);

  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();

  /* Set RTC prescaler: set RTC period to 1sec */
  RTC_SetPrescaler(40000-1);

  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();

  RTC_SetCounter(3600*HH+60*MM+SS);
  RTC_WaitForLastTask();	  

}

void Usart2_Init(void){
  USART_InitTypeDef USART_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); 

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  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);

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_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);
  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
  USART_Cmd(USART2, ENABLE);
}

void Send_string(u8 *str){
  u8 i=0;
  while(str[i]!=0){
  	 USART_SendData(USART2,str[i]);
	 while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==0);
	 i++;  
  }	
}


tx.h

/*
  程序说明: CT117E嵌入式竞赛板LCD驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT117E嵌入式竞赛板
  日    期: 2011-8-9
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __TX_H
#define __TX_H

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"

#define KEY1 GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)
#define KEY2 GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8)
#define KEY3 GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)
#define KEY4 GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_2)

void LED_Init(void);
void KEY_Init(void);
void KEY_Driver(void);
void KEY_Scan(void);
void Tim4_Init(u16 arr,u16 psc);
void RTC_Init(u8 HH,u8 MM,u8 SS);
void Usart2_Init(void);
void Send_string(u8 *str);
extern void Key_action(int code,int sta);



#endif /* __TX_H */

/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/

2.i2c.c中增加

void i2c_write(u16 add,u8 data){
  I2CStart();
  I2CSendByte(0xa0);
  I2CWaitAck();
  I2CSendByte(add);
  I2CWaitAck();
  I2CSendByte(data);
  I2CWaitAck();
  I2CStop();
}

u8 i2c_read(u16 add){
  u8 temp;
  I2CStart();
  I2CSendByte(0xa0);
  I2CWaitAck();
  I2CSendByte(add);
  I2CWaitAck();

  I2CStart();
  I2CSendByte(0xa1);
  I2CWaitAck();
  temp=I2CReceiveByte();
  I2CSendAck();
  I2CStop();
  return temp;
}

3.主文件中:

#include "stm32f10x.h"
#include "lcd.h"
#include "tx.h"
#include "stdio.h"
#include "i2c.h"

u32 TimingDelay = 0;

u8 RXD_flag=0;
u8 RXD_buf[20];
u8 str[20];
u8 i;

u16 time;
u8 hour,min,sec;
u8 t_hour=11,t_min=59,t_sec=50;//设置初始时间
u8 a_hour=12,a_min=0,a_sec=0;//设置闹钟

u8 time_flag=0;//在设置时间时的切换标志
u8 alarm_flag=0;//在设置闹钟时的切换标志

u8 SET_flag=0;//0时钟显示,1时钟设置,2报警设置
u8 KEY1_flag=0; //0是时钟设置,1是切换
u8 KEY2_flag=0;	//0是闹钟设置,1是切换
u16 time_count=0;	//时间设置次数
u16 alarm_count=0;	 //报警次数
u8 ms200_flag=1;

u16 LED_MODE=0xffff;
u16 led1_cnt=0;

void Show_real_data(void);
void Show_set_time(void);
void Show_set_alarm(void);
void Led_action(void);
void Usart_action(int i);
void Key_action(int code,int sta);
void In_data(void);
void De_data(void);		
void Delay_Ms(u32 nTime);

//Main Body
int main(void)
{
	SysTick_Config(SystemCoreClock/1000);

	Delay_Ms(200);
	
	STM3210B_LCD_Init();
	LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(White);
	
    i2c_init();
	LED_Init();
	KEY_Init();
	Tim4_Init(2000,72);
	RTC_Init(11,59,50);
	Usart2_Init();
	
	time_count=0;
    alarm_count=0;

	time_count=i2c_read(0x00); Delay_Ms(5);
    alarm_count=i2c_read(0x01); Delay_Ms(5);
	a_hour=i2c_read(0x02); Delay_Ms(5);
	a_min=i2c_read(0x03); Delay_Ms(5);
	a_sec=i2c_read(0x04); Delay_Ms(5);

	while(1){
	  KEY_Driver();

	  if(ms200_flag){
	  	ms200_flag=0;
	  	Led_action();
		if(SET_flag==0)
		  Show_real_data();
		else if(SET_flag==1)
		  Show_set_time();
		else if(SET_flag==2)
		  Show_set_alarm();		
	  }
	  		   	  
   } 	
}



void Show_real_data(void){
  sprintf((char*)str,"       MAIN     ");
  LCD_DisplayStringLine(Line2, str);

  sprintf((char*)str,"   RTC:");
  LCD_DisplayStringLine(Line5, str);

  LCD_DisplayChar(Line5, 200,hour/10+'0');
  LCD_DisplayChar(Line5, 185,hour%10+'0');
  LCD_DisplayChar(Line5, 170,':');	

  LCD_DisplayChar(Line5, 155,min/10+'0');
  LCD_DisplayChar(Line5, 140,min%10+'0');
  LCD_DisplayChar(Line5, 125,':');
  
  LCD_DisplayChar(Line5, 110,sec/10+'0');
  LCD_DisplayChar(Line5, 95,sec%10+'0');	

}

void Show_set_time(void){
  sprintf((char*)str,"    RTC-SETTING   ");
  LCD_DisplayStringLine(Line2, str);

  sprintf((char*)str,"   RTC:");
  LCD_DisplayStringLine(Line5, str);


  if(time_flag==0)
    LCD_SetTextColor(Green);
  else 
    LCD_SetTextColor(White);
  LCD_DisplayChar(Line5, 200,t_hour/10+'0');
  LCD_DisplayChar(Line5, 185,t_hour%10+'0');
  LCD_SetTextColor(White);
  LCD_DisplayChar(Line5, 170,':');	   

  if(time_flag==1)
    LCD_SetTextColor(Green);
  else 
    LCD_SetTextColor(White);
  LCD_DisplayChar(Line5, 155,t_min/10+'0');
  LCD_DisplayChar(Line5, 140,t_min%10+'0');
  LCD_SetTextColor(White);
  LCD_DisplayChar(Line5, 125,':');	  

  if(time_flag==2)
    LCD_SetTextColor(Green);
  else 
    LCD_SetTextColor(White);
  LCD_DisplayChar(Line5, 110,t_sec/10+'0');
  LCD_DisplayChar(Line5, 95,t_sec%10+'0');
  LCD_SetTextColor(White);

}

void Show_set_alarm(void){
  sprintf((char*)str,"   ALARM-SETTING   ");
  LCD_DisplayStringLine(Line2, str);

  sprintf((char*)str," ALARM:");
  LCD_DisplayStringLine(Line5, str);


  if(alarm_flag==0)
    LCD_SetTextColor(Green);
  else 
    LCD_SetTextColor(White);
  LCD_DisplayChar(Line5, 200,a_hour/10+'0');
  LCD_DisplayChar(Line5, 185,a_hour%10+'0');
  LCD_SetTextColor(White);
  LCD_DisplayChar(Line5, 170,':');	   

  if(alarm_flag==1)
    LCD_SetTextColor(Green);
  else 
    LCD_SetTextColor(White);
  LCD_DisplayChar(Line5, 155,a_min/10+'0');
  LCD_DisplayChar(Line5, 140,a_min%10+'0');
  LCD_SetTextColor(White);
  LCD_DisplayChar(Line5, 125,':');	  

  if(alarm_flag==2)
    LCD_SetTextColor(Green);
  else 
    LCD_SetTextColor(White);
  LCD_DisplayChar(Line5, 110,a_sec/10+'0');
  LCD_DisplayChar(Line5, 95,a_sec%10+'0');
  LCD_SetTextColor(White);

}
void Led_action(void){   
  if(SET_flag==0){
  	 led1_cnt++;
	 if(led1_cnt>=10){
	   LED_MODE^=(1<<8);
	   GPIOC->ODR=LED_MODE;
	   GPIO_SetBits(GPIOC,GPIO_Pin_9);
	   GPIO_SetBits(GPIOC,GPIO_Pin_10);
	   GPIOD->ODR|=(1<<2);   
       GPIOD->ODR&=~(1<<2);
	   led1_cnt=0;  
	 }	 
  }   
  else if(SET_flag==1){	    	 
	 LED_MODE&=~(1<<9);
	 GPIOC->ODR=LED_MODE;
	 GPIO_SetBits(GPIOC,GPIO_Pin_8);
	 GPIO_SetBits(GPIOC,GPIO_Pin_10);
	 GPIOD->ODR|=(1<<2);   
	 GPIOD->ODR&=~(1<<2);
  } 
  else if(SET_flag==2){	
	 LED_MODE&=~(1<<10);
	 GPIOC->ODR=LED_MODE;
	 GPIO_SetBits(GPIOC,GPIO_Pin_9);
	 GPIO_SetBits(GPIOC,GPIO_Pin_8);
	 GPIOD->ODR|=(1<<2);   
     GPIOD->ODR&=~(1<<2);
  }  
}

void Usart_action(int i){
  if(i==1){
  	sprintf((char*)str,"New RTC:%.2d:%.2d:%.2d\r\n",t_hour,t_min,t_sec);
    Send_string(str);
  }
  else if(i==2){
  	sprintf((char*)str,"New Alarm:%.2d:%.2d:%.2d\r\n",a_hour,a_min,a_sec);
    Send_string(str);
  }
  for(i=0;i<20;i++)
    RXD_buf[i]=0;
  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);	 
}

//KEY1_flag
void Key_action(int code,int sta){
  if(sta==0){
  if(code==1){
  	if(KEY1_flag==0){	//设置
	   SET_flag^=1;
	   KEY2_flag=1;
	   if(SET_flag==0){
	     time_count++;
		 i2c_write(0x00,time_count);  Delay_Ms(5);
		 //if(RXD_flag){
		 //  RXD_flag=0; 
		   Usart_action(1);
		 //}
		 KEY2_flag=0;	  		 
	   }
	}
	else if(KEY1_flag==1){	//切换闹钟选择
	  alarm_flag++;
	  if(alarm_flag>2)
	    alarm_flag=0;	  	
	}	
  }
  else if(code==2){
  	if(KEY2_flag==0){	//设置
	   if(SET_flag==0)
	    SET_flag=2;
	   else if(SET_flag==2)
	    SET_flag=0;
	   
	   KEY1_flag=1;
	   if(SET_flag==0){
	     alarm_count++;
		 i2c_write(0x01,alarm_count);Delay_Ms(5);
		 i2c_write(0x02,a_hour);Delay_Ms(5);
	     i2c_write(0x03,a_min);Delay_Ms(5);
	     i2c_write(0x04,a_sec);Delay_Ms(5);
		 //if(RXD_flag){
		 //  RXD_flag=0; 
		   Usart_action(2);
		 //}
		 KEY1_flag=0;
	   }	 	  
	}
	else if(KEY2_flag==1){	//切换闹钟选择
	  time_flag++;
	  if(time_flag>2)
	    time_flag=0;	  	
	}  	   
  }
  }
  else if(sta==1){
   if(code==3)	    
	  In_data();   
  else if(code==4)	   
	  De_data();   
  }
}

void In_data(void){
  if(SET_flag==1){
  	if(time_flag==0){
	  t_hour+=1;
	  if(t_hour>=24)
	    t_hour=0;
	}
	else if(time_flag==1){
	  t_min+=1;
	  if(t_min>=60)
	    t_min=0;	
	}
	else if(time_flag==2){
	  t_sec+=1;
	  if(t_sec>=60)
	    t_sec=0;	
	}
  }
  else if(SET_flag==2){
  	if(alarm_flag==0){
	  a_hour+=1;
	  if(a_hour>=24)
	    a_hour=0;
	}
	else if(alarm_flag==1){
	  a_min+=1;
	  if(a_min>=60)
	    a_min=0;	
	}
	else if(alarm_flag==2){
	  a_sec+=1;
	  if(a_sec>=60)
	    a_sec=0;	
	}
  }
}

void De_data(){
  if(SET_flag==1){
  	if(time_flag==0){
	  t_hour--;
	  if(t_hour+1<=0)
	    t_hour=23;
	}
	else if(time_flag==1){
	  t_min--;
	  if(t_min+1<=0)
	    t_min=59;	
	}
	else if(time_flag==2){
	  t_sec--;
	  if(t_sec+1<=0)
	    t_sec=0;	
	}
  }
  else if(SET_flag==2){
  	if(alarm_flag==0){
	  a_hour--;
	  if(a_hour+1<=0)
	    a_hour=23;
	}
	else if(alarm_flag==1){
	  a_min--;
	  if(a_min+1<=0)
	    a_min=59;	
	}
	else if(alarm_flag==2){
	  a_sec--;
	  if(a_sec+1<=60)
	    a_sec=59;	
	}
  }
}

void Delay_Ms(u32 nTime)
{
	TimingDelay = nTime;
	while(TimingDelay != 0);	
}

4.中断
stm32f10x_it.c中

void SysTick_Handler(void)
{
	TimingDelay--;
}

extern u8 ms200_flag;
void TIM4_IRQHandler(void)
{
  static u16 ms200_count=0;
  if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
  {
    TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
	ms200_count++;
	KEY_Scan();
	if(ms200_count>=100){
	  ms200_count=0;
	  ms200_flag=1;	 
	}
  }
}

extern u16 time;
extern u8 hour,min,sec;
void RTC_IRQHandler(void)
{
  if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
  {
    RTC_ClearITPendingBit(RTC_FLAG_SEC);
    time=RTC_GetCounter();
	if(time==23*3600+59*60+59){
	   RTC_SetCounter(0);
	}
	hour=time/3600;
	min=time%3600/60;
	sec=time%3600%60;
    
  }
}

extern u8 RXD_flag;
extern u8 RXD_buf[20];
u8 RXD_count=0;
void USART2_IRQHandler(void)
{
  u16 temp;
  if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET){
    USART_ClearITPendingBit(USART2, USART_IT_RXNE);
	temp=USART_ReceiveData(USART2);
	if(temp=='\n'){
	   RXD_flag=1; 
	   RXD_count=0;
	   USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
	}
    else 
	  RXD_buf[RXD_count++]=temp;
  }
}

三、总结:
1.功能得到实现,但长短按键效果不是很好。长按的时候增加的太快了,不是每个数都显示。其他的都还好。
2.前期自己做的时候,参考了别人的程序,分成小函数来写,然后调用。思路比较清晰。

四、遇到的问题:
1.三个灯的控制,开一个灯,另外两个灯的状态也需要变,只用位操作会出现问题,试了挺长时间,用了位操作+函数直接置位实现了。
2.串口发送的时候,如果加上串口发送标志的判断,就不一定能显示。去掉之后可以显示。
3.lcd高亮显示,要按字符来操作,因此字符的位置需要确定好。而且界面切换时,可能会显示之前界面的字符。我的方法是这些位置都替换掉,就不会串位了。

上一篇:串口通信协议基本样式


下一篇:Lcd液晶拼接屏黑边拼缝消除技术