2011年3月2日星期三

使用MSP430 F449单片机实现的实时时钟(RTC)

      本程序采用MSP430处理器的基本定时器Basic Timer发生中断信号,每0.50秒中断一次。Menu为设置键,按一下进入时间设置模式,再按一下回复走秒模式LEFT、RIGHT键功能为为设置项选择,仅在时间设置模式下有效UP、DOWN键功能为调节大小,且仅在时间设置模式下有效。


硬件连接:
P14~P10:手机MP3用5维导航按键,分别为RIGHT、DOWN、LEFT、MENU、UP键,采用下降沿中断
P37~P34:LED,置位则亮
外接32768Hz无源晶振
COM0~3、S0~S39外接160段LCD,4MUX,1/3BIAS,3.3V
P62:外接有源蜂鸣器,置位则响
//软件调试已通过,连续走秒12小时误差不超过1秒*
//*以CASIO G-SHOCK手表为准
//额定电压3.3~3.4V,过低的电压会导致走秒变慢


#include "msp430x44x.h"
unsigned char place=2,buff=0,time_c=0,time_s=0;
unsigned char tab_time[3]={30,25,21},max_time[3]={59,59,23};
#define sec tab_time[0]
#define min tab_time[1]
#define hrs tab_time[2]
const char tab_num[]=
{
0xaf,0x06,0x6d,0x4f,
0xc6,0xcb,0xeb,0x0e,
0xef,0xcf,0xee,0xe3,
0x61,0x67,0xe9,0xe8,
};
#define a 0x10
#define b 0x20
#define c 0x40
#define d 0x80
#define e 0x1
#define f 0x2
#define g 0x4
#define h 0x8
const char tab_asc[]=
{
a+e+f+d+c, f, e+c+f+h+d, 0, c+f+h, 0, c+f+h+d, f, //abcd
a+e+c+f+h,0, a+e+c+f, 0, a+e+h+c+d, f, e+c+f+d, f, //efgh
d, f, d+h, f, d, f+e+h, e+f+h,0, //ijkl
e+f+a+d, f+a+b+c, e+f+b, b+c+h, c+f+h+d, 0, a+e+f+c, f, //mnop
a+e+d+c, f+d, d, a+f+b+g+h,a+e+c+d+h, 0, a+d, a+f, //qrst
e+f+h+d, f, e+f+g, e, e+f+h+d, f+d+b+c, b+g, e+h, //uvwx
b+d, e, c+g+h, 0 //yz
};
void delay(unsigned int x)
{
while(x--);
}
void clrlcd(void)
{
unsigned char i;
for (i=0; i<20; i++)LCDMEM[i] = 0x00; // Clear LCD memory to clear display
}
void display_asc(char *str,unsigned char n)
{
unsigned char i,k=8,temp;
if(n<=6)
for(i=0;i<n;i++)
{
temp=(str[i]-'A')<<1;
LCDMEM[k++]=tab_asc[temp++];
LCDMEM[k++]=tab_asc[temp];
}
}
void main( void )
{
//系统初始化Sysyem Intialize
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer to prevent time out reset
FLL_CTL0 |= XCAP14PF; // Configure load caps
delay(10000); // Delay for 32 kHz crystal tostabilize
//液晶初始化LCD Initialize
//基本定时器初始化Basic Timer Initialize
LCDCTL = 0xFD; // 4-Mux LCD, segments S0-S39
BTCTL = BTDIV+BTFRFQ1+BTIP2+BTIP0; //置位BTDIV让BTCNT1与BTCNT2联动
//使用BTFRFQ设定LCD刷新频率;使用BTIP设定BT中断频率
P5SEL = 0xFC; // Select P5.2-7 as Com and Rxx for LCD
clrlcd();
//按键侦测初始化KEY Initialize
P1DIR &= 0xE0; //P10~P14输入
P1IES = 0x1F; //下降沿中断
P1IE = 0x1F;
P3OUT = 0xF0; P3DIR = 0xF0;
P6OUT = BIT2; P6DIR |= BIT2;
display_asc("HELLO",5);
delay(50000);delay(50000);
P6OUT = 0x00; P3OUT = 0x00;
//主程序开始MAIN PROGRAM BEGIN
clrlcd();
LCDMEM[ 8]=0x90;LCDMEM[ 9]=0x12; //Display "TIME"
LCDMEM[10]=0x80;LCDMEM[11]=0x02; //显示“TIME”
LCDMEM[12]=0x93;LCDMEM[13]=0x72;
LCDMEM[14]=0x5B;LCDMEM[15]=0x94;
LCDMEM[7] = 0x0A; //显示时钟冒号
_EINT(); //开启总中断
IE2 |= BTIE; //开启BT中断
loop:
if(time_s) //如果时间在走动
{
if(buff==BIT1)time_s ^= BIT0; //如果OK键按下,停止/继续走秒
LCDMEM[7] ^= 0x0A; //时钟的冒号闪烁Blinking the ':'
if(time_c) //如果到每秒中断Every sec INT?
{ //
if(sec<59) //更新时间寄存器
sec++; //change time rigister
else //
{ //
sec=0; //
if(min<59) //
min++; //
else //
{ //
min=0; //
if(hrs<23) //
hrs++; //
else //
hrs=0; //
} //
} //
LCDMEM[0]=tab_num[sec%10]; //时间刷新
LCDMEM[1]=tab_num[sec/10]; //refresh time display
LCDMEM[2]=tab_num[min%10]; //
LCDMEM[3]=tab_num[min/10]; //
LCDMEM[4]=tab_num[hrs%10]; //
LCDMEM[5]=tab_num[hrs/10]; //
} //
} //
else //如果时间停止
{
if(time_c) //如果每秒中断,则清空当先设置位置的显示
{
LCDMEM[place*2] = 0x00;
LCDMEM[1+place*2] = 0x00;
}
else //如果半秒中断,则复原当前设置位置的显示
{ //从而实现当先设置位置的闪烁
LCDMEM[place*2] = tab_num[tab_time[place]%10];
LCDMEM[1+place*2] = tab_num[tab_time[place]/10];
}
switch(buff)
{
case 0x01:tab_time[place]++;
if(tab_time[place]>max_time[place])tab_time[place]=0;break;
case 0x02:time_s ^= BIT0;break;
case 0x04:LCDMEM[place*2] = tab_num[tab_time[place]%10];
LCDMEM[1+place*2] = tab_num[tab_time[place]/10]; //先善后,把当前位置数字显示
place++;if(place==3)place=0;break; //再切换到高一位
case 0x08:if(tab_time[place])tab_time[place]--;
else tab_time[place]=max_time[place];break;
case 0x10:LCDMEM[place*2] = tab_num[tab_time[place]%10]; //先善后,把当前位置数字显示
LCDMEM[1+place*2] = tab_num[tab_time[place]/10]; //再切换到低一位
if(place)place--;else place=2;break;
}
}
buff=0; //把键值复位,以免重复操作
time_c ^=BIT0; //取反半秒/每秒中断标志
LPM3; //进入LPM3休眠
goto loop;
}
#pragma vector=BASICTIMER_VECTOR
__interrupt void btrefre(void) //每0.5秒中断一次
{
//IFG2 &= 0x7F; //BTIFG会被自动清零,无需软件清零
LPM3_EXIT;
}
#pragma vector=PORT1_VECTOR
__interrupt void key(void)
{
unsigned char temp;
P1IE ^= 0x1F;
P6OUT ^= BIT2;
delay(10000); //短暂延时防止抖动可能造成的重复中断
buff=P1IN; //P1IN寄存器采样
delay(500); //短暂延时后对P1IN寄存器重新采样
temp=P1IN; //如果不一样说明存在抖动,本次按键忽略
if((temp&0x1F)!=(buff&0x1F)){buff=0;goto error;}
buff ^= 0x1F; //后5位取反
buff &= 0x1F; //只保留低5位
delay(10000); //防止松开按键时的多次抖动,避免形成死循环或者中断嵌套
for(temp=0;temp<20;temp++)while(P1IN<0x1F)delay(5000);
error:
P6OUT ^= BIT2;
P1IFG = 0x00;
P1IE ^= 0x1F;
LPM3_EXIT;
}
view raw 20110302.c hosted with ❤ by GitHub

没有评论:

发表评论