电子开发网

电子开发网电子设计 | 电子开发网Rss 2.0 会员中心 会员注册
搜索: 您现在的位置: 电子开发网 >> 电子开发 >> 单片机 >> 正文

单片机基于算盘码的新型时钟

作者:佚名    文章来源:本站原创    点击数:    更新时间:2013-1-12

现在将一个实际编制的、带有调整时间功能的算盘码新型时钟程序发布。硬件电路由于只有一个三基色LED和一个按键开关,就不贴出了。所选MCU主要是利用其内置的RTCC。
单个按键开关有短按和长按两种用法。在正常报时状态,短按无作用,长按可以进入调时状态。进入调时状态后,按照十小时、小时、十分、分的顺序依次调整。每次短按键循环进行增量步进,长按键进入下一档位,4种都调完最后一次长按键就回到正常报时状态。在调整状态,调整“小时”和“分钟”时用白色和蓝色分别显示,白色表示正在调整的档位,蓝色则表示不调整的档位。例如,在调整到第三档的时候,第一个拍发的数码是白色,表示“十分”,第二个拍发的数码是蓝色,表示“分”,在这个档位短按键只调整白色的“十分”,不调整蓝色的“分”。

/*------------------------------------------------------------------- 
编译器:MCC18 V3.40 
日期:2011 0924             
版本:V1.1 
功能:用过去在Pic16论坛上发布过的算盘码编码格式,在pic18f26j13的RTCC上实现可以 
用两位码和光色来表示小时与分钟的新型时钟。 
前一位码的光色表示“十小时”,码型表示“小时”。后一位码的光色表示“十分钟”,码型表示“分钟”。 
光色表示的数值依照“蓝,绿,黄,红,青,紫”依次表示“0,1,2,3,4,5”。 
码型以长短发光表示,以“划”表示发光时间略长,“点”表示发光时间很短。以下从0--9的码型分别为 
划划,点,点点,点点点,点点点点,划,划点,划点点,划点点点,划点点点点。 
用较短的停顿区分前后码,用较长的停顿表示分组。 
例如,21点整,表示为“黄点,蓝划划” 
修改时钟,要长按唯一的按键,直到发出持续的白光(白里泛紫),松键就用白光点划表示等待修改的位,用蓝光点划表示不修改的位。 
修改状态连续发出的两个码型,前面一组表示十小时和小时,后面一组表示十分钟和分钟。每次修改时,先修改十小时位,再修改小时位。 
此时显示的两个码前面是十小时,后面是小时。前码白光后码蓝光时修改十小时,通过短按键循环改变该位的值,修改完毕长按键就转入后位修改, 
这时是前码蓝光,后码白光,同样是循环改变,完成这组后长按就进入十分钟和分钟修改。后一组的修改过程和结束方式同前。 
长按键要看到一组两个码完整显示再松手,才能保证进入下一步。 
修改完成后会自动保存到RTCC,继续正常发光报时任务。 
硬件电路非常简单,除去主振荡器12m和实时钟晶体32768Hz外,只有程序最前部键定义连接的一个按键和一个三基色led。其它均按MCU手册要求配电容电阻即可。 
特别声明,本算盘码的编码方式,修改时钟方式和整个程序属于本人原创,可基于个人研究目的进行引用和复制,但不得作为商业用途使用。 
-------------------------------------------------------------------*/
 
#include <P18f26j13.h> 

#define Key PORTCbits.RC2 
#define LEDR TRISBbits.TRISB2        //红led 
#define LEDG TRISBbits.TRISB0        //绿led 
#define LEDB TRISBbits.TRISB3        //蓝led 

void
 main (void); 
void
 InterruptHandlerHigh (void); 

unsigned char
 *ppptr; 
static const
 unsigned int morse_code[12]={0xee00,0x8000,0xa000,0xa800,0xaa00,0xe000,0xe800,0xea00, 
0xea80
,0xeaa0,0x0000,0x0000};        //算盘码码型 
static const unsigned char code_lenth[12]={0x0c,0x06,0x08,0x0a,0x0c,0x08,0x0a,0x0c,0x0f,0x11,0x0a,0x0a}; 
                                    //算盘码码长 
unsigned int *morse_ptr; 
unsigned char
 *code_lenth_ptr; 
static
 unsigned char morse_lenth; 
static
 unsigned int timing_code[4]={0x0000,0xaa00,0x0000,0x0000};        //轮流拍发的码型存放位置 
static unsigned char timing_code_lenth[4]={0x05,0x05,0x00,0x05};            //轮流拍发的码长存放位置 
unsigned char tens_or_ones; 
unsigned char
 colour,minus; 

unsigned char
 key_pules,key_count; 
static
 unsigned long key_status=0xffffffff;        //存储按键历史的变量,每次中断存一位,为0表示长按键 
unsigned char key_down,key_up,last_key;            //表征按键按下、抬起的变量 
unsigned char t=0; 
unsigned char
 minut_colour,minut; 
unsigned char
 hour,hour_colour; 
unsigned char
 in_hour=1;            //区别小时和分钟的变量 
unsigned int temp; 
unsigned int
 temperature;            //测试的变量名,没有改正 

unsigned char
 Rtimehi[4]={0x0,0x09,0x1,0x54},Rtimelo[4]={0x11,0x11,0x15,0x30};        //保存RTCC日期时间的两组变量 
//***************主函数***************** 
void main() 
{
 
    unsigned char
 i,j; 
    //**********RC2作为按键使用初始化********************** 
    ANCON1bits.PCFG11=1;    //RC2作为数字IO,不给ADC 
    TRISCbits.TRISC2=1;        //输入,接Key 
    //*************************RTCC初始化******************* 
    T1GCON=0; 
    T1CON=0X8B;                //允许tmr1的振荡器 
    RTCCFG=0X07; 
    RTCCAL=0X0;                //校准值 
    PADCFG1=0X02;            //输出秒时钟 
    _asm  movlw 0x55 _endasm 
    _asm movwf EECON2,0 _endasm 
    _asm movlw 0xAA _endasm 
    _asm  movwf EECON2,0 _endasm 
    _asm  bsf RTCCFG,5,1 _endasm    //开启写入 
    RTCCFGbits.RTCEN=1; 
    RTCCFG|=0x03;        //置指针为0b11 
    while (RTCCFGbits.RTCSYNC);    //等待不忙 
        for (i=0;i<4;i++)    //读 
        { 
            Rtimelo[i]=RTCVALL; 
            Rtimehi[i]=RTCVALH; 
        }
 
        //****************TIMERS******************* 
        T0CON=0X84;                //定时器, 分频 
        INTCONbits.T0IE=1; 
        T5CON=0X3F;                //1/4Fosc,1:8 prescale,T1OSC, 16 bits WR,enabled 
        T5GCON=0;                //no gate 
        PIE5bits.TMR5IE=1; 
        //*****************中断开启*************** 
        INTCONbits.PEIE=1; 
        INTCONbits.GIE=1; 
        //****************按键相关设置************* 
        morse_ptr=timing_code; 
        code_lenth_ptr=timing_code_lenth; 
        t=timing_code_lenth[1]; 
        temp=timing_code[1]; 
        key_up=0;                        //缺省为按键抬起状态 
        key_down=0; 
        last_key=1; 
        //**************************主循环************************ 
        while(1) 
        {
 
            RTCCFG|=0x03;        //置指针为0b11 
            Rtimelo[0]=RTCVALL;        //读年 
            Rtimehi[0]=RTCVALH;        //读空 
            Rtimelo[1]=RTCVALL;        //读日 
            Rtimehi[1]=RTCVALH;        //读月 
            Rtimelo[2]=RTCVALL;        //读小时 
            Rtimehi[2]=RTCVALH;        //读星期 
            Rtimelo[3]=RTCVALL;        //读秒 
            Rtimehi[3]=RTCVALH;        //读分 
    
            hour_colour=Rtimelo[2]>>4;            //十小时颜色 
            hour=Rtimelo[2]&0x0f;                //小时 
            minut_colour=Rtimehi[3]>>4;            //十分颜色 
            minut=Rtimehi[3]&0x0f;                //分钟 
            timing_code[1]=morse_code[hour];            //小时的码型 
            timing_code_lenth[1]=code_lenth[hour];        //小时的码长 
            timing_code[2]=morse_code[minut];            //分的码型 
            timing_code_lenth[2]=code_lenth[minut];    //分的码长 

            //以下为修改时钟的键操作部分 
            if (key_status==0) 
            {
 
                hour_colour=6;                //白色光 
                minut_colour=0; 
                for
 (i=0;i<3;i++) 
                timing_code[i]=0xffff;            //全长划,表示进入调整时钟模式 
                while (key_status==0); 
                for
 (i=0;i<3;i++) 
                    timing_code[i]=0;    
                while
 (key_status)                //一次长按键之前,修改十小时值 
                { 
                    timing_code[1]=morse_code[Rtimelo[2]>>4];    //十小时 
                    timing_code_lenth[1]=code_lenth[Rtimelo[2]>>4]; 
                    timing_code[2]=morse_code[Rtimelo[2]&0x0f];    //小时 
                    timing_code_lenth[2]=code_lenth[Rtimelo[2]&0x0f]; 
                    if
 (key_up==1)                //如果发现短时间按键的抬键信号 
                    { 
                        Rtimelo[2]+=0x10;                //步进十小时 
                        key_up=0;                    //清除短时间按键标志 
                    } 
                    if
 (Rtimelo[2]>0x23) 
                        Rtimelo[2]=0; 
                    }
 
                    while
 (key_status==0) key_up=0;        //防止一次按键连续动作 
                        hour_colour=0;                //lan色光 
                    minut_colour=6;                //白色光 
                    while (key_status)                //一次长按键之前,修改小时值 
                    { 
                        timing_code[1]=morse_code[Rtimelo[2]>>4];    //十小时 
                        timing_code_lenth[1]=code_lenth[Rtimelo[2]>>4]; 
                        timing_code[2]=morse_code[Rtimelo[2]&0x0f];    //小时 
                        timing_code_lenth[2]=code_lenth[Rtimelo[2]&0x0f]; 
                        if
 (key_up==1)                //如果发现短时间按键的抬键信号 
                        { 
                            Rtimelo[2]++;                //步进小时 
                            key_up=0;                    //清除短时间按键标志 
                        } 
                        if
 (Rtimelo[2]>0x23)            //总小时数若大于23,则小时个位置0 
                        Rtimelo[2]=0x20; 
        
                        if
 ((Rtimelo[2]&0x0f)>9)        //小时值若大于9 
                        Rtimelo[2]&=0xf0;            //修改为0 
                    } 
                    while
 (key_status==0) key_up=0;        //防止一次按键连续动作 
                    //以下修改分钟 
                    hour_colour=6;                //白色光 
                    minut_colour=0;                //蓝色光 
                    while (key_status)                //一次长按键之前,修改十分钟值 
                    { 
                        timing_code[1]=morse_code[Rtimehi[3]>>4];    //十分钟 
                        timing_code_lenth[1]=code_lenth[Rtimehi[3]>>4]; 
                        timing_code[2]=morse_code[Rtimehi[3]&0x0f];    //分钟 
                        timing_code_lenth[2]=code_lenth[Rtimehi[3]&0x0f]; 
                        if
 (key_up==1)                        //如果发现短时间按键的抬键信号 
                        { 
                            Rtimehi[3]+=0x10;                    //步进十分钟 
                            key_up=0;                            //清除短时间按键标志 
                        } 
                        if
 (Rtimehi[3]>0x59)                //总fen数若大于59,则十分钟位置0 
                        Rtimehi[3]&=0x0f; 
                    }
 
                    while
 (key_status==0) key_up=0;        //防止一次按键连续动作 
                    hour_colour=0;                        //蓝色光 
                    minut_colour=6;                        //白色光 
                    bwhile (key_status)                    //一次长按键之前,修改分钟值 
                    { 
                        timing_code[1]=morse_code[Rtimehi[3]>>4];    //十分钟 
                        timing_code_lenth[1]=code_lenth[Rtimehi[3]>>4]; 
                        timing_code[2]=morse_code[Rtimehi[3]&0x0f];    //分钟 
                        timing_code_lenth[2]=code_lenth[Rtimehi[3]&0x0f]; 
                        if
 (key_up==1)                        //如果发现短时间按键的抬键信号 
                        {    
                            Rtimehi[3]++;                        //步进分钟 
                            key_up=0;                            //清除短时间按键标志 
                        } 
                        if
 ((Rtimehi[3]&0x0f)>9)            //fen数个位若大于9,则分钟位置0 
                            Rtimehi[3]=Rtimehi[3]&0xf0; 
                    }
 
                    while
 (key_status==0) key_up=0;        //防止一次按键连续动作 
                    //写入RTCC 
                    RTCCFG|=0x03;        //置指针为0b11 
                    while (RTCCFGbits.RTCSYNC);    //等待不忙 
                    for (i=0;i<4;i++)    //写 
                    { 
                        RTCVALL=Rtimelo[i]; 
                        RTCVALH=Rtimehi[i]; 
                    } 
            }
 
            //到达MAIN最后部分 
        } 
}
 
//---------------------------------------------------------------------------- 
// High priority interrupt vector 
#pragma code InterruptVectorHigh = 0x08 
void InterruptVectorHigh (void) 
{
 
  _asm 
    goto
 InterruptHandlerHigh         //jump to interrupt routine 
  _endasm 
}
 
//---------------------------------------------------------------------------- 
// High priority interrupt routine 
#pragma code 
#pragma interrupt InterruptHandlerHigh 

void
 
InterruptHandlerHigh () 
{
 
    if
 (INTCONbits.TMR0IF) 
    {
                                 //check for TMR0 overflow 
        INTCONbits.TMR0IF = 0;        //clear interrupt flag 
        TMR0H=0X20;                            //略加快点划速率 
        TMR0L=0; 
        if
 ((t<=0)|t>25) 
        {
 
            if
 (morse_ptr>&timing_code[2]) 
            {
 
                morse_ptr=timing_code; 
                code_lenth_ptr=timing_code_lenth; 
            }
 
            else
 
            {
 
                morse_ptr++; 
                code_lenth_ptr++; 
            }
 
            if
 (morse_ptr>(&timing_code[1]))        //小时在1,分在2,据此决定in_hour 
                in_hour=0; 
            else
 
                in_hour=1; 
            if
 (in_hour==0)                    //十分钟颜色 
            { 
                if
 (minut_colour==0)                                //蓝 
                { 
                    LEDG=1; 
                    LEDR=1; 
                    LEDB=0; 
                }
 
                else if
 (minut_colour==1)                            //绿 
                { 
                    LEDG=0; 
                    LEDR=1; 
                    LEDB=1; 
                }
 
                else if
 (minut_colour==2)                            //黄 
                { 
                    LEDG=0; 
                    LEDR=0; 
                    LEDB=1; 
                }
 
                else if
 (minut_colour==3)                            //红 
                { 
                    LEDG=1; 
                    LEDR=0; 
                    LEDB=1; 
                }
 
                else if
 (minut_colour==4)                            //青 
                { 
                    LEDG=0; 
                    LEDR=1; 
                    LEDB=0; 
                }
 
                else if
 (minut_colour==5)                            //紫 
                { 
                    LEDG=1; 
                    LEDR=0; 
                    LEDB=0; 
                }
 
                else
                                                //白 
                { 
                    LEDG=0; 
                    LEDR=0; 
                    LEDB=0; 
                } 
            }
 
            else
                                //十小时颜色 
            { 
                if
 (hour_colour==0)                                //蓝 
                { 
                    LEDG=1; 
                    LEDR=1; 
                    LEDB=0; 
                }
 
                else if
 (hour_colour==1)                            //绿 
                { 
                    LEDG=0; 
                    LEDR=1; 
                    LEDB=1; 
                }
 
                else if
 (hour_colour==2)                            //黄 
                { 
                    LEDG=0; 
                    LEDR=0; 
                    LEDB=1; 
                }
 
                else if
 (hour_colour==3)                            //红 
                { 
                    LEDG=1; 
                    LEDR=0; 
                    LEDB=1; 
                }
     
                else if
 (hour_colour==4)                            //青 
                { 
                    LEDG=0; 
                    LEDR=1; 
                    LEDB=0; 
                }
 
                else if
 (hour_colour==5)                            //紫 
                { 
                    LEDG=1; 
                    LEDR=0; 
                    LEDB=0; 
                }
 
                else
                                                //白 
                { 
                    LEDG=0; 
                    LEDR=0; 
                    LEDB=0; 
                } 
            }
 
            temp=*morse_ptr;                    //取得指针位置的值 
            t=*code_lenth_ptr;                    //同上 
        } 
        else
 
        {
 
            t--; 
        }
 
        if
 ((temp&0x8000)==0)                //这段是拍发算盘码的执行部分 
            LATB = LATB|0b00001101; 
        else
 
            LATB = LATB&0b1110010; 
        temp=temp<<1; 
    }
 
    else if
 (PIR5bits.TMR5IF)            //该定时器用来识别按键动作 
    { 
        PIR5bits.TMR5IF = 0;            //clear interrupt flag 
        if (key_down==1&last_key==1)    //只有下键后才进入判断 
        { 
            if
 (key_status)                //在没有全0序列情况下 
            if (Key==1)                    //确认抬键 
            { 
                key_up=1; 
                key_down=0; 
            } 
        }
 
        else if
 (last_key==0) 
        {
 
            if
 (Key==0) 
            {
 
                key_down=1;                        //确认下键 
                key_up=0; 
            } 
        }
 
        last_key=Key;                    //当前键值赋予旧键值 
        key_status=key_status<<1;        //键状态左移1位 
        key_status|=Key;                //末位置Key的值 
    } 
}

Tags:单片机,pic18,时钟,程序  
责任编辑:admin
请文明参与讨论,禁止漫骂攻击,不要恶意评论、违禁词语。 昵称:
1分 2分 3分 4分 5分

还可以输入 200 个字
[ 查看全部 ] 网友评论
关于我们 - 联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 在线帮助 - 文章列表
返回顶部
刷新页面
下到页底
晶体管查询