<acronym id="xonnx"></acronym>
      <td id="xonnx"></td>
    1. <pre id="xonnx"></pre>

      1. 專注電子技術學習與研究
        當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

        基于PROTUES與單片機的空調遙控器的實現-課程設計

        作者:張騰   來源:來自張騰   點擊數:  更新時間:2014年07月05日   【字體:

        空調遙控器可以用來廟宇空調機的控制溫度(室內溫度)、工作狀態(常態、除濕、通 風)、風扇風速(強、弱、中)以及定時時間(空調工作多少小時自動開機或延時多少小時自動開機)。使用者在遙控器上廟宇預期的空調機工作狀態、控制溫度及 延時時間后,這些參數即送至空調機,空調機按要求開始工作。

        該遙控器的要求如下:
        (1) 數字顯示器:第一組顯示時間,發送前指示設定的延時時間:0——9 h,發送后指示剩余的延時時間;第二組顯示控制溫度15——35℃。
        (2) 工作狀態指示器3組:第一組指示設定的工作狀態:常態、除濕、通風;第二組指示延時開機、延時停機、取消等三種延時要求;第三組指示空調機的三種工作速度:慢速、中速、高速。
        (3)紅外發射管,發射的調制頻率是45 KHz。
        (4)3節5號電供電。
        (5)面板示意圖見圖。
         
        設計以AT89C51為核心的遙控器電路,并編寫相關的系統軟件(匯編、C51程序均可)。
         
         
         
        設計思路:

                 數字顯示器使用LCD1602顯示時間和溫度值,其中時間的切換利用AT89C51內部自帶的定時器0,定時初值為3cb0,定時器工作模式為’01’16位定時器,工作狀態利用LED燈的亮滅來指示,其中LED亮代表相對應的工作模式被選中,各種工作狀態的切換使用8個獨立按鍵來實現,分別位‘工作狀態設定鍵’、‘延時狀態設定鍵’、‘風速選定鍵’、‘溫度+鍵’、‘溫度-鍵’、‘延時時間位選定鍵’、‘延時時間設置鍵’、‘發送鍵’;按下‘發送鍵’后信息的發送使用串行口的方式發送給上位機并顯現出來,當延時時間到啟動空調。

        具體實現:

        經分析將該設計劃分為如下4個模塊:按鍵模塊,LED狀態顯示模塊,LCD1602顯示模塊,雙機串口通信模塊

        按鍵模塊:

        仿真原理圖:

                 

         
         

        詳細描述:8個按鍵的功能如下表:

        按鍵
        功能
        K1

        工作狀態設定鍵(常態、除濕、通風)

        K2

        延時狀態設定鍵(延時開、延時關、取消)

        K3

        風速選定鍵(慢、中、快)

        K4

        溫度設定鍵(增加+

        K5

        溫度設定鍵(減少-

        K6

        延時時間位選定鍵(XXXXXX

        K7

        延時時間設置鍵(默認為循環增加)

        K8

        發送鍵

        K1按下時,保持P05位狀態,按下第一次最后一位置0,倒數第二、三位置1按下第二次時到數第二位置0,倒數第一、三位置1,按下第三次時倒數第三位置0,倒數第一、二位置1,依次循環,代碼實現:P0=(states1[i]&(P0|0x07));

        K2按下時,保持P0倒數第1、2、3位和正數第1、2、3狀態按下第一次時倒數第一位亮表示延時開,按下第二次時倒數第五位亮表示延時關,按下第三次時倒數第3、4位皆滅表示取消延時,依次循環,代碼實現:  P0=(states2[j]&(P0|0x18));

        K3按下時,保持P05位不變,按下最高兩位置1,第三位置0,表示慢速,按下第二次時第二位置0,第一、三位置1,表示中速,按下第三次時第一位置0,第一、二位置1,依次循環,代碼實現:P0=(states3[k]&(P0|0xe0));

        LED狀態顯示模塊:

        仿真原理圖:

        詳細描述:8個按鍵的功能如下表:

        LED
        狀態指示
        D1

        正常

        D2

        除濕

        D3

        通風

        D4

        延時開(如果D4/D5兩燈全滅則取消延時)

        D5

        延時關

        D6

        D7

        D8

        LCD1602顯示模塊:

        仿真原理圖:

        詳細描述:LCD1602一共可以顯示16x2個字符,其中數據線為8位分別接AT89C51的P2端口的8個管腳,控制線為RS、RW、E分別接P3.3,P3.4,P3.5管腳,仿真電路中排阻是必要的它的功能是電阻作為有功原件串聯在電路中能消除振蕩,目的是得到更好的EMC性能。

        主要子函數包括:(詳細代碼見附錄源程序LCD部分)

        void initLCM( void);       //LCD初始化子程序

        void DisplayListChar(unsigned char X,unsigned char Y, unsigned char *DData);                    //顯示指定坐標的一串字符子函數

        void DisplayOneChar(uchar X,uchar Y,uchar DData);//顯示單個字符

        雙機串口通信功能:

        仿真原理圖:

        詳細描述:

        利用串口查詢的方式實現兩臺單片機之間通信的功能:單片機1(模擬遙控器)作為發送機其P3.0/RXD、P3.1/TXD分別接從機(模擬空調)的P3.1/TXD、P3.0/RXD引腳。發送機和接收機串口采用方式1,8位UART,波特率可變,其中T1的采用方式3(8位自填裝模式),計數初值為f4f4,因此串口的波特率為2400bits

        主要實現代碼如下:(詳細代碼見附錄源代碼部分:)

        主機發送:

        while(++counter<=8)

               {SBUF=sender[counter-1];

               while(TI==0);

               TI=0;

               while(RI==0);

               RI=0;

              

               }

        從機接收:

        counter++;

         RI=0;       //接受中斷標志清零,可以接收新的數據

         receive=SBUF; //開始接收新的數據

         ADDRR[counter-1]=receive;//把接受的數據存入字符串數組ADDRR中

         delay_LCM(100);

         delay_LCM(100);

         SBUF=ADDRR[counter-1];//由單片機2向單片機1發送數據

         while(TI==0);          //循環等待直到發送數據完畢

         TI=0;

        設計過程中遇到的問題及解決過程:

        問題1、LCD1602不能夠顯示

        最終解決方案:經查閱相關資料與書上LCD1602電路連線圖相對照發現未接排阻。仿真電路中排阻是必要的它的功能是電阻作為有功原件串聯在電路中能消除振蕩,目的是得到更好的EMC性能。經加入排阻后能夠正常顯示。

        問題2、通過串口線兩片單片機不能正常的通信

        最終解決方案:原因是在主機中由于我既用到了定時器來作為計時中斷,有用到了定時器為串口提供波提率,我誤把定時器0來為串口提供波特率,定時器1來為做計時時鐘,后查閱書籍在《單片機原理及控制技術》P161、L17中提到方式1和方式3的波特率“與定時器T1的溢出率有關。”也就是說串口通信方式1的波特率不能由定時器0來提供后經改變兩定時器的功能后串口通信正常。

        問題3、編譯程序代碼時總會出現“ERROR L107:ADDRESS SPACE OVERFLOW”.

        最終解決方案:AT89C51有三種存儲器模式:“SMALL模式,COMPACT模式,LARGE模式。不同的存儲模式對變量的默認的存儲器類型不一樣。”程序在編譯時默認為小編譯模式,此時數據的存儲容量為128B當我定義的數據變量所占據的地址空間超過128B時,編譯器就會報錯。我首先嘗試將編譯器的模式設置為CMOPACT模式,但發現編譯器雖無報錯但仿真的結果并不是我所期望的結果,最終我在SMALL模式下,將我所定義的數據變量盡量縮減,例如用10個字符“0123456789”來表示21個溫度數據,這樣的缺點是給軟件的編寫帶來了較大的復雜度,優點是可以節省內存空間,最終將所用字節縮減至97遠小于128B,編譯無錯誤,且仿真成功。

        課程設計收獲與心得:

        本次課程設計從審題、模塊的劃分、各個模塊的實現和各個模塊之間的連接均為自己獨立完成,無抄襲借鑒他人的現象發生,通過本次課程設計自己幾乎將單片機教材又細致的看了一遍尤其是中斷一章看了不下3遍 其中串口一節更是把每個字都仔細研究一番,最終完成了課程設計題目的要求。通過此次課程設計增強了我對學習單片機的信心,也激發了我對單片機設計的熱情。 成為我大學生涯中的一次難忘的經歷,我會在今后生活中更加深入學習單片機知識,爭取設計出更多自己喜歡的又實用價值的作品。

        附錄:

        軟件仿真圖:



        仿真文件和程序下載地址:http://www.thefapper.com/f/kongtiao.rar

        源代碼:

        第一部分:LCD顯示文件

         


        ******************************************************************/


        #include<reg51.h>

        #include<stdio.h>

        #define uchar unsigned char

        states1[3]={0xfe,0xfd,0xfb};

        states2[3]={0xf7,0xef,0xff};

        states3[3]={0xdf,0xbf,0x7f};

        unsigned char inittempreture[12]="tempreture:";

        unsigned char inittime[5]="time:";

        //unsigned char  time[10]="0123456789";

        unsigned char tempreture[10]="0123456789";


        sbit k1=P1^0;

        sbit k2=P1^1;

        sbit k3=P1^2;

        sbit k4=P1^3;

        sbit k5=P1^4;

        sbit k6=P1^5;

        sbit k7=P1^6;

        sbit k8=P1^7;


        #define uint unsigned int

        #define uchar  unsigned char

        uchar datasend=0;


        uchar keynum;

        uchar timenum;

        uchar n;

        uchar count;

        uchar counter=0;

        unsigned char  time[7]="000000";

        unsigned char sender[9]="00000000";


        extern void initLCM( void);               //LCD初始化子程序

        extern void DisplayListChar(unsigned char X,unsigned char Y, unsigned char *DData);                    //顯示指定坐標的一串字符子函數

        extern void DisplayOneChar(uchar X,uchar Y,uchar DData);

        extern delay_LCM(unsigned int k);

        extern void WriteCommandLCM(uchar WCLCM,uchar BusyC);

         void delay(unsigned int i)

          {unsigned int j;

           unsigned char k;

           for(j=i;j>0;j--)

               for(k=255;k>0;k--);

          }

        void delay1ms()

        {unsigned int i;

        for(i=500000;i>0;i--);

        }

        Initial_time0com()

        {

        TMOD=0X21;

        TL0=0Xb0;

        TH0=0X3c;

        IE=0x82;

        TR0=0;

         }

         Initial_sconcom()

         {

         //TOMD=0X02;

          TH1=0Xf4;

          TL1=0Xf4;

          PCON=0X00;

          TR1=1;

          SCON=0X50;

         }




        void main()

        {

        unsigned int i=0;

        unsigned int j=0;

        unsigned int k=0;

        unsigned char l=0;

        unsigned int m=0;

        unsigned int n=0;

        count=20;

        n=count; //count和n配合使用得到1S鐘定時

        keynum=0;//記錄按鍵被按了幾次

        timenum=0;//記錄現在正在修改的是時分秒6位數字鐘的哪一位

        initLCM();//lcd1602初始化

        Initial_time0com();//定時器0的初始化在這里的作用是產生時分秒的進位

        Initial_sconcom();//串口和定時器1的初始化發送數據

        /****************************************以下代碼為LCD1602一開始顯示的狀態*************************/

        delay_LCM(100);

        DisplayListChar(0,0,inittempreture);

        delay_LCM(100);

        DisplayListChar(0,1,inittime);

        delay_LCM(100);

        delay_LCM(100);

        delay_LCM(50);

        /*****************************************以上代碼為LCD1602一開始顯示的狀態*******************************************/

        while(1)   //通過大循環不斷掃描按鍵狀態

        {


        DisplayListChar(5,1,time); //顯示定時時間的初始狀態000000

                delay_LCM(100);

        /****************************如果按鍵1被按下3種狀態之間循環切換**********/

        if(k1==0)

        {

        delay(255);

           P0=(states1[i]&(P0|0x07));

        datasend=(states1[i]&(datasend|0x07));

        delay(255);

        i++;

           }

        if(i==3)

              i=0;

        /****************************如果按鍵2被按下2種狀態之間循環切換**********/

        if(k2==0)

        {

        delay(255);

        P0=(states2[j]&(P0|0x18));

        datasend=(states2[j]&(datasend|0x18));

        delay(255);

        j++;

        }

        if(j==3)

              j=0;

        /****************************如果按鍵3被按下3種狀態之間循環切換**********/

        if(k3==0)

        {

        delay(255);

           P0=(states3[k]&(P0|0xe0));

        datasend=(states3[k]&(datasend|0xe0));

        delay(255);

        k++;

           }

        if(k==3)

              k=0;

        /****************************如果按鍵4、5被按下則根據按鍵次數l計算出溫度值顯示在LCD1602上**********/

        if(k4==0)

        {if(l!=21)

        {l++;

           }

        delay_LCM(100);

        if(l<=5)

        {

        delay_LCM(1000);

        DisplayOneChar(11,0,tempreture[1]);

        delay_LCM(100);

           DisplayOneChar(12,0,tempreture[l+4]);

        }

        if((l>5)&&(l<=15))

        {

        delay_LCM(1000);

        DisplayOneChar(11,0,tempreture[2]);

        delay_LCM(100);

           DisplayOneChar(12,0,tempreture[l-6]);

        }

        if(l>15)

        {

        delay_LCM(1000);

        DisplayOneChar(11,0,tempreture[3]);

        delay_LCM(100);

           DisplayOneChar(12,0,tempreture[l-16]);

        }

        }

        if(k5==0)

        {

        if(l>1)

        {l--;

        }

        if(l<=5)

        {

        delay_LCM(1000);

        DisplayOneChar(11,0,tempreture[1]);

        delay_LCM(100);

           DisplayOneChar(12,0,tempreture[l+4]);

        }

        if((l>5)&&(l<=15))

        {

        delay_LCM(1000);

        DisplayOneChar(11,0,tempreture[2]);

        delay_LCM(100);

           DisplayOneChar(12,0,tempreture[l-6]);

        }

        if(l>15)

        {

        delay_LCM(1000);

        DisplayOneChar(11,0,tempreture[3]);

        delay_LCM(100);

           DisplayOneChar(12,0,tempreture[l-16]);

        }

        }

        /****************************如果按鍵6被按下定時0關閉,設置不同時間位置的定時時間,具體位置由按鍵次數循環切換**********/

        if(k6==0)

        { TR0=0;

         delay_LCM(100);

         if(k6==0)

         {

             timenum++;

                  delay_LCM(100);

                  delay_LCM(100);

         }

        }

        /****************************如果按鍵7被按下并且此時定時器0處于停止則每按一次按鍵定時值循環加1**********/

        if((k7==0)&&(TR0==0))

        {

        delay_LCM(100);

        if(k7==0)

        {

                delay_LCM(100);

           time[((timenum-1)%6)]++;

                if(time[((timenum-1)%6)]>'9')

                time[((timenum-1)%6)]='0';

        }

        }

        /****************************如果按鍵8被按下開定時器0發送數據并開始定時**********/

        if(k8==0)

        { TR0=1;

             sender[0]=datasend;

             sender[1]=time[0];

             sender[2]=time[1];

             sender[3]=time[2];

             sender[4]=time[3];

             sender[5]=time[4];

             sender[6]=time[5];

             sender[7]=l;


          while(++counter<=8)

          {SBUF=sender[counter-1];

        while(TI==0);

        TI=0;

        while(RI==0);

        RI=0;

        }

        counter=0;


        }

            }

        }


        void time0_int(void) interrupt 1

        {TL0=0xb0;

        TH0=0x3c;

        if((time[0]=='0')&&(time[1]=='0')&&(time[2]=='0')&&(time[3]=='0')&&(time[4]=='0')&&(time[5]=='0'))

        {TR0=0;


        delay_LCM(100); 

        }

        n--;

        if(n==0)

        {     if(time[5]=='0')

               {time[5]='9';

                 if(time[4]=='0')

                   {time[4]='5';

           if(time[3]=='0')

        {time[3]='9';

         if(time[2]=='0')

            {time[2]='5';

         if(time[1]==0)

            {TR0=0;

        // p1_0=0;

        //DisplayListChar(1,1,kaiji);

        }


         else

            time[1]--;

         }

         else

         time[2]--;}

        else

                    time[3]--;}

                 else

                    time[4]--;

        }

              else

               time[5]--;

        n=count;}

        }


           


        /*******************************************************************/

        //Name of this design:     LCD show Electric Clock

        //Author:                  張騰

        //Date:                    20014-6-02

        /*******************************************************************/


        #include <reg51.h>

        #include <intrins.h>

        #include <string.h>

        #include <absacc.h>

        #define uchar  unsigned char

        #define uint   unsigned int


        #define BUSY  0x80                               //lcd忙檢測標志

        #define DATAPORT P2                             //定義P0口為LCD通訊端口


        //sbit light=P1^3; //????????????????????????????????????????/

        //sbit LCM_RS=P2^0; //數據/命令端

        sbit LCM_RS=P3^3;

        sbit LCM_RW=P3^4; //讀/寫選擇端

        sbit LCM_EN=P3^5;         //使能信號    


        void delay_LCM(uint);             //LCD延時子程序

        void lcd_wait(void);               //LCD檢測忙子程序

        void WriteCommandLCM(uchar WCLCM,uchar BusyC);                              //寫指令到ICM子函數

        void WriteDataLCM(uchar WDLCM);                                             //寫數據到LCM子函數

        void DisplayOneChar(uchar X,uchar Y,uchar DData);                           //顯示指定坐標的一個字符子函數

        void initLCM( void);               //LCD初始化子程序

        void DisplayListChar(uchar X,uchar Y, unsigned char *DData);                    //顯示指定坐標的一串字符子函數



        /*********延時K*1ms,12.000mhz**********/


        void delay_LCM(uint k)

        {

            uint i,j;

            for(i=0;i<k;i++)

            {

                for(j=0;j<60;j++)

                {;}

            }

        }

        /**********寫指令到LCM子函數************/


        void WriteCommandLCM(uchar WCLCM,uchar BusyC)

        {

            if(BusyC)lcd_wait();   //lcd如果忙就一直檢測,直到不忙為止

        DATAPORT=WCLCM;

        LCM_RS=0;                   // 選中指令寄存器

            LCM_RW=0;               // 寫模式

            LCM_EN=1; //下跳沿時執行命令

        _nop_();

        _nop_();

        _nop_();

            LCM_EN=0;

        }


        /**********寫數據到LCM子函數************/


        void WriteDataLCM(uchar WDLCM)

        {

            lcd_wait( );                //檢測忙信號

        DATAPORT=WDLCM;

             LCM_RS=1;                   // 選中數據寄存器

            LCM_RW=0;              // 寫模式

            LCM_EN=1;

            _nop_();

        _nop_();

        _nop_();

            LCM_EN=0;

        }


        /***********lcm內部等待函數*************/



        void lcd_wait(void)

        {

            DATAPORT=0xff;

        LCM_EN=1;

         LCM_RS=0;  

            LCM_RW=1;  

            _nop_();

            while(DATAPORT&BUSY)  //如果忙的話就一直檢測

        {  LCM_EN=0;

          _nop_();

          _nop_();

          LCM_EN=1;

          _nop_();

          _nop_();

          }

            LCM_EN=0;

        }



        /**********LCM初始化子函數***********/


        void initLCM( )

        {

        DATAPORT=0;

        delay_LCM(15);

        WriteCommandLCM(0x38,0);    //三次顯示模式設置,不檢測忙信號

            delay_LCM(5);

            WriteCommandLCM(0x38,0);

            delay_LCM(5);

            WriteCommandLCM(0x38,0);

            delay_LCM(5);


            WriteCommandLCM(0x38,1);    //8bit數據傳送,2行顯示,5*7字型,檢測忙信號

            WriteCommandLCM(0x08,1);    //關閉顯示,檢測忙信號

            WriteCommandLCM(0x01,1);    //清屏,檢測忙信號 光標復位到00H

            WriteCommandLCM(0x06,1);    //顯示光標右移設置,檢測忙信號

            WriteCommandLCM(0x0c,1);    //顯示屏打開,光標不顯示,不閃爍,檢測忙信號

        }


        /****************顯示指定坐標的一個字符子函數*************/


        void DisplayOneChar(uchar X,uchar Y,uchar DData)

        {

        uchar mx,my;

        my=Y&1;

        mx=X&0xf;

            if(my>0)mx+=0x40;               //若y為1(顯示第二行),地址碼+0X40

            mx+=0x80;                    //指令碼為地址碼+0X80

            WriteCommandLCM(mx,0);

            WriteDataLCM(DData);

        }


        /***********顯示指定坐標的一串字符子函數***********/


        void DisplayListChar(uchar X,uchar Y, unsigned char *DData)

        {

            uchar i=0,n;

            Y&=0x01;

            X&=0x0f;

        n=strlen(DData);

            while(i<n)

            {

                DisplayOneChar(X,Y,DData[i]);

                i++;

                X++;

            }

        }

         

        關閉窗口

        相關文章

        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