用MSP430F437做一个电子时钟 设置时间问题

2019-07-15 20:43发布

小妹是刚刚接触430的初学者,SOS
想做一个电子时钟,MSP430F437上,FET仿真器,液晶屏是定制的,现在做的程度是能在LCD上每秒增加,秒满60进分,分满60进小时这样的。想增加一个设置时间的功能,碍于中断了解不是很懂,程序加上我main里面的anjian()之前每秒在跑的就停止了,不知如何往下做,求指导


加红部分是自己瞎写的地方,不知如何改可以设置时间
想要的功能是 K1键为功能键,按一下移动到秒的个位上——闪烁提示可以修改,再按就往秒十位移动,以此类推
                      K2、K3配合K1使用                       K2为减               K3为加


附上已写乱七八糟的代码


#include<msp430x43x.h>

#define uint unsigned int
#define uchar unsigned char

uchar table[]={0XAF,0XA0,0XCB,0XE9,0XE4,0X6D,0X6F,0XA8,0XEF,0XED};
uchar numxiaoshi,numfenzhong,nummiao,xiaoshishi,xiaoshige,fenzhongshi,fenzhongge,miaoshi,miaoge,keybuf;
void delayms(uint z)//延时函数
{
  uint i,j;
  for(i=z;i>0;i--)
    for(j=110;j>0;j--);
}
void display()//显示函数
{
  //以下4行显示小时
  LCDMEM[1]=table[xiaoshishi];
  delayms(10);
  LCDMEM[2]=table[xiaoshige];
  delayms(10);
  //以下4行显示分钟
  LCDMEM[3]=table[fenzhongshi];
  delayms(10);
  LCDMEM[4]=table[fenzhongge];
  delayms(10);
  //以下4行显示秒
  LCDMEM[6]=table[miaoshi];
  delayms(10);
  LCDMEM[7]=table[miaoge];
  delayms(10);
}
void init()//定时器A初始化
{
  WDTCTL=WDTPW+WDTHOLD;
  P3DIR=0x00;
  P4DIR=0xff;
  P5DIR=0xff;

  P2DIR=0xff;
  P3SEL=0;

  P2SEL=0;
  P4SEL=0;
  P5SEL=0;
  //BCSCTL1=CALBC1_1MHZ;
  //DCOCTL=CALBC1_1MHZ;
  //TACTL=TASSEL_2+MC_3+ID_3;
  TACTL|=TASSEL0+MC0;
  CCTL0=CCIE;
  CCR0=32768;
  _EINT();
}
void init_lcd (void)
{
   int j;
   FLL_CTL0|=XCAP14PF;
   BTCTL=BTDIV+BT_fCLK2_DIV4;
   LCDCTL=LCDON+LCD4MUX+LCDP2;
   BTCTL|=BTFRFQ1;
   P5SEL=0XFC;
   for(j=0;j<14;j++)
  {
    LCDMEM[j]=0;
  }

}
/************端口P1初始化,设置时间*****K3/P1.0   K2/P1.3   K1/P1.4 ****/
void anjian()                  
{                                       
  P1DIR|=0X00;                 // 设置P1.0 P1.3 P1.4 为输入方向
  P1IE|=0X19;                 // 设置P1.0 P1.3 P1.4 可以中断
  P1IES|=0X19;                 // 设置P1.0 P1.3 P1.4 为下降沿中断
  P1IFG&=~0X19;
  _EINT();
  while(1)
  {
    if(keybuf==0) //如果按键为K1
     {
       delayms(10);
       if(keybuf==0)
       {
         while(!(P1IN==0x19));
            _DINT();
         while(1)
         {
           miaoshi=nummiao/10;
           miaoge=nummiao%10;
           fenzhongshi=numfenzhong/10;
           fenzhongge=numfenzhong%10;
           xiaoshishi=numxiaoshi/10;
           xiaoshige=numxiaoshi%10;
           display();
           if(keybuf==1)
           {
             delayms(10);
             if(keybuf==1)
             {
               while(!(P1IN==0x19));
               nummiao++;
               if(nummiao>59)
                 nummiao=0;
             }
           }
           if(keybuf==2)
           {
             delayms(10);
             if(keybuf==2)
             {
               while(!(P1IN==0x19));
               numfenzhong++;
               if(numfenzhong>59)
                 numfenzhong=0;
             }
           }
           /*if(P1IN==0x01)
           {
             delayms(10);
             if(P1IN==0x01)
             {
               while(!(P1IN==0x19));
               numxiaoshi++;
               if(numxiaoshi>23)
                 numxiaoshi=0;
             }
           }*/
           if(keybuf==0)
           {
             delayms(10);
             if(keybuf==0)
             {
               while(!(P1IN==0x19));
               _EINT();
               break;
              }
            }
          }
        }
       }
  }
  
}
unsigned char keycode()
{
  unsigned char x;
  if((P1IN&0x19)== 0x09) // 是否第一个按键K1   
  {
    delayms(10);
    if((P1IN&0x19)== 0x09)
      x=0;
  }
  else
  if((P1IN&0x19)== 0x11) // 是否第二个按键K2
  {
     delayms(10);
     if((P1IN&0x19)== 0x11)
       x=1;
  }
  else
  if((P1IN&0x19)== 0x18) // 是否第三个按键K3
  {
     delayms(10);
     if((P1IN&0x19)== 0x18)
      x=2;
  }
  return(x);
}
void main(void)
{
  init();
  init_lcd();

  while(1)
  {   
    //anjian();                           /*****设置时间*****/
    miaoshi=nummiao/10;
    miaoge=nummiao%10;
    fenzhongshi=numfenzhong/10;
    fenzhongge=numfenzhong%10;
    xiaoshishi=numxiaoshi/10;
    xiaoshige=numxiaoshi%10;

    LCDMEM[5]=0x32;   
    display();
  }
}
#pragma vector=tiMERA0_VECTOR
__interrupt void Timer_A()
{
  nummiao++;
  LCDMEM[5]=0x00;
  if(nummiao>59)
  {
    nummiao=0;
    numfenzhong++;
  }
  if(numfenzhong>59)
  {
    numfenzhong=0;
    numxiaoshi++;
  }
  if(numxiaoshi>23)
  {
    numxiaoshi=0;
  }   
}
/******************P1中断*********************************/
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{ //端口1 的中断服务程序
  P1IFG&=~0X19;
  while((P1IN&0X19)!=0x19) //没有按键按下,返回全1――0x19
  {
    delayms(50); //延时消除抖动
    while((P1IN&0X19)!=0x19)
    {
       keybuf = keycode();
      while((P1IN&0X19)==0); //等待按键松开   
    }
  }
  //_BIC_SR_IRQ(LPM3_bits);
}


