第十三届蓝桥杯嵌入式省赛程序设计详细题解
第十三届蓝桥杯嵌入式省赛题目相对于第十二届较为简单,没有那么多串口的数据处理以及判断!
(图片来源网络,侵删)
第十三届省赛主要是制作一个可由串口设置密码的密码锁。本实验中,我们将用到LED模块、按键模块、串口模块、定时器的PWM模块以及官方会提供源码的LCD模块。
文末有小编写的代码
一、CubeMX配置
1.使能外部高速时钟:
2.配置时钟树:
4.GPIO输入
5. TIM定时器
5.1 TIM2输出PWM脉冲
设置默认Pluse为50,即占空比为50%
5.2 TIM4实现定时5s
5.3 TIM3定时器实现微妙(us)延迟
6.USART(通信)
USART串口接收数据,我使用两种方法实现,大家选取其中一种即可!
1.定长接收数据
2,不定长接收数据+DMA方式
此种方法的核心是空闲中断!
二、代码实现
2.1 main函数实现
int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_TIM2_Init(); MX_USART1_UART_Init(); MX_TIM3_Init(); MX_TIM4_Init(); MX_TIM1_Init(); /* USER CODE BEGIN 2 */ LCD_Init(); LCD_Clear(Black); LCD_SetBackColor(Black); LCD_SetTextColor(White); HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2); led(1,0); led(2,0); led(3,0); led(4,0); led(5,0); led(6,0); led(7,0); led(8,0); HAL_UART_Receive_IT(&huart1, buff, 7); HAL_TIM_Base_Start_IT(&htim4); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ Key_handle(); lcd(); if(key4_count>=3&&led_flag==0) { led(2,1); delay_us(50000); delay_us(50000); led(2,0); delay_us(50000); delay_us(50000); } } /* USER CODE END 3 */ }
2.2 lcd函数实现
void lcd() { if(pass_flag==1) { show_output(); if(systick-PWMTick>5000) { led(1,0); pwm1(); first='@'; first_flag=-1; second='@'; second_flag=-1; third='@'; third_flag=-1; pass_flag=0; LCD_Clear(Black); } } if(pass_flag==0) { show_input(); } } void show_input() { LCD_DisplayStringLine(Line1," PSD "); sprintf(B1," B1:%c",first); LCD_DisplayStringLine(Line3,B1); sprintf(B2," B2:%c",second); LCD_DisplayStringLine(Line4,B2); sprintf(B3," B3:%c",third); LCD_DisplayStringLine(Line5,B3); } char pl[50]; char zkb[50]; int c_pl; int c_ARR; int c_zkb; int c_pluse; void show_output() { LCD_DisplayStringLine(Line1," STA "); c_ARR=__HAL_TIM_GET_AUTORELOAD(&htim2); c_pl=100000/(c_ARR+1); sprintf(pl," F:%dHz",c_pl); LCD_DisplayStringLine(Line3,pl); c_pluse=__HAL_TIM_GET_COMPARE(&htim2,TIM_CHANNEL_2); c_zkb=c_pluse*100/(c_ARR+1); sprintf(zkb," S:%d%%",c_zkb); LCD_DisplayStringLine(Line4,zkb); }
2.3 按键扫描功能实现
int Keynum() { int key=0; if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0)==0) { HAL_Delay(5); if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0)==0) { key=1; LCD_Clear(Black); } while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0)==0); } if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1)==0) { HAL_Delay(5); if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1)==0) { key=2; LCD_Clear(Black); } while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1)==0); } if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)==0) { HAL_Delay(5); if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)==0) { key=3; LCD_Clear(Black); } while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)==0); } if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)==0) { HAL_Delay(5); if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)==0) { key=4; LCD_Clear(Black); } while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)==0); } return key; } char first='@'; int first_flag=-1; char second='@'; int second_flag=-1; char third='@'; int third_flag=-1; char pass1='1'; char pass2='2'; char pass3='3'; int pass_flag=0; int lcd_flag=0; int ledTick=0; void Key_handle() { int keynum=Keynum(); if(keynum==1) { first_flag++; switch(first_flag%10) { case 0:first='0';break; case 1:first='1';break; case 2:first='2';break; case 3:first='3';break; case 4:first='4';break; case 5:first='5';break; case 6:first='6';break; case 7:first='7';break; case 8:first='8';break; case 9:first='9';break; } } if(keynum==2) { second_flag++; switch(second_flag%10) { case 0:second='0';break; case 1:second='1';break; case 2:second='2';break; case 3:second='3';break; case 4:second='4';break; case 5:second='5';break; case 6:second='6';break; case 7:second='7';break; case 8:second='8';break; case 9:second='9';break; } } if(keynum==3) { third_flag++; switch(third_flag%10) { case 0:third='0';break; case 1:third='1';break; case 2:third='2';break; case 3:third='3';break; case 4:third='4';break; case 5:third='5';break; case 6:third='6';break; case 7:third='7';break; case 8:third='8';break; case 9:third='9';break; } } if(keynum==4) { led_flag=0; key4_count++; if(pass1==first&&pass2==second&&pass3==third) { key4_count=0; pass_flag=1; pwm2(); led(1,1); //定时器中断在回调函数中清屏函数不起作用 // __HAL_TIM_CLEAR_FLAG(&htim1,TIM_FLAG_UPDATE); // HAL_TIM_Base_Start_IT(&htim1); PWMTick=systick; } else { pass_flag=0; first='@'; first_flag=-1; second='@'; second_flag=-1; third='@'; third_flag=-1; } if(key4_count>=3) { __HAL_TIM_CLEAR_FLAG(&htim4,TIM_FLAG_UPDATE); HAL_TIM_Base_Start_IT(&htim4); } } }
2.4 PWM脉冲转换
void pwm2() { __HAL_TIM_SET_AUTORELOAD(&htim2,50-1); __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,5); } //方波 void pwm1() { __HAL_TIM_SET_AUTORELOAD(&htim2,100-1); __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,50); }
2.5 某种状态持续5s的两种操作方法
1.利用系统滴答计时器
本实验中 实现输出2KHz 10%占空比的脉冲信号,持续5秒钟,切换为 1KHz 方波信号输出的功能 使用的是系统滴答计时器。
2.TIM定时器定时5s
本实验中实现 指示灯 LD2 以 0.1秒为间隔亮、灭闪烁报警,5 秒后熄灭的功能使用的是TIM4定时器定时5s。
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance==TIM4) { led_flag=1; HAL_TIM_Base_Stop_IT(&htim4); } }
2.6 延迟100ms
delay_us函数实现定时微妙(us)
void delay_us(int delay) { HAL_TIM_Base_Start(&htim3); // 启动定时器 __HAL_TIM_SET_COUNTER(&htim3, 0); // 重置计数器 while (__HAL_TIM_GET_COUNTER(&htim3)delay_us(50000)代表延迟50000us即50ms,但因为定时器最大计数值为65535,如果delay_us(100000)就超过了定时器最大计数值,所以可以采取delay_us(50000)两次来实现100ms定时!
2.7 USART串口与修改密码
USART串口接收数据,我使用两种方法实现,大家选取其中一种即可!
1.接收固定长度数据
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(buff[0]==pass1&&buff[1]==pass2&&buff[2]&&buff[3]=='-'&&judge()==1) { pass1=buff[4]; pass2=buff[5]; pass3=buff[6]; HAL_UART_Transmit(&huart1,(unsigned char *)"Success\r\n", 9, 50); } else { HAL_UART_Transmit(&huart1,(unsigned char *)"error\r\n", 7, 50); } HAL_UART_Receive_IT(&huart1, buff, 7); } int judge() { for(int i=0;i if((buff[i] return 1; } } }
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。
还没有评论,来说两句吧...