⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ds1302.c

📁 Msp430的c语言程序集
💻 C
字号:
/***************************************************************

                 DS1302实时时钟实验
          网址:http://www.wejay.com.cn

		  功能:在数码管上显示从DS1302读取的时间日期星期数据
		           时间格式:时-分-秒
			   日期格式:年月日-星期
			   C键:选择显示时间还是日期
			   D键:循环选择所要编辑的位
			   E键:编辑的位的数值加1
			   F键:编辑的位的数值减1


****************************************************************/
#include "msp430x14x.h"
#define  uint unsigned int
#define  uchar unsigned char
#define SCLK_HIGH P3OUT|=BIT3
#define SCLK_LOW P3OUT&=~BIT3
#define RST_HIGH P3OUT|=BIT1
#define RST_LOW P3OUT&=~BIT1
#define IO_HIGH P3OUT|=BIT2
#define IO_LOW P3OUT&=~BIT2
#define IO_OUT P3DIR|=BIT2
#define IO_IN P3DIR&=~BIT2
#define IO_DATA P3IN&BIT2
uchar num=100;
uchar TimeFlag=1; //显示日期时间标志
uchar EditFlag=0; //闪烁显示标志
uchar KeyValue=0xFF;
uchar DNum=0; //D键按的次数
//共阳数码管编码表
const uchar Code[18]={0xC0,0xF9,0xA4,0xB0,//0,1,2,3
                0x99,0x92,0x82,0xF8,//4,5,6,7
                0x80,0x90,0x88,0x83,//8,9,A,b
                0xC6,0xA1,0x86,0x8E,//C,d,E,F
                0xBF,0xFF};//-,全灭
//键值编码表
const uchar KeyCode[16]={0x77,0x7B,0x7D,0x7E,//0,1,2,3
                   0xB7,0xBB,0xBD,0xBE,//4,5,6,7
                   0xD7,0xDB,0xDD,0xDE,//8,9,A,b
                   0xE7,0xEB,0xED,0xEE};//C,d,E,F
uchar DS1302[8]={0,0,0,0,0,0,0,0}; //秒,分,时,日,月,星期,年
uchar DateBit[8]={0,0,0,0,0,0,16,0}; //日期各位显示的数值
uchar TimeBit[8]={0,0,16,0,0,16,0,0}; //时间各位显示的数值
uchar BitCode=0x80; //数码管位码初值
//时钟初始化函数
void InitClock(void){
  BCSCTL1=RSEL2+RSEL1+RSEL0;//XT2开启 LFXT1工作在低频模式 ACLK不分频 最高的标称频率
  DCOCTL=DCO2+DCO1+DCO0;//DCO为最高频率
  do{
    IFG1&=~OFIFG;//清除振荡器失效标志
    for(uint i=255;i>0;i--);
  }while(IFG1&OFIFG);//判断XT2是否起振
  BCSCTL2=SELM1+SELS;//MCLK SMCLK时钟源为TX2CLK不分频
}
//端口初始化函数
void InitPort(void){
  P1SEL=0x00;//P1口所有引脚设置为一般的IO口
  P1DIR=0x0F;//P1.0 P1.1 P1.2 P1.3设置为输出方向
  P1OUT=0x00;//P1口先输出低电平
  P1IE=0xF0;//P1.4 P1.5 P1.6 P1.7中断允许
  P1IES=0xF0;//P1.4 P1.5 P1.6 P1.7下降沿触发中断
  P3SEL=0x00;//P3口所有引脚设置为一般的IO口
  P3DIR=0x0E;//P3.1 P3.2 P3.3设置为输出方向
  P2SEL=0x00;//P2口所有引脚设置为一般的IO口
  P4SEL=0x00;//P4口所有引脚设置为一般的IO口
  P2DIR=0xFF;//P2口所有引脚设置为输出方向
  P4DIR=0xFF;//P4口所有引脚设置为输出方向
  P2OUT=0x00;//P2口先输出低电平
  P4OUT=0xFF;//P4口先输出低电平
  P5SEL&=~BIT7;//P5.7设置为一般的IO口
  P5DIR|=BIT7;//P5.7设置为输出方向
  P5OUT&=~BIT7;//P5.7输出低电平来使能74HC573来驱动数码管
}
//ms级延时子程序
void DelayMs(uint ms){
  while(ms--){
    for(uint i=0;i<800;i++);
  }
}
//数码管扫描显示程序
void Display(void){
  for(uchar i=0;i<8;i++){
    if(EditFlag==1&&DNum>0){ //判断是否闪烁
      if(TimeFlag==0){ //判断日期还是时间闪烁
        switch(DNum){ //根据D按的次数判断日期那一位闪烁
          case 1:P4OUT=BitCode&0x3F;break;
          case 2:P4OUT=BitCode&0xCF;break;
          case 3:P4OUT=BitCode&0xF3;break;
          case 4:P4OUT=BitCode&0xFE;break;
        }
      }else{
        switch(DNum){ //根据D按的次数判断时间那一位闪烁
          case 1:P4OUT=BitCode&0x3F;break;
          case 2:P4OUT=BitCode&0xE7;break;
          case 3:P4OUT=BitCode&0xFC;break;
        }
      }
    }else{
      P4OUT=BitCode; //输出位码
    }
    if(TimeFlag==1) P2OUT=Code[TimeBit[i]];//判断显示时间还是日期
    else P2OUT=Code[DateBit[i]];
    BitCode>>=1;//位码右移一位
    if(BitCode==0) BitCode=0x80;
    DelayMs(1); //延时1ms
    P2OUT=0xFF;
  }
}
//10us级延时子程序
void Delayus(uint us){
  while(us--){
    for(uint i=0;i<8;i++);
  }
  }
