〇、新建工程
①打开STM32Cube,点击中间部分的“Access To MCU SELECTOR”;
②搜索“STM32G431RBT6”
③“System Core”中点“RCC”,“High Speed Clock(HSE)”选择“Crystal/Ceramic Resonator”(外部时钟使能),“SYS”中“Debug”选择“Serial Wire”;
④时钟配置输入24MHz,选择“HSE”,选择“PLLCLK”,“HCLK(MHz)”选择“80MHz”回车;
最终:
⑤设置引脚,包括看GPIO默认输出状态(eg.例如设置GPIO output level为High);
⑥点“Project Manager”中,“Project”的“Project Name”设置名字,“Toolchain/IDE”设置“MDK-ARM” “Min Version” 设置版本(eg.本机为“v5”),下方“Use Default Firmware Location”勾选取消,点击最后方三个点选择库文件打开;
⑦“Code Generator”中“Generated files”的第一个“Generate peripheral initialzation as a pair of ...”,点击“GENERATE CODE”生成代码打开;
一、点亮LED
step1: PD2输出高电平(PD2为使能端)
step2: PC8~PC15输出低电平,即点亮
step3: PD2输出低电平
注意:
PS: 下载要注意去“魔术棒”那里设置一下,“Debug”的右半边“Use”选择“CMSIS-DAP Debugger”
再勾选“Reset and Run”
.h文件最后留一行可以避免Waring
void led_show(uint8_t led,uint8_t mode)
{
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
if(mode)//mode==1,置低电平,即点亮
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8 << (led - 1),GPIO_PIN_RESET);
else
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8 << (led - 1),GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
二、按键
属于上拉输入,即按键没有按下时输入得到高电平,按键按下时,输入得到低电平;
uint8_t led1_state=0;
void key_scan()
{
B1_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);
if(B1_state == 0 && B1_last_state ==1)//按键S1按下
{
if(led1_state)
led1_state=0;
else
led1_state=1;
led_show(1,led1_state);
}
B1_last_state = B1_state;
}
三、LCD
重要:解决lcd与led引脚冲突问题
这些lcd函数改变了pc端的引脚的一个输出,一开始配置的时候将PD2置成高电平,是为了让初始化的时候就让led的一端即led的负端置高电平,默认一个熄灭的状态---》由此我们可以在lcd初始化之前让PD2置低电平
(即加上: HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);) 这样lcd就不会去改变led的状态
然后再到 LCD_DisplayStringLine(u8 Line, u8 *ptr)
函数中增加一句:
uint16_t temp = GPIOC->ODR;
就是在执行这个函数之前先把PC端这个输出状态全部存到这个temp变量里面;
再在结束之后将它的输出状态给它复原:
GPIOC->ODR = temp;
四、LED闪烁
1、原理:定时器中断
在Cube里选择TIM2(即通用定时器,TIM1是高级定时器)
(PSC是预分频器,ARR是自动重装载值,CNT是计时器)
PS: PSC不能超过2的16次方即65535;
再点“NMC Settings”,选择使能(Enable打勾);
五、长按键和短按键
①TIM3中Clock Source选择“Internal Clock”(内部时钟)
②PSC设置为8000-1,ARR直接设置为最大值即可(65535)
if(B1_state == 0 && B1_last_state ==1)//按键B1按下
{
TIM3->CNT = 0;
}
else if(B1_state == 0 && B1_last_state == 0)//当按键B1一直按着
{
if(TIM3->CNT >= 10000)//按键B1长按
{
count++;
}
}
else if(B1_state == 1 && B1_last_state == 0)//当按键B1松开
{
if(TIM3->CNT < 10000)
{
count += 2;
}
}
PS:在main函数中记得使能tim3
HAL_TIM_Base_Start(&htim3);//使能
六、lcd高亮显示
①首先定义一个变量uint8_t lcd_highshow;
②在按下某个按钮的时候lcd_highshow++,然后lcd_highshow对3取余(因为有三种选项可以高亮),确保lcd_highshow在0,1,2循环;
uint8_t lcd_highshow;
if(B4_state == 0 && B4_last_state ==1)//按键B4按下
{
lcd_highshow++;
lcd_highshow %= 3;
led_show(2, 0);
}
void lcd_show()
{
sprintf(text," text ");
LCD_DisplayStringLine(Line0,(uint8_t *)text);
if(lcd_highshow == 0)
{
LCD_SetBackColor(Yellow);//高亮显示
sprintf(text," count:%d ",count);
LCD_DisplayStringLine(Line3,(uint8_t *)text);
LCD_SetBackColor(Black);
sprintf(text," pare1 ");
LCD_DisplayStringLine(Line4,(uint8_t *)text);
sprintf(text," pare2 ");
LCD_DisplayStringLine(Line5,(uint8_t *)text);
}
else if(lcd_highshow == 1)
{
sprintf(text," count:%d ",count);
LCD_DisplayStringLine(Line3,(uint8_t *)text);
LCD_SetBackColor(Yellow);//高亮显示
sprintf(text," pare1 ");
LCD_DisplayStringLine(Line4,(uint8_t *)text);
LCD_SetBackColor(Black);
sprintf(text," pare2 ");
LCD_DisplayStringLine(Line5,(uint8_t *)text);
}
else if(lcd_highshow == 2)
{
sprintf(text," count:%d ",count);
LCD_DisplayStringLine(Line3,(uint8_t *)text);
sprintf(text," pare1 ");
LCD_DisplayStringLine(Line4,(uint8_t *)text);
LCD_SetBackColor(Yellow);//高亮显示
sprintf(text," pare2 ");
LCD_DisplayStringLine(Line5,(uint8_t *)text);
LCD_SetBackColor(Black);
}
led_show(1,led_mode);
}
七、PWM输出
①打开Cube创建完工程,然后将引脚PA1设置为TIM2_CH2;
②Timers中选择TIM2,再在TIM2中Channel2选择“PWM Generation CH2”
③计算当输出频率为1000Hz时的ARR值与PSC值;
④修改ARR与PSC值,生成代码;
设置频率
⑤打开keil文件,点开tim.c前面的"+"号(如果没有出现加号,则可以先编译一下),然后找到“stm32g4xx_hal_tim.h”打开,找到HAL_TIM_PWM_Start(大概在2400多行)将其复制粘贴到main函数的可输入代码段中,参数选择&htim2与TIM_CHANNEL_2(可以去函数的定义找);
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
设置占空比
⑥计算占空比
⑦在
main函数中写入TIM2->CCR2 = 50(通道2对应CCR2,CRR2 = 50 即 占空比为 50%)
⑧CCR全称叫输出比较寄存器
当CCR>CNT时,PA1输出;当CCR<CNT时,PA1输出0;
占空比=0.5s/1s=50%=CCR*t/(ARR+1)*t=CCR/(ARR+1)
八、输入捕获量测量引脚输出PWM频率
1、
caoture_value为捕获值
2、配置PA7引脚完成脉冲捕获功能
①TIM17 CH1与TIM3 CH2都可以实现,这里选择TIM17 CH1
②选择TIM17,勾选“Activated”,Channel选择“Input Capture direct mode”(即输入捕获)
③把PSC设置成80-1,在点击“NMC Settings”选择使能(PS:预分频的大小要介于可以测量高频率和低频信号不会溢出;捕获定时器的频率至少要高于输入信号的频率)
④把test1中的code文件夹copy过来(记得添加路径)
⑤在tim.h中的stm32g4xx_hal_tim.h文件中找到“
HAL_StatusTypeDef HAL_TIM_IC_Start_IT**复制,并粘贴在main函数中;
HAL_TIM_IC_Start_IT(&htim17,TIM_CHANNEL_1);
//因为我们设置PA1为TIM17,CH1的捕获输入
⑥在stm32g4xx_hal_tim.h文件中找到HAL_TIM_IC_CaptureCallback(输入捕获回调函数),在fun.c中写输入捕获测量的中断函数
PS: 在写到if(htim->Instance == TIM17) 时去stm32g4xx_hal_tim.h中 ctrl+F 查找函数readcapture(获取捕获值的函数)
uint32_t fre,capture_value;//fre为频率,capture_value为捕获值
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM17)
{
capture_value = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);
TIM17->CNT = 0;//将计数器清零
fre = 80000000/(80*capture_value);//测量频率
}
}
⑦写lcd_show
fun.c文件中写入:
uint32_t fre,capture_value;//fre为频率,capture_value为捕获值
char text[20];
void lcd_show()
{
sprintf(text," text ");
LCD_DisplayStringLine(Line0,(uint8_t *)text);
sprintf(text," fre:%d ",fre);
LCD_DisplayStringLine(Line2,(uint8_t *)text);
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM17)
{
//不用调用函数的另一种写法:capture_value = TIM17->CCR1;
capture_value = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);//中断时获取一个捕获值
//去ReadCheaper函数的定义中会发现其实读取CCR的值,这是因为在捕获到上升沿的时候会将CNT赋值给CCR
TIM17->CNT = 0;//将计数器清零
fre = 80000000/(80*capture_value);//测量频率
}
}
PS:去ReadCheaper函数的定义中会发现其实读取CCR的值,这是因为在捕获到上升沿的时候会将CNT赋值给CCR,故而也可以直接写capture_value = TIM17->CCR1;
LCD_Init();
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
九、输入捕获测555定时器频率
①配置一个test03_input_capture,芯片图基本配置(PA14配置“SYS_JTCK—SWCLK”,PA13配置“SYS_JTMS—SWDIO”,PF0配置“RCC_OSC_IN”,PF1配置“RCC_OSC_OUT”);
②PA15配置“TIM2_CH1”;
③PB4配置“TIM16_CH1”;
④Timers中“TIM2”选择“Channel1”中的“Input Capture direct mode”(输入捕获直接模式)
⑤PSC设置成80-1
⑥“NVIC Settings”使能(选择“Enable”)
⑦TIM16勾选一下“Activated”,Channel再选择“Input Capture direct mode”,PSC设置成80-1,生成文件
⑧打开C文件,把code文件添加一下(包括文件路径,Debug等等)
在
main函数中输入一下代码(用于使能):
/* USER CODE BEGIN 2 */
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim16,TIM_CHANNEL_1);
/* USER CODE END 2 */
⑨在fun.c函数中写HAL_TIM_IC_CaptureCallback(频率输出函数)和lcd_show:
uint32_t fre1,capture_value1,fre2,capture_value2;//fre为频率,capture_value为捕获值
char text[20];
void lcd_show()
{
sprintf(text," text ");
LCD_DisplayStringLine(Line0,(uint8_t *)text);
sprintf(text," R39_fre1:%d ",fre1);
LCD_DisplayStringLine(Line2,(uint8_t *)text);
sprintf(text," R40_fre2:%d ",fre2);
LCD_DisplayStringLine(Line4,(uint8_t *)text);
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM16)//频率输出1 R39
{//
//不用调用函数的另一种写法:capture_value = TIM16->CCR1;
capture_value1 = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);//中断时获取一个捕获值
//去ReadCheaper函数的定义中会发现其实读取CCR的值,这是因为在捕获到上升沿的时候会将CNT赋值给CCR
TIM16->CNT = 0;//将计数器清零
fre1 = 80000000/(80*capture_value1);//测量频率
}
if(htim->Instance == TIM2)//频率输出2 R40
{
//不用调用函数的另一种写法:capture_value = TIM2->CCR1;
capture_value2 = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);//中断时获取一个捕获值
//去ReadCheaper函数的定义中会发现其实读取CCR的值,这是因为在捕获到上升沿的时候会将CNT赋值给CCR
TIM2->CNT = 0;//将计数器清零
fre2 = 80000000/(80*capture_value2);//测量频率
}
}
⑩main函数LCD的初始化,以及lcd_show的写入;
十、adc测量
即通过设置PB15和PB12为ADC输入模式去测量R37与R37与R38的电压值,可通过调整可调电位器R37与R38去改变测量到的电压值;
①创建一个工程test04_adc,完成基本配置;
②STM32Cube配置:
a、PB12设置为ADC1_IN11,PB15设置为ADC2_IN15,然后在左侧找到“Analog”,ADC1中找到“IN11”并设置为“IN11 Single-ended”;ADC2中找到“IN15 Single-ended”并打上勾,生成代码;
③将之前的code复制到工程中,在adc.c的下拉菜单中找到“stm32g4xx_hal_adc.h”,找到函数HAL_ADC_GetValue和函数HAL_ADC_Start(ADC输入模式开启),并在fun.c中编写lcd_show:
char text[20];
void lcd_show()
{
sprintf(text," text ");
LCD_DisplayStringLine(Line0,(uint8_t *)text);
HAL_ADC_Start(&hadc1);
uint32_t adc_value = HAL_ADC_GetValue(&hadc1);//R38
sprintf(text," value:%d ",adc_value); //显示adc值
LCD_DisplayStringLine(Line3,(uint8_t *)text);
}
④在main中完成LCD的初始化,并在while(1)中使用lcd_show();
⑤编写电压测量函数:
double get_vol(ADC_HandleTypeDef *hadc)//电压测量函数,参数表中的hadc如果是hadc1就是对应R38,如果是hadc2就是对应R37
{
HAL_ADC_Start(hadc);
uint32_t adc_value = HAL_ADC_GetValue(hadc);
return 3.3*adc_value/4096;//电压计算公式
}
PS:电压计算公式为上述的原因:由模拟输入的电路图可知R37上的电压值为0~3.3V,读到的ad值是0 ~ 4096,故电压测量计算公式为 adc_value*3.3 / 4096,而为什么是4096呢,这是因为在ADC的“Resolution”为 ADC 12 bit resolution(从Cube中可以看),2的12次方就等于4096;
lcd_show函数可以改为:
void lcd_show()
{
sprintf(text," text ");
LCD_DisplayStringLine(Line0,(uint8_t *)text);
sprintf(text," R37_VOL:%.2fV ",get_vol(&hadc2)); //显示adc值
LCD_DisplayStringLine(Line3,(uint8_t *)text);
sprintf(text," R38_VOL:%.2fV ",get_vol(&hadc1)); //显示adc值
LCD_DisplayStringLine(Line5,(uint8_t *)text);
}
十一、串口发送和接收
根据数据手册
USART对应的引脚为PA9和PA10
①创建一个新工程teest05_usart,完成Cube基本设置,在左侧找到“Connectivity”,再其中的“USART1”中Mode选择“Asynchronous”(意为异步通信),可以注意到波特率是115200Bits/s,Gpio口的两个设置的是
PC4和PC5,是错误的,这里我们需要重新设置为PA9和PA10,再把中断使能一下(“NVIC Setting”),生成代码;
【接收】
②编译一下,先去usart.c中找到“stm32gxx_hal_uart.h”,再在文件中找到HAL_UART_Transmit函数,在main函数中先写入头文件headfile.h,再在while()中写入一下代码:
char text01[20];
sprintf(text01,"Lan Qiao Bei\r\n");
HAL_UART_Transmit(&huart1,(uint8_t *)text01,sizeof(text01),50);//参数表依次为串口编号,文本,大小,时间
HAL_Delay(1000);//每隔1s发送一次
随后编译烧录;
打开嵌入式资源数据包,找到软件环境中的串口调试工具,然后设置端口(右键此电脑,找到管理,查看USB串行设备是哪个端口)以及波特率(要与Cube中USART设置的一样,一般是9600或115200),设置完成后打开串口就可以看到接收区每隔1s开发板通过串口给电脑发送的文本;
【发送】
③在“stm32gxx_hal_uart.h”中找到HAL_UART_RxCpltCallback(串口接收中断回调函数)
PS:注意要将rec_data存到fun.h中:
extern uint8_t rec_data
在fun.c的HAL_UART_RxCpltCallback函数中,把发送写在接收前面的逻辑:
由于在main函数的代码里写入了HAL_UART_Receive_IT(huart, &rec_data, 1);故会先执行接收再发送
接收-->发送-->接收;
也可以不在函数中写入HAL_UART_Receive_IT(huart, &rec_data, 1);将其写入main函数中的while循环里
uint8_t rec_data;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1)
{
HAL_UART_Transmit(huart,&rec_data,1,50);//参数表依次为串口编号,文本,大小,时间
HAL_UART_Receive_IT(huart, &rec_data, 1);//参数表:串口句柄,接收的数据,接收数据字节数
//函数里也可以不写HAL_UART_Receive_IT(huart, &rec_data, 1);直接放main中的while里
}
}
十二、利用定时器进行串口不定长数据接收
以第12届真题为例:

