stm32 看门狗 BKP(HAL库)

(一)概述

stm32有两个看门狗:硬件看门狗(LSI 40KHz,时间精度不高)和窗口看门狗(APB1)。

(二)硬件看门狗实现代码

IWDG_HandleTypeDef hiwdg;

// 硬件看门狗初始化
static void MX_IWDG_Init(IWDG_HandleTypeDef *pHiwdg)
{
    pHiwdg->Instance = IWDG;
    pHiwdg->Init.Prescaler = IWDG_PRESCALER_4;
    pHiwdg->Init.Reload = 0xFFF; // Tout = ((4 * 2^prer) * rlr) / 40 = 409ms,看门狗溢出时间

    if (HAL_IWDG_Init(pHiwdg) != HAL_OK)
    {
        Error_Handler();
    }
}

int main(void)
{
     ........
     MX_IWDG_Init(&hiwdg);
     ........
     HAL_IWDG_Start(&hiwdg);

    while (1)
    {
        ........
        HAL_IWDG_Refresh(&hiwdg);
    }
    
}

(三)初始上电获取硬件看门狗复位状态

if (__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST) != RESET)
{
    
}/* 硬件看门狗复位 */

__HAL_RCC_CLEAR_RESET_FLAGS();

(四)看门狗复位后IO状态的保持方法

法一:硬件方式,锁存器。

法二:软件方式,当需要关注的IO状态改变时,立马存在Flash中,初始上电判断复位类型是硬件看门狗,就进行Flash读取和IO操作。该方式的缺点:由于stm32的Flash写操作是页写,每次写之前,都要先擦除,而且Flash的写次数有限,故经常写,Flash经常写的区域有可能被写坏。

法三:软件方式,BKP+初始判断处理(stm32F103RC大容量,备份寄存器是42个16位的寄存器)。

// BKP
#define BKP_DATA_LEN               16   
#define BKP_MAX_DATA_LEN           42
#define BKP_INTERVAL_POINT         10

// 写备份寄存器
void BKP_Write(uint8_t *pSourcedata, uint32_t num)
{
	assert_param(num <= BKP_MAX_DATA_LEN);
	
	volatile uint32_t *pDestData;
	
	RCC->APB1ENR |= (1 << 27 | 1 << 28); 	// 电源接口时钟/备份时钟开启
	PWR->CR |= 1 << 8;				 	// 允许写入后备寄存器
	
	if (num > BKP_INTERVAL_POINT)
	{	
		pDestData = &(BKP->DR1);		
		
		for (uint32_t i = 0; i < BKP_INTERVAL_POINT; i++)
		{
			*(pDestData + i) = *(pSourcedata + i);
		}
		
		pDestData = &(BKP->DR11);
		
		for (uint32_t i = 0; i < (num - BKP_INTERVAL_POINT); i++)
		{
			*(pDestData + i) = *(pSourcedata + i + BKP_INTERVAL_POINT);
		}
	}
	else
	{
		pDestData = &(BKP->DR1);		
		
		for (uint32_t i = 0; i < num; i++)
		{
			*(pDestData + i) = *(pSourcedata + i);
		}
	}	
}

// 读备份寄存器
void BKP_Read(uint8_t *pReadData, uint32_t num)
{
	assert_param(num <= BKP_MAX_DATA_LEN);
	
	volatile uint32_t *pSourceData;	
	
	if (num > BKP_INTERVAL_POINT)
	{
		pSourceData = &(BKP->DR1);
		
		for (uint32_t i = 0; i < BKP_INTERVAL_POINT; i++)
		{
			*(pReadData + i) = *(pSourceData + i);
		}	
	
		pSourceData = &(BKP->DR11);
		
		for (uint32_t i = 0; i < (num - BKP_INTERVAL_POINT); i++)
		{
			*(pReadData + i + BKP_INTERVAL_POINT) = *(pSourceData + i);
		}	
	}
	else
	{
		pSourceData = &(BKP->DR1);
		
		for (uint32_t i = 0; i < num; i++)
		{
			*(pReadData + i) = *(pSourceData + i);
		}
	}
}

 

你可能感兴趣的:(STM32)