当前位置:   article > 正文

蓝桥杯嵌入式第十四届模拟赛第一期--程序设计部分_蓝桥杯嵌入式第14届第一次模拟

蓝桥杯嵌入式第14届第一次模拟

原题:

代码:

LCD显示:

  1. void lcd_proc(void)
  2. {
  3. char text[30];
  4. VR37=getADC(&hadc2);
  5. if(view)//数据界面
  6. {
  7. sprintf(text," DATA ");
  8. LCD_DisplayStringLine(Line3,(uchar*)text);
  9. sprintf(text," VR37:%.2lfV ",VR37);
  10. LCD_DisplayStringLine(Line4,(uchar*)text);
  11. sprintf(text," PA7:%dHz ",PA7);
  12. LCD_DisplayStringLine(Line5,(uchar*)text);
  13. }else//参数设置界面
  14. {
  15. sprintf(text," PARA ");
  16. LCD_DisplayStringLine(Line3,(uchar*)text);
  17. sprintf(text," VP1:%.1lfV ",VP1);
  18. LCD_DisplayStringLine(Line4,(uchar*)text);
  19. }
  20. }

这个按照题目要求来就是了,没有什么需要注意的地方。

KEY:

  1. void key_proc(void)
  2. {
  3. if(keys[0].single_flag==1)//按键B1 切换界面
  4. {
  5. view=!view;
  6. LCD_Clear(Black);
  7. keys[0].single_flag=0;//防止重复
  8. }else if(keys[1].single_flag==1)//按键B2
  9. {
  10. if(view==0)//只在参数界面有效
  11. {
  12. VP1+=0.3;
  13. if(VP1>=3.4) VP1=0.0;
  14. }
  15. keys[1].single_flag=0;
  16. }else if(keys[2].single_flag==1)//按键B3
  17. {
  18. if(view==1)//只在数据界面有效
  19. {
  20. PA7+=1000;
  21. if(PA7>=11000) PA7=1000;
  22. value=1000000/(PA7);
  23. __HAL_TIM_SetAutoreload(&htim3,value-1);
  24. __HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,(value+1)*pwm/100);
  25. }
  26. keys[2].single_flag=0;
  27. }
  28. }

对于每个按键的处理,唯一的难点可能就是在调整频率的时候,同时要调整占空比,因为调整重装载值也会影响到占空比,需要维持占空比的不变。

__HAL_TIM_SetAutoreload(&htim3,value-1);//调整重装载值

__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,(value+1)*pwm/100);//调整占空比

 LED:

  1. void led_proc(void)
  2. {
  3. if(VR37>VP1)
  4. {
  5. if(uwTick-ledTick<100) return ;
  6. ledTick=uwTick;
  7. reverse_bit(&led_sta,2);
  8. }else
  9. {
  10. clear_bit(&led_sta,2);
  11. }
  12. if(view==1)
  13. set_bit(&led_sta,0);
  14. else
  15. clear_bit(&led_sta,0);
  16. if(view==0)
  17. set_bit(&led_sta,1);
  18. else
  19. clear_bit(&led_sta,1);
  20. LED_Display(led_sta);
  21. }

此题目的只有三种亮灯情况:

  • 当前显示:数据界面,LD1亮,否则灭
  • 当前显示:参数界面,LD2亮,否则灭
  • 当VR37>VP1:LD以0.1s的频率闪烁

 这里将LED的状态用一个变量 led_sta 保存,通过函数对这个变量里面的各个位数进行修改即可。唯一的重点是LD3的闪烁。应该是可以使用定时器来完成闪烁的,在中断里面实现反转LD3,但是不知道为啥,我用定时器会出错,频率会变,所以就用了另一种方法,SysTick,能够不用开定时器也能起到计时的功能。uwTick 记录板子上电运行的时间,每毫秒加一,通过这个来记录时间变化,在 if 判断下面的语句将每过 100 ms 执行一次,也就实现了LD3的以0.1ms的闪烁。

