久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

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

CH451驅動的數碼管+按鍵+電子表+溫度程序

作者:佚名   來源:本站原創   點擊數:  更新時間:2011年09月30日   【字體:
//這是一個CH451芯片驅動的數碼管+按鍵+ds1302電子表+ds18b20溫度的c語言程序
//已經在51單片機開發板上測試通過,帶有溫度報警,有詳細的注釋.
//程序的完整版本下載地址:http://www.zg4o1577.cn/f/ch451.rar
//本程序版權所無您可以隨意修改.
#include <reg51.h>
#include <math.h>
#include <intrins.h>
/*************************************************************
  _crol_ 字符循環左移 
  _cror_ 字符循環右移
  _irol_ 整數循環左移 
  _iror_ 整數循環右移 
  _lrol_ 長整數循環左移 
  _lror_ 長整數循環右移
  _nop_ 空操作8051 NOP 指令
*************************************************************/
#define uchar unsigned char
#define uint unsigned int
/******************************DS1302宏定義******************/
#define WRITE_SECOND       0x80 
#define WRITE_MINUTE       0x82 
#define WRITE_HOUR         0x84 
#define READ_SECOND        0x81 
#define READ_MINUTE        0x83 
#define READ_HOUR          0x85 
#define WRITE_PROTECT      0x8E 
/***********************CH451宏定義************************/
#define CH451_RESET     0x0201             //復位
#define CH451_LEFTMOV   0x0300             //設置移動方式-作移
#define CH451_LEFTCYC   0x0301             //設置移動方式-左循
#define CH451_RIGHTMOV  0x0302             //設置移動方式-右移
#define CH451_RIGHTCYC  0x0303             //設置移動方式-右循 
#define CH451_SYSOFF    0x0400             //關顯示、鍵盤、看門狗
#define CH451_SYSON1    0x0401             //開顯示
#define CH451_SYSON2    0x0403             //開顯示、鍵盤
#define CH451_SYSON3    0x0407             //開顯示、鍵盤、看門狗功能
#define CH451_DSP       0x0500             //設置默認顯示方式
#define CH451_BCD       0x0580             //設置BCD譯碼方式
#define CH451_TWINKLE   0x0600             //設置閃爍控制——正常顯示
#define CH451_DIG0      0x0800             //數碼管位0顯示
#define CH451_DIG1      0x0900             //數碼管位1顯示 
#define CH451_DIG2      0x0a00             //數碼管位2顯示
#define CH451_DIG3      0x0b00             //數碼管位3顯示
#define CH451_DIG4      0x0c00             //數碼管位4顯示
#define CH451_DIG5      0x0d00             //數碼管位5顯示 
#define CH451_DIG6      0x0e00             //數碼管位6顯示 
#define CH451_DIG7      0x0f00             //數碼管位7顯示
/*************************************************************/
sbit ACC_7=ACC^7;     //位尋址寄存器定義 
sbit SCLK=P2^1;                 //ds1302管腳定義            
sbit IO=P2^0;                                
sbit RST=P1^7;                    

sbit DQ=P1^6;   //ds18b20定義
sbit P26=P2^6; 

sbit ch451_dclk=P3^4;                    //串行數據時鐘上升延激活
sbit ch451_din=P3^3;                     // 串行數據輸出,接CH451的數據輸人
sbit ch451_load=P2^3;                    //串行命令加載,上升延激活
sbit ch451_dout=P2^2;               //鍵值數據輸入,接ch451數據輸出  
      
int temp;
int tt;          //真實溫度變量  
uchar  ch451_key=0;                     // 存放鍵盤中斷中讀取的鍵值
uint display[8]={0x0a00,0x0900,0x0b00,0x0800,
    0x0c00,0x0d00,0x0e00,0x0f00};
uchar BCD[10]={0xbe,0x24,0xea,0xe6,    //0,1,2,3,
               0x74,0xd6,0xde,0xa4,   //4,5,6,7,
               0xfe,0xf6     //8,9
              };    
/*************精確延時函數*****************/
void delay(uint i)  
{
while(--i);
}


/************************蜂鳴器程序********/
 void speaker(void)
 {
 uchar i,j;
 for(j=0;j<250;j++)
 for(i=0;i<250;i++)
  {
 P26=~P26;
 for(i=0;i<250;i++);
 }
   P26=1;      //防止結束時候是低電平
 }
