当前位置:   article > 正文

蓝桥杯嵌入式STM32G431RBT6知识点(主观题部分)

蓝桥杯嵌入式STM32G431RBT6知识点(主观题部分)

目录

1  前置准备

1.1 Keil

1.1.1  编译器版本及微库

1.1.2  添加官方提供的LCD及I2C文件

1.2  CubeMX

1.2.1   时钟树

1.2.2   其他

1.2.3  明确CubeMX路径,放置芯片包

2  GPIO

2.1  实验1:LED1-LED8循环亮灭

​编辑

2.2  实验2:按键控制LED亮灭(检测电平法)

2.3  实验3:按键控制LED亮灭(外部中断法)

 2.4  实验4:蜂鸣器

2.5  实验5:按键消抖

2.6  实验6:长按短按

2.7  实验7:双击

2.8  实验8: 长按双击综合

3  ADC/DAC

3.1  实验1:获取电位器引脚的电压

 3.2  实验2:设定双引脚电压并读取

4  I2C EEPROM

4.1  实验1:EEPROM的读写+浮点数的处理

4.2  实验2:大位数读取

4.3  实验3:EEPROM掉电不丢失

4.4  实验4:第一次上电问题

 4.5  实验5:MCP4017可编程电阻

5  UART/USART

5.1  实验1:轮询收发

 5.2  实验2:中断收发

5.3  实验3:中断回调函数

5.4  字符串问题注意

 5.5  实验4:发送指定格式的字符串并从字符串中提取指定信息

5.6  实验5:DMA及几种收发方式的分析

5.7  实验6:串口的不定长收发(DMA+空闲中断)

6  TIM

6.1  实验1:延时

6.2  实验2:PWM输出(控制蜂鸣器)

6.3  实验3:检测555信号发生器信号频率和占空比

 6.4  实验4:检测自己输出的PWM频率和占空比(上升沿中断)

6.5  实验5:检测自己输出的PWM频率和占空比(PWM中断)

7  RTC

7.1  实验1:显示年月日时分秒

7.2  实验2:秒中断

7.3  实验3:闹钟中断


1  前置准备

1.1 Keil

1.1.1  编译器版本及微库

编译器版本调整至version 5,勾选Micro LIB

1.1.2  添加官方提供的LCD及I2C文件

这五个文件是需要添加进自己的工程中的

这个是官方比赛提供的数据包,有关I2C的文件从2中提取,有关LCD的文件从5中提取(.c文件在Src中,.h文件在Inc中)

1.2  CubeMX

1.2.1   时钟树

1.2.2   其他

 

1.2.3  明确CubeMX路径,放置芯片包

2  GPIO

2.1  实验1:LED1-LED8循环亮灭

 在最小系统原理图中找到LED1-LED8对应的引脚是PC8-PC15,那么我们在CubeMX中将这几个引脚配置成GPIO_Output即可

while内的代码:

  1. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_SET);//常用函数1
  2. HAL_Delay(100);//常用函数2
  3. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET);
  4. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9,GPIO_PIN_SET);
  5. HAL_Delay(100);
  6. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9,GPIO_PIN_RESET);
  7. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_10,GPIO_PIN_SET);
  8. HAL_Delay(100);
  9. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_10,GPIO_PIN_RESET);
  10. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_11,GPIO_PIN_SET);
  11. HAL_Delay(100);
  12. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_11,GPIO_PIN_RESET);
  13. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_12,GPIO_PIN_SET);
  14. HAL_Delay(100);
  15. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_12,GPIO_PIN_RESET);
  16. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
  17. HAL_Delay(100);
  18. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
  19. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);
  20. HAL_Delay(100);
  21. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET);
  22. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_SET);
  23. HAL_Delay(100);
  24. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_RESET);

2.2  实验2:按键控制LED亮灭(检测电平法)

 参考按键的引脚,同时别忘了把按键对应的引脚调整为上拉输入(起始高电平)

while内代码:

  1. if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==GPIO_PIN_RESET)
  2. {
  3. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_SET);
  4. HAL_Delay(500);
  5. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET);
  6. }

2.3  实验3:按键控制LED亮灭(外部中断法)

找到按键对应引脚:

 打开外部中断:

  1. /* USER CODE BEGIN PFP */
  2. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_PIN)
  3. {
  4. if(GPIO_PIN==GPIO_PIN_0)
  5. {
  6. HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_8);
  7. }
  8. }
  9. /* USER CODE END PFP */

 2.4  实验4:蜂鸣器

当PB3为高电平时,二极管断开,所以蜂鸣器路; 当PB3为低电平时,二极管导通,所以蜂鸣器路短路

只要配置好PB3的GPIO,就能轻松使用,这里不再用代码解释

2.5  实验5:按键消抖

按键按下和放下的过程中会出现抖动,进而出现高低电平的交替,我们通过扫描两次按键的情况来具体判断情况

1.如果第一次扫描为高电平,那么按键没有被按下

2.如果第一次扫描为低电平,第二次扫描为高电平,那么认为是抖动,不计入成功按键

3.如果两次扫描均为低电平,成功按键

两次扫描的间隔用定时器中断来做

芯片信号频率为80MHz,分频系数设置为8000-1,计数器溢出值设置为100-1,那么定时器溢出时间为10ms

  1. /* USER CODE BEGIN PTD */
  2. char buf[20];
  3. struct keys{
  4. int step;
  5. int state;
  6. }key[4];
  7. /* USER CODE END PTD */
  8. /* USER CODE BEGIN PFP */
  9. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  10. {
  11. if(htim->Instance==TIM1)
  12. {
  13. key[0].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
  14. key[1].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
  15. key[2].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
  16. key[3].state=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
  17. for(int i=0;i<4;i++)
  18. {
  19. switch(key[i].step)
  20. {
  21. case 0:
  22. {
  23. if(key[i].state==GPIO_PIN_RESET)
  24. {
  25. key[i].step=1;
  26. }
  27. }
  28. break;
  29. case 1:
  30. {
  31. if(key[i].state==GPIO_PIN_RESET)
  32. {
  33. key[i].step=2;
  34. sprintf(buf,"%d",i);
  35. LCD_DisplayStringLine(Line4,(uint8_t*)buf);
  36. }
  37. else
  38. {
  39. key[i].step=0;
  40. }
  41. }
  42. break;
  43. case 2:
  44. {
  45. if(key[i].state==GPIO_PIN_SET)
  46. {
  47. key[i].step=0;
  48. }
  49. }
  50. break;
  51. }
  52. }
  53. }
  54. }
  55. /* USER CODE END PFP */
  56. /* USER CODE BEGIN 2 */
  57. LCD_Init();
  58. LCD_Clear(Blue);
  59. LCD_SetBackColor(Blue);
  60. LCD_SetTextColor(White);
  61. I2CInit();
  62. HAL_TIM_Base_Start_IT(&htim1);
  63. /* USER CODE END 2 */

2.6  实验6:长按短按

1.如果第一次扫描为高电平,则没有按键

2.如果第一次扫描为低电平,第二次扫描为高电平,那么认为是抖动,不计入成功按键

3.如果两次扫描均为低电平,成功按键,如果按键时间大于700ms,则视为长按,若小于700ms,则视为短按

  1. /* USER CODE BEGIN PTD */
  2. char buf[20];
  3. struct keys{
  4. int step;
  5. int state;
  6. }key[4];
  7. int a=-1;
  8. int cnt;
  9. /* USER CODE END PTD */
  10. /* USER CODE BEGIN PFP */
  11. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  12. {
  13. if(htim->Instance==TIM1)
  14. {
  15. key[0].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
  16. key[1].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
  17. key[2].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
  18. key[3].state=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
  19. for(int i=0;i<4;i++)
  20. {
  21. switch(key[i].step)
  22. {
  23. case 0:
  24. {
  25. if(key[i].state==GPIO_PIN_RESET)
  26. {
  27. key[i].step=1;
  28. cnt=0;
  29. }
  30. }
  31. break;
  32. case 1:
  33. {
  34. if(key[i].state==GPIO_PIN_RESET)
  35. {
  36. key[i].step=2;
  37. sprintf(buf,"SINGLE");
  38. LCD_ClearLine(Line4);
  39. LCD_DisplayStringLine(Line4,(uint8_t*)buf);
  40. }
  41. else
  42. {
  43. key[i].step=0;
  44. }
  45. }
  46. break;
  47. case 2:
  48. {
  49. if(key[i].state==GPIO_PIN_RESET)
  50. {
  51. if(i==a&&cnt>70)
  52. {
  53. sprintf(buf,"%d %d",i,cnt);
  54. LCD_ClearLine(Line4);
  55. LCD_DisplayStringLine(Line4,(uint8_t*)buf);
  56. }
  57. else
  58. {
  59. a=i;
  60. }
  61. cnt++;
  62. }
  63. else
  64. {
  65. key[i].step=0;
  66. }
  67. }
  68. break;
  69. }
  70. }
  71. }
  72. }
  73. /* USER CODE END PFP */

2.7  实验7:双击

1.如果第一次能够被视为成功按键,那么计时开始

2.如果两次成功按键的间隔小于700ms,视为双击成功

  1. /* USER CODE BEGIN PTD */
  2. char buf[20];
  3. struct keys{
  4. int step;
  5. int state;
  6. int cnt;
  7. }key[4];
  8. int a=-1;
  9. int cnt;
  10. /* USER CODE END PTD */
  11. /* USER CODE BEGIN PFP */
  12. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  13. {
  14. if(htim->Instance==TIM1)
  15. {
  16. key[0].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
  17. key[1].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
  18. key[2].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
  19. key[3].state=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
  20. for(int i=0;i<4;i++)
  21. {
  22. switch(key[i].step)
  23. {
  24. case 0:
  25. {
  26. if(key[i].state==GPIO_PIN_RESET)
  27. {
  28. key[i].step=1;
  29. }
  30. }
  31. break;
  32. case 1:
  33. {
  34. if(key[i].state==GPIO_PIN_RESET)
  35. {
  36. sprintf(buf,"SINGLE");
  37. LCD_ClearLine(Line4);
  38. LCD_DisplayStringLine(Line4,(uint8_t*)buf);
  39. if(i==a)
  40. {
  41. if(key[i].cnt<70)
  42. {
  43. sprintf(buf,"%d %d",i,key[i].cnt);
  44. LCD_ClearLine(Line4);
  45. LCD_DisplayStringLine(Line4,(uint8_t*)buf);
  46. key[i].step=0;
  47. a=-1;
  48. }
  49. key[0].cnt=0;
  50. key[1].cnt=0;
  51. key[2].cnt=0;
  52. key[3].cnt=0;
  53. }
  54. else
  55. {
  56. a=i;
  57. }
  58. key[i].step=2;
  59. }
  60. else
  61. {
  62. key[i].step=0;
  63. }
  64. }
  65. break;
  66. case 2:
  67. {
  68. if(key[i].state==GPIO_PIN_SET)
  69. {
  70. key[i].step=0;
  71. }
  72. }
  73. break;
  74. }
  75. }
  76. key[a].cnt++;
  77. }
  78. }
  79. /* USER CODE END PFP */

2.8  实验8: 长按双击综合

其实不用写在一个定时器内,那样逻辑会比较复杂。我们可以开两个定时器,一个定时器检测长按,一个定时器检测双击

  1. /* USER CODE BEGIN PTD */
  2. char buf[20];
  3. struct keys{
  4. int state;
  5. int step1;
  6. int step2;
  7. int double_time;
  8. }key[4];
  9. int a=-1,b=-1;
  10. int cnt;
  11. /* USER CODE END PTD */
  12. /* USER CODE BEGIN PFP */
  13. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  14. {
  15. if(htim->Instance==TIM3)
  16. {
  17. key[0].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
  18. key[1].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
  19. key[2].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
  20. key[3].state=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
  21. for(int i=0;i<4;i++)
  22. {
  23. switch(key[i].step2)
  24. {
  25. case 0:
  26. {
  27. if(key[i].state==GPIO_PIN_RESET)
  28. {
  29. key[i].step2=1;
  30. cnt=0;
  31. }
  32. }
  33. break;
  34. case 1:
  35. {
  36. if(key[i].state==GPIO_PIN_RESET)
  37. {
  38. key[i].step2=2;
  39. /*sprintf(buf,"SINGLE");
  40. LCD_ClearLine(Line4);
  41. LCD_DisplayStringLine(Line4,(uint8_t*)buf);*/
  42. }
  43. else
  44. {
  45. key[i].step2=0;
  46. }
  47. }
  48. break;
  49. case 2:
  50. {
  51. if(key[i].state==GPIO_PIN_RESET)
  52. {
  53. if(i==b&&cnt>70)
  54. {
  55. sprintf(buf,"LONG:%d %d",i,cnt);
  56. LCD_ClearLine(Line4);
  57. LCD_DisplayStringLine(Line4,(uint8_t*)buf);
  58. }
  59. else
  60. {
  61. b=i;
  62. }
  63. cnt++;
  64. }
  65. else
  66. {
  67. key[i].step2=0;
  68. }
  69. }
  70. break;
  71. }
  72. }
  73. }
  74. if(htim->Instance==TIM1)
  75. {
  76. key[0].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
  77. key[1].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
  78. key[2].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
  79. key[3].state=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
  80. for(int i=0;i<4;i++)
  81. {
  82. switch(key[i].step1)
  83. {
  84. case 0:
  85. {
  86. if(key[i].state==GPIO_PIN_RESET)
  87. {
  88. key[i].step1=1;
  89. }
  90. }
  91. break;
  92. case 1:
  93. {
  94. if(key[i].state==GPIO_PIN_RESET)
  95. {
  96. sprintf(buf,"SINGLE");
  97. LCD_ClearLine(Line4);
  98. LCD_DisplayStringLine(Line4,(uint8_t*)buf);
  99. if(i==a)
  100. {
  101. if(key[i].double_time<70)
  102. {
  103. sprintf(buf,"DOUBLE:%d %d",i,key[i].double_time);
  104. LCD_ClearLine(Line4);
  105. LCD_DisplayStringLine(Line4,(uint8_t*)buf);
  106. key[i].step1=0;
  107. a=-1;
  108. }
  109. key[0].double_time=0;
  110. key[1].double_time=0;
  111. key[2].double_time=0;
  112. key[3].double_time=0;
  113. }
  114. else
  115. {
  116. a=i;
  117. }
  118. key[i].step1=2;
  119. }
  120. else
  121. {
  122. key[i].step1=0;
  123. }
  124. }
  125. break;
  126. case 2:
  127. {
  128. if(key[i].state==GPIO_PIN_SET)
  129. {
  130. key[i].step1=0;
  131. }
  132. }
  133. break;
  134. }
  135. }
  136. key[a].double_time++;
  137. }
  138. }
  139. /* USER CODE END PFP */
  140. /* USER CODE BEGIN 2 */
  141. LCD_Init();
  142. LCD_Clear(Blue);
  143. HAL_TIM_Base_Start_IT(&htim1);
  144. HAL_TIM_Base_Start_IT(&htim3);
  145. /* USER CODE END 2 */

3  ADC/DAC

3.1  实验1:获取电位器引脚的电压

我们想获取两个电位器的电压:

这里以PB12为例: 

  1. /* USER CODE BEGIN PTD */
  2. char buf[20];
  3. /* USER CODE END PTD */
  4. /* USER CODE BEGIN PFP */
  5. double getADC()
  6. {
  7. HAL_ADC_Start(&hadc1);
  8. return HAL_ADC_GetValue(&hadc1)*3.3/4096;
  9. }
  10. /* USER CODE END PFP */
  11. /* USER CODE BEGIN 2 */
  12. LCD_Init();
  13. LCD_Clear(Blue);
  14. LCD_SetBackColor(Blue);
  15. LCD_SetTextColor(White);
  16. /* USER CODE END 2 */
  17. /* USER CODE BEGIN 3 */
  18. sprintf(buf,"%.3lf",getADC());
  19. LCD_ClearLine(Line4);
  20. LCD_DisplayStringLine(Line4,(uint8_t*)buf);
  21. HAL_Delay(1000);
  22. }
  23. /* USER CODE END 3 */

转动电位器R38可观察到电压发生明显变化 

 3.2  实验2:设定双引脚电压并读取

 

这里我们发现测量ADC的两个引脚均在ADC1上,所以获取电压会有先后之分

 采样时间调长,采样准确些,这里我们看到优先采集PA4,再采集PA3

  1. /* USER CODE BEGIN PFP */
  2. void setDAC()
  3. {
  4. HAL_DAC_Start(&hdac1,DAC_CHANNEL_1);
  5. HAL_DAC_Start(&hdac1,DAC_CHANNEL_2);
  6. HAL_DAC_SetValue(&hdac1,DAC_CHANNEL_1,0,1.1*4096/3.3);
  7. HAL_DAC_SetValue(&hdac1,DAC_CHANNEL_2,0,2.2*4096/3.3);
  8. }
  9. double getADC()
  10. {
  11. HAL_ADC_Start(&hadc2);
  12. return HAL_ADC_GetValue(&hadc2)*3.3/4096;
  13. }
  14. /* USER CODE END PFP */
  15. /* USER CODE BEGIN 2 */
  16. LCD_Init();
  17. LCD_Clear(Blue);
  18. LCD_SetBackColor(Blue);
  19. LCD_SetTextColor(White);
  20. setDAC();
  21. /* USER CODE END 2 */
  22. /* USER CODE BEGIN 3 */
  23. sprintf(buf,"%.3lf",getADC());
  24. LCD_ClearLine(Line4);
  25. LCD_DisplayStringLine(Line4,(uint8_t*)buf);
  26. HAL_Delay(1);//需要延时
  27. sprintf(buf,"%.3lf",getADC());
  28. LCD_ClearLine(Line5);
  29. LCD_DisplayStringLine(Line5,(uint8_t*)buf);
  30. HAL_Delay(1000);
  31. }
  32. /* USER CODE END 3 */

4  I2C EEPROM

4.1  实验1:EEPROM的读写+浮点数的处理

对于EEPROM读写的函数我们有固定模板:

  1. uint8_t EEPROM_Read(uint8_t addr)
  2. {
  3. I2CStart();
  4. I2CSendByte(0xa0);
  5. I2CWaitAck();
  6. I2CSendByte(addr);
  7. I2CWaitAck();
  8. I2CStart();
  9. I2CSendByte(0xa1);
  10. I2CWaitAck();
  11. uint8_t temp=I2CReceiveByte();
  12. I2CWaitAck();
  13. I2CStop();
  14. return temp;
  15. }
  16. void EEPROM_Write(uint8_t addr,uint8_t info)
  17. {
  18. I2CStart();
  19. I2CSendByte(0xa0);
  20. I2CWaitAck();
  21. I2CSendByte(addr);
  22. I2CWaitAck();
  23. I2CSendByte(info);
  24. I2CWaitAck();
  25. I2CStop();
  26. }

借用3.2的实验数据进行读写,建议EEPROM不要写在while内,EEPROM的读写是有寿命的,每次读写都要延时一下:

  1. /* USER CODE BEGIN PTD */
  2. char buf[20];
  3. double V1[5],V2[5];
  4. uint8_t addr,res1,res2,res3,res4;
  5. /* USER CODE END PTD */
  6. /* USER CODE BEGIN PFP */
  7. void setDAC()
  8. {
  9. HAL_DAC_Start(&hdac1,DAC_CHANNEL_1);
  10. HAL_DAC_Start(&hdac1,DAC_CHANNEL_2);
  11. HAL_DAC_SetValue(&hdac1,DAC_CHANNEL_1,0,1.1*4096/3.3);
  12. HAL_DAC_SetValue(&hdac1,DAC_CHANNEL_2,0,2.2*4096/3.3);
  13. }
  14. double getADC()
  15. {
  16. HAL_ADC_Start(&hadc2);
  17. return HAL_ADC_GetValue(&hadc2)*3.3/4096;
  18. }
  19. uint8_t EEPROM_Read(uint8_t addr)
  20. {
  21. I2CStart();
  22. I2CSendByte(0xa0);
  23. I2CWaitAck();
  24. I2CSendByte(addr);
  25. I2CWaitAck();
  26. I2CStart();
  27. I2CSendByte(0xa1);
  28. I2CWaitAck();
  29. uint8_t temp=I2CReceiveByte();
  30. I2CWaitAck();
  31. I2CStop();
  32. return temp;
  33. }
  34. void EEPROM_Write(uint8_t addr,uint8_t info)
  35. {
  36. I2CStart();
  37. I2CSendByte(0xa0);
  38. I2CWaitAck();
  39. I2CSendByte(addr);
  40. I2CWaitAck();
  41. I2CSendByte(info);
  42. I2CWaitAck();
  43. I2CStop();
  44. }
  45. /* USER CODE END PFP *//* USER CODE BEGIN 2 */
  46. LCD_Init();
  47. LCD_Clear(Blue);
  48. LCD_SetBackColor(Blue);
  49. LCD_SetTextColor(White);
  50. I2CInit();
  51. setDAC();
  52. HAL_Delay(1);
  53. for(int i=0;i<5;i++)
  54. {
  55. V1[i]=getADC();
  56. HAL_Delay(1);
  57. V2[i]=getADC();
  58. HAL_Delay(1);
  59. }
  60. for(int i=0;i<5;i++)
  61. {
  62. EEPROM_Write(addr++,(uint8_t)V1[i]);
  63. HAL_Delay(50);
  64. EEPROM_Write(addr++,(V1[i]-(uint8_t)V1[i])*100);
  65. HAL_Delay(50);
  66. EEPROM_Write(addr++,(uint8_t)V2[i]);
  67. HAL_Delay(50);
  68. EEPROM_Write(addr++,(V2[i]-(uint8_t)V2[i])*100);
  69. HAL_Delay(50);
  70. }
  71. addr=0;
  72. for(int i=0;i<5;i++)
  73. {
  74. res1=EEPROM_Read(addr++);
  75. HAL_Delay(50);
  76. res2=EEPROM_Read(addr++);
  77. HAL_Delay(50);
  78. res3=EEPROM_Read(addr++);
  79. HAL_Delay(50);
  80. res4=EEPROM_Read(addr++);
  81. HAL_Delay(50);
  82. sprintf(buf,"%.2lf %.2lf",res1+(double)res2/100,res3+(double)res4/100);
  83. LCD_DisplayStringLine(Line4,(uint8_t*)buf);
  84. }
  85. /* USER CODE END 2 */

4.2  实验2:大位数读取

8位范围:0-255

16位范围:0-65535

24位范围:0-16777215

32位范围:0-4294967296

这里以到24位为例

  1. /* USER CODE BEGIN PTD */
  2. char buf[20];
  3. int num[10]={105798,367842,56674,4,256,8917,56565,34343,1025,788};
  4. uint8_t temp1,temp2,temp3,res1,res2,res3;
  5. uint8_t addr;
  6. /* USER CODE END PTD */
  7. /* USER CODE BEGIN PFP */
  8. uint8_t EEPROM_Read(uint8_t addr)
  9. {
  10. I2CStart();
  11. I2CSendByte(0xa0);
  12. I2CWaitAck();
  13. I2CSendByte(addr);
  14. I2CWaitAck();
  15. I2CStart();
  16. I2CSendByte(0xa1);
  17. I2CWaitAck();
  18. uint8_t temp=I2CReceiveByte();
  19. I2CWaitAck();
  20. I2CStop();
  21. return temp;
  22. }
  23. void EEPROM_Write(uint8_t addr,uint8_t info)
  24. {
  25. I2CStart();
  26. I2CSendByte(0xa0);
  27. I2CWaitAck();
  28. I2CSendByte(addr);
  29. I2CWaitAck();
  30. I2CSendByte(info);
  31. I2CWaitAck();
  32. I2CStop();
  33. }
  34. /* USER CODE END PFP */
  35. /* USER CODE BEGIN 2 */
  36. LCD_Init();
  37. LCD_Clear(Blue);
  38. LCD_SetBackColor(Blue);
  39. LCD_SetTextColor(White);
  40. I2CInit();
  41. for(int i=0;i<10;i++)
  42. {
  43. temp1=num[i]&0xFF;
  44. temp2=((num[i]-temp1)>>8)&0xFF;
  45. temp3=((num[i]-temp1-(temp2<<8))>>16)&0xFF;
  46. EEPROM_Write(addr++,temp1);
  47. HAL_Delay(50);
  48. EEPROM_Write(addr++,temp2);
  49. HAL_Delay(50);
  50. EEPROM_Write(addr++,temp3);
  51. HAL_Delay(50);
  52. }
  53. addr=0;
  54. for(int i=0;i<10;i++)
  55. {
  56. res1=EEPROM_Read(addr++);
  57. HAL_Delay(50);
  58. res2=EEPROM_Read(addr++);
  59. HAL_Delay(50);
  60. res3=EEPROM_Read(addr++);
  61. HAL_Delay(50);
  62. sprintf(buf,"%d",res1+(res2<<8)+(res3<<16));
  63. LCD_ClearLine(Line4);
  64. LCD_DisplayStringLine(Line4,(uint8_t*)buf);
  65. HAL_Delay(1000);
  66. }
  67. /* USER CODE END 2 */

4.3  实验3:EEPROM掉电不丢失

去掉上面程序的写的部分,重新烧录即可验证

4.4  实验4:第一次上电问题

我们以这道题为例:如果我们将程序烧录到新板时,EEPROM的值是不确定的,而题目要求初次上电就要能读取相关值。所以我们需要判断板子是否是第一次上电,然后做出相关步骤

  1. if(EEPROM_Read(0xaa)!=1&&EEPROM_Read(0xab)!=1)
  2. {
  3. EEPROM_Write(0xaa,1);//我们设定0xaa为是否是第一次上电(新板)的标志位1
  4. HAL_Delay(20);
  5. EEPROM_Write(0xab,1);//我们设定0xab为是否是第一次上电(新板)的标志位2
  6. HAL_Delay(20);
  7. EEPROM_Write(0xa0,30);
  8. HAL_Delay(20);
  9. EEPROM_Write(0xa1,50);
  10. HAL_Delay(20);
  11. EEPROM_Write(0xa2,70);
  12. HAL_Delay(20);
  13. }

 4.5  实验5:MCP4017可编程电阻

原理:

Rs为单个电阻阻值;RWS为总阻值,与R17串联,两者对VDD电压进行分压,可以通过测量PB14的电压判断可编程电阻的阻值。

MCP4017的默认总阻值为100kΩ ,对应0-127个档位,当寄存器为0时,阻值为0;当寄存器为0x7F时阻值为100kΩ

R = 787.4 * readresistor


V=3.3*\tfrac{R}{R+10}

模板:

  1. void RWrite(uint8_t value)
  2. {
  3. I2CStart();
  4. I2CSendByte(0x5e);
  5. I2CWaitAck();
  6. I2CSendByte(value);
  7. I2CWaitAck();
  8. I2CStop();
  9. }
  10. uint8_t RRead(void)
  11. {
  12. uint8_t value;
  13. I2CStart();
  14. I2CSendByte(0x5F);
  15. I2CWaitAck();
  16. value = I2CReceiveByte();
  17. I2CSendNotAck();
  18. I2CStop();
  19. return value;
  20. }

检测从0-127,PB14的电压

  1. /* USER CODE BEGIN PFP */
  2. void RWrite(uint8_t value)
  3. {
  4. I2CStart();
  5. I2CSendByte(0x5e);
  6. I2CWaitAck();
  7. I2CSendByte(value);
  8. I2CWaitAck();
  9. I2CStop();
  10. }
  11. uint8_t RRead(void)
  12. {
  13. uint8_t value;
  14. I2CStart();
  15. I2CSendByte(0x5F);
  16. I2CWaitAck();
  17. value = I2CReceiveByte();
  18. I2CSendNotAck();
  19. I2CStop();
  20. return value;
  21. }
  22. double getADC()
  23. {
  24. HAL_ADC_Start(&hadc1);
  25. return HAL_ADC_GetValue(&hadc1)*3.3/4096;
  26. }
  27. /* USER CODE END PFP */
  28. /* USER CODE BEGIN WHILE */
  29. for(int i=0;i<128;i++)
  30. {
  31. RWrite(i);
  32. HAL_Delay(20);
  33. sprintf(buf,"%d %lf",RRead(),getADC());
  34. LCD_ClearLine(Line4);
  35. LCD_DisplayStringLine(Line4,(uint8_t*)buf);
  36. HAL_Delay(1000);
  37. }
  38. while (1)
  39. {
  40. /* USER CODE END WHILE */

5  UART/USART

CubeMX默认的引脚是不对的,所以别忘了更改引脚

5.1  实验1:轮询收发

HAL_UART_Receive:接收不完指定数量的字符不会进行下一步,设置的等待时间一般为无限大

  1. /* USER CODE BEGIN WHILE */
  2. HAL_UART_Receive(&huart1,(uint8_t*)buf,5,0xFFFF);//接收不完指定数量的字符不会进行下一步
  3. HAL_UART_Transmit(&huart1,(uint8_t*)buf,5,0xFFFF);
  4. while (1)
  5. {
  6. /* USER CODE END WHILE */

 5.2  实验2:中断收发

CubeMX别忘打开串口中断

HAL_UART_Receive_IT:不会等待,最多收指定个数,收几个无所谓,但是只有收满了才会进入中断回调函数

下面这个程序如果不写在while里是不会收到除了空白以外的任何字符的,因为只执行一次的话Receive函数已经过了,不会再执行

  1. while (1)
  2. {
  3. /* USER CODE END WHILE */
  4. /* USER CODE BEGIN 3 */
  5. HAL_UART_Receive_IT(&huart1,(uint8_t*)buf,5);//不会等待,最多收5个,收几个无所谓
  6. HAL_UART_Transmit_IT(&huart1,(uint8_t*)buf,5);
  7. }
  8. /* USER CODE END 3 */

5.3  实验3:中断回调函数

  1. /* USER CODE BEGIN PFP */
  2. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  3. {
  4. if(huart->Instance==USART1)
  5. {
  6. HAL_UART_Transmit_IT(&huart1,(uint8_t*)buf,5);
  7. HAL_UART_Receive_IT(&huart1,(uint8_t*)buf,5);
  8. }
  9. }
  10. /* USER CODE END PFP */
  11. /* USER CODE BEGIN WHILE */
  12. HAL_UART_Receive_IT(&huart1,(uint8_t*)buf,5);//不会等待,最多收5个,收几个无所谓
  13. while (1)
  14. {
  15. /* USER CODE END WHILE */

5.4  字符串问题注意

每个字符串结尾都有\r\n占两个位置,而且如果我们在串口助手里勾选发送新行后,每次发送的字符串后都带\r\n

 5.5  实验4:发送指定格式的字符串并从字符串中提取指定信息

比如我们想发送时间,指定格式为时:分:秒,我们想从串口收到的字符串中提取到时,分,秒三个信息

这里用到sscanf函数来提取信息

当然也可以根据实际情况单个单个提取,不过会略显复杂

  1. /* USER CODE BEGIN PTD */
  2. char buf[20];
  3. int hour,min,second;
  4. /* USER CODE END PTD */
  5. /* USER CODE BEGIN PFP */
  6. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  7. {
  8. if(huart->Instance==USART1)
  9. {
  10. sscanf(buf,"%d:%d:%d",&hour,&min,&second);
  11. sprintf(buf,"hour:%d",hour);
  12. LCD_ClearLine(Line2);
  13. LCD_ClearLine(Line4);
  14. LCD_ClearLine(Line6);
  15. LCD_DisplayStringLine(Line2,(uint8_t*)buf);
  16. sprintf(buf,"min:%d",min);
  17. LCD_DisplayStringLine(Line4,(uint8_t*)buf);
  18. sprintf(buf,"second:%d",second);
  19. LCD_DisplayStringLine(Line6,(uint8_t*)buf);
  20. memset(buf,0,sizeof(buf));
  21. HAL_UART_Receive_IT(&huart1,(uint8_t*)buf,8);
  22. }
  23. }
  24. /* USER CODE END PFP */
  25. /* USER CODE BEGIN 2 */
  26. LCD_Init();
  27. LCD_Clear(Blue);
  28. LCD_SetBackColor(Blue);
  29. LCD_SetTextColor(White);
  30. I2CInit();
  31. /* USER CODE END 2 */
  32. /* Infinite loop */
  33. /* USER CODE BEGIN WHILE */
  34. HAL_UART_Receive_IT(&huart1,(uint8_t*)buf,8);
  35. while (1)
  36. {
  37. /* USER CODE END WHILE */

5.6  实验5:DMA及几种收发方式的分析

打开DMA: 

 打开中断:

DMA是默认打开中断的

 因为DMA是不占用CPU的,我们可以尽量使用DMA来提高效率

这里我们发现收到的数据不完整,然后我们延时一下,这次数据完整

  1. /* USER CODE BEGIN PTD */
  2. char buf[20];
  3. int hour,min,second;
  4. /* USER CODE END PTD */
  5. /* USER CODE BEGIN PFP */
  6. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  7. {
  8. if(huart->Instance==USART1)
  9. {
  10. sscanf(buf,"%d:%d:%d",&hour,&min,&second);
  11. sprintf(buf,"hour:%d",hour);
  12. LCD_ClearLine(Line2);
  13. LCD_ClearLine(Line4);
  14. LCD_ClearLine(Line6);
  15. LCD_DisplayStringLine(Line2,(uint8_t*)buf);
  16. sprintf(buf,"min:%d",min);
  17. LCD_DisplayStringLine(Line4,(uint8_t*)buf);
  18. sprintf(buf,"second:%d",second);
  19. LCD_DisplayStringLine(Line6,(uint8_t*)buf);
  20. sprintf(buf,"%02d:%02d:%02d",hour,min,second);
  21. HAL_UART_Transmit_DMA(&huart1,(uint8_t*)buf,8);
  22. //int t=100000; while(t--);
  23. LCD_DisplayStringLine(Line8,(uint8_t*)buf);
  24. memset(buf,0,sizeof(buf));
  25. HAL_UART_Receive_DMA(&huart1,(uint8_t*)buf,8);
  26. }
  27. }
  28. /* USER CODE END PFP */
  29. /* USER CODE BEGIN WHILE */
  30. HAL_UART_Receive_DMA(&huart1,(uint8_t*)buf,8);
  31. while (1)
  32. {
  33. /* USER CODE END WHILE */

然后我们试图将Transmit一句改成IT,然后将USART1的中断优先级调整比DMA高,然后发现仍然可以接收到

但是如果我们全部改成IT,就不可取了,初步分析是中断回调函数的事件过多

所以我们尽量采取DMA的方式收发数据

5.7  实验6:串口的不定长收发(DMA+空闲中断)

其中中断服务函数需要到

 中找

  1. /* USER CODE BEGIN WHILE */
  2. HAL_UART_Receive_DMA(&huart1,(uint8_t*)buf,20);
  3. __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
  4. while (1)
  5. {
  6. /* USER CODE END WHILE */
  7. void USART1_IRQHandler(void)
  8. {
  9. /* USER CODE BEGIN USART1_IRQn 0 */
  10. if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)==SET)
  11. {
  12. __HAL_UART_CLEAR_IDLEFLAG(&huart1);
  13. HAL_UART_DMAStop(&huart1);
  14. len=20-__HAL_DMA_GET_COUNTER(huart1.hdmarx);
  15. HAL_UART_Transmit_DMA(&huart1,(uint8_t*)buf,len);
  16. HAL_UART_Receive_DMA(&huart1,(uint8_t*)buf,20);
  17. }
  18. /* USER CODE END USART1_IRQn 0 */
  19. HAL_UART_IRQHandler(&huart1);
  20. /* USER CODE BEGIN USART1_IRQn 1 */
  21. /* USER CODE END USART1_IRQn 1 */
  22. }

6  TIM

6.1  实验1:延时

  1. while (1)
  2. {
  3. /* USER CODE END WHILE */
  4. /* USER CODE BEGIN 3 */
  5. if(__HAL_TIM_GetCounter(&htim1)==10000)
  6. {
  7. HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_8);
  8. __HAL_TIM_SetCounter(&htim1,0);
  9. }
  10. }
  11. /* USER CODE END 3 */

6.2  实验2:PWM输出(控制蜂鸣器)

PWM原理如图所示: 

  1. /* USER CODE BEGIN 2 */
  2. LCD_Init();
  3. LCD_Clear(Blue);
  4. LCD_SetBackColor(Blue);
  5. LCD_SetTextColor(White);
  6. I2CInit();
  7. LED_Close();
  8. HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
  9. __HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,5000);
  10. /* USER CODE END 2 */

6.3  实验3:检测555信号发生器信号频率和占空比

 分析:每次捕捉到上升沿我们就进入一次中断,这时我们就得到了一个信号周期的大小

现在我们已知定时器计一个数的时间,只要我们读取定时器计了多少数,就能通过公式:

信号周期=定时器计一个数的时间*定时器计数值

算出信号周期,进而算出信号频率

占空比的计算可以另外设置一个通道,根据占空比的定义:

占空比=一个周期内高电平的时间/一个周期

测量PA15引脚对应的555信号发生器:

注意:分频系数设置为80比较好,这样记一次数的时间比较短,测量比较精确,而且计数器不容易溢出

注意TIM2CHANNEL1对应的引脚设置成PA15

这里注意打印%的方法

  1. /* USER CODE BEGIN PFP */
  2. void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
  3. {
  4. if(htim->Instance==TIM2&&htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)
  5. {
  6. cnt=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);
  7. cnt_down=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_2);
  8. __HAL_TIM_SetCounter(&htim2,0);
  9. f=10000000/cnt;
  10. duty=1-(double)cnt_down/(double)cnt;
  11. }
  12. }
  13. /* USER CODE END PFP */
  14. /* USER CODE BEGIN 2 */
  15. LCD_Init();
  16. LCD_Clear(Blue);
  17. LCD_SetBackColor(Blue);
  18. LCD_SetTextColor(White);
  19. I2CInit();
  20. HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);
  21. HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_2);
  22. /* USER CODE END 2 */
  23. while (1)
  24. {
  25. /* USER CODE END WHILE */
  26. /* USER CODE BEGIN 3 */
  27. sprintf(buf,"%dHz %.2lf%%",f,duty*100);
  28. LCD_DisplayStringLine(Line4,(uint8_t*)buf);
  29. HAL_Delay(1000);
  30. LCD_ClearLine(Line4);
  31. }
  32. /* USER CODE END 3 */

 6.4  实验4:检测自己输出的PWM频率和占空比(上升沿中断)