0s0-349193671microMsg.1394070050612.jpg
0s0-2034385000microMsg.1394070015329.jpg

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
4条回答
1522495332
1楼-- · 2019-07-16 01:10
本帖最后由 1522495332 于 2014-4-9 09:43 编辑

代码看得头疼,我给几个建议
1、变量的设置
时、分、秒为:uchar uHour, uMinute, uSecond;
他们的十位与个位分别为:uchar uHighHour, uLowHour, uHighMinute, uLowMintue, uHighSecond,uLowSecond;//如果定义成数组,那操作就更方便了
uchar uNumber[6];//后面的代码就用这个,不用上面的那6个变量)
光标位置为:uchar uCursor; // 取值0~6,秒的个位为0, 时的十位为5,退出设置为6

2、按键中断可以判断中断标志 P1IFG,比起直接判断P1IN来得好
例如
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
    if(P1IFG & BIT0)
    {

          //K3按下,光标处的数值加一
          if(uCursor<6)
         {
                 uNumber[uCursor]++;
                 //code... 再对 uLowSecond 的取值范围进行判断
         }
    }
    else if(P1IFG & BIT3)
    {

         //K2按下,光标处的数值减一
          //
参考上面 K3 的代码
    }
    else if(P1IFG & BIT4)
    {
          //K1
按下,光标左移
          if(uCursor<5)
          {
               //code...
恢复光标处的数值
                 uCursor++

           }
           else if(5 ==uCursor)
          {
               //code...
uHighHour, uLowHour合成uHour
               //code...
uHighMinute, uLowMintue合成uMinute
               //code...
uHighSecond, uLowSecond合成Second
              uCursor = 6;
          }
          else
          {
               uCursor = 0
           }
    }

    //其它代码
   P1IFG = 0;

}
3、使用 display() 函数实现光标闪烁功能void display(){  //以下4行显示小时  static uchar cnt = 0;//计数,范围0~20;0~10显示光标,11~20显示数字。取值范围小,光标闪烁快;取值范围大,光标闪烁慢,自己修改  uchar i;  for(i=1;i<7;i++)  {       if(uCursor == i - 1)       {             LCDMEM=(cnt<10) ? '_' : table[uNumber[i-1]];  // '_' 是下划线或者其它光标符号对应的8位二进制数,请自行替换
       }       else      {             LCDMEMtable[uNumber[i-1]];      }      delayms(10);  }  if(cnt<20)    cnt++;  else    cnt = 0;
}
4、大量使用while结构,对于初学者来说是个不好的习惯,既然你的按键是用中断进行处理,你又何必加上查询呢?这是多此一举的做法。5、主函数太乱了,我就不发表意见了
如有疑问,继续提问
依然落叶飘零
2楼-- · 2019-07-16 03:51
同时用到定时器中断和外部中断,一定要设置中断优先级,否则进入外部中断的时候,定时器中断不工作,则定时器中断不响应,时间就不走了。另外,用单片机定时器做的时钟存在误差,如果想准确则必须用到时钟芯片。
z00
3楼-- · 2019-07-16 09:33
代码有点乱 最好能有程序的流程图 编程思想比代码重要
youzizhile
4楼-- · 2019-07-16 12:24
先画流程图,在设计程序,然后验证比较容易确定问题

一周热门 更多>