看门狗
也是通过定时器来实现的,不同之处在于它定时时间到了之后就会发生一个reset signal,然后系统重启。
The difference between WDT and PWM timer is that WDT generates the reset signal
看门狗的定时器框图还是比较简单的,而且跟定时器的很类似,也是有一个prescaler和mux开关。
注意到WTCON寄存器还是挺厉害的,控制了prescaler,mux开关,中断,还有复位发生。
WTDAT和WTCNT两个寄存器应该就是负责喂狗和倒计时的。
看门狗时钟频率计算公式如图所示
看register map里面还有WTCLRINT寄存器,是用来清中断的。差点漏了。
小字里面的介绍,关于WTDAT,主要说了在初始化的时候WTDAT的值是不会自动load进去WTCNT的,所以WTCNT里面的初始值是0x8000,最好是自己在初始化的时候也写一个值进去WTCNT里面。WTCNT 里面的小字也是这样讲的。
#define WTCON (0xE2700000)
#define WTDAT (0xE2700004)
#define WTCNT (0xE2700008)
#define WTCLRINT (0xE270000C)
#define rWTCON (*(volatile unsigned int *)WTCON)
#define rWTDAT (*(volatile unsigned int *)WTDAT)
#define rWTCNT (*(volatile unsigned int *)WTCNT)
#define rWTCLRINT (*(volatile unsigned int *)WTCLRINT)
// 初始化WDT使之可以产生中断
void wdt_init_reset(void)
{
// 第一步,设置好预分频器和分频器,得到时钟周期是128us
rWTCON &= ~(0xff<<8);
rWTCON |= (65<<8); // 1MHz
rWTCON &= ~(3<<3);
rWTCON |= (3<<3); // 1/128 MHz, T = 128us
// 第二步,设置中断和复位信号的使能或禁止
rWTCON &= ~(1<<2); // disable wdt interrupt
rWTCON |= (1<<0); // enable wdt reset
// 第三步,设置定时时间
// WDT定时计数个数,最终定时时间为这里的值×时钟周期
rWTDAT = 10000; // 定时1.28s
rWTCNT = 10000; // 定时1.28s
// 其实WTDAT中的值不会自动刷到WTCNT中去,如果不显式设置WTCON中的值,它的值就是
// 默认值,然后以这个默认值开始计数,所以这个时间比较久。如果我们自己显式的
// 设置了WTCNT和WTDAT一样的值,则第一次的定时值就和后面的一样了。
//rWTDAT = 1000; // 定时0.128s
//rWTCNT = 1000; // 定时0.128s
// 第四步,先把所有寄存器都设置好之后,再去开看门狗
rWTCON |= (1<<5); // enable wdt
}
代码是直接复制课程的代码
这部分可以将就着对着数据手册来看
看门狗中断部分的代码就不贴上来了,具体要改的地方是自己要 添加一个isr,然后再main函数里面绑定中断号。
对,记得再isr后面要清中断,之前试过没清导致我的按键都不会响。
RTC
real time clock
对应的寄存器
继续从RTC的图出发
RTCCON寄存器
看数据手册的读写寄存器
相关的有
BCDSEC
BCDMINi
BCDHOUR
BCDDAYWEEK
BCDDAY
BCDMON
BCDYEAR
具体实现的方法
通过一个结构体的方式,把年月日时分秒都包含在里面,然后读写的时候通过结构体变量的引用方法,把对应的值写入对应的寄存器里面
需要注意的点:
1、要进行16进制和BCD码的相互转换
static unsigned int num_2_bcd(unsigned int num)
{
// 第一步,把56拆分成5和6
// 第二步,把5和6组合成0x56
return (((num / 10)<<4) | (num % 10));
}
// 函数功能:把bcd码bcd转成十进制,譬如把0x56转成56
static unsigned int bcd_2_num(unsigned int bcd)
{
// 第一步,把0x56拆分成5和6
// 第二步,把5和6组合成56
return (((bcd & 0xf0)>>4)*10 + (bcd & (0x0f)));
}
2、读写之前都要先通过RTCCON寄存器打开读写开关,读写完之后再关上读写开关
闹钟模式
在register map里面可以看到有年月日时分秒的alarm寄存器
而且还可以设置是否发生中断。
例如:
ALMSEC寄存器是设置发生ALARM的条件的
RTCALM是设置是否允许ALARM以及哪个条件可以触发ALARM
INTP是用于在发生中断之后清除中断的。
最终做了什么出来?
参考课程的代码,然后自己改RTC的时间,读写读出来,
然后再结合看门狗的中断方式,相当于一个定时器,定时一秒之后就打印出当前的时间,每一秒刷新一次时间这样。
过程中还是出现了不少问题的,例如头文件没有包含,在main函数里面没有绑定中断号,没有使能中断,没有吧中断服务程序跟中断号绑定在一起。
在配置看门狗定时器的时候也熟悉了时间的计算,挺好的。