//按键分析程序
void KeyProcess(void){
  uchar OutData=0x07;
  for(uchar i=0;i<4;i++){//扫描4列
    OutData|=0xF0;
    P1OUT=OutData;
    if(P1IN!=OutData) KeyValue=P1IN;
    OutData>>=1;
  }
  P1OUT=0x00;//恢复原来的值
}
//端口1中断处理程序
#pragma vector=PORT1_VECTOR
__interrupt void Port1INT(void){
  for(uint i=1000;i>0;i--);
  KeyProcess();
  P1IFG=0x00;//清除中断标志位
}
//向DS1302写一字节数据,address为命令字节
void WriteByte(uchar Command,uchar WriteData){
  uchar j,k=1;
  RST_LOW;
  SCLK_LOW;
  RST_HIGH;
  for(j=0;j<=7;j++){
    if(Command&k) IO_HIGH;
    else IO_LOW;
    SCLK_HIGH;
    k<<=1;
    SCLK_LOW;
  }
  k=1;
  for(j=0;j<=7;j++){
    if(WriteData&k) IO_HIGH;
    else IO_LOW;
    SCLK_HIGH;
    k<<=1;
    SCLK_LOW;
  }
  RST_LOW;
}
//读取DS1302一字节数据,address为命令字节
uchar ReadByte(uchar Command){
  uchar i,k=1;
  RST_LOW;
  SCLK_LOW;
  RST_HIGH;
  for(i=0;i<8;i++){
    if(Command&k) IO_HIGH;
    else IO_LOW;
    SCLK_HIGH;
    k<<=1;
    if(i!=7) SCLK_LOW;
  }
  k=0;
  for(i=0;i<8;i++){
    k>>=1;
    SCLK_LOW;
    IO_IN;
    if(IO_DATA) k|=0x80;
    IO_OUT;
    SCLK_HIGH;
  }
  RST_LOW;
  return(k);
}
//读取DS1302的秒,分,时,日,月,星期,年
void ReadDS1302(){
uchar i;
for(i=0;i<=6;i++) DS1302[i]=ReadByte(0x80+2*i+1);
//计算时间日期的各位要显示的数据
TimeBit[7]=DS1302[0]&0x0F;
TimeBit[6]=DS1302[0]&0x70;
TimeBit[6]>>=4;
TimeBit[4]=DS1302[1]&0x0F;
TimeBit[3]=DS1302[1]&0x70;
TimeBit[3]>>=4;
TimeBit[1]=DS1302[2]&0x0F;
TimeBit[0]=DS1302[2]&0x30;
TimeBit[0]>>=4;
DateBit[5]=DS1302[3]&0x0F;
DateBit[4]=DS1302[3]&0x30;
DateBit[4]>>=4;
DateBit[3]=DS1302[4]&0x0F;
DateBit[2]=DS1302[4]&0x10;
DateBit[2]>>=4;
DateBit[7]=DS1302[5]&0x07;
DateBit[1]=DS1302[6]&0x0F;
DateBit[0]=DS1302[6]&0xF0;
DateBit[0]>>=4;
}
//定时器A初始化
void InitTimerA(void){
  TACTL=TASSEL1+ID1+ID0+MC0+TACLR;//选择1/8SMCLK 增计数 清除TAR
  CCTL0=CCIE;//CCR0中断允许 比较模式
  CCR0=10000;//时间间隔10ms
}
//定时器A中断
#pragma vector=TIMERA0_VECTOR
__interrupt void TimerAINT(void){
  num--;
  if(num==0){
    EditFlag=!EditFlag; //更新闪烁标志
    num=50;
  }
}
//时间编辑程序
void TimeEdit(uchar flag){
uchar Data,NowData;
if(flag){ //判断加1还是减1
switch(DNum){ //判断编辑时间的哪一位
case 1:{
Data=ReadByte(0x85); //读取小时数据
NowData=Data+1;
if((NowData&0x0F)>9) NowData=NowData+6;
if(NowData>=0x24) NowData=0;
WriteByte(0x84,NowData); //写入小时数据
break;
}
case 2:{
Data=ReadByte(0x83); //读取分数据
NowData=Data+1;
if((NowData&0x0F)>9) NowData=NowData+6;
if(NowData>=0x60) NowData=0;
WriteByte(0x82,NowData); //写入分数据
break;
}
case 3:{
Data=ReadByte(0x81); //读取秒数据
NowData=Data+1;
if((NowData&0x0F)>9) NowData=NowData+6;
if((NowData&0x7F)>=0x60) NowData=0;
WriteByte(0x80,(NowData&0x7F)|(Data&0x80)); //写入秒数据
break;
}
}
}else{
switch(DNum){ //判断编辑时间的哪一位
case 1:{
Data=ReadByte(0x85); //读取小时数据
if(Data==0){
NowData=0x23;
}else{
NowData=Data-1;
if((NowData&0x0F)>9) NowData=NowData-6;
}
WriteByte(0x84,NowData); //写入小时数据
break;
}
case 2:{
Data=ReadByte(0x83); //读取分数据
if(Data==0){
NowData=0x59;
}else{
NowData=Data-1;
if((NowData&0x0F)>9) NowData=NowData-6;
}
WriteByte(0x82,NowData); //写入分数据
break;
}
case 3:{
Data=ReadByte(0x81); //读取秒数据
if(Data==0){
NowData=0x59;
}else{
NowData=Data-1;
if((NowData&0x0F)>9) NowData=NowData-6;
}
WriteByte(0x80,(NowData&0x7F)|(Data&0x80)); //写入秒数据
break;
}
}
}
}
//日期编辑程序
void DateEdit(uchar flag){
uchar Data,NowData;
if(flag){ //判断加1还是减1
switch(DNum){ //判断编辑日期的哪一位
case 1:{ //年加1
Data=ReadByte(0x8d); //读取年数据
NowData=Data+1; //年加1
if((NowData&0x0F)>9) NowData=NowData+6; //BCD调整
if(NowData>=0xA0) NowData=0; //年>=100时,年=0
WriteByte(0x8c,NowData); //年写入DS1302
break;
}
case 2:{
Data=ReadByte(0x89); //读取月数据
NowData=Data+1; //月加1
if((NowData&0x0F)>9) NowData=NowData+6; //BCD调整
if(NowData>=0x13) NowData=1; //月>=13,月=1
WriteByte(0x88,NowData); //月写入DS1302
break;
}
case 3:{
Data=ReadByte(0x87); //读取日数据
NowData=Data+1; //日加1
if((NowData&0x0F)>9) NowData=NowData+6; //BCD调整
if(NowData>=0x32) NowData=1; //日>=32,日=1
WriteByte(0x86,NowData); //日写入DS1302
break;
}
case 4:{
Data=ReadByte(0x8B); //读取星期数据
NowData=Data+1; //星期加1
if(NowData>=8) NowData=1; //星期>=8,星期=1
WriteByte(0x8A,NowData); //星期写入DS1302
break;
}
}
}else{
switch(DNum){
case 1:{ //年减1
Data=ReadByte(0x8d); //读取年数据
if(Data==0){
NowData=0x99; //如果年=0,减1则为99
}else{
NowData=Data-1; //年减1
if((NowData&0x0F)>9) NowData=NowData-6; //BCD调整
}
WriteByte(0x8c,NowData); //年写入DS1302
break;
}
case 2:{
Data=ReadByte(0x89); //读取月数据
NowData=Data-1; //月减1
if((NowData&0x0F)>9) NowData=NowData-6; //BCD调整
if(NowData==0) NowData=0x12; //月=0,月=12
WriteByte(0x88,NowData); //月写入DS1302
break;
}
case 3:{
Data=ReadByte(0x87); //读取日数据
NowData=Data-1; //日减1
if((NowData&0x0F)>9) NowData=NowData-6; //BCD调整
if(NowData==0) NowData=0x31; //日=0,日=31
WriteByte(0x86,NowData); //日写入DS1302
break;
}
case 4:{
Data=ReadByte(0x8B); //读取星期数据
NowData=Data-1; //星期减1
if(NowData==0) NowData=7; //星期=0,星期=7
WriteByte(0x8A,NowData); //星期写入DS1302
break;
}
}
}
}
//按钮功能函数
void KeyFun(void){
  switch(KeyValue){
  case 0xE7:{//C键按下切换显示日期还是时间
    TimeFlag=!TimeFlag;
    DNum=0;
    KeyValue=0xFF;
    break;
  }
  case 0xEB:{ //D键按下,DNum加1
    DNum++;
    if((TimeFlag==0)&&(DNum>=5)) DNum=0; //如果当前编辑的是日期并且DNum>=5,则编辑完毕,返回正常状态
    if((TimeFlag==1)&&(DNum>=4)) DNum=0; //如果当前编辑的是时间并且DNum>=4,则编辑完毕,返回正常状态
    KeyValue=0xFF;
    break;
  }
  case 0xED:{ //E键按下,所选位加1
    if(TimeFlag==1) TimeEdit(1); //判断编辑日期还是时间
    else DateEdit(1);
    KeyValue=0xFF;
    break;
  }
  case 0xEE:{ //F键按下,所选位减1
    if(TimeFlag==1) TimeEdit(0); //判断编辑日期还是时间
    else DateEdit(0);
    KeyValue=0xFF;
    break;
  }
  }
}
void main(){
  WDTCTL=WDTPW+WDTHOLD;//关闭看门狗
  InitClock();
  InitPort();
  InitTimerA();
  _EINT();//打开中断
  WriteByte(0x80,ReadByte(0x81)&0x7F); //启动DS1302
  while(1){
    KeyFun();
    ReadDS1302();
    Display();
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -