×
嵌入式 > 嵌入式开发 > 详情

第8课:WatchDog定时器和RTC

发布时间:2020-07-09 发布时间:
|
首先来讲看门狗定时器:它有2个功能

1:当系统发生紊乱时,自动重启系统

2:普通定时

对于定时狗而言,它使用的是PCLK,和PWM一样有2个分屏器,但是它多了一样复位信号发生器,当看门狗中的CNT递减到0时,复位信号将被发出。作为写一般的程序而言,我们要做的就是不能让看门狗中的计数器CNT到0,要进行“喂狗”。

喂狗:在CNT递减到0之前,重设CNT里的值

原本我们的程序是0.5秒小灯亮,0.5秒小灯暗,现在加入了看门狗,如果发送5秒中内不喂狗的话,就将重启开发板

程序:main.c

功能:初始化计时器,小灯,uart,中断等

#include"s3c2440.h"
#define UART_CLK 50000000
#define UART_BAUD_RATE 115200
#define UART_BRD (int)(UART_CLK/(UART_BAUD_RATE *16))-1
void init_uart()
{
rGPHCON |=0;
rGPHUP = 0x0c;
rULCON0 = 0x3;
rUCON0 = 0x5;
rUFCON0 = 0;
rUMCON0 = 0;
rUBRDIV0 = UART_BRD;
}

void init_led()
{
rGPECON = GPE12_out|GPE13_out;
}

void init_timer0()
{
rTCFG0 = 0x63;
rTCFG1 = 0x1;
rTCNTB0 = 0xFFFF;
rTCON = 0xa;
rTCON = 0x9;
}

void init_irq()
{
rINTMOD = 0;
rINTMSK = ~(1<<10);
}

int main()
{
init_uart();
init_led();
init_irq();
init_timer0();
while(1);
}

程序:int.C

功能:中断服务程序中让小灯闪和灭,同时喂狗。

#include"s3c2440.h"

void ISR_Handle()
{
rGPEDAT ^= (3<<12);
rWTCNT = 0x1dce; //喂狗
rSRCPND = 1<<10;
rINTPND = 1<<10;
}

void setwatchdog()
{
rWTCON = 0xff39;
rWTCNT = 0x1dce;
}

看门狗在crt0.s中设置这里从略。

接下来说说RTC模块。

这个模块通常外接电池,在系统断电后负责计时,和断电后闹钟功能。还能做实时系统的内部时钟。

RTC模块内部的寄存器中的数字都是由BCD码编成的。注意转换。

还有RTC内部有闰年发生器。但是由于内部的年只有8位共2个BCD码 只能表示00到99,这里的00指的是2000年。

这里需要指出的就是在读取时间的时候有可能会有1秒偏差,因为秒是最后读的,在读00的时候,之前的年月日有可能还是之前的值,产生偏差,可以采取读到00就再复读一次前面的值的方法解决。

以下设计了一个简单的RTC实时时钟的测试模块。

实现3个功能

1设置内部时间 年月日时分秒

2设置闹钟时间 时分秒

3显示当前时间

通过uart对开发版的内部RTC模块进行设置。

程序:main.c

功能:初始化串口,rtc,中断

#include"s3c2440.h"
#define UART_CLK 50000000
#define UART_BAUD_RATE 115200
#define UART_BRD (int)(UART_CLK/(UART_BAUD_RATE *16))-1
void init_uart()
{
rGPHCON |=0;
rGPHUP = 0x0c;
rULCON0 = 0x3;
rUCON0 = 0x5;
rUFCON0 = 0;
rUMCON0 = 0;
rUBRDIV0 = UART_BRD;
}

void uart_write(char *data)
{
while (*data != \0) {
while (!(rUTRSTAT0 & 0x4));
rUTXH0 = *data;
data++;
}
}

void init_irq()
{
rINTMOD = 0;
rINTMSK = ~(1<<28);
rINTSUBMSK = ~1;
rINTMSK &= ~(1<<30);
}

void init_rtc()
{
rRTCCON = 0x1;
rTICNT = 0x0;
}

void bcd2uart(char n)
{
char a=0;
a = (n>>4)+0;
rUTXH0 = a;
while (!(rUTRSTAT0 & 0x4));
a = (n&0xf)+0;
rUTXH0 = a;
}

void menu()
{
uart_write("Welcome to RTC Module\r\n");
uart_write("You can select the follow funtion\r\n");
uart_write("1 Set RTC Time\r\n");
uart_write("2 Set Alarm Time\r\n");
uart_write("3 Show RTC Time\r\n");
}

void alarm()
{
rRTCALM = 0x47;
}
int main()
{
init_uart();
init_irq();
init_rtc();
menu();
alarm();
while(1);
}

程序:int.C

功能:通过isr实现3大功能

#include"s3c2440.h"
void fillrtc(char *t,volatile unsigned long *p) //used by set alarm time and set the normal time
{
char a,b,c;
int n=0;
while(*t != ;){
while((*t != :) && (*t != ;)){
if(n == 0){
a = *t++;
n++;
}
else if(n == 1){
b = *t++;
n++;
}
}
if(n == 1)
c = (a - 0);
else if(n == 2)
c = ((a - 0)<<4) | (b - 0);
*p-- = c;
if(p == (volatile unsigned long *)0x57000080) //the funtion of this reg is setting the day(like sunday);
p--; //so the date will be set before,this reg can be ignored
n = 0;
if( *t != ; )
t++;
}
}

void settime()
{
char time[30];
char *t = time;
volatile unsigned long *p = &rBCDYEAR;
uart_write("\r\nplease set time in this format YEAR:MONTH:DATA:HOUR:MIN:SEC;\r\n");
do{
while(!(rUTRSTAT0 & 0x1));
*t = rURXH0;
rUTXH0 = *t++;
}
while(*(t-1) != ;);
fillrtc(time,p);
uart_write("\r\nset time over.please check it\r\n");
}

void setalarmtime()
{
uart_write("\r\nset the alarm time like HOUR:MIN:SEC;\r\n");
char time[30];
char *t = time;
volatile unsigned long *p = &rALMHOUR;
do{
while(!(rUTRSTAT0 & 0x1));
*t = rURXH0;
rUTXH0 = *t++;
}
while(*(t-1) != ;);
fillrtc(time,p);
uart_write("\r\nset alarmtime over.\r\n");
}


void showtime() //ignore one second devition
{
uart_write("\r\nNow,the RTC time is:\r\nYear:20");
char a;
a = (char)rBCDYEAR;
bcd2uart(a);
uart_write(" Month:");
a = (char)rBCDMON;
bcd2uart(a);
uart_write(" Date:");
a = (char)rBCDDATE;
bcd2uart(a);
uart_write(" Hour:");
a = (char)rBCDHOUR;
bcd2uart(a);
uart_write(" Min:");
a = (char)rBCDMIN;
bcd2uart(a);
uart_write(" Sec:");
a = (char)rBCDSEC;
bcd2uart(a);
uart_write("\r\n");
}
void ISR_Handle()
{
int n;
char select,a;
n = rINTOFFSET;
switch(n){
case 28: //take a choice by int
if(rSUBSRCPND = 0){
while(!(rUTRSTAT0 & 0x1));
select = rURXH0;
rUTXH0 = select;
switch(select){
case 1:settime();break;
case 2:setalarmtime();break;
case 3:showtime();break;
default:uart_write("please input in 1 to 3\r\n");
}
}
break;
case 30: //when alarm clock reach,int_rtc will actived
uart_write("\r\nAlarm!!!");
uart_write(":");
a = (char)rBCDHOUR;
bcd2uart(a);
uart_write(":");
a = (char)rBCDMIN;
bcd2uart(a);
uart_write(":");
a = (char)rBCDSEC;
bcd2uart(a);
uart_write("\r\n");
break;
default:uart_write("undefined interrupt\r\n");
}
rSUBSRCPND = 1;
rSRCPND = 5<<28;
rINTPND = 5<<28;
}



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
基于CAN总线与以太网的嵌入式网关电路设计