蓝桥杯嵌入式 各个模块代码以及部分省赛代码
本文使用hal库以及cubemax介绍各个模块简单逻辑原理以及代码代码简洁包含各个模块源码lanqiao:蓝桥杯嵌入式组省赛代码 - AtomGit | GitCodehttps://gitcode.com/w930747729/lanqiao上面链接为省赛11 - 16届的源代码需要可以下载。有错误请私信。模块led控制寄存器的方式编写按键结构体式实现短按、长按、双击lcd:字符串中实现局部高亮功能频率测量基础方法adc基础方法uart定时器实现 接收不等长字符串i2c:基础写法rtc闹钟实现pwm控制ccr和psc寄存器led原理图该电路板采用74LS573锁存器作为LED驱动电路的核心组件以实现对LCD模块引脚变化的隔离保护。通过这种方式当LCD模块的引脚状态发生变化时不会对LED模块的输出造成干扰。因此每次需要更新LED显示状态时必须向锁存器提供一个脉冲信号以锁存并保持当前的LED数据。结合原理图看出led控制引脚是PC8~PC15。74LS573锁存器的控制引脚是PD2cubemax将PB8~PB15、PD2引脚设置为输出模式然后生成代码代码引脚电平控制寄存器是ODR只需要控制对应引脚的寄存器值就可以改变引脚电平也就是置0或者置1不必调用writepin函数会影响其他引脚电平uint8_t LED_Buff 0xFF; void led_set(uint8_t num, uint8_t state) { if(num 1 || num 8) return; if(state){ LED_Buff ~(0x1 (num - 1)); // 亮 } else{ LED_Buff | (0x1 (num - 1)); // 灭 } GPIOC-ODR (GPIOC-ODR 0x00FF) | ((uint16_t)LED_Buff 8); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); }初始化的时候可以把灯全部关掉// LED 全灭 for(int i 1; i 8; i) { led_set(i, 0); }key原理图按键按下引脚变为低电平需要考虑按键机械抖动使用定时器扫描的方式 消除抖动cubemax本设计采用 TIM7 定时器生成定时中断定时器时钟频率为 80MHz。配置预分频系数为 799800-1自动重装载值 ARR200计数器计数频率为 80000000/(7991)100000Hz计数器每自增 1 次的时间为 0.00001s。当计数器递增至 ARR 设定值 200 时触发溢出中断最终定时中断周期为 0.00001s×2000.002s2ms代码注意要把定时器中断打开以及使用完后需要清楚标志位也就是调用close函数定时器扫描 按键按下 增加计数值time松手手时候进行判断按下时间 判断 情况双击写法单击一次等待一段时间 这段时间之类再次安一次 就可以判断为双击struct key__{ uint16_t time; uint16_t double_time; // 用于记录松手后的等待时间 uint8_t state; // 0:松开, 1:短按(最终确认), 2:长按(最终确认), 3:双击, 4:第一次松手等待中 GPIO_TypeDef *GPIO; uint16_t Pin; }; struct key__ key[4] { {0, 0, 0, GPIOB, GPIO_PIN_0}, // B1 {0, 0, 0, GPIOB, GPIO_PIN_1}, // B2 {0, 0, 0, GPIOB, GPIO_PIN_2}, // B3 {0, 0, 0, GPIOA, GPIO_PIN_0} // B4 }; void key_close(void) { key[0].state 0; key[1].state 0; key[2].state 0; key[3].state 0; } void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim-Instance TIM7) { //2ms 中断 for(int i 0; i 4; i) { if(HAL_GPIO_ReadPin(key[i].GPIO, key[i].Pin) GPIO_PIN_RESET){ if(key[i].state 0 || key[i].state 4){ key[i].time; } }else{ if(key[i].time 5){ if(key[i].time 400){ key[i].state 2; //长按 key[i].time 0; }else if(key[i].time 20 key[i].state 0){ key[i].state 4; key[i].double_time 0; }else if(key[i].state 4){ if(key[i].time 20){ key[i].state 3; //双击 key[i].double_time 0; } } } key[i].time 0; if(key[i].state 4){ key[i].double_time; if(key[i].double_time 100){ key[i].state 1; //短按 key[i].double_time 0; } } } } } }//key 定时器 HAL_TIM_Base_Start_IT(htim7);lcd原理图添加官方资源包就行 lcd.c lcd.h fonts.hcubemax不用设置代码注意 初始化lcd以及清理屏幕控制指针到达的时候 就改变颜色//LCD 初始化 LCD_Init(); LCD_Clear(Black); LCD_SetTextColor(White); LCD_SetBackColor(Black);void LCD_DisplayStringLine_my(u8 Line, u8 *ptr,uint16_t or_color,uint16_t new_color,uint8_t site,uint8_t size) { u32 i 0; u16 refcolumn 319;//319; while ((*ptr ! 0) (i 20)) // 20 { if(i site i site size){ LCD_SetTextColor(new_color); LCD_DisplayChar(Line, refcolumn, *ptr); LCD_SetTextColor(or_color); }else{ LCD_DisplayChar(Line, refcolumn, *ptr); } refcolumn - 16; ptr; i; } }频率测量原理图使用输入捕获方式 捕获引脚上升沿 得到一个周期的时间 计算出频率cubemaxPA15设置TIM2通道1PB4设置TIM3通道1打开中断配置pre为800-1 polarity selection设置为rising edge代码注意打开输入捕获中捕获第一个上升沿得到ccr的值 ccr是上升沿时候存入的cnt值 然后捕获第二个上升沿 得到ccr的值 这就是一个周期 计算周期时间 t 1/80mhz/800* 差值 故 f 80mhz/800 /差值struct fre__ { uint32_t ic_val1; // 第一次捕获的值 uint32_t ic_val2; // 第二次捕获的值 uint32_t diff; // 时间差 float freq; // 计算出的频率 uint8_t ic_flag; // 捕获标志位 }; struct fre__ fre_pb4; struct fre__ fre_pa15; void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if(htim-Instance TIM3) { if(fre_pb4.ic_flag 0) { fre_pb4.ic_val1 HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); fre_pb4.ic_flag 1; } else if(fre_pb4.ic_flag 1) { fre_pb4.ic_val2 HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); if(fre_pb4.ic_val2 fre_pb4.ic_val1) fre_pb4.diff fre_pb4.ic_val2 - fre_pb4.ic_val1; if(fre_pb4.diff 0) fre_pb4.freq 100000.0f / (fre_pb4.diff); fre_pb4.ic_flag 0; } } if(htim-Instance TIM2) { if(fre_pa15.ic_flag 0) { fre_pa15.ic_val1 HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); fre_pa15.ic_flag 1; } else if(fre_pa15.ic_flag 1) { fre_pa15.ic_val2 HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); if(fre_pa15.ic_val2 fre_pa15.ic_val1) fre_pa15.diff fre_pa15.ic_val2 - fre_pa15.ic_val1; if(fre_pa15.diff 0) fre_pa15.freq 100000.0f / (fre_pa15.diff); fre_pa15.ic_flag 0; } } }// 频率测量定时器 HAL_TIM_IC_Start_IT(htim3, TIM_CHANNEL_1); // 启动 TIM3 (PB4) HAL_TIM_IC_Start_IT(htim2, TIM_CHANNEL_1); // 启动 TIM2 (PA15)adc原理图cubemax代码内部使用的是逐次逼近的方法来adc自己百度原理 这里 知道比例就行 x/3.3 val/4096 因为是12位的adc 因此是4096// ADC 读取 double adc1_val 0; double adc2_val 0; double getADC(ADC_HandleTypeDef *hadc) { uint16_t adc_val; HAL_ADC_Start(hadc); HAL_ADCEx_Calibration_Start(hadc, ADC_SINGLE_ENDED); adc_val HAL_ADC_GetValue(hadc); HAL_ADC_Stop(hadc); return adc_val * 3.3 / 4096.0; }uart原理图使用异步通信的方式 结合定时器判断是否发送完数据cubemax波特率 9600 一般比赛就是这个 其余不用更改TIM4设置psc800-1代码注意打开中断以及开启定时器//UART 接收 定时器启动 HAL_UART_Receive_IT(huart1, rx_data, 1); HAL_TIM_Base_Start(htim4);串口发送一个字符之间的时间是1.5ms 因此 定时器来 判断是否 超过这个数据 超过则发送完成将完成的数据存入 数组里面uint8_t rx_data; uint8_t rx_buffer[20]; uint8_t rx_idx 0; uint8_t rx_flag 0; void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart-Instance USART1) { TIM4-CNT 0; // 重置 TIM4 计数器 rx_flag 1; // 设置接收完成标志 rx_buffer[rx_idx] rx_data; // 存储接收到的数据 rx_idx; if(rx_idx20) rx_idx 0; // 防止越界 HAL_UART_Receive_IT(huart1, rx_data, 1); } } void uart_receive(void){ if(TIM4-CNT 150 rx_flag 1){ // 超过150ms未接收新数据认为接收完成 HAL_UART_Transmit(huart1, rx_buffer, rx_idx, 50); for(int i 0; i 20; i) { rx_buffer[i] 0; // 清空接收缓冲区 } rx_idx0; rx_flag 0; TIM4-CNT 0; } }I2C原理图cubemax移植资源包i2c就行代码注意初始化I2C// I2C EEPROM I2CInit();at24c02的写地址就是 0xa0 读地址0xa1 逻辑就是i2c发送接收逻辑: 发送器件地址 发送内存地址 发送数据void e2prrom_write(uint8_t addr, uint8_t data){ I2CStart(); I2CSendByte(0xa0); I2CWaitAck(); I2CSendByte(addr); I2CWaitAck(); I2CSendByte(data); I2CWaitAck(); I2CStop(); HAL_Delay(5); } uint8_t e2prrom_read(uint8_t addr){ I2CStart(); I2CSendByte(0xa0); I2CWaitAck(); I2CSendByte(addr); I2CWaitAck(); I2CStart(); I2CSendByte(0xa1); I2CWaitAck(); uint8_t data I2CReceiveByte(); I2CSendNotAck(); I2CStop(); return data; }RTC原理图无cubemax打开就行 也可设置初始时间 一一对应的设置闹钟需要打开中断代码闹钟中断函数void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc){ led_flag 1; }结构体需要自定义 需要获取时间就调用下面两个函数 time和data这两个函数需要同时使用RTC_TimeTypeDef sTime; RTC_DateTypeDef sDate; RTC_AlarmTypeDef sAlarm; HAL_RTC_GetTime(hrtc, sTime, RTC_FORMAT_BIN); HAL_RTC_GetDate(hrtc, sDate, RTC_FORMAT_BIN); sTime.Hours 10; sTime.Minutes 10; sTime.Seconds 10; HAL_RTC_SetTime(hrtc,sTime,RTC_FORMAT_BIN); HAL_RTC_SetDate(hrtc,sDate,RTC_FORMAT_BIN); sAlarm.AlarmTime.Hours 11; sAlarm.AlarmTime.Minutes 11; sAlarm.AlarmTime.Seconds 11; HAL_RTC_SetAlarm_IT(hrtc,sAlarm,RTC_FORMAT_BIN);PWM原理图无cubemax以PA7为例开启pwm的输出通道控制输出频率 计算 就是 f 主频/psc * arr占空比 puty ccr / arr ccr是比较阈值 cnt达到ccr会实现触发电平改变控制途中mode选项来改变 因此 把arr固定 控制频率就控制 psc 控制puty就控制 ccr代码这两行代码控制ccr和psc__HAL_TIM_SET_COMPARE(htim3,TIM_CHANNEL_2,500); __HAL_TIM_SET_PRESCALER(htim3,800-1);初始化时候 记得开启 pwmHAL_TIM_PWM_Start(htim3,TIM_CHANNEL_2);简单的逻辑讲解 主要是依照源码看一下理解以下就懂了 比较好记忆。以下是我的整体main函数代码 由于代码量少 我就放在一个.c文件里面了/* USER CODE BEGIN Header */ /** ****************************************************************************** * file : main.c * brief : Main program body ****************************************************************************** * attention * * Copyright (c) 2026 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include main.h #include adc.h #include rtc.h #include tim.h #include usart.h #include gpio.h /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include lcd.h #include stdio.h #include string.h #include i2c_hal.h /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ uint8_t led_flag0; char buff[20]; RTC_TimeTypeDef sTime; RTC_DateTypeDef sDate; //按键状态定义0-松开, 1-短按, 2-长按, 3-双击, struct key__{ uint16_t time; uint16_t double_time; // 用于记录松手后的等待时间 uint8_t state; // 0:松开, 1:短按(最终确认), 2:长按(最终确认), 3:双击, 4:第一次松手等待中 GPIO_TypeDef *GPIO; uint16_t Pin; }; struct key__ key[4] { {0, 0, 0, GPIOB, GPIO_PIN_0}, // B1 {0, 0, 0, GPIOB, GPIO_PIN_1}, // B2 {0, 0, 0, GPIOB, GPIO_PIN_2}, // B3 {0, 0, 0, GPIOA, GPIO_PIN_0} // B4 }; void key_close(void) { key[0].state 0; key[1].state 0; key[2].state 0; key[3].state 0; } void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim-Instance TIM7) { //2ms 中断 for(int i 0; i 4; i) { if(HAL_GPIO_ReadPin(key[i].GPIO, key[i].Pin) GPIO_PIN_RESET){ if(key[i].state 0 || key[i].state 4){ key[i].time; } }else{ if(key[i].time 5){ if(key[i].time 400){ key[i].state 2; //长按 key[i].time 0; }else if(key[i].time 20 key[i].state 0){ key[i].state 4; key[i].double_time 0; }else if(key[i].state 4){ if(key[i].time 20){ key[i].state 3; //双击 key[i].double_time 0; } } } key[i].time 0; if(key[i].state 4){ key[i].double_time; if(key[i].double_time 100){ key[i].state 1; //短按 key[i].double_time 0; } } } } } } // LED 状态变量1-亮0-灭 uint8_t LED_Buff 0xFF; void led_set(uint8_t num, uint8_t state) { if(num 1 || num 8) return; if(state){ LED_Buff ~(0x1 (num - 1)); // 亮 } else{ LED_Buff | (0x1 (num - 1)); // 灭 } GPIOC-ODR (uint16_t)LED_Buff 8; HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); } void led_control(void){ if(key[0].state 1){ key_close(); for(int i 1; i 8; i) { led_set(i, 1); // 短按全亮 } }else if(key[0].state 2){ key_close(); for(int i 1; i 8; i) { led_set(i, 0); // 长按全灭 } }else if(key[0].state 3){ key_close(); for(int i 1; i 8; i) { led_set(i, (i % 2)); // 双击奇数亮偶数灭 } }else if(led_flag 1){ led_flag 0; // 奇数灭偶数亮 for(int i 1; i 8; i) { led_set(i, (i % 2 0)); } } } // 频率测量 struct fre__ { uint32_t ic_val1; // 第一次捕获的值 uint32_t ic_val2; // 第二次捕获的值 uint32_t diff; // 时间差 float freq; // 计算出的频率 uint8_t ic_flag; // 捕获标志位 }; struct fre__ fre_pb4; struct fre__ fre_pa15; void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if(htim-Instance TIM3) { if(fre_pb4.ic_flag 0) { fre_pb4.ic_val1 HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); fre_pb4.ic_flag 1; } else if(fre_pb4.ic_flag 1) { fre_pb4.ic_val2 HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); if(fre_pb4.ic_val2 fre_pb4.ic_val1) fre_pb4.diff fre_pb4.ic_val2 - fre_pb4.ic_val1; if(fre_pb4.diff 0) fre_pb4.freq 100000.0f / (fre_pb4.diff); // 修正Prescaler 为 800-1对应 100KHz fre_pb4.ic_flag 0; } } if(htim-Instance TIM2) { if(fre_pa15.ic_flag 0) { fre_pa15.ic_val1 HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); fre_pa15.ic_flag 1; } else if(fre_pa15.ic_flag 1) { fre_pa15.ic_val2 HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); if(fre_pa15.ic_val2 fre_pa15.ic_val1) fre_pa15.diff fre_pa15.ic_val2 - fre_pa15.ic_val1; if(fre_pa15.diff 0) fre_pa15.freq 100000.0f / (fre_pa15.diff); fre_pa15.ic_flag 0; } } } // ADC 读取 double adc1_val 0; double adc2_val 0; double getADC(ADC_HandleTypeDef *hadc) { uint16_t adc_val; HAL_ADC_Start(hadc); adc_val HAL_ADC_GetValue(hadc); HAL_ADC_Stop(hadc); return adc_val * 3.3 / 4096.0; } // UART 接收 uint8_t rx_data; uint8_t rx_buffer[20]; uint8_t rx_idx 0; uint8_t rx_flag 0; void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart-Instance USART1) { TIM4-CNT 0; // 重置 TIM4 计数器 rx_flag 1; // 设置接收完成标志 rx_buffer[rx_idx] rx_data; // 存储接收到的数据 rx_idx; if(rx_idx20) rx_idx 0; // 防止越界 HAL_UART_Receive_IT(huart1, rx_data, 1); } } void uart_receive(void){ if(TIM4-CNT 150 rx_flag 1){ // 超过150ms未接收新数据认为接收完成 HAL_UART_Transmit(huart1, rx_buffer, rx_idx, 50); for(int i 0; i 20; i) { rx_buffer[i] 0; // 清空接收缓冲区 } rx_idx0; rx_flag 0; TIM4-CNT 0; } } // I2C EEPROM 读写 void e2prrom_write(uint8_t addr, uint8_t data){ I2CStart(); I2CSendByte(0xa0); I2CWaitAck(); I2CSendByte(addr); I2CWaitAck(); I2CSendByte(data); I2CWaitAck(); I2CStop(); HAL_Delay(5); } uint8_t e2prrom_read(uint8_t addr){ I2CStart(); I2CSendByte(0xa0); I2CWaitAck(); I2CSendByte(addr); I2CWaitAck(); I2CStart(); I2CSendByte(0xa1); I2CWaitAck(); uint8_t data I2CReceiveByte(); I2CSendNotAck(); I2CStop(); return data; } // RTC 闹钟回调 void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc){ led_flag 1; } //LCD 显示字符串支持局部高亮 void LCD_DisplayStringLine_my(u8 Line, u8 *ptr, u16 set_color, u16 now_color , u8 site, u8 size) { u32 i 0; u16 refcolumn 319;//319; u8 *ptr_site; ptr_site ptr site - 1; while ((*ptr ! 0) (i 20)) // 20 { if(ptr ptr_site){ while(size--){ LCD_SetTextColor(set_color); LCD_DisplayChar(Line, refcolumn, *ptr); refcolumn - 16; ptr; i; } } LCD_SetTextColor(now_color); LCD_DisplayChar(Line, refcolumn, *ptr); refcolumn - 16; ptr; i; } } /* USER CODE END 0 */ /** * brief The application entry point. * retval int */ 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_TIM7_Init(); MX_TIM2_Init(); MX_TIM3_Init(); MX_ADC1_Init(); MX_ADC2_Init(); MX_USART1_UART_Init(); MX_TIM4_Init(); MX_RTC_Init(); /* USER CODE BEGIN 2 */ //key 定时器 HAL_TIM_Base_Start_IT(htim7); // 频率测量定时器 HAL_TIM_IC_Start_IT(htim3, TIM_CHANNEL_1); // 启动 TIM3 (PB4) HAL_TIM_IC_Start_IT(htim2, TIM_CHANNEL_1); // 启动 TIM2 (PA15) //LCD 初始化 LCD_Init(); LCD_Clear(Black); LCD_SetTextColor(White); LCD_SetBackColor(Black); // PWM 输出 HAL_TIM_PWM_Start(htim2, TIM_CHANNEL_2); __HAL_TIM_SET_COMPARE(htim2, TIM_CHANNEL_2, 500); // 设置 PWM 占空比为 50% //UART 接收 定时器启动 HAL_UART_Receive_IT(huart1, rx_data, 1); HAL_TIM_Base_Start(htim4); // I2C EEPROM I2CInit(); e2prrom_write(0,10); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ // LED 全灭 for(int i 1; i 8; i) { led_set(i, 0); } //LCD 局部高亮测试 sprintf(buff, hello world); LCD_DisplayStringLine_my(Line0, (uint8_t *)buff, Red, White, 8, 2); while (1) { adc1_val getADC(hadc1); adc2_val getADC(hadc2); sprintf(buff, ADC1:%.2fV , adc1_val); LCD_DisplayStringLine(Line1, (uint8_t *)buff); sprintf(buff, ADC2:%.2fV , adc2_val); LCD_DisplayStringLine(Line2, (uint8_t *)buff); sprintf(buff, PB4: %.2fHz , fre_pb4.freq); LCD_DisplayStringLine(Line3, (uint8_t *)buff); sprintf(buff, PA15: %.2fHz , fre_pa15.freq); LCD_DisplayStringLine(Line4, (uint8_t *)buff); sprintf(buff, -----------------); LCD_DisplayStringLine(Line5, (uint8_t *)buff); sprintf(buff, UART RX: %s, rx_buffer); LCD_DisplayStringLine(Line6, (uint8_t *)buff); uart_receive(); sprintf(buff, e2prom:%d, e2prrom_read(0)); LCD_DisplayStringLine(Line7, (uint8_t *)buff); HAL_RTC_GetTime(hrtc, sTime, RTC_FORMAT_BIN); HAL_RTC_GetDate(hrtc, sDate, RTC_FORMAT_BIN); sprintf(buff, time: %02d:%02d:%02d , sTime.Hours, sTime.Minutes, sTime.Seconds); LCD_DisplayStringLine(Line8, (uint8_t *)buff); sprintf(buff, date: %d/%02d/%d, sDate.Year2000, sDate.Month, sDate.Date); LCD_DisplayStringLine(Line9, (uint8_t *)buff); led_control(); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } /** * brief System Clock Configuration * retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct {0}; /** Configure the main internal regulator output voltage */ HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState RCC_HSE_ON; RCC_OscInitStruct.LSIState RCC_LSI_ON; RCC_OscInitStruct.PLL.PLLState RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM RCC_PLLM_DIV3; RCC_OscInitStruct.PLL.PLLN 20; RCC_OscInitStruct.PLL.PLLP RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ RCC_PLLQ_DIV2; RCC_OscInitStruct.PLL.PLLR RCC_PLLR_DIV2; if (HAL_RCC_OscConfig(RCC_OscInitStruct) ! HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(RCC_ClkInitStruct, FLASH_LATENCY_2) ! HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ /** * brief This function is executed in case of error occurrence. * retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * param file: pointer to the source file name * param line: assert_param error line source number * retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf(Wrong parameters value: file %s on line %d\r\n, file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */