当前位置:   article > 正文

stm32毕设项目-基于stm32的智能药箱--初始化解释_stm32智能小药箱

stm32智能小药箱

目录

1.LED灯初始化

2.LCD初始化

3.按键初始化

4.蜂鸣器初始化

5.rtc初始化


1.LED灯初始化
  1. //led.h
  2. #ifndef _LED_H
  3. #define _LED_H
  4. #include "./SYSTEM/sys/sys.h"
  5. /******************************************************************************************/
  6. /* 引脚 定义 */
  7. #define LED0_GPIO_PORT GPIOB
  8. #define LED0_GPIO_PIN GPIO_PIN_5
  9. #define LED0_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0) /* PB口时钟使能 */
  10. #define LED1_GPIO_PORT GPIOE
  11. #define LED1_GPIO_PIN GPIO_PIN_5
  12. #define LED1_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0) /* PE口时钟使能 */
  13. /******************************************************************************************/
  14. /* LED端口定义 */
  15. #define LED0(x) do{ x ? \
  16. HAL_GPIO_WritePin(LED0_GPIO_PORT, LED0_GPIO_PIN, GPIO_PIN_SET) : \
  17. HAL_GPIO_WritePin(LED0_GPIO_PORT, LED0_GPIO_PIN, GPIO_PIN_RESET); \
  18. }while(0) /* LED0翻转 */
  19. #define LED1(x) do{ x ? \
  20. HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_SET) : \
  21. HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_RESET); \
  22. }while(0) /* LED1翻转 */
  23. /* LED取反定义 */
  24. #define LED0_TOGGLE() do{ HAL_GPIO_TogglePin(LED0_GPIO_PORT, LED0_GPIO_PIN); }while(0) /* 翻转LED0 */
  25. #define LED1_TOGGLE() do{ HAL_GPIO_TogglePin(LED1_GPIO_PORT, LED1_GPIO_PIN); }while(0) /* 翻转LED1 */
  26. /******************************************************************************************/
  27. /* 外部接口函数*/
  28. void led_init(void); /* 初始化 */
  29. #endif
  1. //led.c
  2. void led_init(void)
  3. {
  4. GPIO_InitTypeDef gpio_init_struct;
  5. LED0_GPIO_CLK_ENABLE(); /* LED0时钟使能 */
  6. LED1_GPIO_CLK_ENABLE(); /* LED1时钟使能 */
  7. gpio_init_struct.Pin = LED0_GPIO_PIN; /* LED0引脚 */
  8. gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */
  9. gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
  10. gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
  11. HAL_GPIO_Init(LED0_GPIO_PORT, &gpio_init_struct); /* 初始化LED0引脚 */
  12. gpio_init_struct.Pin = LED1_GPIO_PIN; /* LED1引脚 */
  13. HAL_GPIO_Init(LED1_GPIO_PORT, &gpio_init_struct); /* 初始化LED1引脚 */
  14. LED0(1); /* 关闭 LED0 */
  15. LED1(1); /* 关闭 LED1 */
  16. }

在led初始化中需要使能对应GPIO的时钟,设置GPIO的模式推完输出,默认上拉。

2.LCD初始化

由于屏和主板都是使用正点原子的产品,引脚,屏的资源已经固定,所以采用正点原子的源码略做修改,大家有需要可以去看正点原子的资料。

