在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<s id="cmphk"><label id="cmphk"></label></s>
    <span id="cmphk"><var id="cmphk"></var></span>
    <dfn id="cmphk"><var id="cmphk"></var></dfn>
    <menu id="cmphk"><thead id="cmphk"></thead></menu>

    <address id="cmphk"></address>

      <dfn id="cmphk"></dfn>
      
      
      <span id="cmphk"></span>

      <object id="cmphk"><tt id="cmphk"></tt></object>
      1. 新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 不用延時去抖的按鍵程序

        不用延時去抖的按鍵程序

        作者: 時間:2016-11-13 來源:網絡 收藏
        今天完成一個很好的按鍵程序,一般教科書上寫的都是延時去抖,那樣一旦進入按鍵掃描子程序就不得不等待延時,這樣會影響cpu做其他的事。一種高效的按鍵掃描方法是用定時掃描。把所有程序都附在下面,希望大家能看懂,也請多多指教。本程序的主要功能是采樣定時掃描的高效按鍵掃描程序設置電壓電流的值,實時顯示在lcd1602上,在1602上可左移、右移,數值加減,以及設置/確認(復用鍵),還有一個短路鍵。

        //主函數 main

        本文引用地址:http://www.biyoush.com/article/201611/316430.htm

        #include <msp430x14x.h>
        #include "key.h"
        #include "lcd1602.h"

        uchar Key_Flag=0;
        uchar Keyval = 0;
        uchar Respond_Key_Flag=0; //響應鍵
        uchar Set_Confirm_Flag=0; //設設置/確認標志

        uchar Volt_buf[5]={1,2,.,2,6};
        uchar Curr_buf[5]={0,5,.,5,4};

        void Init_port();
        void Init_SysClk();
        void Init_TimerB();
        void key_process();
        //////////////////主函數///////////////
        void main()
        {
        WDTCTL = WDTPW + WDTHOLD; //關閉看門狗
        Init_port();
        Init_LCD() ;
        Init_SysClk();
        Init_TimerB();
        _EINT();

        Disp1Char(0,0,U) ;
        Disp1Char(1,0,:) ;
        DispNChar(3,0, 5,Volt_buf);
        Disp1Char(0x0F,0,V) ;

        Disp1Char(0,1,I) ;
        Disp1Char(1,1,:) ;
        DispNChar(3,1, 5,Curr_buf);
        Disp1Char(0x0F,1,A) ;



        while(1)
        {
        key_process();


        }

        }
        /*******************************************
        函數名稱:key_process
        功 能:根據按鍵值執(zhí)行任務
        參 數:無
        返回值 :無
        ********************************************/
        void key_process()
        {
        static uchar x=3;
        uchar keyvalue;
        static uchar key_one_flag=0;

        keyvalue = Key_Scan();
        Keyval = 0;
        if(Set_Confirm_Flag == 1)
        {
        if(keyvalue == 1) //設置/確認鍵
        {
        key_one_flag ^= 1;
        if(key_one_flag==1)
        {
        write_cmd(0x0f); //打開顯示屏,顯示光標,光標所在位置的字符閃爍
        LocateXY(3,0); //向液晶寫入顯示字符位置的坐標信息
        }
        else
        {
        write_cmd(0x0c);//開顯示, 關光標,光標所在位置的字符不閃爍
        Set_Confirm_Flag =0;
        }
        }

        if((keyvalue == 2)&&( Respond_Key_Flag==1)) //短路鍵
        {

        Respond_Key_Flag=0;
        Disp1Char(3,0,Z) ;
        //TACCR0 = 65535; //PWM占空比設置為百分之百
        }


        if((keyvalue == 3)&&( Respond_Key_Flag==1)) //左移
        {

        Respond_Key_Flag=0;
        if(x >3)
        {
        --x;
        if(x<8)
        LocateXY(x,0);
        else
        LocateXY(x-5,1);
        }
        else
        {
        x=12;
        LocateXY(x-5,1);
        }
        }



        if((keyvalue == 4)&&( Respond_Key_Flag==1)) //右移
        {
        Respond_Key_Flag=0;

        if(x < 12)
        {
        ++x;
        if(x<8)
        LocateXY(x,0);
        else
        LocateXY(x-5,1);
        }
        else
        {
        x=3;
        LocateXY(x,0);
        }

        }




        if((keyvalue == 5)&&( Respond_Key_Flag==1)) //數值"+"鍵
        {
        Respond_Key_Flag=0;

        if(x<3 || x>12)
        {
        write_data( ) ;
        }
        else if(x==5||x==10)
        {
        write_data(.) ;
        if(x==5)
        LocateXY(x,0);
        if(x==10)
        LocateXY(x-5,1);

        }
        else
        {
        if((x>=3)&&(x<=7))
        {
        if(Volt_buf[x-3]<9)
        Volt_buf[x-3] += 1;
        else Volt_buf[x-3]=0;
        Disp1Char(x,0,Volt_buf[x-3]) ;
        LocateXY(x,0);
        }
        else
        {
        if(Curr_buf[x-8]<9)
        Curr_buf[x-8] += 1;
        else Curr_buf[x-8]=0;
        Disp1Char(x-5,1,Curr_buf[x-8]) ;
        LocateXY(x-5,1);
        }
        }
        }




        if((keyvalue == 6)&&( Respond_Key_Flag==1)) //數值"-"鍵
        {
        Respond_Key_Flag=0;

        if(x<3 || x>12)
        {
        write_data( ) ;
        }
        else if(x==5||x==10)
        {
        write_data(.) ;
        if(x==5)
        LocateXY(x,0);
        if(x==10)
        LocateXY(x-5,1);

        }
        else
        {
        if((x>=3)&&(x<=7))
        {
        if(Volt_buf[x-3]>0)
        Volt_buf[x-3] -= 1;
        else Volt_buf[x-3]=9;
        Disp1Char(x,0,Volt_buf[x-3]) ;
        LocateXY(x,0);
        }
        else
        {
        if(Curr_buf[x-8]>0)
        Curr_buf[x-8] -= 1;
        else Curr_buf[x-8]=9;
        Disp1Char(x-5,1,Curr_buf[x-8]) ;
        LocateXY(x-5,1);
        }
        }
        }

        }


        }

        /*============================================
        函數名稱:Init_port
        功 能:初始化I/O端口
        參 數:無
        返回值 :無
        ==============================================*/
        void Init_port()
        {
        /*下面六行程序關閉所有的IO口*/
        P1DIR = 0XFF;P1OUT = 0XFF;
        P2DIR = 0XFF;P2OUT = 0XFF;
        P3DIR = 0XFF;P3OUT = 0XFF;
        P4DIR = 0XFF;P4OUT = 0XFF;
        P5DIR = 0XFF;P5OUT = 0XFF;
        P6DIR = 0XFF;P6OUT = 0XFF;
        P6DIR |= BIT2;P6OUT |= BIT2; //關閉電平轉換
        //定義液晶端口

        P4DIR = 0XFF; //數據口
        P4OUT = 0;
        //定義按鍵端口
        P1DIR =BIT6 + BIT7; //設置P1.0~P.3為輸入狀態(tài),P.7為輸出


        }
        /*============================================
        函數名稱:Init_SysClk
        功 能:初始化系統(tǒng)時鐘
        參 數:無
        返回值 :無
        ==============================================*/

        void Init_SysClk()
        {

        unsigned int i;

        BCSCTL1 &= ~XT2OFF; // XT2= HF XTAL

        do
        {
        IFG1 &= ~OFIFG; // Clear OSCFault flag
        for (i = 0xFF; i > 0; i--); // Time for flag to set
        }
        while ((IFG1 & OFIFG)); // OSCFault flag still set?

        BCSCTL2 |= SELM_2; // MCLK= XT2 (safe),分頻椅子為1
        BCSCTL2 |= SELS; //SMCLK的時鐘源為TX2CLK,分頻因子為1

        }


        /*============================================
        函數名稱:Init_TimerB
        功 能:初始化定時器B,設定基準時間500us
        參 數:無
        返回值 :無
        ==============================================*/
        void Init_TimerB()
        {
        TBCTL |= TBSSEL1 +TBCLR; //MCLK ,8M
        TBCCTL0 = CCIE;
        TBCCR0 =4000; //定時500us
        TBCTL |= MC_1; // Start Timer_B in up mode
        }


        /*===========================================
        函數名稱:TimerB_ISR
        功 能:設定時間間隔
        參 數:無
        返回值 :無
        =============================================*/
        // Timer B0 interrupt service routine
        #pragma vector=TIMERB0_VECTOR
        __interrupt void TimerB_ISR (void)
        {
        static uchar Flag_500us = 0;
        Flag_500us ++;
        if(Flag_500us ==20)
        {
        Key_Flag =1; //定時10ms
        Flag_500us=0;
        // TBCCTL0 = ~CCIE; //關中斷,單步調試時用,不然一直在中斷里


        }

        }


        //按鍵頭文件 key.h

        #ifndef MSP430_KEY_PROCESS_H
        #define MSP430_KEY_PROCESS_H
        /***************************************************
        程序功能:用定時掃描方式讀取6個行列式按鍵的鍵值
        ****************************************************/
        #include
        #include "lcd1602.h"

        #define keyin (P1IN & 0x0F)

        uchar KEY_BUFFER ;
        uchar KEY_BUFFER1 ;

        uchar KEY_DATA = 0x00;
        uchar Num=0;
        extern uchar Key_Flag;
        extern uchar Keyval;
        extern uchar Respond_Key_Flag;
        extern uchar Set_Confirm_Flag;

        /*******************************************
        函數名稱:Delay10us
        功 能:延時約10us
        參 數:無
        返回值 :無
        ********************************************/
        void Delay10us(void)
        {
        uint i=10;
        while (i != 0)
        {
        i--;
        }
        }
        /*******************************************
        函數名稱:Key_Scan
        功 能:掃描按鍵值
        參 數:無
        返回值 :Keyval
        ********************************************/
        uchar Key_Scan()
        {

        if(Key_Flag ==1 ) //10ms掃描一次
        {
        Key_Flag =0;
        //位處理,先用一個字節(jié)把八位按鍵的值讀出來,然后再進行判斷
        P1OUT =0X70;
        Delay10us();//給硬件響應時間
        KEY_BUFFER =keyin;
        KEY_BUFFER =~KEY_BUFFER;
        KEY_BUFFER1 =KEY_BUFFER<<4;

        P1OUT =0XB0;
        Delay10us();
        KEY_BUFFER =keyin;
        KEY_BUFFER =~KEY_BUFFER;
        KEY_BUFFER &=0X0F; //屏蔽高四位
        KEY_BUFFER1 |=KEY_BUFFER ;

        if(KEY_BUFFER1 != KEY_DATA) //首先判斷是否有鍵按下
        {
        KEY_DATA =KEY_BUFFER1; //讀鍵值
        Num =0;
        }
        else //KEY_BUFFER1 = KEY_DATA的處理
        {
        Num ++;

        if(Num==4) //Num=4,讀4次有效,延時達到40ms
        {
        if(KEY_DATA==0x10) //判斷鍵值
        Keyval=1;
        else if(KEY_DATA==0x20)
        Keyval=2;
        else if(KEY_DATA==0x40)
        Keyval=3;
        else if(KEY_DATA==0x80)
        Keyval=4;
        else if(KEY_DATA==0x01)
        Keyval=5;
        else if(KEY_DATA==0x02)
        Keyval=6;
        else Keyval=0;

        }
        else // Num!=4 的處理
        {


        if( KEY_DATA == 0x00) //按鍵放開,允許響應
        {
        Num=0;
        Respond_Key_Flag =1; //按鍵響應標志位
        }
        else //按鍵沒放開,連續(xù)按
        {

        if((KEY_DATA == 0x10)&&(Num >=100)) //1s,判斷是否為設置/確認鍵
        {
        Num =0;
        Set_Confirm_Flag =1;

        }


        }

        }

        }

        }

        return Keyval;

        }
        #endif




        //液晶1602頭文件 lcd1602.h

        #ifndef MSP430_LCD1602_PROCESS_H
        #define MSP430_LCD1602_PROCESS_H
        //硬件連接 P4 數據口 P3.2---EN P3.1---RW P3.0----RS

        #include"msp430x14x.h"
        typedef unsigned int uint;
        typedef unsigned char uchar;
        //定義MCU與LCD的接口
        /**************宏定義***************/
        #define Busy 0x80
        #define CtrlDir P3DIR
        #define CLR_RS P3OUT&=~BIT0 //RS = P3.0
        #define SET_RS P3OUT|=BIT0
        #define CLR_RW P3OUT&=~BIT1//RW = P3.1
        #define SET_RW P3OUT|=BIT1
        #define CLR_EN P3OUT&=~BIT2//EN = P3.2
        #define SET_EN P3OUT|=BIT2
        /*******************************************
        函數名稱:Delay5ms
        功 能:延時約5ms
        參 數:無
        返回值 :無
        ********************************************/
        void Delay5ms(void)
        {
        uint i=40000;
        while (i != 0)
        {
        i--;
        }
        }
        /*******************************************
        函數名稱:WaitForEnable
        功 能:等待1602液晶完成內部操作
        參 數:無
        返回值 :無
        ********************************************/
        void WaitForEnable(void)
        {
        P4DIR &= 0x00; //將P4口切換為輸入狀態(tài)

        CLR_RS;
        SET_RW;
        _NOP();
        SET_EN;
        _NOP();
        _NOP();

        while((P4IN & Busy)!=0); //檢測忙標志

        CLR_EN;

        P4DIR |= 0xFF; //將P4口切換為輸出狀態(tài)
        }
        /*******************************************
        函數名稱:write_cmd
        功 能:向液晶模塊寫入命令
        參 數:com--命令,
        返回值 :無
        ********************************************/
        void write_cmd(unsigned char com)
        {
        WaitForEnable(); //等待液晶不忙
        CLR_RS ; //RS=0,RW=0,寫指令
        CLR_RW;
        _NOP();
        P4OUT = com;
        _NOP();
        SET_EN ;
        _NOP();
        _NOP();
        CLR_EN;
        }

        /*******************************************
        函數名稱:write_data
        功 能:向液晶顯示的當前地址寫入顯示數據
        參 數:data--顯示字符數據
        返回值 :無
        ********************************************/
        void write_data(unsigned char data)
        {
        WaitForEnable(); //等待液晶不忙
        SET_RS; //RS=1,RW=0,寫數據
        CLR_RW;
        _NOP();
        P4OUT = data;
        _NOP();
        SET_EN ; //產生負脈沖
        _NOP();
        _NOP();
        CLR_EN ;
        }

        /*============================================
        函數名稱:Init_LCD
        功 能:初始化液晶
        參 數:無
        返回值 :無
        ==============================================*/
        void Init_LCD()
        {
        CtrlDir |= 0x07; //控制線端口設為輸出狀態(tài)
        P4DIR = 0xFF; //數據端口設為輸出狀態(tài)

        write_cmd(0x38); //規(guī)定的復位操作
        Delay5ms();
        write_cmd(0x38);
        Delay5ms();
        write_cmd(0x38);
        Delay5ms();

        write_cmd(0x38);//16×2顯示,5×7點陣,8位數據接口
        write_cmd(0x08);//關閉顯示
        write_cmd(0x01);//清屏,數據指針=0,所有顯示=0
        write_cmd(0x06);//讀或寫一個字符后地址指針加1 &光標加1,整屏顯示不移動
        write_cmd(0x0c);//開顯示, 關光標,光標所在位置的字符不閃爍

        }

        /*******************************************
        函數名稱:LocateXY
        功 能:向液晶寫入顯示字符位置的坐標信息
        參 數:x--位置的列坐標
        y--位置的行坐標
        返回值 :無
        ********************************************/
        void LocateXY(uchar x,uchar y)
        {
        uchar temp;

        temp = x&0x0f;
        y &= 0x01;
        if(y) temp |= 0x40; //如果在第2行
        temp |= 0x80;

        write_cmd(temp);
        }
        /*******************************************
        函數名稱:Disp1Char
        功 能:在某個位置顯示一個字符
        參 數:x--位置的列坐標
        y--位置的行坐標
        data--顯示的字符數據
        返回值 :無
        ********************************************/
        void Disp1Char(uchar x,uchar y,uchar data)
        {
        LocateXY( x, y );
        write_data( data );
        }

        /***********************************************
        函數名稱:DispStr
        功 能:讓液晶從某個位置起連續(xù)顯示一個字符串
        參 數:x--位置的列坐標
        y--位置的行坐標
        ptr--指向字符串存放位置的指針
        返回值 :無
        ***********************************************/
        void DispStr(uchar x,uchar y,uchar *ptr)
        {
        uchar *temp;
        uchar i,n = 0;

        temp = ptr;
        while(*ptr++ !=