USART:

  1. void uart_rx(void)
  2. {
  3. char text[30];
  4. if(rx_p>0)
  5. {
  6. if(rx_p==1)
  7. {
  8. char temp[2];
  9. sscanf(rxdata,"%s",temp);
  10. int t=temp[0]-'0';
  11. if(t>=1&&t<=9)
  12. {
  13. pwm=t*10;
  14. __HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,(value+1)*pwm/100);
  15. }else
  16. {
  17. sprintf(text,"Error\r\n");
  18. HAL_UART_Transmit(&huart1,(uint8_t*)text,strlen(text),50);
  19. }
  20. }
  21. rx_p=0;
  22. memset(rxdata,0,30);
  23. }
  24. }

串口读到的数据在 rxdata 中,通过 sscanf 将数据读取出来存到一个变量中,判断该变量是否合法,如果合法,则对占空比进行更改,否则通过串口输出一个Error。

实用小函数:

  1. //在变量 num 中对 bit_index 位置0
  2. void clear_bit(unsigned char *num, int bit_index)
  3. {
  4. *num = (*num & ~(1 << bit_index));
  5. }
  6. //在变量 num 中对 bit_index 位置1
  7. void set_bit(unsigned char *num, int bit_index)
  8. {
  9. *num = (*num & ~(1 << bit_index)) | (1 << bit_index);
  10. }
  11. //在变量 num 中对 bit_index 位反转
  12. void reverse_bit(unsigned char *num, int bit_index) {
  13. unsigned char reversed = (*num) >> bit_index;
  14. reversed = reversed ^ (1 << bit_index);
  15. *num = (*num) ^ reversed;
  16. }

lcd.c

该文件是官方所给出的,但是在板子上LCD与LED的引脚是相互冲突的,有时候会影响LED的值,需要对以下三个函数进行如下更改:

main.c

  1. /* USER CODE BEGIN Header */
  2. /**
  3. ******************************************************************************
  4. * @file : main.c
  5. * @brief : Main program body
  6. ******************************************************************************
  7. * @attention
  8. *
  9. * Copyright (c) 2024 STMicroelectronics.
  10. * All rights reserved.
  11. *
  12. * This software is licensed under terms that can be found in the LICENSE file
  13. * in the root directory of this software component.
  14. * If no LICENSE file comes with this software, it is provided AS-IS.
  15. *
  16. ******************************************************************************
  17. */
  18. /* USER CODE END Header */
  19. /* Includes ------------------------------------------------------------------*/
  20. #include "main.h"
  21. #include "adc.h"
  22. #include "tim.h"
  23. #include "usart.h"
  24. #include "gpio.h"
  25. /* Private includes ----------------------------------------------------------*/
  26. /* USER CODE BEGIN Includes */
  27. #include "lcd.h"
  28. #include "stdio.h"
  29. #include "interrupt.h"
  30. #include "myadc.h"
  31. #include "string.h"
  32. #include "led.h"
  33. /* USER CODE END Includes */
  34. /* Private typedef -----------------------------------------------------------*/
  35. /* USER CODE BEGIN PTD */
  36. extern struct key keys[4];
  37. extern char rxdata[30];
  38. extern uint8_t rxdat;
  39. extern uchar rx_p;
  40. extern uint frq;
  41. extern float duty;
  42. int pwm=10;
  43. int view=1;
  44. double VR37=2.35;
  45. int PA7=1000;
  46. double VP1=0.3;
  47. int value=1000-1;
  48. uchar led_sta=0x00;
  49. int LD3=0;
  50. __IO uint32_t ledTick=0;
  51. /* USER CODE END PTD */
  52. /* Private define ------------------------------------------------------------*/
  53. /* USER CODE BEGIN PD */
  54. /* USER CODE END PD */
  55. /* Private macro -------------------------------------------------------------*/
  56. /* USER CODE BEGIN PM */
  57. /* USER CODE END PM */
  58. /* Private variables ---------------------------------------------------------*/
  59. /* USER CODE BEGIN PV */
  60. /* USER CODE END PV */
  61. /* Private function prototypes -----------------------------------------------*/
  62. void SystemClock_Config(void);
  63. /* USER CODE BEGIN PFP */
  64. void lcd_proc(void);
  65. void key_proc(void);
  66. void led_proc(void);
  67. void uart_rx(void);
  68. void clear_bit(unsigned char *num, int bit_index);
  69. void set_bit(unsigned char *num, int bit_index);
  70. void reverse_bit(unsigned char *num, int bit_index);
  71. /* USER CODE END PFP */
  72. /* Private user code ---------------------------------------------------------*/
  73. /* USER CODE BEGIN 0 */
  74. /* USER CODE END 0 */
  75. /**
  76. * @brief The application entry point.
  77. * @retval int
  78. */
  79. int main(void)
  80. {
  81. /* USER CODE BEGIN 1 */
  82. /* USER CODE END 1 */
  83. /* MCU Configuration--------------------------------------------------------*/
  84. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  85. HAL_Init();
  86. /* USER CODE BEGIN Init */
  87. /* USER CODE END Init */
  88. /* Configure the system clock */
  89. SystemClock_Config();
  90. /* USER CODE BEGIN SysInit */
  91. /* USER CODE END SysInit */
  92. /* Initialize all configured peripherals */
  93. MX_GPIO_Init();
  94. MX_TIM4_Init();
  95. MX_ADC2_Init();
  96. MX_USART1_UART_Init();
  97. MX_TIM3_Init();
  98. MX_TIM2_Init();
  99. MX_TIM8_Init();
  100. /* USER CODE BEGIN 2 */
  101. LCD_Init();
  102. LCD_SetBackColor(Black);
  103. LCD_SetTextColor(White);
  104. LCD_Clear(Black);
  105. HAL_TIM_Base_Start_IT(&htim4);
  106. //HAL_TIM_Base_Start_IT(&htim2);
  107. HAL_UART_Receive_IT(&huart1,&rxdat,1);//开启中断
  108. HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);//初始化
  109. HAL_TIM_IC_Start_IT(&htim8,TIM_CHANNEL_1);
  110. /* USER CODE END 2 */
  111. /* Infinite loop */
  112. /* USER CODE BEGIN WHILE */
  113. while (1)
  114. {
  115. lcd_proc();
  116. key_proc();
  117. led_proc();
  118. if(rx_p!=0)
  119. {
  120. int temp=rx_p;
  121. HAL_Delay(1);
  122. if(temp==rx_p) uart_rx();
  123. }
  124. /* USER CODE END WHILE */
  125. /* USER CODE BEGIN 3 */
  126. }
  127. /* USER CODE END 3 */
  128. }
  129. /* USER CODE BEGIN 4 */
  130. void lcd_proc(void)
  131. {
  132. char text[30];
  133. VR37=getADC(&hadc2);
  134. if(view)//数据界面
  135. {
  136. sprintf(text," DATA ");
  137. LCD_DisplayStringLine(Line3,(uchar*)text);
  138. sprintf(text," VR37:%.2lfV ",VR37);
  139. LCD_DisplayStringLine(Line4,(uchar*)text);
  140. sprintf(text," PA7:%dHz ",PA7);
  141. LCD_DisplayStringLine(Line5,(uchar*)text);
  142. }else//参数设置界面
  143. {
  144. sprintf(text," PARA ");
  145. LCD_DisplayStringLine(Line3,(uchar*)text);
  146. sprintf(text," VP1:%.1lfV ",VP1);
  147. LCD_DisplayStringLine(Line4,(uchar*)text);
  148. }
  149. }
  150. void key_proc(void)
  151. {
  152. if(keys[0].single_flag==1)
  153. {
  154. view=!view;
  155. LCD_Clear(Black);
  156. keys[0].single_flag=0;
  157. }else if(keys[1].single_flag==1)
  158. {
  159. if(view==0)
  160. {
  161. VP1+=0.3;
  162. if(VP1>=3.4) VP1=0.0;
  163. }
  164. keys[1].single_flag=0;
  165. }else if(keys[2].single_flag==1)
  166. {
  167. if(view==1)
  168. {
  169. PA7+=1000;
  170. if(PA7>=11000) PA7=1000;
  171. value=1000000/(PA7);
  172. __HAL_TIM_SetAutoreload(&htim3,value-1);
  173. __HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,(value+1)*pwm/100);
  174. }
  175. keys[2].single_flag=0;
  176. }
  177. }
  178. void led_proc(void)
  179. {
  180. if(VR37>VP1)
  181. {
  182. if(uwTick-ledTick<100) return ;
  183. ledTick=uwTick;
  184. reverse_bit(&led_sta,2);
  185. }else
  186. {
  187. clear_bit(&led_sta,2);
  188. }
  189. if(view==1)
  190. set_bit(&led_sta,0);
  191. else
  192. clear_bit(&led_sta,0);
  193. if(view==0)
  194. set_bit(&led_sta,1);
  195. else
  196. clear_bit(&led_sta,1);
  197. LED_Display(led_sta);
  198. }
  199. void uart_rx(void)
  200. {
  201. char text[30];
  202. if(rx_p>0)
  203. {
  204. if(rx_p==1)
  205. {
  206. char temp[2];
  207. sscanf(rxdata,"%s",temp);
  208. int t=temp[0]-'0';
  209. if(t>=1&&t<=9)
  210. {
  211. pwm=t*10;
  212. __HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,(value+1)*pwm/100);
  213. }else
  214. {
  215. sprintf(text,"Error\r\n");
  216. HAL_UART_Transmit(&huart1,(uint8_t*)text,strlen(text),50);
  217. }
  218. }
  219. rx_p=0;
  220. memset(rxdata,0,30);
  221. }
  222. }
  223. void clear_bit(unsigned char *num, int bit_index)
  224. {
  225. *num = (*num & ~(1 << bit_index));
  226. }
  227. void set_bit(unsigned char *num, int bit_index)
  228. {
  229. *num = (*num & ~(1 << bit_index)) | (1 << bit_index);
  230. }
  231. void reverse_bit(unsigned char *num, int bit_index) {
  232. unsigned char reversed = (*num) >> bit_index;
  233. reversed = reversed ^ (1 << bit_index);
  234. *num = (*num) ^ reversed;
  235. }
  236. /* USER CODE END 4 */
  237. #endif /* USE_FULL_ASSERT */

