/*************************************************************
Function : IWDGReset_TIM5_Init
Description: 初始化TIM5,用来校准LSI时钟
Input : none
return : none
*************************************************************/
static void IWDGReset_TIM5_Init(void)
{
TIM_ICInitTypeDef TIM_ICInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);//打开TIM5时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//打开AFIO时钟,引脚重映射一定要时,一定要有这句话
TIM_PrescalerConfig(TIM5, 0, TIM_PSCReloadMode_Immediate);//不对TIM5之中进行分频,所以TIM5这时候的时钟是72M
GPIO_PinRemapConfig(GPIO_Remap_TIM5CH4_LSI, ENABLE);//在内部吧LSI连接到TIM4的CH4上,用CH4来测量LSI时钟频率
TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;//TIM5的CH4
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//检测上升沿
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//管脚与寄存器直接对应
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV8;//输入捕获8预分频,即检测到8个上升沿才生成中断标志
TIM_ICInitStructure.TIM_ICFilter = 0;//不滤波
TIM_ICInit(TIM5, &TIM_ICInitStructure);//初始化TIM5的CH4
TIM_ITConfig(TIM5, TIM_IT_CC4, ENABLE);//打开CH4中断源
TIM5->SR = 0;//清除TIM5的所有标志位
TIM_Cmd(TIM5, ENABLE);//打开TIM5
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;//设置TIM5的中断优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
u32 LsiFreq = 40000; //LSI时钟频率默认为40kHz
extern u16 CaptureNumber; //捕获次数
/*************************************************************
Function : IWDGReset_LSICalibration
Description: 校准LSI时钟频率
Input : none
return : none
*************************************************************/
static void IWDGReset_LSICalibration(void)
{
RCC_LSICmd(ENABLE);//打开LSI时钟
while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY)==RESET); //等待LSI时钟稳定
IWDGReset_TIM5_Init();//初始化TIM5
while(CaptureNumber != 2);//等待检测到LSI的2个上升沿
PRINTF("LSI freq: %dHz\r\n", LsiFreq);//将测量的LSI频率打印出来
TIM_ITConfig(TIM5, TIM_IT_CC4, DISABLE);//关闭CH4中断源
}
/*************************************************************
Function : IWDGReset_Init
Description: 独立看门狗初始化
Input : none
return : none
*************************************************************/
void IWDGReset_Init(void)
{
IWDGReset_LSICalibration(); //打开LSI,并校准LSI时钟
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);//允许访问IWDG相关寄存器
IWDG_SetPrescaler(IWDG_Prescaler_32); //32分频
IWDG_SetReload(LsiFreq/128); //设置看门狗喂狗时间为250ms,装载值=0.25/(LsiFreq/32)=LsiFreq/128
IWDG_Enable(); //打开IWDG
}/*************************************************************
Function : IWDGReset_Init
Description: 独立看门狗初始化
Input : none
return : none
*************************************************************/
void IWDGReset_Init(void)
{
IWDGReset_LSICalibration();//打开LSI,并校准LSI时钟
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);//允许访问IWDG相关寄存器
IWDG_SetPrescaler(IWDG_Prescaler_32);//32分频
IWDG_SetReload(LsiFreq/128);//设置看门狗喂狗时间为250ms,装载值=0.25/(LsiFreq/32)=LsiFreq/128
IWDG_Enable();//打开IWDG
}
#ifndef __IWDGRESET_H__
#define __IWDGRESET_H__
#include "stm32f10x.h"
void IWDGReset_Init(void);
#endif
u16 CaptureNumber = 0;
extern u32 LsiFreq;
/*************************************************************
Function : TIM5_IRQHandler
Description: TIM5中断服务程序
Input : none
return : none
*************************************************************/
void TIM5_IRQHandler(void)
{
static u16 capture = 0;
static u16 IC1ReadValue1 = 0, IC1ReadValue2 = 0;
if (TIM_GetITStatus(TIM5, TIM_IT_CC4) != RESET)
{
if(CaptureNumber == 0)//第一次捕获到上升沿
{
IC1ReadValue1 = TIM_GetCapture4(TIM5);//获取当前计数值
}
else if(CaptureNumber == 1)//第二次捕获到上升沿
{
IC1ReadValue2 = TIM_GetCapture4(TIM5);//获取当前计数值
if (IC1ReadValue2 > IC1ReadValue1)//没有超过最大计数值
{
capture = (IC1ReadValue2 - IC1ReadValue1);//计算两个上升沿之间的计数值
}
else//超过了最大计数值
{
capture = ((0xFFFF - IC1ReadValue1) + IC1ReadValue2);//计算两个上升沿之间的计数值
}
LsiFreq = (uint32_t) SystemCoreClock / capture;
LsiFreq *= 8;//计算LSI频率=72M/capture*8 (乘上8是因为TIM5的CH4 8预分频)
}
CaptureNumber++;//捕获上升沿次数自增
TIM_ClearITPendingBit(TIM5, TIM_IT_CC4);//清除标志位
}
}
/*************************************************************
Function : main
Description: main入口
Input : none
return : none
*************************************************************/
int main(void)
{
BSP_Init();
PRINTF("\nmain() is running!\r\n");
IWDGReset_Init();
while(1)
{
LED1_Toggle(); //LED闪烁
Delay_ms(200); //延时大改250ms以上,就会看门狗复位
IWDG_ReloadCounter();//喂狗
}
}
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
同时在stm32f10x_it.c中,将LsiFreq *= 8;这就话屏蔽掉,然后编译下载,有如下现象:
上一篇:STM32窗口看门狗WWDG复位
下一篇:STM32 备份寄存器操作
推荐阅读最新更新时间:2024-03-16 15:14