ARM7的万年历的设计.docx
《ARM7的万年历的设计.docx》由会员分享,可在线阅读,更多相关《ARM7的万年历的设计.docx(29页珍藏版)》请在冰豆网上搜索。
ARM7的万年历的设计
万年历的设计
一.项目要求:
在ARM7(ARM7TDMI-S)的的核心板上实现“万年历”的的数码管显示。
二.开发工具:
1.使用ADS1.2编写硬件程序,并联合AXD进行调试
2.H-JTAG烧写程序(笔记本用JLINK烧写调试程序)
三.功能要求:
基本功能:
1.在数码管上显示年,月,日,周,时,分,秒
2.整点提示功能
3.时间可调(相应闪烁)
扩展功能:
四,功能分析:
1,数码管显示年,月,日,周,时,分,秒
a)显示部分,采用数码管的动态扫描,开发板上只有一个4位一体的数码管,所以要实现时间的切换,因开发板上ARM7和74HC595之间进行(SPI)通信,把数据传到数码管上显示。
b)按键处理部分,采用中断的方式,只用当有按键按下时才去扫描按键
c)时钟使用RTC模块,
2,整点提示功能:
a)只需设置ARM7内部的RTC模块的相关Reg即可
3,时间可调:
在时间的相应位置闪烁,并实现可调功能,采用TIME0
五,总体框架:
六,程序清单;
/****************************************************
*文件名:
万年历(用数码管显示)
*编写人:
霍小波
*完成时间:
2011-3-14-15-00
*摘要:
在一个四位一体的数码管上能显示年,月,日,周,时,分,秒,具有
整点报铃,调时(并在相应的位闪烁)
****************************************************/
#include"whole.h"
#include"delay.h"
#include"OFF_Beep.h"
#include"RTC.h"
//------外部函数的声明----
externvoidHC595_Init(void);//HC595的初始化
externuint8HC595_SendData(uint8data);//发送数据
externvoidSMG_Init(void);//数码管初始化
externvoidDisplay(uint32data,uint8i);//数码管的显示
externvoidKey_Init(void);//按键初始化
externKey_Scan(void);//按键扫描
//------变量的声明-------
uint8i;
uint32dat;
uint8num=0;//记录按键按下的次数,来显示不同的时间
TIMEa,b;//定义时钟结构体
uint8flag8=0;//第1,2个数码管的闪烁;(在显示的地方处理)
uint8flag9=0;//第3,4个数码管的闪烁;
uint8flag7=0;//选择是高位闪烁还是低位闪烁
uint8num1=0;//选择哪个数码管闪
uint8dot=0;//选择数码管的小数点位置
uint8flag5=0;//上电运行分,秒
uint8flag6=0;//有键按下,并一直显示相应的数值
uint32dat;//在数码管上待显示的数据
/**********************************************************
*名称:
void__irqEXINT0_IRQ(void)
*功能:
外部中断1的中断服务程序,用来扫描按键
*入口参数:
无
*出口参数:
无
**********************************************************/
void__irqEXINT0_IRQ(void)
{
i=Key_Scan();
while((EXTINT&0x01)!
=0)
{
EXTINT=0x01;
}
VICVectAddr=0;
}
/**********************************************************
*名称:
void__irqTIME0_IRQ(void)
*功能:
定时器0的中断服务程序,用来闪烁相应的位
*入口参数:
无
*出口参数:
无
**********************************************************/
void__irqTIME0_IRQ(void)
{
if(flag7==1)//闪烁第3,4个数码管
{
flag8=0;
flag9=~flag9;
}
if(flag7==2)//闪烁第1,2个数码管
{
flag9=0;
flag8=~flag8;
}
T0IR=0x01;
VICVectAddr=0;
}
/********************************************************
*名称:
voidTIME0_Init(void)
*功能:
定时器0的初始化(并未开启定时器),在调时时才开启,提高CPU的速度
*入口参数:
无
*出口参数:
无
********************************************************/
voidTIME0_Init(void)
{
T0TC=0;//定时计数器设置为0
T0PR=0;//时钟不分频
T0MCR=0x03;//复位,并产生中断
T0MR0=Fpclk*0.4;//时间为1秒
T0IR=0x01;//清除中断标志
//T0TCR=0x01;//启动定时器
VICIntSelect=0x000000;//设置所有中断为IRQ向量中断
VICVectCntl1=0x20|4;//定时器0的
VICVectAddr1=(uint32)TIME0_IRQ;
VICIntEnable=0x00004010;
}
/***********************************************
*名称:
void__irqRTC_IRQ(void)//RTC中断服务程序
*功能:
整点报铃,当每一次小时加1,报警一次
*入口参数:
无
*出口参数:
无
***********************************************/
void__irqRTC_IRQ(void)//RTC中断服务程序
{
if((CIIR&0x04)!
=0)
{
Beep_ON();
DelayMs(100);
Beep_OFF();//关闭BEEP
}
while((ILR&0x01)!
=0)
ILR=0x01;//清除中断标志
VICVectAddr=0;
}
/*************************************************
*名称:
voidRTC_Init(void)//RTC初始化
*功能:
RTC的初始化
*入口参数:
无
*出口参数:
无
*************************************************/
voidRTC_Init(void)//RTC初始化
{
PREINT=Fpclk/32768-1;//设置基准时钟分频器
PREFRAC=Fpclk-(Fpclk/32768)*32768;
AMR=0xff;//屏蔽报警
CIIR=0x04;//设置分增加1产生一次中断
ILR=0x03;//清除中断
VICIntSelect=0x000000;//设置所有中断为IRQ向量中断
VICVectCntl5=0x20|13;//
VICVectCntl0=0x20|14;//外部中断0
VICVectAddr5=(uint32)RTC_IRQ;//设置计数器增加中断入口地址
VICVectAddr0=(uint32)EXINT0_IRQ;//外部中断的地址
VICIntEnable=VICIntEnable|(1<<13);//使能中断
VICIntEnable=0x00004000;
}
/******************************************************
*名称:
uint32Show(void)
*功能:
显示时钟,
*入口参数:
无
*出口参数:
在数码管上待显示的时钟数据
******************************************************/
uint32Show(void)
{
if(i==1)
{
flag5=1;//当键按下时,flag5=1;每次显示按键值所对应的数据标志位
CCR=0x00;//有键按下,关闭RTC
i=0;//
num++;//记录按键按下的次数,来显示不同的时间
if(num==1)
{
flag6=1;flag7=1;//flag6=1;显示分,秒,flag7=1;调时闪烁后两位标志
}
elseif(num==2)
{
flag6=2;flag7=1;//显示周,小时
}
elseif(num==3)
{
flag6=3;flag7=1;//显示月,日
}
elseif(num==4)
{
flag6=4;flag7=1;//显示年
}
elseif(num==5)
{
flag6=5;flag7=1;//取消闪烁
num=0;
T0TCR=0x00;//关闭定时器
flag8=0;flag9=0;//取消闪烁
}
}
GetTime(&a);//获得时间的数据
if(flag6==1)
{
dat=(a.min*100)+a.sec;
dot=3;
}
if(flag6==2)
{
dat=(a.dow*100)+a.hour;
dot=3;
}
if(flag6==3)
{
dat=(a.mon*100)+a.day;
dot=3;
}
if(flag6==4)
{
dat=a.year;
dot=0;
}
if((flag6==5)||(flag5==0))
{
CCR=0x01;
dat=(a.min*100)+a.sec;
dot=3;
}
elseif(i==2)
{
DelayMs(5);
if(i==2)
{
i=0;
num1++;
DelayMs(5);
if(num1==1)
{
if(num!
=0)
{
flag7=1;
T0TCR=0x01;//启动定时器0,开始闪烁(后两位)
}
}
elseif(num1==2)
{
if(num!
=0)
{
flag7=2;
T0TCR=0x01;//启动定时器0,开始闪烁(前两位)
}
}
elseif(num1==3)
{
num1=0;
T0TCR=0x00;//关闭定时器,停止闪烁
flag8=0;flag9=0;
}
}
}
elseif(i==3)//调时,设置时间(+)
{
DelayMs(10);
if(i==3)
{
i=0;
if((num==1)&&(num1==1))
{
GetTime(&a);
a.sec++;
if(a.sec==60)a.sec=0;
Set_Time(&a);
}
elseif((num==1)&&(num1==2))
{
GetTime(&a);
a.min++;
if(a.min==60)a.min=0;
Set_Time(&a);
}
elseif((num==2)&&(num1==1))
{
GetTime(&a);
a.hour++;
if(a.hour==24)a.hour=0;
Set_Time(&a);
}
elseif((num==2)&&(num1==2))
{
GetTime(&a);
a.dow++;
if(a.dow==8)a.dow=1;
Set_Time(&a);
}
elseif((num==3)&&(num1==1))
{
GetTime(&a);
a.day++;
if(a.day==32)a.day=1;
Set_Time(&a);
}
elseif((num==3)&&(num1==2))
{
GetTime(&a);
a.mon++;
if(a.mon==13)a.mon=1;
Set_Time(&a);
}
elseif((num==4)&&(num1==1))
{
GetTime(&a);
a.year++;
Set_Time(&a);
}
elseif((num==4)&&(num1==2))
{
GetTime(&a);
a.year=a.year+100;
Set_Time(&a);
}
}
}
elseif(i==4)//调时,设置时间(-)
{
DelayMs(10);
if(i==4)
{
i=0;
if((num==1)&&(num1==1))
{
GetTime(&a);
a.sec--;
if(a.sec==-1)a.sec=59;
Set_Time(&a);
}
elseif((num==1)&&(num1==2))
{
GetTime(&a);
a.min--;
if(a.min==0)a.min=59;
Set_Time(&a);
}
elseif((num==2)&&(num1==1))
{
GetTime(&a);
a.hour--;
if(a.hour==-1)a.hour=23;
Set_Time(&a);
}
elseif((num==2)&&(num1==2))
{
GetTime(&a);
a.dow--;
if(a.dow==0)a.dow=7;
Set_Time(&a);
}
elseif((num==3)&&(num1==1))
{
GetTime(&a);
a.day--;
if(a.day==0)a.day=31;
Set_Time(&a);
}
elseif((num==3)&&(num1==2))
{
GetTime(&a);
a.mon--;
if(a.mon==0)a.mon=12;
Set_Time(&a);
}
elseif((num==4)&&(num1==1))
{
GetTime(&a);
a.year--;
if(a.year==0)a.year=99;
Set_Time(&a);
}
elseif((num==4)&&(num1==2))
{
GetTime(&a);
a.year=a.year-100;
if(a.year==0)a.year=900;
Set_Time(&a);
}
}
}
return(dat);
}
intmain(void)
{
uint32data;
HC595_Init();
SMG_Init();
RTC_Init();
Key_Init();
TIME0_Init();
Beep_Init();//初始化BEEP
Beep_OFF();//关闭BEEP
b.year=2011;
b.mon=3;
b.day=14;
b.dow=1;
b.hour=15;
b.min=59;
b.sec=55;
Set_Time(&b);//设置时钟
while
(1)
{
data=Show();//取出要显示的数据
Display(data,dot);//在数码管上显示时间
}
return(0);
}
#include"whole.h"
#include"OFF_Beep.h"
#defineBEEP(1<<24)
voidBeep_Init(void)//初始化BEEP
{
PINSEL2=PINSEL2&0xfffffff7;
IO1DIR=IO1DIR|BEEP;
}
voidBeep_OFF(void)//关闭BEEP
{
IO1SET=IO1SET|BEEP;
}
voidBeep_ON(void)
{
IO1CLR=IO1CLR|BEEP;
}
#include"whole.h"
#include"delay.h"
voidDelayMs(uint32dly)
{
uint32i;
for(;dly>0;dly--)
for(i=0;i<220;i++);
}
#include"whole.h"
//#include"74HC595.h"
#defineHC595_nCS(1<<28)//HC595的选通信号为P3.28
#defineHC595_RCK(1<<16)//时钟P1.16
/*******************************************************
**函数名:
HC595_Init()
**函数功能:
对74HC595及SPI0的初始化
**入口参数:
无
**出口参数:
无
*******************************************************/
voidHC595_Init(void)
{
//------------初始化引脚------
PINSEL0=(PINSEL0&0xffff00ff)|0x00005500;//设置P0.4P0.5P0.6为SPI0引脚
PINSEL2=PINSEL2&0xffffff7f;//设置为GPIO
PINSEL2=PINSEL2&0xfffffff7;//设置为GPIO
//-----------设置引脚为输出------------
IO3DIR=IO3DIR|HC595_nCS;
IO1DIR=IO1DIR|HC595_RCK;
IO3CLR=HC595_nCS;//选中HC595为从机
//-------------SPI寄存器的初始化-----------
S0PCCR=0x64;//设置SPI时钟的分频值为0x64,即SPI时钟=Fpclk/100
S0PCR=0x30;//设置SPI为主模式,CPOL=1,CPHA=1;
}
/*****************************************************
**名称:
uint8HC595_SendData(uint8data)
**功能:
向74HC595发送一字节数据
**入口参数:
data
**出口参数:
S0PDR
****************************************************/
uint8HC595_SendData(uint8data)
{
IO1CLR=HC595_RCK;//先将RCK拉低
S0PDR=data;//准备数据,
while((S0PSR&0x80)==0);//等待SPIF置位,完成数据的传输
IO1SET=HC595_RCK;//控制HC595将数据并行输出
return(S0PDR);
}
#include"whole.h"
#include"delay.h"
#definesmgA1(1<<22)//P2.22
#definesmgA2(1<<23)//P0.23
#definesmgA3(1<<19)//P1.19
#definesmgA4(1<<24)//P0.24
externuint8flag8;
externuint8flag9;
externuint8HC595_SendData(uint8data);//发送数据
//--------数字0--9的共阳段码-------------
uint8constTAB[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x98};
//---------数码管的初始化---------------
voidSMG_Init(void)
{
IO2DIR=IO2DIR|smgA1;
IO0DIR=IO0DIR|smgA2|smgA4;
IO1DIR=IO1DIR|smgA3;
}
voidNumbTube_Bit(uint8data)
{
if((data&0x01)!
=0)IO2CLR=smgA1;//控制smgA1
elseIO2SET=smgA1;
if((data&0x02)!
=0)IO0CLR