interrupt.c

  1. #include "interrupt.h"
  2. #include "usart.h"
  3. struct key keys[4];
  4. extern int view;
  5. extern int LD3;
  6. extern uchar led_sta;
  7. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  8. {
  9. if(htim->Instance==TIM4)//中断来源
  10. {
  11. //读取四个按键的状态
  12. keys[0].key_status=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
  13. keys[1].key_status=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
  14. keys[2].key_status=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
  15. keys[3].key_status=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
  16. //状态机消抖
  17. for(int i=0;i<4;i++)
  18. {
  19. switch(keys[i].judge_status)
  20. {
  21. case 0:
  22. {
  23. if(keys[i].key_status==0)
  24. {
  25. keys[i].judge_status=1;
  26. keys[i].key_time=0;
  27. }
  28. }
  29. break;
  30. case 1:
  31. {
  32. if(keys[i].key_status==0)
  33. {
  34. keys[i].judge_status=2;
  35. }else
  36. {
  37. keys[i].judge_status=0;
  38. }
  39. }
  40. break;
  41. case 2:
  42. {
  43. if(keys[i].key_status==0)
  44. {
  45. keys[i].key_time++;
  46. if(keys[i].key_time>=70)
  47. {
  48. keys[i].long_flag=1;
  49. }
  50. }else
  51. {
  52. keys[i].judge_status=0;
  53. if(keys[i].key_time<70)
  54. {
  55. keys[i].single_flag=1;
  56. }
  57. }
  58. }
  59. break;
  60. }
  61. }
  62. }
  63. }
  64. char rxdata[30];
  65. uint8_t rxdat;
  66. uchar rx_p;
  67. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  68. {
  69. rxdata[rx_p++]=rxdat;
  70. HAL_UART_Receive_IT(&huart1,&rxdat,1);
  71. }
  72. //输入捕获,测试所用
  73. double ccrl_vala=0,ccrl_valb=0;
  74. uint frq=0;
  75. float duty=0;
  76. void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
  77. {
  78. if(htim->Instance==TIM8)
  79. {
  80. if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1) //中断消息来源 选择直接输入的通道
  81. {
  82. //读取定时器的计时值
  83. ccrl_vala=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);
  84. ccrl_valb=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2);
  85. //将定时器的计时值清零
  86. __HAL_TIM_SetCounter(htim,0);
  87. //计算频率 主频/分频系数/计时值
  88. frq=(80000000/80)/ccrl_vala;
  89. duty=(ccrl_valb/ccrl_vala)*100;
  90. HAL_TIM_IC_Start(htim,TIM_CHANNEL_1);
  91. HAL_TIM_IC_Start(htim,TIM_CHANNEL_2);
  92. }
  93. }
  94. }

interrupt.h

  1. #ifndef _INTERRUPT_H_
  2. #define _INTERRUPT_H_
  3. #include "led.h"
  4. #include "main.h"
  5. #include "stdbool.h"
  6. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
  7. struct key
  8. {
  9. bool single_flag;
  10. bool long_flag;
  11. unsigned int key_time;
  12. unsigned int key_status;
  13. unsigned int judge_status;
  14. };
  15. #endif

led.c

  1. #include "led.h"
  2. void LED_Display(uchar dsLED)
  3. {
  4. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET); //将GPIOC的所有引脚全部置高电平,LED灯熄灭
  5. HAL_GPIO_WritePin(GPIOC,dsLED<<8,GPIO_PIN_RESET); //根据dsLEDd的数值将对应LED点亮
  6. HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET); //将锁存器打开
  7. HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET); //将锁存器关闭
  8. }

led.h

  1. #ifndef _LED_H_
  2. #define _LED_H_
  3. #include "main.h"
  4. void LED_Display(uchar dsLED);
  5. #endif

myadc.c

  1. #include "myadc.h"
  2. //读取adc
  3. double getADC(ADC_HandleTypeDef *pin)
  4. {
  5. unsigned int adc;
  6. HAL_ADC_Start(pin);
  7. adc=HAL_ADC_GetValue(pin);
  8. return adc*3.3/4096;
  9. }

myadc.h

  1. #ifndef _MYADC_H_
  2. #define _MYADC_H_
  3. #include "main.h"
  4. double getADC(ADC_HandleTypeDef *pin);
  5. #endif

  ----THE END-----

有关蓝桥杯嵌入式的模块知识请参考如下:

蓝桥杯嵌入式模块学习系列

【蓝桥杯嵌入式学习G431】模块一:LED-CSDN博客

【蓝桥杯嵌入式学习G431】模块二:LCD-CSDN博客

【蓝桥杯嵌入式学习G431】模块三:KEY-CSDN博客

【蓝桥杯嵌入式学习G431】模块四:PWM-CSDN博客

【蓝桥杯嵌入式学习G431】模块五:USART-CSDN博客

【蓝桥杯嵌入式学习G431】模块六:ADC-CSDN博客

(还有几个模块没更新~)


有关蓝桥杯嵌入式历届真题请参考如下:

蓝桥杯嵌入式历届真题系列

蓝桥杯嵌入式第十二届省赛--程序设计部分-CSDN博客

蓝桥杯嵌入式第十三届省赛第一场--程序设计部分-CSDN博客

蓝桥杯嵌入式第十五届模拟赛--程序设计部分-CSDN博客

蓝桥杯嵌入式第十四届模拟赛第一期--程序设计部分-CSDN博客 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/705972
推荐阅读
相关标签
  

闽ICP备14008679号