当前位置:网站首页>Pandora IOT development board learning (HAL Library) - Experiment 6 independent watchdog experiment (learning notes)
Pandora IOT development board learning (HAL Library) - Experiment 6 independent watchdog experiment (learning notes)
2022-07-04 03:38:00 【Xiaohui_ Super】
This code refers to the punctual atomic routine
List of articles
Experimental function
Routine source code :(main.c)
The experiment was carried out by pressing WK_UP Press the button to feed the dog , If the dog is not fed within the specified time limit , The SCM will restart .
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "iwdg.h"
/********************************************************************************* ___ _ _____ _____ _ _ _____ _____ _ __ / _ \ | | |_ _|| ___|| \ | ||_ _|| ___|| | / / / /_\ \| | | | | |__ | \| | | | | |__ | |/ / | _ || | | | | __| | . ` | | | | __| | \ | | | || |_____| |_ | |___ | |\ | | | | |___ | |\ \ \_| |_/\_____/\___/ \____/ \_| \_/ \_/ \____/ \_| \_/ * ****************************************************************************** * The punctual atoms Pandora STM32L475 IoT Development board experiment 6 * Independent watchdog experiment HAL Library version * Technical support :www.openedv.com * Taobao shop :http://openedv.taobao.com * Focus on wechat public platform wechat :" The punctual atoms ", Free access STM32 Information . * Guangzhou Xingyi Electronic Technology Co., Ltd * author : The punctual atoms @ALIENTEK * ******************************************************************************/
int main(void)
{
HAL_Init();
SystemClock_Config(); // Initialize the system clock to 80M
delay_init(80); // Initialization delay function 80M The system clock
uart_init(115200); // Initialize serial port , The baud rate is 115200
LED_Init(); // initialization LED
KEY_Init(); // Initialization key
delay_ms(100); // Time delay 100ms Then initialize the watchdog ,LED_B The change of " so "
IWDG_Init(IWDG_PRESCALER_64, 500); // The frequency division number is 64, The overload value is 500, The overflow time is 1s(4*2^4*500/32=1000ms)
LED_B(0);
while(1)
{
if(KEY_Scan(0) == WKUP_PRES) // If WK_UP Press down , feed a dog
{
IWDG_Feed(); // feed a dog
}
delay_ms(10);
}
}
Code analysis
HAL_Init()
HAL_Init() The definition is as follows :( See notes for specific functions )
HAL_StatusTypeDef HAL_Init(void)
{
HAL_StatusTypeDef status = HAL_OK;
/* To configure Flash Prefetch , Instruction cache , Data caching */
/* Default configuration is : Pre access is closed Instruction cache and data cache are enabled */
#if (INSTRUCTION_CACHE_ENABLE == 0) // Flash Enable pre access configuration , Can accelerate CPU Execution of code
__HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
#endif /* INSTRUCTION_CACHE_ENABLE */
#if (DATA_CACHE_ENABLE == 0)
__HAL_FLASH_DATA_CACHE_DISABLE();
#endif /* DATA_CACHE_ENABLE */
#if (PREFETCH_ENABLE != 0)
__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif /* PREFETCH_ENABLE */
/* Set Interrupt Group Priority */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2); // To configure NVIC Priority groups
/* Use SysTick as time base source and configure 1ms tick (default clock after Reset is MSI) */
if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) // Initialize tick timer , The clock beat is set to 1ms
{
status = HAL_ERROR;
}
else
{
/* Init the low level hardware */
HAL_MspInit(); // Low speed peripheral initialization , such as GPIO、 Interrupt, etc ( Use STM32CubeMx Low speed peripherals are initialized when generating code
// The code is in this kind of function , In other cases, this function can be ignored
}
/* Return function status */
return status;
}
HAL_InitTick()
Tick timer clock beat initialization function
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
HAL_StatusTypeDef status = HAL_OK;
/*Configure the SysTick to have interrupt in 1ms time basis*/
if (HAL_SYSTICK_Config(SystemCoreClock/1000UL) != 0U) // The system clock /1000, The interruption period is 1ms
{
status = HAL_ERROR;
}
else
{
/*Configure the SysTick IRQ priority */
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0); // Set the interrupt priority of the tick timer to the highest
}
/* Return function status */
return status;
}
SystemClock_Config()
SystemClock_Config() The function is defined as follows :( See notes for specific functions , For reference only )
void SystemClock_Config(void)
{
HAL_StatusTypeDef ret = HAL_OK;
RCC_OscInitTypeDef RCC_OscInitStruct; // Define oscillator initialization structure variables
RCC_ClkInitTypeDef RCC_ClkInitStruct; // Define clock initialization structure variables
__HAL_RCC_PWR_CLK_ENABLE(); // Enable power control clock
/*Initializes the CPU, AHB and APB busses clocks*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // take HSE( External high-speed clock ) As a clock source
RCC_OscInitStruct.HSEState = RCC_HSE_ON; // Turn on HSE
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // Turn on PLL( PLL )
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; // take HSE As PLL The clock source of
RCC_OscInitStruct.PLL.PLLM = 1; // PLL-VCO Input clock frequency division coefficient ,1 Express 2 frequency division (8 / 2 = 4M, The external crystal oscillator frequency of the development board is 8MHz)
RCC_OscInitStruct.PLL.PLLN = 20; // PLL-VCO Output clock frequency multiplication coefficient ,4 * 20 = 80M, That is, the output clock frequency is 80MHz
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7; // SAI Frequency division coefficient of clock
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; // SDMMC1, RNG and USB Clock frequency division coefficient
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; // Frequency division coefficient of the main system clock
ret = HAL_RCC_OscConfig(&RCC_OscInitStruct); // Initialize clock configuration
if(ret != HAL_OK) while(1);
/*Initializes the CPU, AHB and APB busses clocks*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; // Configure all clocks at the same time
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // take PLL As the clock source of the system
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB Regardless of the frequency
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; // APB1 Regardless of the frequency
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // APB2 Regardless of the frequency
ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4); // Configure the initial structure variable of the clock ,
// Use Flash Delay 4, Wait state ( Delay ) The quantity of should be according to CPU The clock (HCLK) Frequency and internal voltage range , How to
// Please refer to the chip manual
if(ret != HAL_OK) while(1);
/*Configure the main internal regulator output voltage*/
ret = HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); // Internal register output voltage configuration
// Here is HAL_PWREx_ControlVoltageScaling() Part of the function description :
//PWR_REGULATOR_VOLTAGE_SCALE1 Regulator voltage output range 1 mode, typical output voltage
// at 1.2 V, system frequency up to 80 MHz.
if(ret != HAL_OK) while(1);
}
delay_init()
The tick timer is already HAL_Init() Initialization in , The following function is actually for fac_us Given a value ( At present, the operating system is not involved , Other code will not be studied for the time being ).
static u32 fac_us = 0; //us Delay multiplier
/** * @brief Initialization delay function ,SYSTICK The clock is fixed to AHB The clock * * @param SYSCLK System clock frequency * * @return void */
void delay_init(u8 SYSCLK)
{
#if SYSTEM_SUPPORT_OS // If support is needed OS.
u32 reload;
#endif
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);//SysTick The frequency is HCLK
fac_us = SYSCLK; // Whether used or not OS,fac_us You need to use
#if SYSTEM_SUPPORT_OS // If support is needed OS.
reload = SYSCLK; // The number of counts per second Unit is K
reload *= 1000000 / delay_ostickspersec; // according to delay_ostickspersec Set the overflow time
//reload by 24 Bit register , Maximum :16777216, stay 80M Next , about 209.7ms about
fac_ms = 1000 / delay_ostickspersec; // representative OS The minimum unit that can delay
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; // Turn on SYSTICK interrupt
SysTick->LOAD = reload; // Every time 1/OS_TICKS_PER_SEC Second break once
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // Turn on SYSTICK
#else
#endif
}
LED_Init()
/** * @brief LED IO Initialization function * * @param void * * @return void */
void LED_Init(void)
{
/* LED-B PE9 LED-G PE8 LED-R PE7 */
GPIO_InitTypeDef GPIO_InitStruct; // Define a GPIO Initializing structure variables
__HAL_RCC_GPIOE_CLK_ENABLE(); // Can make GPIOE The clock of
GPIO_InitStruct.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9; // Simultaneous configuration 3 One pin
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // Push pull output mode
GPIO_InitStruct.Pull = GPIO_PULLUP; // Default pull up
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // The speed is set to high speed (25 MHz to 50 MHz)
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); // Initializing structure variables
// take 3 Both pins are set high at the same time
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9, GPIO_PIN_SET);
}
KEY_Init()
/** * @brief Key initialization function * * @param void * * @return void */
void KEY_Init(void)
{
/* KEY0 - PD10 KEY1 - PD9 KEY2 - PD8 WK_UP - PC13 */
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOC_CLK_ENABLE(); // Turn on GPIOC The clock
__HAL_RCC_GPIOD_CLK_ENABLE(); // Turn on GPIOD The clock
GPIO_Initure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 ; //PD8.9.10
GPIO_Initure.Mode = GPIO_MODE_INPUT; // Input
GPIO_Initure.Pull = GPIO_PULLDOWN; // The drop-down
GPIO_Initure.Speed = GPIO_SPEED_HIGH; // High speed
HAL_GPIO_Init(GPIOD, &GPIO_Initure);
GPIO_Initure.Pin = GPIO_PIN_13; //PC13
GPIO_Initure.Mode = GPIO_MODE_INPUT; // Input
GPIO_Initure.Pull = GPIO_PULLUP; // Pull up
GPIO_Initure.Speed = GPIO_SPEED_HIGH; // High speed
HAL_GPIO_Init(GPIOC, &GPIO_Initure);
}
delay_ms()
delay_ms() What runs in the is delay_us(), delay_us() Delay by ticking timer . above delay_init() Have already put fac_us Set up in order to 80, Tick timer counts 80 Time required 10-6 second ( The system clock is 80MHz), namely 1us.
/** * @brief Delay milliseconds (ms) function * * @param nms How many milliseconds does it take * * @return void */
void delay_ms(u16 nms)
{
u32 i;
for(i = 0; i < nms; i++) delay_us(1000);
}
/** * @brief Delay microseconds (us) function * * @remark nus:0~190887435( The maximum value is 2^32/[email protected]_us=22.5) * * @param nus How many microseconds do you need to delay * * @return void */
void delay_us(u32 nus)
{
u32 ticks;
u32 told, tnow, tcnt = 0;
u32 reload = SysTick->LOAD; //LOAD Value
ticks = nus * fac_us; // The number of beats needed
told = SysTick->VAL; // Counter value at the time of first entry
while(1)
{
tnow = SysTick->VAL;
if(tnow != told)
{
if(tnow < told)tcnt += told - tnow; // Notice here SYSTICK It's a decreasing counter .
else tcnt += reload - tnow + told;
told = tnow;
if(tcnt >= ticks)break; // For more than / Equal to the time to delay , The exit .
}
}
}
IWDG_Init()
The initialization of the independent watchdog is simple , After all, it's a library function (HAL library ) Code , We don't need to care about the underlying register operation code .
Here are configuration options IWDG_WINDOW_DISABLE I haven't seen it before , But it doesn't seem to be very important .
// Global variables
IWDG_HandleTypeDef IWDG_Handler; // Independent watchdog handle
/** * @brief Initialize the independent watchdog function * Time calculation ( Probably ):Tout=((4*2^prer)*rlr)/32 ms * * @param prer Frequency division number :IWDG_PRESCALER_4~IWDG_PRESCALER_256 * @param rlr Automatic reload load value ,0~0XFFF * * @return void */
void IWDG_Init(u8 prer, u16 rlr)
{
IWDG_Handler.Instance = IWDG;
IWDG_Handler.Init.Prescaler = prer; // Set up IWDG Division coefficient
IWDG_Handler.Init.Reload = rlr; // Reload value
IWDG_Handler.Init.Window = IWDG_WINDOW_DISABLE;
HAL_IWDG_Init(&IWDG_Handler); // initialization IWDG And open the independent watchdog
}
The frequency division coefficient of the watchdog can only be the following ,
/** @defgroup IWDG_Prescaler IWDG Prescaler * @{ */
#define IWDG_PRESCALER_4 0x00000000u /*!< IWDG prescaler set to 4 */
#define IWDG_PRESCALER_8 IWDG_PR_PR_0 /*!< IWDG prescaler set to 8 */
#define IWDG_PRESCALER_16 IWDG_PR_PR_1 /*!< IWDG prescaler set to 16 */
#define IWDG_PRESCALER_32 (IWDG_PR_PR_1 | IWDG_PR_PR_0) /*!< IWDG prescaler set to 32 */
#define IWDG_PRESCALER_64 IWDG_PR_PR_2 /*!< IWDG prescaler set to 64 */
#define IWDG_PRESCALER_128 (IWDG_PR_PR_2 | IWDG_PR_PR_0) /*!< IWDG prescaler set to 128 */
#define IWDG_PRESCALER_256 (IWDG_PR_PR_2 | IWDG_PR_PR_1) /*!< IWDG prescaler set to 256 */
/** * @} */
The formula for calculating the overflow time of the independent watchdog is Tout=((4*2^prer)*rlr)/32(ms), Division coefficient IWDG_PRESCALER_4~IWDG_PRESCALER_256 The real value of is actually 0~6, So when the frequency division parameter is selected IWDG_PRESCALER_64, Heavy load value filling 500 when , The independent watchdog overflow time is 1s (4 * 24 * 500 / 32 = 1000ms).
LED_B()
LED The control function of is a macro function , We used HAL_GPIO_WritePin() and HAL_GPIO_TogglePin() Two library functions .
#define LED_R(n) (n?HAL_GPIO_WritePin(GPIOE,GPIO_PIN_7,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOE,GPIO_PIN_7,GPIO_PIN_RESET))
#define LED_R_TogglePin HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_7)
#define LED_G(n) (n?HAL_GPIO_WritePin(GPIOE,GPIO_PIN_8,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOE,GPIO_PIN_8,GPIO_PIN_RESET))
#define LED_G_TogglePin HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_8)
#define LED_B(n) (n?HAL_GPIO_WritePin(GPIOE,GPIO_PIN_9,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOE,GPIO_PIN_9,GPIO_PIN_RESET))
#define LED_B_TogglePin HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_9)
KEY_Scan()
The most basic functions of key scanning are the following four , That is, read the corresponding IO The level state of ,
#define KEY0 HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_10)
#define KEY1 HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_9)
#define KEY2 HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_8)
#define WK_UP HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13)
The following key scanning mechanism should be familiar to you , It's easy to understand :
/** * @brief Key handling functions * * @remark Note that this function has response priority ,KEY0>KEY1>KEY2>WK_UP!! * * @param mode 0: Continuous press is not supported ,1: Support continuous press * * @return u8 Return to key value * 0: There's no key press ,1:KEY0 Press down ,2:KEY1 Press down ,3:KEY2 Press down ,4:WK_UP Press down */
u8 KEY_Scan(u8 mode)
{
static u8 key_up = 1; // Key release sign
if(mode == 1)key_up = 1; // Support to click
if(key_up && (KEY0 == 0 || KEY1 == 0 || KEY2 == 0 || WK_UP == 1))
{
delay_ms(10);
key_up = 0;
if(KEY0 == 0) return KEY0_PRES;
else if(KEY1 == 0) return KEY1_PRES;
else if(KEY2 == 0) return KEY2_PRES;
else if(WK_UP == 1) return WKUP_PRES;
}
else if(KEY0 == 1 && KEY1 == 1 && KEY2 == 1 && WK_UP == 0)key_up = 1;
return 0; // No key press
}
IWDG_Feed()
Independent watchdog feed dog function , In fact, the write register operation is encapsulated in three layers .HAL_IWDG_Refresh() --> __HAL_IWDG_RELOAD_COUNTER() --> __HAL_IWDG_RELOAD_COUNTER()
/** * @brief Hello, the independent watchdog * * @param void * * @return void */
void IWDG_Feed(void)
{
HAL_IWDG_Refresh(&IWDG_Handler); // feed a dog
}
/** * @brief Refresh the IWDG. * @param hiwdg pointer to a IWDG_HandleTypeDef structure that contains * the configuration information for the specified IWDG module. * @retval HAL status */
HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg)
{
/* Reload IWDG counter with value defined in the reload register */
__HAL_IWDG_RELOAD_COUNTER(hiwdg);
/* Return function status */
return HAL_OK;
}
#define __HAL_IWDG_RELOAD_COUNTER(__HANDLE__) WRITE_REG((__HANDLE__)->Instance->KR, IWDG_KEY_RELOAD)
Here are some basic bit masks for independent watchdog :
/** * @brief IWDG Key Register BitMask */
#define IWDG_KEY_RELOAD 0x0000AAAAu /*!< feed a dog IWDG Reload Counter Enable */
#define IWDG_KEY_ENABLE 0x0000CCCCu /*!< Peripherals enable IWDG Peripheral Enable */
#define IWDG_KEY_WRITE_ACCESS_ENABLE 0x00005555u /*!< Write enable IWDG KR Write Access Enable */
#define IWDG_KEY_WRITE_ACCESS_DISABLE 0x00000000u /*!< Write disability IWDG KR Write Access Disable */
边栏推荐
- Package and download 10 sets of Apple CMS templates / download the source code of Apple CMS video and film website
- Objective-C description method and type method
- 2022 attached lifting scaffold worker (special type of construction work) free test questions and attached lifting scaffold worker (special type of construction work) examination papers 2022 attached
- PID of sunflower classic
- 渗透实战-guest账户-mimikatz-向日葵-sql提权-离线解密
- 用于TCP协议交互的TCPClientDemo
- Love and self-discipline and strive to live a core life
- Eh, the log time of MySQL server is less than 8h?
- Leetcode51.n queen
- [Wu Enda deep learning] beginner learning record 3 (regularization / error reduction)
猜你喜欢

Easy to win insert sort

Management and thesis of job management system based on SSM
![[latex] production of complex tables: excel2latex and detail adjustment](/img/39/0d448ddf006eda262de3ed75666354.jpg)
[latex] production of complex tables: excel2latex and detail adjustment

What are the virtual machine software? What are their respective functions?

MySQL data query optimization -- data structure of index

Explain AI accelerator in detail: why is this the golden age of AI accelerator?

MySQL one master multiple slaves + linear replication

Want to do something in production? Then try these redis commands

Infiltration practice guest account mimikatz sunflower SQL rights lifting offline decryption

Constantly changing harmonyos custom JS components during the Spring Festival - Smart Koi
随机推荐
Sword finger offer:55 - I. depth of binary tree
What kind of experience is it when the Institute earns 20000 yuan a month!
Monitoring - Prometheus introduction
Summary of Chinese remainder theorem
Command Execution Vulnerability - command execution - vulnerability sites - code injection - vulnerability exploitation - joint execution - bypass (spaces, keyword filtering, variable bypass) - two ex
Consul of distributed service registration discovery and unified configuration management
[untitled]
This function has none of DETERMINISTIC, NO SQL..... (you *might* want to use the less safe log_bin_t
新型数据中心,助力加快构建以数据为关键要素的数字经济
Exercices de renforcement des déclarations SQL (MySQL 8.0 par exemple)
pytest多进程/多线程执行测试用例
SQL injection (1) -- determine whether there are SQL injection vulnerabilities
Solve the problems encountered by the laravel framework using mongodb
Aperçu du code source futur - série juc
Which product is better if you want to go abroad to insure Xinguan?
Defensive programming skills
数据库SQL语句汇总,持续更新......
system information
[PaddleSeg 源码阅读] PaddleSeg计算 mIoU
What is cloud primordial?