解题思路:
【1】
①计算
每次接收到数据CNT清零一次,
当t>1.04ms时,判断为没有下一个数据传入;
设置PSC+1=8000,
8000 / 80000000 = 1 / 10000,
CNT = 15 -> t = 15 * 1 / 10000 = 0.0015s = 1.5ms
设置比1.04要多0.4ms左右,这样更保险,所以可以用判断CNT是否大于15(也就是t是否大于15ms)来判断数据是否接收完成
②Cube设置
a.将USART1的PSC+1(波特率)设置成9600
b.打开一个时钟(本篇以TIM4为例)将Clock Source设置为“Internal Clock”生成代码;
c.在main函数中对时钟4进行使能HAL_TIM_Base_Start(&htim4);
d.编写接收函数uart_data_rec
char send_buff[20];//用来存储发送的字符串
uint8_t rec_data,count;//count为计数器,用于将接收到的数据依次存储进数组中
uint8_t rec_flag;//接收时置一
uint8_t rec_buff[20];//将接收到的数据存储进该数组
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1)
{
//HAL_UART_Transmit(huart,&rec_data,1,50);//参数表依次为串口编号,文本,大小,时间
TIM4->CNT = 0;//不要忘记计数器清零
rec_flag = 1;
rec_buff[count] = rec_data;
count++;
HAL_UART_Receive_IT(huart, &rec_data, 1);//参数表:串口句柄,接收的数据,接收数据字节数
//函数里也可以不写HAL_UART_Receive_IT(huart, &rec_data, 1);直接放main中的while里
}
}
void uart_data_rec()
{
if(rec_flag)
{
if(TIM4->CNT > 15) //数据接收完成
{
//处理数据
if(count == 3 && rec_buff[0] == 'l'&& rec_buff[1] == 'a'&& rec_buff[2] == 'n') //lan
{
sprintf(send_buff,"lan\r\n");//先将字符串存储进去
HAL_UART_Transmit(&huart1,(uint8_t *)send_buff,sizeof(send_buff),50);//串口发送 }
}
else if(count == 4 && rec_buff[0] == 'q'&& rec_buff[1] == 'i'&& rec_buff[2] == 'a'&& rec_buff[3] == 'o')//qiao
{
sprintf(send_buff,"qiao\r\n");//先将字符串存储进去
HAL_UART_Transmit(&huart1,(uint8_t *)send_buff,sizeof(send_buff),50);//串口发送 }
}
else if(count == 3 && rec_buff[0] == 'b'&& rec_buff[1] == 'e'&& rec_buff[2] == 'i')//bei
{
sprintf(send_buff,"bei\r\n");//先将字符串存储进去
HAL_UART_Transmit(&huart1,(uint8_t *)send_buff,sizeof(send_buff),50);//串口发送 }
}
else
{
sprintf(send_buff,"error\r\n");//先将字符串存储进去
HAL_UART_Transmit(&huart1,(uint8_t *)send_buff,sizeof(send_buff),50);//串口发送 }
}
rec_flag = 0;
for(int i=0;i<count;i++)//清除数组
rec_buff[i]=0;
count = 0; //计数器置零
}
}
}
(记得每写一个函数要去.h文件中声明一下)
main的while(1)中:
uart_data_rec();

