18luck网站

18luck网站電子設計 | 18luck网站Rss 2.0 會員中心 會員注冊
搜索: 您現在的位置: 18luck网站 >> 18luck平台 >> 單片機 >> 正文

單片機基於算盤碼的新型時鍾

作者:佚名    文章來源:本站原創    點擊數:    更新時間:2013-1-12

現在將一個(ge) 實際編製的、帶有調整時間功能的算盤碼新型時鍾程序發布。硬件電路由於(yu) 隻有一個(ge) 三基色LED和一個(ge) 按鍵開關(guan) ,就不貼出了。所選MCU主要是利用其內(nei) 置的RTCC。
單個(ge) 按鍵開關(guan) 有短按和長按兩(liang) 種用法。在正常報時狀態,短按無作用,長按可以進入調時狀態。進入調時狀態後,按照十小時、小時、十分、分的順序依次調整。每次短按鍵循環進行增量步進,長按鍵進入下一檔位,4種都調完最後一次長按鍵就回到正常報時狀態。在調整狀態,調整“小時”和“分鍾”時用白色和藍色分別顯示,白色表示正在調整的檔位,藍色則表示不調整的檔位。例如,在調整到第三檔的時候,第一個(ge) 拍發的數碼是白色,表示“十分”,第二個(ge) 拍發的數碼是藍色,表示“分”,在這個(ge) 檔位短按鍵隻調整白色的“十分”,不調整藍色的“分”。

/*------------------------------------------------------------------- 
編譯器:MCC18 V3.40 
日期:2011 0924             
版本:V1.1 
功能:用過去在Pic16論壇上發布過的算盤碼編碼格式,在pic18f26j13的RTCC上實現可以 
用兩(liang) 位碼和光色來表示小時與(yu) 分鍾的新型時鍾。 
前一位碼的光色表示“十小時”,碼型表示“小時”。後一位碼的光色表示“十分鍾”,碼型表示“分鍾”。 
光色表示的數值依照“藍,綠,黃,紅,青,紫”依次表示“0,1,2,3,4,5”。 
碼型以長短發光表示,以“劃”表示發光時間略長,“點”表示發光時間很短。以下從(cong) 0--9的碼型分別為(wei)  
劃劃,點,點點,點點點,點點點點,劃,劃點,劃點點,劃點點點,劃點點點點。 
用較短的停頓區分前後碼,用較長的停頓表示分組。 
例如,21點整,表示為(wei) “黃點,藍劃劃” 
修改時鍾,要長按唯一的按鍵,直到發出持續的白光(白裏泛紫),鬆鍵就用白光點劃表示等待修改的位,用藍光點劃表示不修改的位。 
修改狀態連續發出的兩(liang) 個(ge) 碼型,前麵一組表示十小時和小時,後麵一組表示十分鍾和分鍾。每次修改時,先修改十小時位,再修改小時位。 
此時顯示的兩(liang) 個(ge) 碼前麵是十小時,後麵是小時。前碼白光後碼藍光時修改十小時,通過短按鍵循環改變該位的值,修改完畢長按鍵就轉入後位修改, 
這時是前碼藍光,後碼白光,同樣是循環改變,完成這組後長按就進入十分鍾和分鍾修改。後一組的修改過程和結束方式同前。 
長按鍵要看到一組兩(liang) 個(ge) 碼完整顯示再鬆手,才能保證進入下一步。 
修改完成後會(hui) 自動保存到RTCC,繼續正常發光報時任務。 
硬件電路非常簡單,除去主振蕩器12m和實時鍾晶體(ti) 32768Hz外,隻有程序最前部鍵定義(yi) 連接的一個(ge) 按鍵和一個(ge) 三基色led。其它均按MCU手冊(ce) 要求配電容電阻即可。 
特別聲明,本算盤碼的編碼方式,修改時鍾方式和整個(ge) 程序屬於(yu) 本人原創,可基於(yu) 個(ge) 人研究目的進行引用和複製,但不得作為(wei) 商業(ye) 用途使用。 
-------------------------------------------------------------------*/
 
#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;        //存儲(chu) 按鍵曆史的變量,每次中斷存一位,為(wei) 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日期時間的兩(liang) 組變量 
//***************主函數***************** 
void main() 
{
 
    unsigned char
 i,j; 
    //**********RC2作為(wei) 按鍵使用初始化********************** 
    ANCON1bits.PCFG11=1;    //RC2作為(wei) 數字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    //開啟寫(xie) 入 
    RTCCFGbits.RTCEN=1; 
    RTCCFG|=0x03;        //置指針為(wei) 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; 
        //****************按鍵相關(guan) 設置************* 
        morse_ptr=timing_code; 
        code_lenth_ptr=timing_code_lenth; 
        t=timing_code_lenth[1]; 
        temp=timing_code[1]; 
        key_up=0;                        //缺省為(wei) 按鍵抬起狀態 
        key_down=0; 
        last_key=1; 
        //**************************主循環************************ 
        while(1) 
        {
 
            RTCCFG|=0x03;        //置指針為(wei) 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];    //分的碼長 

            //以下為(wei) 修改時鍾的鍵操作部分 
            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)            //總小時數若大於(yu) 23,則小時個(ge) 位置0 
                        Rtimelo[2]=0x20; 
        
                        if
 ((Rtimelo[2]&0x0f)>9)        //小時值若大於(yu) 9 
                        Rtimelo[2]&=0xf0;            //修改為(wei) 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數若大於(yu) 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數個(ge) 位若大於(yu) 9,則分鍾位置0 
                            Rtimehi[3]=Rtimehi[3]&0xf0; 
                    }
 
                    while
 (key_status==0) key_up=0;        //防止一次按鍵連續動作 
                    //寫(xie) 入RTCC 
                    RTCCFG|=0x03;        //置指針為(wei) 0b11 
                    while (RTCCFGbits.RTCSYNC);    //等待不忙 
                    for (i=0;i<4;i++)    //寫(xie)  
                    { 
                        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,據此決(jue) 定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 個字
[ 查看全部 ] 網友評論
關於我們 - 聯係我們 - 廣告服務 - 友情鏈接 - 網站地圖 - 版權聲明 - 在線幫助 - 文章列表
返回頂部
刷新頁麵
下到頁底
晶體管查詢