// NAME: main.c
// DESC: TQ2440看门狗测试程序
// 现象分析:看门狗相应有两种:1、中断 2、复位
// 对应的寄存器设置 rWTCON = rWTCON | 0x1; //看门狗定时器超时复位
// rWTCON = rWTCON | (0x1<<2); //中断使能
// rWTCON = rWTCON | (0x1<<5); //看门狗定时器使能
// 当使能中断,没有喂狗,就发生中断,蜂鸣器响
// 当超时复位使能,没有喂狗,就发生复位
// rWTCNT = 50000; //喂狗,重新赋值,防止中断 时间是4秒内要喂狗一次
//=========================================
/* 头文件包含 */
#include "def.h"
#include "option.h"
#include "2440addr.h"
void delay_ms(U32 time)
{
//定时器3输入时钟频率 = PCLK / {预分频值+1} / {分频值}
//{预分频值} = 0~255
//{分频值} = 2, 4, 8, 16
//PCLK:50MHz 时钟频率:6250KHz 定时1ms 计数:时钟频率*定时时间-1
U32 val = 50000000/(4*2)/1000-1;
rTCFG0 = (rTCFG0 & ~(0xff<<8)) | (3<<8);//Prescaler1 = 3+1
rTCFG1 = (rTCFG1 & ~(0xf<<12)) | (0<<12);//mux = 1/2
rTCNTB3 = val;
rTCMPB3 = rTCNTB3/2; //占空比50%
rTCON = (rTCON & ~(0xf<<16)) | (0xb<<16);//自动重载、变相、手动更新、启动定时器3
rTCON = (rTCON & ~(0x2<<16)); //禁止手动更新
while(time--) //等待一次定时结束
{
while(rTCNTO3 >= (val>>1));
while(rTCNTO3 < (val>>1));
}
}
void led_init(void)
{
//板载LED为GPB[5:8]
rGPBCON = (rGPBCON & ~(0xff<<10)) | (0x55<<10); //rGPBCON为01 配置为输出
rGPBUP = (rGPBUP & ~(0xf<<5)) | (0xf<<5); //rGPBUP为1 禁止上拉
rGPBDAT = (rGPBDAT & ~(0xf<<5)) |(0xf<<5); //LED灯全关
}
void led_display(unsigned char data)
{
//0x0全灭 0xf全亮 0x01 0x02 0x04 0x80 各自灯亮
rGPBDAT = (rGPBDAT & ~(0xf<<5)) | ((~data) <<5);
}
void buzzer_freq_set(U32 freq)
{
//定时器1输入时钟频率 = PCLK / {预分频值+1} / {分频值}
//{预分频值} = 0~255
//{分频值} = 2, 4, 8, 16
//PCLK:50MHz 时钟频率:6250KHz 定时1ms 计数:时钟频率*定时时间-1
// 50000000/(16*8) = 390625
rGPBCON = (rGPBCON & ~0x3) | 0x2;//GPB0口设置为TOUT PWM 0b10
rTCFG0 = (rTCFG0 & ~0xff) | 15; //Prescaler0 = 15+1
rTCFG1 = (rTCFG1 & ~0xf) | 0x2; //mux = 1/8 0b0010
rTCNTB0 = 50000000/(16*8)/freq;
rTCMPB0 = rTCNTB0/2; //占空比50%
rTCON = (rTCON & ~0x1f) | 0xb; //禁止死区、自动重载、变相、手动更新、启动定时器3
rTCON = (rTCON & ~0x2); //禁止手动更新
}
void buzzer_stop(void)
{
rGPBCON = (rGPBCON & ~0x3) | 0x1;//GPB0口设置为输出0b01
rGPBDAT = (rGPBDAT & ~0x1); //GPB0口输出低电平关掉蜂鸣器
}
void beep(U32 freq,U32 time)
{
buzzer_freq_set(freq);
delay_ms(time);
buzzer_stop();
}
void wdt_init(void)
{
//t_看门狗 = 1/[PCLK/(预分频值+1)/分频系数]
// 1/[50000000/250/16] = 12.5KHz
rWTCON = (rWTCON & ~(0xff<<8)) | (0xf9<<8); //预分频值 249+1
rWTCON = rWTCON & ~(0x3<<3); // 0b00 16
rWTDAT = 50000; //设置看门狗定时器超时时间为4秒(50÷12.5)
rWTCNT = 50000; //不会自动加载,首次要进行手动赋值
rWTCON = rWTCON | 0x1; //看门狗定时器超时复位
rWTCON = rWTCON | (0x1<<2); //中断使能
rWTCON = rWTCON | (0x1<<5); //看门狗定时器使能
rSRCPND = rSRCPND | (0x1<<9);
rINTPND = rINTPND | (0x1<<9);
rSUBSRCPND = rSUBSRCPND | (0x1<<13);
rINTMSK = rINTMSK & ~(0x1<<9);
rINTSUBMSK = rINTSUBMSK & ~(0x1<<13);
}
void __irq watchdog(void)
{
beep(3000,100); //蜂鸣器响
//清中断标志位
rSRCPND = rSRCPND | (0x1<<9);
rINTPND = rINTPND | (0x1<<9);
rSUBSRCPND = rSUBSRCPND | (0x1<<13);
}
void Main(void)
{
led_init();
wdt_init();
beep(3000,100);
/* 中断表地址 指向中断函数 */
pISR_WDT_AC97 = (U32)watchdog;
while(1)
{
led_display(0x5);
delay_ms(2000);
led_display(0xa);
delay_ms(1500);
rWTCNT = 50000; //喂狗,重新赋值,防止中断
}
}