找到板子上能插杜邦线的两个引脚,一个引脚输出PWM,另一个引脚测量输入的PWM有关性质

我选择了PB15和PB11两个引脚,PB15用来产生PWM波,PB11用来测量PWM的有关性质

 PB15:

设置分频系数为8,计数器最大值为1000-1,所以PWM的频率为:

80MHz/8/1000=10000Hz

PB11:

分频系数为80-1,所以计数频率(1/计一个数的时间)为:

80MHz/80=1MHz

 set可以设置为在0-1000内的值,假如我们设置为300,那么占空比为30%

  1. /* USER CODE BEGIN PTD */
  2. int cnt,cnt_down,f;
  3. double duty;
  4. char buf[20];
  5. int set;
  6. /* USER CODE END PTD */
  7. /* USER CODE BEGIN PFP */
  8. void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
  9. {
  10. if(htim->Instance==TIM2&&htim->Channel==HAL_TIM_ACTIVE_CHANNEL_4)
  11. {
  12. cnt=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_4);
  13. cnt_down=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_3);
  14. __HAL_TIM_SetCounter(&htim2,0);
  15. f=1000000/cnt;
  16. duty=1-(double)cnt_down/(double)cnt;
  17. }
  18. }
  19. /* USER CODE END PFP */
  20. /* USER CODE BEGIN 2 */
  21. HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_4);
  22. HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_3);
  23. HAL_TIM_PWM_Start(&htim15,TIM_CHANNEL_2);
  24. __HAL_TIM_SetCompare(&htim15,TIM_CHANNEL_2,set);
  25. LCD_Init();
  26. LCD_Clear(Blue);
  27. /* USER CODE END 2 */
  28. /* USER CODE BEGIN WHILE */
  29. while (1)
  30. {
  31. /* USER CODE END WHILE */
  32. /* USER CODE BEGIN 3 */
  33. sprintf(buf,"%dHz %.4lf",f,duty);
  34. LCD_DisplayStringLine(Line2,(uint8_t*)buf);
  35. HAL_Delay(200);
  36. }
  37. /* USER CODE END 3 */

 最后测量得到频率为10204Hz,占空比为0.5102,和预估结果大致相同