/**********************4*******************/
/*****************DS18B20******************/

void Init_Ds18b20(void)     //DS18B20初始化

{
DQ=0;                    //單片機拉低總線
delay(500);              //精確延時,維持至少480us
DQ=1;                    //釋放總線,即拉高了總線
delay(200);            //此處延時有足夠,確保能讓DS18B20發出存在脈沖。
}

/*****************************************************************************************/
uchar Read_One_Byte()       //讀取一個字節的數據
                            //讀數據時,數據以字節的最低有效位先從總線移出
{
uchar i=0;
uchar dat=0;
for(i=8;i>0;i--)
{
   DQ=0;                  //將總線拉低,要在1us之后釋放總線
                           //單片機要在此下降沿后的15us內讀數據才會有效。
   _nop_();    
   _nop_();              //至少維持了1us,表示讀時序開始
   dat>>=1;               //讓從總線上讀到的位數據,依次從高位移動到低位。
   DQ=1;                  //釋放總線,此后DS18B20會控制總線,把數據傳輸到總線上
delay(1);                 //延時7us,此處參照推薦的讀時序圖,盡量把控制器采樣時間放到讀時序后的15us內的最后部分
   if(DQ)                   //控制器進行采樣
   {
    dat|=0x80;            //若總線為1,即DQ為1,那就把dat的最高位置1;若為0,則不進行處理,保持為0
   }        
delay(60);      //此延時不能少,確保讀時序的長度60us--很重要
}
return (dat);
}
/********************************************************/
void Write_One_Byte(uchar dat)
{
uchar i=0;
for(i=8;i>0;i--)
{
   DQ=0;                        //拉低總線
    _nop_();   
 nop_();                   //至少維持了1us,表示寫時序(包括寫0時序或寫1時序)開始
   DQ=dat&0x01;               //從字節的最低位開始傳輸
                              //指令dat的最低位賦予給總線,必須在拉低總線后的15us內,
                              //因為15us后DS18B20會對總線采樣。

     delay(60);              //必須讓寫時序持續至少60us ----很重要
   DQ=1;                        //寫完后,必須釋放總線,
  /* _nop_(); */  
   dat>>=1;
                                 //因為15us后DS18B20會對總線采樣。
delay(1);
  
}
}

/*************************************************************************/
uint Get_Tmp()                   //獲取溫度
{
float t;
uchar a=11,b=0;
Init_Ds18b20();                //初始化
Write_One_Byte(0xcc);          //忽略ROM指令
Write_One_Byte(0x44);          //溫度轉換指令
Init_Ds18b20();                 //初始化
Write_One_Byte(0xcc);          //忽略ROM指令
Write_One_Byte(0xbe);          //讀讀RAM的存儲器指令
a=Read_One_Byte();           //讀取到的第一個字節為溫度LSB
b=Read_One_Byte();           //讀取到的第二個字節為溫度MSB
temp=b;                      //先把高八位有效數據賦于temp
temp<<=8;                    //把以上8位數據從temp低八位移到高八位
temp=temp|a;                 //兩字節合成一個整型變量
t=temp*0.0625;              //得到真實十進制溫度值
                                //因為DS18B20可以精確到0.0625度
                                //所以讀回數據的最低位代表的是0.0625度
temp=t*10+0.5;                  //此處放大十倍
                                //這樣做的目的將小數點后第一位也轉換為可顯示數字
                                //同時進行一個四舍五入操作。
return(temp);
}
/************************************************************************
      以上實現溫度傳感器的讀取數據
*************************************************************************/
/******************************DS1302*************************************/

 

//地址、數據發送子程序 
void Write1302(uchar addr,uchar dat ) 
{ 
         uchar i,t; 
         RST=0;                                    //RST 引腳為低,數據傳送終止  
         SCLK=0;                              //清零時鐘總線 
         RST=1;                                //RST 引腳為高,邏輯控制有效
         //發送地址 
         for(i=8;i>0;i--) //循環8次移位 
         { 
                  SCLK=0; 
                  t=addr; 
                  IO=(bit)(t&0x01);                   //每次傳輸低字節
                  addr>>=1;                        //右移一位 
                  SCLK=1; 
         } 
    //發送數據 
         for(i=8;i>0;i--) 
         { 
                  SCLK=0; 
                  t=dat; 
                  IO=(bit)(t&0x01);
                  dat>>=1; 
                  SCLK=1; 
         } 
         RST=0; 
} 

