目前共有5篇帖子。 内容转换:不转换▼
 
点击 回复
639 4
【程序】窗口看门狗WWDG的使用
一派护法 十九级
1楼 发表于:2017-3-24 21:42
#include <stm32f10x.h>

uint8_t seg8[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};
uint16_t num = 0;
uint8_t value = 0;

void delay(void)
{
    uint16_t i;
    for (i = 0; i < 20000; i++);
}

void ser_in(uint8_t data)
{
    uint8_t i;
    for (i = 0; i < 8; i++)
    {
        GPIOB->BRR = GPIO_BRR_BR9; // SCLK=PB9
        if (data & 0x80)
            GPIOB->BSRR = GPIO_BSRR_BS7; // DIO=PB7
        else
            GPIOB->BRR = GPIO_BRR_BR7;
        data <<= 1;
        GPIOB->BSRR = GPIO_BSRR_BS9;
    }
}

void par_out(void)
{
    GPIOB->BRR = GPIO_BRR_BR8; // RCLK=PB8
    GPIOB->BSRR = GPIO_BSRR_BS8;
}

void seg_scan(void)
{
    uint8_t i;
    uint16_t numbuf = num;
    for (i = 0; i <= 4; i++)
    {
        ser_in(seg8[numbuf % 10]);
        ser_in(1 << i);
        par_out();
        delay();
        numbuf /= 10;
    }
    
    numbuf = value;
    for (i = 6; i <= 7; i++)
    {
        ser_in(seg8[numbuf % 10]);
        ser_in(1 << i);
        par_out();
        delay();
        numbuf /= 10;
    }
}

int main(void)
{
    RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN;
    PWR->CR |= PWR_CR_DBP; // 允许写入后备寄存器
    
    // 上电复位: PORRSTF=PINRSTF=1
    // 复位键复位: PINRSTF=1
    if (RCC->CSR & RCC_CSR_PORRSTF)
        num = 1970; // 通电时写入初值
    else
        num = BKP->DR1; // 复位时读取寄存器值
    if (RCC->CSR & RCC_CSR_PINRSTF)
        BKP->DR1 = num + 1; // 每次复位都把寄存器的值加1
    if (RCC->CSR & RCC_CSR_WWDGRSTF)
        BKP->DR1 = num - 1; // 如果是看门狗复位则减去1
    RCC->CSR |= RCC_CSR_RMVF; // 清除复位标志信息
    
    /* 配置GPIO口*/
    RCC->APB2ENR = RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN;
    GPIOB->CRL = 0x30000000;
    GPIOB->CRH = 0x00000033;
    GPIOC->CRL = 0x00000080; // PC1设为带电阻输入
    GPIOC->BSRR = GPIO_BSRR_BS1; // PC1带上拉电阻输入
    
    /* 配置WWDG */
    RCC->APB1ENR |= RCC_APB1ENR_WWDGEN; // 开WWDG时钟, 随后WWDG进入free-running(空转)状态
    //WWDG->CFR |= WWDG_CFR_EWI | WWDG_CFR_WDGTB; // WDGTB=11, 8分频
    WWDG->CFR = WWDG_CFR_EWI | WWDG_CFR_WDGTB | WWDG_CFR_W6 | 20; // T[5:0]降到20后才准喂狗
    NVIC_EnableIRQ(WWDG_IRQn); // 开EWI中断
    while ((WWDG->CR & WWDG_CR_T) > (WWDG_CFR_W6 | 20)); // 等待正在空转的WWDG离开窗口区, 进入允许喂狗的区间(T<0x40时喂狗不会触发EWI中断), 防止value变量被置成1
    WWDG->CR = WWDG_CR_WDGA | WWDG_CR_T6 | 35; // T6恒为1, T[5:0]的范围: 35~0, 喂狗时间: 32.768ms, WDGA=1启动看门狗
    // 只有当T[5:0]在20~0时才允许喂狗
    
    while (1)
    {
        seg_scan(); // 在WWDG允许的时间内只能执行一次, 否则会超时
        if (GPIOC->IDR & GPIO_IDR_IDR1) // 如果PC1键按住不放(低电平), 则不喂狗
            WWDG->CR = WWDG_CR_WDGA | WWDG_CR_T6 | 35; // T[5:0]=35
    }
}

// 当T=0x40(即T[5:0]=0)时触发此中断, 离复位还有最后910us的时间
// 此时T6仍为1, 只要及时喂狗仍可视为正常工作而无需复位
void WWDG_IRQHandler(void)
{
    WWDG->SR &= ~WWDG_SR_EWIF;
    value = (value + 1) % 100;
    //WWDG->CR = WWDG_CR_WDGA | WWDG_CR_T6 | 35; // 在中断中阻止Reset
    
    // 该中断必须在T从0x40跳变到0x39期间的910us之内完成
    // 否则将无法执行完毕而提前触发Reset
}
一派护法 十九级
2楼 发表于:2017-3-24 21:43
T[5:0]的最大范围为0~63。
一派护法 十九级
3楼 发表于:2017-3-24 22:01
【不用等待的窗口期配置方法】
/* 配置WWDG */
RCC->APB1ENR |= RCC_APB1ENR_WWDGEN; // 开WWDG时钟, 随后WWDG进入free-running(空转)状态
WWDG->CFR |= WWDG_CFR_EWI | WWDG_CFR_WDGTB; // WDGTB=11, 8分频, 先暂时采用默认的上限值: W6|63=0x7f, 防止触发EWI中断
NVIC_EnableIRQ(WWDG_IRQn); // 开EWI中断
WWDG->CR = WWDG_CR_WDGA | WWDG_CR_T6 | 35; // T6恒为1, T[5:0]的范围: 35~0, 喂狗时间: 32.768ms, WDGA=1启动看门狗
WWDG->CFR = (WWDG->CFR & ~WWDG_CFR_W) | WWDG_CFR_W6 | 20; // 更改上限值, 只有当T[5:0]在20~0时才允许喂狗
一派护法 十九级
4楼 发表于:2017-4-12 21:22
其实,WWDG可以通过下面两种方法关闭。
方法一:关闭WWDG外设时钟
RCC->APB1ENR &= ~RCC_APB1ENR_WWDGEN;
方法二:将WWDG外设复位
RCC->APB1RSTR |= RCC_APB1RSTR_WWDGRST;
RCC->APB1RSTR &= ~RCC_APB1RSTR_WWDGRST;
一派护法 十九级
5楼 发表于:2017-4-12 21:24
方法二可以直接将WWDG_CR_WDGA清零。

回复帖子

内容:
用户名: 您目前是匿名发表
验证码:
(快捷键:Ctrl+Enter)
 

本帖信息

点击数:639 回复数:4
评论数: ?
作者:巨大八爪鱼
最后回复:巨大八爪鱼
最后回复时间:2017-4-12 21:24
 
©2010-2024 Arslanbar Ver2.0
除非另有声明,本站采用知识共享署名-相同方式共享 3.0 Unported许可协议进行许可。