6.5  实验5:检测自己输出的PWM频率和占空比(PWM中断)

 捕捉到上升沿中断其实跟PWM中断一样,都是上升沿开始时触发中断

我们打开PWM中断,使用PWM中断回调函数

  1. /* USER CODE BEGIN PTD */
  2. int cnt,cnt_down,f;
  3. double duty;
  4. char buf[20];
  5. int set;
  6. /* USER CODE END PTD */
  7. /* USER CODE BEGIN PFP */
  8. void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
  9. {
  10. if(htim->Instance==TIM15&&htim->Channel==HAL_TIM_ACTIVE_CHANNEL_2)
  11. {
  12. cnt=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_4);
  13. cnt_down=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_3);
  14. __HAL_TIM_SetCounter(&htim2,0);
  15. f=1000000/cnt;
  16. duty=1-(double)cnt_down/(double)cnt;
  17. }
  18. }
  19. /* USER CODE END PFP */
  20. /* USER CODE BEGIN 2 */
  21. HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_4);
  22. HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_3);
  23. HAL_TIM_PWM_Start_IT(&htim15,TIM_CHANNEL_2);
  24. __HAL_TIM_SetCompare(&htim15,TIM_CHANNEL_2,set);
  25. LCD_Init();
  26. LCD_Clear(Blue);
  27. /* USER CODE END 2 */
  28. /* USER CODE BEGIN WHILE */
  29. while (1)
  30. {
  31. /* USER CODE END WHILE */
  32. /* USER CODE BEGIN 3 */
  33. sprintf(buf,"%dHz %.4lf",f,duty);
  34. LCD_DisplayStringLine(Line2,(uint8_t*)buf);
  35. HAL_Delay(200);
  36. }
  37. /* USER CODE END 3 */

7  RTC

7.1  实验1:显示年月日时分秒

 

  1. /* USER CODE BEGIN PTD */
  2. char buf[20];
  3. /* USER CODE END PTD */
  4. /* USER CODE BEGIN PD */
  5. RTC_TimeTypeDef TIME;
  6. RTC_DateTypeDef DATE;
  7. /* USER CODE END PD */
  8. /* USER CODE BEGIN WHILE */
  9. while (1)
  10. {
  11. /* USER CODE END WHILE */
  12. /* USER CODE BEGIN 3 */
  13. HAL_RTC_GetTime(&hrtc,&TIME,RTC_FORMAT_BIN);
  14. HAL_RTC_GetDate(&hrtc,&DATE,RTC_FORMAT_BIN);
  15. LCD_ClearLine(Line2);
  16. LCD_ClearLine(Line4);
  17. sprintf(buf,"%d-%d-%d",DATE.Year,DATE.Month,DATE.Date);
  18. LCD_DisplayStringLine(Line2,(uint8_t*)buf);
  19. sprintf(buf,"%d:%d:%d",TIME.Hours,TIME.Minutes,TIME.Seconds);
  20. LCD_DisplayStringLine(Line4,(uint8_t*)buf);
  21. }
  22. /* USER CODE END 3 */

7.2  实验2:秒中断

上面我们已经设置好RTC的频率为750MHz,按照如上系数配置,750K/125/6000=1Hz

1秒发生一次中断,而跟我们设定的闹钟时间无关

  1. /* USER CODE BEGIN PTD */
  2. char buf[20];
  3. /* USER CODE END PTD */
  4. /* USER CODE BEGIN PD */
  5. RTC_TimeTypeDef TIME;
  6. RTC_DateTypeDef DATE;
  7. /* USER CODE END PD */
  8. /* USER CODE BEGIN PFP */
  9. void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
  10. {
  11. HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_3);
  12. }
  13. /* USER CODE END PFP */
  14. /* USER CODE BEGIN WHILE */
  15. while (1)
  16. {
  17. /* USER CODE END WHILE */
  18. /* USER CODE BEGIN 3 */
  19. HAL_RTC_GetTime(&hrtc,&TIME,RTC_FORMAT_BIN);
  20. HAL_RTC_GetDate(&hrtc,&DATE,RTC_FORMAT_BIN);
  21. LCD_ClearLine(Line2);
  22. LCD_ClearLine(Line4);
  23. sprintf(buf,"%d-%d-%d",DATE.Year,DATE.Month,DATE.Date);
  24. LCD_DisplayStringLine(Line2,(uint8_t*)buf);
  25. sprintf(buf,"%d:%d:%d",TIME.Hours,TIME.Minutes,TIME.Seconds);
  26. LCD_DisplayStringLine(Line4,(uint8_t*)buf);
  27. }
  28. /* USER CODE END 3 */

7.3  实验3:闹钟中断

日期时分都不看,只看秒,如果闹钟设定的秒跟当前时间一样,则进入中断,自己需要编写的其它代码跟实验2一致

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

闽ICP备14008679号