//數據讀取子程序 
uchar Read1302(uchar addr ) 
{ 
         uchar i,t,dat1,dat2; 
         RST=0; 
         SCLK=0; 
         RST=1; 
         //發送地址 
         for(i=8;i>0;i--)                            //循環8次移位 
         { 
                  SCLK=0; 
                  t=addr; 
                 IO=(bit)(t&0x01);                 //每次傳輸低字節
                  addr>>=1;                           //右移一位
                  SCLK=1; 
         } 
         //讀取數據 
         for(i=8;i>0;i--) 
         { 
                  ACC_7=IO; 
                  SCLK=1; 
                  ACC>>=1;           //右移   
                  SCLK=0; 
         } 
         RST=0; 
         dat1=ACC; 
         dat2=dat1/16;                                       //數據進制轉換 
         dat1=dat1%16;                                     //十六進制轉十進制
         dat1=dat1+dat2*10; 
         return (dat1); 
} 

//初始化DS1302 
void Initial(void) 
{    

         Write1302 (WRITE_PROTECT,0x00);             //禁止寫保護 
         Write1302 (WRITE_SECOND,0x00);              //秒位初始化,開始計時 
         Write1302 (WRITE_MINUTE,0x03);             //分鐘初始化
         Write1302 (WRITE_HOUR,0x23);            // 小時初始化——24小時模式
     //Write1302 (WRITE_PROTECT,0x80);           // 允許寫保護 
             // 調試證明必須禁止寫保護
             //不然修改不了初始值
} 
/*********************************CH451**********************/
 //********************************************
//設置定時器中斷__定時掃描鍵盤
void ch451_init()
{
  ch451_din=0;              //先低后高,選擇4線輸入
  ch451_din=1;
  TMOD=0x10;    //設置定時器T1工作在16位計時狀態
  EA=1;        //開中斷總開關
  ET1=1;                   //允許中斷
  TR1=1;                   //開中斷
  PT1=0;                   //設置低優先級
  TL1=1;     //裝載計數初值
  TH1=0;     //此計數初值用來調試
}
//*****************************************************
//定義一無符號整型變量存儲12字節的命令字。
 void ch451_write(uint command)
{
 uchar i;
  TR1=0;                       //禁止T1中斷
  ch451_load=0;                                  //命令開始       
  for(i=0;i<12;i++){                             //送入12位數據,低位在前
    ch451_din=command&1; 
    ch451_dclk=0;
    command>>=1;
    ch451_dclk=1;                               //上升沿有效
  }
  ch451_load=1;                                 //上升沿加載數據
  TR1=1;          // 開啟T1中斷
}

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

//中斷子程序  使用定時器中斷T1,寄存器組1
void ch451_inter() interrupt 3 using 1
{      
  
  uchar i;           //定義循環變量
  
  uchar command,keycode;       //定義控制字寄存器,和中間變量定時器
 
  command=0x07;          //讀取鍵值命令的高4位0111B
  ch451_load=0;          //命令開始
  for(i=0;i<4;i++){
    ch451_din=command&1;      //低位在前,高位在后
    ch451_dclk=0;
    command>>=1;         //右移一位
    ch451_dclk=1;         //產生時鐘上升沿鎖通知CH451輸入位數據
 }
  ch451_load=1;         //產生加載上升沿通知CH451處理命令數據
  keycode=0;          //清除keycode
  for(i=0;i<7;i++){
    keycode<<=1;         //數據作移一位,高位在前,低位在后
    keycode|=ch451_dout;       //從高到低讀入451的數據
    ch451_dclk=0;         //產生時鐘下升沿通知CH451輸出下一位
    ch451_dclk=1;
 }
  ch451_key=keycode;       //保存上次的鍵值

TL1=1;       //重新裝載計數初值
TH1=0;       //此計數初值用來調試  
}

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


void main()
{
int HIGH=270;      //定義溫度上限變量
uchar A0,A1,A2,A3;    //記錄溫度各位數的變量
uchar b,c;      //定義存放DS1302中數據的變量        
P26=1;        //關閉蜂鳴器
Initial();     //初始化DS1302     
        //初始化以后此語句必須關掉 防止每次上電初始化DS1302 
        //關掉此語句編譯時會為此產生一個警告
            /*改動*/
ch451_init();        // 設置定時器中斷__定時掃描鍵盤
ch451_write(CH451_RESET);     //CH451復位
ch451_write(CH451_SYSON2);     //開顯示、鍵盤
ch451_write(CH451_DSP);      //設置BCD不譯碼方式     由于板畫錯了  此設置很重要
ch451_write(CH451_TWINKLE);      //設置閃爍控制——正常顯示
             

while(1)
{
tt=Get_Tmp();     //讀出當前溫度
A3=tt/1000;      //千位
A2=(tt%1000)/100;       //百位
A1=(tt%100)/10;       //十位——這么處理的目的是顯示小數點,因為A1實際是溫度的個位
A0=tt%10;         //個位
ch451_write(display[0]+BCD[A0]);    //顯示溫度小數位
ch451_write(display[1]+BCD[A1]+1);    //顯示溫度個位  此處加一為了加入小數點
ch451_write(display[2]+BCD[A2]);    //顯示溫度十位
ch451_write(display[3]+BCD[A3]);    //顯示溫度百位

 if(Get_Tmp()>HIGH)         //如果溫度大于上限度    
  {
 delay(10);         //延時是為了防止脈沖不穩定干擾
 if(Get_Tmp()>HIGH)          //可以消除蜂鳴器非正常響
            /*合理的改動*/
 {
 Write1302(0xc0,Read1302(READ_MINUTE)/10*16+Read1302(READ_MINUTE)%10);  //寫入當前記錄的數據所對應的時間——分   
 Write1302(0xc2,Read1302(READ_HOUR)/10*16+Read1302(READ_HOUR)%10);  //寫入當前記錄的數據所對應的時間——小時
                  /**寫入的應該是16進制而不是十進制**/
 speaker();         //如果溫度大于 HIGH度,蜂鳴器報警
  }
  }   
 if(Get_Tmp()<0)         //如果溫度小于0度
 {
 delay(10);         //延時是為了防止脈沖不穩定干擾
 if(Get_Tmp()<0)      //可以消除溫度非正常顯示為負
            /*合理的改動*/
 {
 tt=abs(tt);
 ch451_write(display[0]+BCD[A0]);    //顯示溫度小數位
 ch451_write(display[1]+BCD[A1]+1);    //顯示溫度個位  此處加一為了加入小數點
 ch451_write(display[2]+BCD[A2]);    //顯示溫度十位
 ch451_write(display[3]+BCD[A2]);    //顯示溫度百位
 ch451_write(display[4]+0x40);      //顯示負號
 }  
 }         
//對各個按鍵進行定義
  switch(ch451_key)
  {
  case 0x40: {
              
     b=Read1302(0xc1);     //讀出數據所對應的時間——分  
     c=Read1302(0xc3);     //讀出數據所對應的時間——小時   */
     ch451_write(display[4]+BCD[b%10]);     //顯示分鐘個位
     ch451_write(display[5]+BCD[b/10]);    //顯示分鐘十位
     ch451_write(display[6]+BCD[c%10]);     //顯示小時個位
     ch451_write(display[7]+BCD[c/10]);     //顯示小時十位
    }     break;       //按下第1個鍵時調出DS1302中產生溫度報警的時間
  case 0x43: { ch451_write(display[4]+0);     //關顯示分鐘個位
     ch451_write(display[5]+0);    //關顯示分鐘十位
     ch451_write(display[6]+0);     //關顯示小時個位
     ch451_write(display[7]+0);     //關顯示小時十位;
    }     break;          //按下第2個鍵關時間顯示
  case 0x41: speaker(); break;       //按下第3個鍵時蜂鳴器響
  case 0x42: {
       A3=HIGH/1000;      //千位
     A2=(HIGH%1000)/100;       //百位
     A1=(HIGH%100)/10;       //十位——這么處理的目的是顯示小數點,因為A1實際是溫度的個位
     A0=HIGH%10;         //個位
     ch451_write(display[4]+BCD[A0]);    //顯示溫度小數位
     ch451_write(display[5]+BCD[A1]+1);    //顯示溫度個位  此處加一為了加入小數點
     ch451_write(display[6]+BCD[A2]);    //顯示溫度十位
     ch451_write(display[7]+BCD[A3]);    //顯示溫度十位    
    }       break;    //按下第4個鍵顯示上限溫度 
  case 0x48: {
     delay(65000);     //使按鍵增大溫度上限值得過程變慢
       HIGH=HIGH+1;
       A3=HIGH/1000;      //千位
     A2=(HIGH%1000)/100;       //百位
     A1=(HIGH%100)/10;       //十位——這么處理的目的是顯示小數點,因為A1實際是溫度的個位
     A0=HIGH%10;         //個位
     ch451_write(display[4]+BCD[A0]);    //顯示溫度小數位
     ch451_write(display[5]+BCD[A1]+1);    //顯示溫度個位  此處加一為了加入小數點
     ch451_write(display[6]+BCD[A2]);    //顯示溫度十位
     ch451_write(display[7]+BCD[A3]);    //顯示溫度百位        
    }   ; break;      //按下第5個鍵增加溫度上限值
  case 0x4b: {
     delay(65000);      //使按鍵減小溫度上限值得過程變慢
       HIGH=HIGH-1;
       A3=HIGH/1000;      //千位
     A2=(HIGH%1000)/100;        //百位
     A1=(HIGH%100)/10;       //十位——這么處理的目的是顯示小數點,因為A1實際是溫度的個位
     A0=HIGH%10;          //個位
     ch451_write(display[4]+BCD[A0]);    //顯示溫度小數位
     ch451_write(display[5]+BCD[A1]+1);    //顯示溫度個位  此處加一為了加入小數點
     ch451_write(display[6]+BCD[A2]);    //顯示溫度十位
     ch451_write(display[7]+BCD[A3]);    //顯示溫度十位     
    
    }   ; break;      //按下第6個鍵減小溫度上限值
  case 0x49: { 
      while(ch451_key!=0x43)
        {
     ch451_write(display[0]+BCD[Read1302(READ_SECOND)%10]);  //顯示分鐘的個位
     ch451_write(display[1]+BCD[Read1302(READ_SECOND)/10]);  //顯示秒的十位
     ch451_write(display[2]+0x40);        //顯示負號
     ch451_write(display[3]+BCD[Read1302(READ_MINUTE)%10]);  //顯示分鐘的個位
     ch451_write(display[4]+BCD[Read1302(READ_MINUTE)/10]);     //顯示分鐘的十位
     ch451_write(display[5]+0x40);           //顯示負號  
     ch451_write(display[6]+BCD[Read1302(READ_HOUR)%10]);     //顯示小時的個位
     ch451_write(display[7]+BCD[Read1302(READ_HOUR)/10]);     //顯示分鐘的十位 
     }       
    }   ; break;      //按下第7個鍵動態顯示當前的時間——電子表
  case 0x4a:    ; break;      //按下第8個鍵無效
  }

/****************************************************************/
              
}
}
  