【2】串口的空闲中断
十三、eeprom读写
①eeprom是非易失性存储器(掉电后数据不丢失)
PS:有两点需要注意
a、主机给从机发信息,从机接到信息后要给主机回应;
b、从机给主机发信息,主机接到信息后也要给从机回应;


由于电路图中E1、E2、E3引脚都是接地的,所以A0、A1、A2都是0,最后一位R/W表示为1时读取,为0时写入;
①创建工程,完成基本配置;
②去蓝桥杯资料中找到“竞赛平台”,将里面的示例的i2c的hal库文件(i2c_hal.h和i2c_hal.c)复制到code中;
③打开i2c.c,编写eeprom写入函数(eeprom_write(uint8_t addr,uint8_t dat))以及eeprom读出函数(eeprom_read(uint8_t addr))
PS:参数表中的addr是片内地址(注意与芯片地址区分),有0~255个地址;
//eeprom写入数据(data不能超过0~255这个范围)
void eeprom_write(uint8_t addr, uint8_t dat)//参数表第一个参数是芯片的片内地址,第二个是写的数据
{
I2CStart();//开启I2C
I2CSendByte(0xa0);//发送一个字节的数据;AT24C02地址是1010 0000,1010的16进制就是a,最后一位是0,代表写
I2CWaitAck();//等待回应
I2CSendByte(addr);
I2CWaitAck();
I2CSendByte(dat);
I2CWaitAck();
I2CStop();//关闭I2C
HAL_Delay(20);//延时20ms,避免连续写入出错,因为eeprom写入需要时间
}
uint8_t eeprom_read(uint8_t addr)//eeprom从主机读数据
{
I2CStart();
I2CSendByte(0xa0);//锁定从机地址
I2CWaitAck();
I2CSendByte(addr);//告诉主机要读哪个地址的数据
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0xa1);//写指令
I2CWaitAck();
uint8_t dat = I2CReceiveByte();
I2CSendNotAck();//主机不发送回应
I2CStop();
return dat;
}
④main函数中记得#include "i2c_hal.h",
在while(1)外
LCD_Init();
LCD_SetTextColor(White);
LCD_SetBackColor(Black);
LCD_Clear(Black);
I2C_Init();
eeprom_write(0,11);
uint8_t dat = eeprom_read(0);
char text[20];
在while(1)中
sprintf(text," %d ",dat);
LCD_DisplayStringLine(Line0,(uint8_t *)text);
十四、RTC实时时钟
主要功能实现:
1、设置时钟和日期
2、读取时间和日期
3、设置一个闹钟
①新建工程,完成Cube基本配置,生成代码;
②Cube设置:先在TIM中找到RTC,分别使能时钟源、使能日历,选择Alarm A(闹钟A)
如下图:

芯片引脚配置:

③写一个获取时间和日期的函数
sTime 与 sDate的定义可以参考rtc.c中的定义
char text[20];
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef sDate = {0};
void lcd_show()
{
HAL_RTC_GetTime(&hrtc,&sTime,RTC_FORMAT_BIN);//最后的参数是决定要二进制(RTC_FORMAT_BIN)还是十进制(RTC_FORMAT_BCD)
HAL_RTC_GetDate(&hrtc,&sDate,RTC_FORMAT_BIN);
sprintf(text," text ");
LCD_DisplayStringLine(Line0,(uint8_t *)text);
sprintf(text," %2d:%2d:%2d ",sTime.Hours,sTime.Minutes,sTime.Seconds);
LCD_DisplayStringLine(Line3,(uint8_t *)text);
sprintf(text," %d-%d-%d-%d ",sDate.Year,sDate.Month,sDate.Date,sDate.WeekDay);
LCD_DisplayStringLine(Line5,(uint8_t *)text);
}
PS:即使不需要获取日期,也要将获取日期的函数添上,不然时间不会流动
④编写闹钟函数
在lcd_show()函数中加入 led_show(1,led_mode);//最好不要放在中断里
再在fun.c文件中写一个中断函数
uint8_t led_mode;
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
led_mode = 1;
}