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

Grace ·
更新时间:2024-09-20
· 725 次阅读

一、问题

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

二、解答:

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<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;i0) { 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<ODR=LED_MODE; GPIO_SetBits(GPIOC,GPIO_Pin_9); GPIO_SetBits(GPIOC,GPIO_Pin_10); GPIOD->ODR|=(1<ODR&=~(1<<2); led1_cnt=0; } } else if(SET_flag==1){ LED_MODE&=~(1<ODR=LED_MODE; GPIO_SetBits(GPIOC,GPIO_Pin_8); GPIO_SetBits(GPIOC,GPIO_Pin_10); GPIOD->ODR|=(1<ODR&=~(1<<2); } else if(SET_flag==2){ LED_MODE&=~(1<ODR=LED_MODE; GPIO_SetBits(GPIOC,GPIO_Pin_9); GPIO_SetBits(GPIOC,GPIO_Pin_8); GPIOD->ODR|=(1<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;i2) 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高亮显示,要按字符来操作,因此字符的位置需要确定好。而且界面切换时,可能会显示之前界面的字符。我的方法是这些位置都替换掉,就不会串位了。


作者:fancyZT



蓝桥杯 嵌入 嵌入式

需要 登录 后方可回复, 如果你还没有账号请 注册新账号