用cubemx创建stm32独立看门狗的线程,并定时喂狗

一、STM32cubeMX创建项目

STM32使用的是nucleostm32f411re官方的开发板
下面是RT-Thread官网下的教程,帮你更方便的创建基于RT-Thread实时操作系统的STM32开发环境。
RT-Thread帮助文档

二、FinSH组件的移植

使用Finsh组件三步骤:1.实现该函数及rt_hw_console_output函数;2.rtconfig.h中开启RT_USING_FINSH宏;3.添加Finsh组件(cmd.c、msh.c、shell.c)
FinSH组件的文档
在board.c文件中的void rt_hw_board_init()函数中添加串口初始化代码,stm32f411re中使用的是默认的串口2。

void rt_hw_board_init()
{
     
    /* System Clock Update */
    SystemCoreClockUpdate();
	 /*USART2_UART_Init */
    MX_USART2_UART_Init();
    /* System Tick Configuration */
    _SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);

    /* Call components board initial (use INIT_BOARD_EXPORT()) */
#ifdef RT_USING_COMPONENTS_INIT
    rt_components_board_init();
#endif

#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
    rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
#endif
}

并在该文件的最下方添加 void rt_hw_console_output(const char *str)和char rt_hw_console_getchar(void)

void rt_hw_console_output(const char *str)
{
     
        rt_size_t i = 0, size = 0;
        char a = '\r';
        
        __HAL_UNLOCK(&huart2);
        
        size = rt_strlen(str);
        for (i = 0; i < size; i++)
        {
     
        if (*(str + i) == '\n')
        {
     
                HAL_UART_Transmit(&huart2, (uint8_t *)&a, 1, 1);
        }
                HAL_UART_Transmit(&huart2, (uint8_t *)(str + i), 1, 1);
        }
}

char rt_hw_console_getchar(void)
{
     
     int ch ;
	HAL_UART_Receive(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY);

        return ch;
}

然后就可以愉快的在窗口助手下面使用FinSH组件了。
用cubemx创建stm32独立看门狗的线程,并定时喂狗_第1张图片

IWDT独立看门狗的环境搭建

在上面创建的环境下需要自己在Drivers文件下添加stm32f4xx_hal_iwdg.c 然后找到stm32f4xx_hal_conf.h开启#define HAL_IWDG_MODULE_ENABLED 因为在一开始用cubeMX创建项目是并没有开启IWDG,当然也可以直接使用cubeMX开启IWDG
再者还需要打开rtconf.h文件里开启#define RT_USING_HEAP

// Memory Management Configuration
// Dynamic Heap Management
//  Dynamic Heap Management
#define RT_USING_HEAP

这样为了给线程分配堆空间

IWDT独立看门狗的程序编写

在创建的.c文件中编写以下程序

#include "iwdt.h"
#include "stm32f4xx_hal_def.h"
#include "stm32f4xx_hal.h"
#include "stm32f4xx_hal_iwdg.h"
#include 

  




//IWDG_InitTypeDef IWDG_Init;
IWDG_HandleTypeDef IWDG_Handle;
static rt_thread_t IWDG_thread;
/*
 * 设置 IWDG 的超时时间
 * Tout = prv/40 * rlv (s)
 *      prv可以是[4,8,16,32,64,128,256]
 * prv:预分频器值,取值如下:
 *     @arg IWDG_PRESCALER_4: IWDG prescaler set to 4
 *     @arg IWDG_PRESCALER_8: IWDG prescaler set to 8
 *     @arg IWDG_PRESCALER_16: IWDG prescaler set to 16
 *     @arg IWDG_PRESCALER_32: IWDG prescaler set to 32
 *     @arg IWDG_PRESCALER_64: IWDG prescaler set to 64
 *     @arg IWDG_PRESCALER_128: IWDG prescaler set to 128
 *     @arg IWDG_PRESCALER_256: IWDG prescaler set to 256
 *
 *		独立看门狗使用LSI作为时钟。
 *		LSI 的频率一般在 30~60KHZ 之间,根据温度和工作场合会有一定的漂移,我
 *		们一般取 40KHZ,所以独立看门狗的定时时间并一定非常精确,只适用于对时间精度
 *		要求比较低的场合。
 *
 * rlv:预分频器值,取值范围为:0-0XFFF
 * 函数调用举例:
 * IWDG_Config(IWDG_PRESCALER_64 ,625);  // IWDG 1s 超时溢出 
 *						(64/40)*625 = 1s
 */