3.按键初始化
  1. //key.h
  2. #ifndef __KEY_H
  3. #define __KEY_H
  4. #include "./SYSTEM/sys/sys.h"
  5. /******************************************************************************************/
  6. /* 引脚 定义 */
  7. #define KEY0_GPIO_PORT GPIOE
  8. #define KEY0_GPIO_PIN GPIO_PIN_4
  9. #define KEY0_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0) /* PE口时钟使能 */
  10. #define KEY1_GPIO_PORT GPIOE
  11. #define KEY1_GPIO_PIN GPIO_PIN_3
  12. #define KEY1_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0) /* PE口时钟使能 */
  13. #define KEY2_GPIO_PORT GPIOE
  14. #define KEY2_GPIO_PIN GPIO_PIN_2
  15. #define KEY2_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0) /* PE口时钟使能 */
  16. #define WKUP_GPIO_PORT GPIOA
  17. #define WKUP_GPIO_PIN GPIO_PIN_0
  18. #define WKUP_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */
  19. /******************************************************************************************/
  20. #define KEY0 HAL_GPIO_ReadPin(KEY0_GPIO_PORT, KEY0_GPIO_PIN) /* 读取KEY0引脚 */
  21. #define KEY1 HAL_GPIO_ReadPin(KEY1_GPIO_PORT, KEY1_GPIO_PIN) /* 读取KEY1引脚 */
  22. #define KEY2 HAL_GPIO_ReadPin(KEY2_GPIO_PORT, KEY2_GPIO_PIN) /* 读取KEY2引脚 */
  23. #define WK_UP HAL_GPIO_ReadPin(WKUP_GPIO_PORT, WKUP_GPIO_PIN) /* 读取WKUP引脚 */
  24. #define KEY0_PRES 1 /* KEY0按下 */
  25. #define KEY1_PRES 2 /* KEY1按下 */
  26. #define KEY2_PRES 3 /* KEY2按下 */
  27. #define WKUP_PRES 4 /* KEY_UP按下(即WK_UP) */
  28. void key_init(void); /* 按键初始化函数 */
  29. uint8_t key_scan(uint8_t mode); /* 按键扫描函数 */
  30. #endif
  1. //key.c
  2. #include "./BSP/KEY/key.h"
  3. #include "./SYSTEM/delay/delay.h"
  4. /**
  5. * @brief 按键初始化函数
  6. * @param 无
  7. * @retval 无
  8. */
  9. void key_init(void)
  10. {
  11. GPIO_InitTypeDef gpio_init_struct;
  12. KEY0_GPIO_CLK_ENABLE(); /* KEY0时钟使能 */
  13. KEY1_GPIO_CLK_ENABLE(); /* KEY1时钟使能 */
  14. KEY2_GPIO_CLK_ENABLE(); /* KEY2时钟使能 */
  15. WKUP_GPIO_CLK_ENABLE(); /* WKUP时钟使能 */
  16. gpio_init_struct.Pin = KEY0_GPIO_PIN; /* KEY0引脚 */
  17. gpio_init_struct.Mode = GPIO_MODE_INPUT; /* 输入 */
  18. gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
  19. gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
  20. HAL_GPIO_Init(KEY0_GPIO_PORT, &gpio_init_struct); /* KEY0引脚模式设置,上拉输入 */
  21. gpio_init_struct.Pin = KEY1_GPIO_PIN; /* KEY1引脚 */
  22. gpio_init_struct.Mode = GPIO_MODE_INPUT; /* 输入 */
  23. gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
  24. gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
  25. HAL_GPIO_Init(KEY1_GPIO_PORT, &gpio_init_struct); /* KEY1引脚模式设置,上拉输入 */
  26. gpio_init_struct.Pin = KEY2_GPIO_PIN; /* KEY2引脚 */
  27. gpio_init_struct.Mode = GPIO_MODE_INPUT; /* 输入 */
  28. gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
  29. gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
  30. HAL_GPIO_Init(KEY2_GPIO_PORT, &gpio_init_struct); /* KEY2引脚模式设置,上拉输入 */
  31. gpio_init_struct.Pin = WKUP_GPIO_PIN; /* WKUP引脚 */
  32. gpio_init_struct.Mode = GPIO_MODE_INPUT; /* 输入 */
  33. gpio_init_struct.Pull = GPIO_PULLDOWN; /* 下拉 */
  34. gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
  35. HAL_GPIO_Init(WKUP_GPIO_PORT, &gpio_init_struct); /* WKUP引脚模式设置,下拉输入 */
  36. }
  37. uint8_t key_scan(uint8_t mode)
  38. {
  39. static uint8_t key_up = 1; /* 按键按松开标志 */
  40. uint8_t keyval = 0;
  41. if (mode) key_up = 1; /* 支持连按 */
  42. if (key_up && (KEY0 == 0 || KEY1 == 0 || KEY2 == 0 || WK_UP == 1)) /* 按键松开标志为1, 且有任意一个按键按下了 */
  43. {
  44. delay_ms(10); /* 去抖动 */
  45. key_up = 0;
  46. if (KEY0 == 0) keyval = KEY0_PRES;
  47. if (KEY1 == 0) keyval = KEY1_PRES;
  48. if (KEY2 == 0) keyval = KEY2_PRES;
  49. if (WK_UP == 1) keyval = WKUP_PRES;
  50. }
  51. else if (KEY0 == 1 && KEY1 == 1 && KEY2 == 1 && WK_UP == 0) /* 没有任何按键按下, 标记按键松开 */
  52. {
  53. key_up = 1;
  54. }
  55. return keyval; /* 返回键值 */
  56. }

使能按键的GPIO对应时钟,设置按键对应模式,采用扫描式,改成外部中断可能会更好。

4.蜂鸣器初始化
  1. #ifndef __BEEP_H
  2. #define __BEEP_H
  3. #include "./SYSTEM/sys/sys.h"
  4. /******************************************************************************************/
  5. /* 引脚 定义 */
  6. #define BEEP_GPIO_PORT GPIOB
  7. #define BEEP_GPIO_PIN GPIO_PIN_8
  8. #define BEEP_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0) /* PB口时钟使能 */
  9. /******************************************************************************************/
  10. /* 蜂鸣器控制 */
  11. #define BEEP(x) do{ x ? \
  12. HAL_GPIO_WritePin(BEEP_GPIO_PORT, BEEP_GPIO_PIN, GPIO_PIN_SET) : \
  13. HAL_GPIO_WritePin(BEEP_GPIO_PORT, BEEP_GPIO_PIN, GPIO_PIN_RESET); \
  14. }while(0)
  15. /* BEEP状态翻转 */
  16. #define BEEP_TOGGLE() do{ HAL_GPIO_TogglePin(BEEP_GPIO_PORT, BEEP_GPIO_PIN); }while(0) /* BEEP = !BEEP */
  17. void beep_init(void); /* 初始化蜂鸣器 */
  18. #endif
  1. #include "./BSP/BEEP/beep.h"
  2. /**
  3. * @brief 初始化BEEP相关IO口, 并使能时钟
  4. * @param 无
  5. * @retval 无
  6. */
  7. void beep_init(void)
  8. {
  9. GPIO_InitTypeDef gpio_init_struct;
  10. BEEP_GPIO_CLK_ENABLE(); /* BEEP时钟使能 */
  11. gpio_init_struct.Pin = BEEP_GPIO_PIN; /* 蜂鸣器引脚 */
  12. gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */
  13. gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
  14. gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
  15. HAL_GPIO_Init(BEEP_GPIO_PORT, &gpio_init_struct); /* 初始化蜂鸣器引脚 */
  16. BEEP(0); /* 关闭蜂鸣器 */
  17. }

LCD灯,按键,蜂鸣器本质都是GPIO所以代码类似。蜂鸣器采用的是有源蜂鸣器,只有响和不响两种状态。

5.rtc初始化
  1. uint8_t rtc_init(void)
  2. {
  3. /* 检查是不是第一次配置时钟 */
  4. uint16_t bkpflag = 0;
  5. __HAL_RCC_PWR_CLK_ENABLE(); /* 使能电源时钟 */
  6. __HAL_RCC_BKP_CLK_ENABLE(); /* 使能备份时钟 */
  7. HAL_PWR_EnableBkUpAccess(); /* 取消备份区写保护 */
  8. bkpflag = rtc_read_bkr(0); /* 读取BKP0的值 */
  9. g_rtc_handle.Instance = RTC;
  10. g_rtc_handle.Init.AsynchPrediv = RTC_AUTO_1_SECOND; /*时钟周期设置,理论值:32767, 这里也可以用 RTC_AUTO_1_SECOND */
  11. g_rtc_handle.Init.OutPut = RTC_OUTPUTSOURCE_NONE;
  12. if (HAL_RTC_Init(&g_rtc_handle) != HAL_OK)
  13. {
  14. return 1;
  15. }
  16. if ((bkpflag != 0X5050) && (bkpflag != 0x5051)) /* 之前未初始化过,重新配置 */
  17. {
  18. rtc_set_time(2023, 4, 5, 10, 25, 35); /* 设置时间 */
  19. }
  20. //HAL_RTC_Init
  21. __HAL_RTC_ALARM_ENABLE_IT(&g_rtc_handle, RTC_IT_SEC); /* 允许秒中断 */
  22. HAL_NVIC_SetPriority(RTC_IRQn, 0x2, 0); /* 优先级设置 */
  23. HAL_NVIC_EnableIRQ(RTC_IRQn); /* 使能RTC中断通道 */
  24. rtc_get_time(); /* 更新时间 */
  25. return 0;
  26. }
  27. void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc)
  28. {
  29. uint16_t retry = 200;
  30. __HAL_RCC_RTC_ENABLE(); /* RTC时钟使能 */
  31. RCC_OscInitTypeDef rcc_oscinitstruct;
  32. RCC_PeriphCLKInitTypeDef rcc_periphclkinitstruct;
  33. /* 使用寄存器的方式去检测LSE是否可以正常工作 */
  34. RCC->BDCR |= 1 << 0; /* 开启外部低速振荡器LSE */
  35. while (retry && ((RCC->BDCR & 0X02) == 0)) /* 等待LSE准备好 */
  36. {
  37. retry--;
  38. delay_ms(5);
  39. }
  40. if (retry == 0) /* LSE起振失败 使用LSI */
  41. {
  42. rcc_oscinitstruct.OscillatorType = RCC_OSCILLATORTYPE_LSI; /* 选择要配置的振荡器 */
  43. rcc_oscinitstruct.LSEState = RCC_LSI_ON; /* LSI状态:开启 */
  44. rcc_oscinitstruct.PLL.PLLState = RCC_PLL_NONE; /* PLL无配置 */
  45. HAL_RCC_OscConfig(&rcc_oscinitstruct); /* 配置设置的rcc_oscinitstruct */
  46. rcc_periphclkinitstruct.PeriphClockSelection = RCC_PERIPHCLK_RTC; /* 选择要配置的外设 RTC */
  47. rcc_periphclkinitstruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI; /* RTC时钟源选择 LSI */
  48. HAL_RCCEx_PeriphCLKConfig(&rcc_periphclkinitstruct); /* 配置设置的rcc_periphClkInitStruct */
  49. rtc_write_bkr(0, 0X5051);
  50. }
  51. else
  52. {
  53. rcc_oscinitstruct.OscillatorType = RCC_OSCILLATORTYPE_LSE ; /* 选择要配置的振荡器 */
  54. rcc_oscinitstruct.LSEState = RCC_LSE_ON; /* LSE状态:开启 */
  55. rcc_oscinitstruct.PLL.PLLState = RCC_PLL_NONE; /* PLL不配置 */
  56. HAL_RCC_OscConfig(&rcc_oscinitstruct); /* 配置设置的rcc_oscinitstruct */
  57. rcc_periphclkinitstruct.PeriphClockSelection = RCC_PERIPHCLK_RTC; /* 选择要配置外设 RTC */
  58. rcc_periphclkinitstruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; /* RTC时钟源选择LSE */
  59. HAL_RCCEx_PeriphCLKConfig(&rcc_periphclkinitstruct); /* 配置设置的rcc_periphclkinitstruct */
  60. rtc_write_bkr(0, 0X5050);
  61. }
  62. }
  63. void RTC_IRQHandler(void)
  64. {
  65. if (__HAL_RTC_ALARM_GET_FLAG(&g_rtc_handle, RTC_FLAG_SEC) != RESET) /* 秒中断 */
  66. {
  67. rtc_get_time(); /* 更新时间 */
  68. __HAL_RTC_ALARM_CLEAR_FLAG(&g_rtc_handle, RTC_FLAG_SEC); /* 清除秒中断 */
  69. // printf("sec:%d\r\n", calendar.sec); /* 打印秒钟 */
  70. }
  71. /* 顺带处理闹钟标志 */
  72. if (__HAL_RTC_ALARM_GET_FLAG(&g_rtc_handle, RTC_FLAG_ALRAF) != RESET) /* 闹钟标志 */
  73. {
  74. __HAL_RTC_ALARM_CLEAR_FLAG(&g_rtc_handle, RTC_FLAG_ALRAF); /* 清除闹钟标志 */
  75. // rtc_get_time();
  76. // time_arr[4]=calendar.hour;
  77. // time_arr[5]=calendar.min;
  78. //Create_show_medicinfo();
  79. // printf("zd1\r\n");
  80. Alar_listNum=Alerm_node->list;
  81. BEEP(1);
  82. EatFlag=1;
  83. Shoe_medicinfiFlag=1;
  84. // __HAL_RTC_ALARM_CLEAR_FLAG(&g_rtc_handle, RESET);
  85. Chinge_alarm();
  86. // printf("Alarm Time:%d-%d-%d %d:%d:%d\n", calendar.year, calendar.month, calendar.date, calendar.hour, calendar.min, calendar.sec);
  87. }
  88. __HAL_RTC_ALARM_CLEAR_FLAG(&g_rtc_handle, RTC_FLAG_OW); /* 清除溢出中断标志 */
  89. while (!__HAL_RTC_ALARM_GET_FLAG(&g_rtc_handle, RTC_FLAG_RTOFF)); /* 等待RTC寄存器操作完成, 即等待RTOFF == 1 */
  90. // printf("zd2\r\n");
  91. }

rtc实时时钟:STM32RTC是STM32系列微控制器中的实时时钟模块,它可以提供精确的时间和日期信息。该模块可以通过外部低速晶振或者内部LSI时钟源来提供时钟信号。同时,它还可以提供闹钟功能和周期性唤醒功能。

rtc初始化需要先使能时钟,这里默认使用外部低速振荡器,当系统下电时可以转为内部时钟,保证时间正常。使能秒中断,实现每秒计数器加一,rtc时间的实现的本质就是对计数器的时间进行计算,系统时间为1970年1月1日0时0分0秒到当前时间的总秒数。使能闹钟中断,当闹钟中的值,和rtc秒的计数器的值一致时产生闹钟中断,处理闹钟过程。处理的闹钟过程包括更新下一个闹钟的信息,打开闹钟提示,更新标志位,其他任务通过获取标志位实现不同的功能。

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

闽ICP备14008679号