關閉窗口

相關文章

主站蜘蛛池模板: 中文一区| 99精品网 | 国产亚洲精品久久久优势 | 国产一区二区精品 | 一区二区精品视频 | 久久久久久亚洲精品 | 国产做a爱免费视频 | 亚洲a视频| 国产精品成人久久久久a级 久久蜜桃av一区二区天堂 | 亚洲不卡在线观看 | 久久精品国产亚洲 | 欧美性猛交一区二区三区精品 | 中文字幕视频一区二区 | 免费a在线 | 午夜小视频在线播放 | av国产精品毛片一区二区小说 | 欧洲精品视频一区 | 国产国拍亚洲精品av | 人人擦人人 | 欧美大片久久久 | 日日噜噜噜夜夜爽爽狠狠视频97 | 国产成人亚洲精品 | 亚洲一区二区三区久久久 | 日韩在线大片 | 日韩成人免费视频 | 在线一区观看 | 亚洲成人免费网址 | 毛片免费看 | 日韩免费在线 | 国产黄色小视频 | 在线日韩欧美 | 日韩视频在线免费观看 | 日韩在线成人 | 日韩三级在线观看 | 视频第一区 | 国产欧美一区二区在线观看 | 99精品久久| 久久综合一区二区三区 | av免费网站在线观看 | 亚洲不卡| 国产精品成av人在线视午夜片 |