void IWDG_Config(uint8_t prv ,uint16_t rlv)//IWDG_Config(IWDG_PRESCALER_64 ,625); 
{
     	
	IWDG_Handle.Instance = IWDG;
	// 设置预分频器值
	IWDG_Handle.Init.Prescaler = prv;
	// 设置重装载寄存器值
	IWDG_Handle.Init.Reload = rlv;
//	// 设置要与向下计数器进行比较的窗口值
//	IWDG_Handle.Init.Window = IWDG_WINDOW_DISABLE;
	// 初始化IWDG
	HAL_IWDG_Init(&IWDG_Handle);	
	// 启动 IWDG
	__HAL_IWDG_START(&IWDG_Handle);
}

// 喂狗
void IWDG_Feed(void)
{
     
	// 把重装载寄存器的值放到计数器中,喂狗,防止IWDG复位
	// 当计数器的值减到0的时候会产生系统复位
	HAL_IWDG_Refresh(&IWDG_Handle);
}

void TaskInit(void)
{
     
	IWDG_thread = rt_thread_create("IWDGThread",       /* 线程名字 */
                                IWDG_thread_entry,  /* 线程入口函数 */
                                RT_NULL,           /* 线程入口函数参数 */
                                256,               /* 线程栈大小 */
                                2,                 /* 线程的优先级 */
                                10                 /* 线程时间片 */
                   	            );
	if(IWDG_thread != RT_NULL)
	{
     
		rt_thread_startup(IWDG_thread);
//		IWDG_Config(IWDG_PRESCALER_64 ,625); 
	}
	
	
//	rt_thread_t rt_thread_create(const char *name,
//                             void (*entry)(void *parameter),
//                             void       *parameter,
//                             rt_uint32_t stack_size,
//                             rt_uint8_t  priority,
//                             rt_uint32_t tick);
}


/*************************************************************************
*                             线程入口函数定义
*************************************************************************
*/
void IWDG_thread_entry(void *parameter)
{
     
	while(1)
	{
     	
//		IWDG_Config(IWDG_PRESCALER_64 ,625); 
		rt_thread_mdelay(1000);
        IWDG_Feed();		
		rt_kprintf("System Running Time:%d s \n",rt_tick_get()/RT_TICK_PER_SECOND);
	}
}


在main.c中添加以下代码

  /* USER CODE BEGIN 2 */
   if (__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST) != RESET)
	{
     
		/* 独立看门狗复位 */
		/*  亮红灯 */
		 GPIOA->BSRR = 1<<(5) ; //PB5?????,??LED;

		/* 清除标志 */
		__HAL_RCC_CLEAR_RESET_FLAGS();
		
		/*如果一直不喂狗,会一直复位,加上前面的延时,会看到红灯闪烁
		在1s 时间内喂狗的话,则会持续亮绿灯*/
	}
	else
	{
     
		/*不是独立看门狗复位(可能为上电复位或者手动按键复位之类的) */
		/* 亮蓝灯 */
		GPIOA->BSRR = 1<<(5+16) ; //PB5?????,??LED;
	}
	IWDG_Config(IWDG_PRESCALER_64 ,625);
	TaskInit();
  /* USER CODE END 2 */

用cubeMX生成的代码有放在其指定的位置里面,不然当重新用cubeMX生成代码时,程序将会被覆盖。
下面就是实验结果
用cubemx创建stm32独立看门狗的线程,并定时喂狗_第2张图片
IWDT代码链接

你可能感兴趣的:(stm32,嵌入式)