久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费
標題:
單片機數碼管動態掃描程序DS12C887紅外遙控ds18b20
[打印本頁]
作者:
daniu
時間:
2014-12-26 21:21
標題:
單片機數碼管動態掃描程序DS12C887紅外遙控ds18b20
///////////////////////////////////////////////////////////////////////////
/////////DS12C887+8位數碼管定時器中斷動態掃描遙控時鐘單片機程序模塊////////
///////////////////////////////////////////////////////////////////////////
[功能] 0: 8位數碼管定時器中斷動態掃描顯示
1:通過單片機解碼紅外遙控編碼并按上圖方式顯示出來
2:可通過遙控器調整時間,日期以及鬧鐘
3:時鐘芯片采用DS12C887+,內部集成電池與晶體,不怕掉電丟時間信息
4:在調整時間過程中會有動態效果(正在調試中!!!以經搞好了)
5:在下一版本中會增計算器功能,也是用遙控器操作 值得大家期待!
6: ds18b20溫度顯示(正在弄這個ds18b20)
7:數碼管掃描數據在P0口通過鎖存器(74HC573)輸出,ds12c887的雙向數據則直接接P0口
//以下是C源文件==============================================================================
#include <reg51.h>//80C51頭文件
#define uint unsigned int//16bit無符整型0~465536
#define ulint unsigned long int//32bit無符長整0~4294967295
#define uchar unsigned char//8bit宏定義無符字符型0-256
#define c(x) (x*120000/120000)// (x*216000/120000) //定義時鐘頻率便于紅外遙控解碼
//單片機硬件設置
sbit duan = P2^0;//數碼管段選定義
sbit wei = P2^1;//數碼管位選定義
sbit Ir_Pin=P3^3;//紅外接收端口
sbit beep = P2^7;//蜂鳴器
//時鐘芯片ds12c887控制引腳與單片機連接
sbit dscs = P2^6;//時鐘片選
sbit dsas = P2^5;//地址選取通
sbit dsrw = P2^4;//讀寫輸入
sbit dsds = P2^3;//數據選通或輸入
sbit dsirq= P2^2;//中斷請求輸出
sbit DQ =P2^2;//定義溫度傳感器(18b20)通信端口
//字符碼表
uchar code Led_Tab[]={//共陽數碼管字符碼
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,//0---f,ff全滅,
0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0xfe,0xbf,0xf7,0xc6,0x9c};//上,中,下3短橫線
uchar code Led_Sel[]={//位碼
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
//定義各個變量
uchar shan_xia=0,zuo_you=8,Ir_Buf[4],ds_temp=0,i;//上下變量,左右變量,遙控數字,紅外結果
bit ok=0,power=0,mute,ds=0,i_k=0;//ds為0時才準讀時鐘芯片,減少頻繁讀時鐘, i_k為5秒延時開關
uint ms;//屏閃時基變量,溫度傳感變量
//以下是動態掃描變量
uchar Led_Buf[8],Led_Buf_temp[8],Led_Index;//顯示緩沖區,調時閃動緩沖區,位碼索引
//聲明子函數
void init();//初始化
void write_ds(uchar add,uchar date);//時鐘芯片寫函數
uchar read_ds(uchar add);//時鐘芯片讀函數
void delay(uint z);//延時
void hyyk();//紅外遙控
uint Ir_Get_Low();//低電平時間采集
uint Ir_Get_High();//高電平時間采集
//遙控調時,數值放入顯示緩沖區同步顯示,預寫時鐘
//經數據采集函數(time_set())根據各項格式顯示特征識別后
//按mute鍵寫時鐘芯片相應地址達到調整時鐘信息的目的
void ykm_set();
void time_set();//時間調整數據采集分析寫調時緩沖區函數
void ykm_out();//遙控碼顯示
void led_out(uchar add_1,uchar add_2,uchar add_3,uchar add_4);//送出地址,讀出信息,更新顯示緩沖區
void led_flash(uchar k,uchar z);//調時閃爍 K為閃動開關 Z為閃動內容
//溫度顯示子函數聲明
void delay_18b20(uint i);//延時
Init_DS18B20(void);//初始化函數
WriteOneChar(uchar dat);//寫一個字節
ReadOneChar(void);//讀一個字節
ReadTemperature(void);//讀取溫度
void out_18b20();//顯示
//主程序==================================================================================
void main()//程序入口
{
init();//初始化
while(1)//循環等待中斷
{
hyyk();//遙控
if ((Ir_Buf[0]==0x02)&&(Ir_Buf[2]==0x14))//POWER鍵值翻轉并響鈴
{
ok=0;zuo_you=8;shan_xia=0;//有遙控power時復位ok與上下,左右值,取消閃屏顯示時間
power=(!power);
if(power==0)
{
delay(10);
beep=0;
delay(20);
beep=1;
}
Ir_Buf[2]=0xff;
}
if (power==1){uchar i;mute=1; for(i=0;i<8;i++) Led_Buf_temp[i]=16;}//在power標志為1時關屏關鈴
if(power==0)//power標志為0時根據shan_xia鍵值顯示內容
{
ykm_set();//遙控調時,調整好后按mute鍵寫時鐘
led_flash(ok,shan_xia);
if(ok==0){ds=0;i_k=0;ds_temp=0;}
if(ds==0)
{
if(shan_xia==0)led_out(4,2,0,19);//時間
else if(shan_xia==1)led_out(9,8,7,17);//日期
else if(shan_xia==2)led_out(5,3,1,18);//鬧鐘
else if(shan_xia==3)led_out(6,6,6,18);//星期
else if(shan_xia==4)out_18b20();//溫度
else ykm_out();//遙控碼
}
ds=1;//關時鐘芯片讀與顯存刷新,在中斷掃描時會打開
//只有在需要顯示具體內容時才會訪問時鐘芯片對應的具體地址并更新顯示緩沖區
//ok鍵值翻轉
if ((Ir_Buf[0]==0x02)&&(Ir_Buf[2]==0x15))
{
if((ok==1)&&(zuo_you<8)){zuo_you=8;i_k=1;i=1;}//如果是位閃狀態按ok鍵就進入全閃狀態
else {ok=(!ok);zuo_you=8;}//否則閃<==>不閃 狀態翻轉一次
//if(ok==0){i_k=0;ds_temp=0;}//不閃時可以刷新數據
Ir_Buf[2]=0xff;
}
//MUTE鍵值翻轉并響鈴
if ((Ir_Buf[0]==0x02)&&(Ir_Buf[2]==0x0c))
{
if(((ok==1)&&(zuo_you>7))&&(ds_temp>0))time_set();//如果從位閃變為全閃并且8秒寫時鐘窗口打開則寫時鐘
else mute=(!mute);//否則此鍵為靜音轉換功能
if(mute==0)
{
delay(10);
beep=0;
delay(20);
beep=1;
}
Ir_Buf[2]=0xff;
}
//按遙控器左鍵加一
if ((Ir_Buf[0]==0x02)&&(Ir_Buf[2]==0x11))
{
if(ok==0)mute=1;//如果沒有閃屏按此鍵關閉聲音
if(ok==1)
{
if(++zuo_you>7) zuo_you=0;//左移,超出苑圍轉到最右邊
while(Led_Buf[zuo_you]>9){if((++zuo_you)>7) zuo_you=0;}//正在如果要閃動的位不是十則一直數還
Ir_Buf[2]=0xff;
}
}
//按遙控器右鍵減一
if ((Ir_Buf[0]==0x02)&&(Ir_Buf[2]==0x10))
{
if(ok==0)mute=0;//如果沒有閃屏按此鍵打開聲音
if(ok==1)
{
if((--zuo_you)==255) zuo_you=7;//右移,超出苑圍轉到最左邊
while(Led_Buf[zuo_you]>9){if((--zuo_you)==255) zuo_you=7;}//正在閃動的位不是十進制數則一直移動開遙控
Ir_Buf[2]=0xff;
}
}
//按遙控器上鍵加一
if ((Ir_Buf[0]==0x02)&&(Ir_Buf[2]==0x12))
{
if((ok==1)&&(zuo_you<8))
{
Led_Buf[zuo_you]++;//位閃狀態有上鍵按下對應位加一
if(Led_Buf[zuo_you]>9)Led_Buf[zuo_you]=0;//超出為0
}
else
{
zuo_you=8;//改變顯示內容時位閃變全屏閃
if(++shan_xia>5) shan_xia=0;//超出為0
}
Ir_Buf[2]=0xff;
}
//按遙控器下鍵減一
if ((Ir_Buf[0]==0x02)&&(Ir_Buf[2]==0x13))
{
if((ok==1)&&(zuo_you<8))
{
Led_Buf[zuo_you]--;//位閃狀態有上鍵按下對應位減一
if(Led_Buf[zuo_you]==255)Led_Buf[zuo_you]=9;//超出則為9
}
else
{
zuo_you=8;//改變顯示內容時位閃變全屏閃
if((--shan_xia)==255) shan_xia=5;//自減,超出則為4
}
Ir_Buf[2]=0xff;
}
}
}
}
//數碼管掃描===============================================================
timer0() interrupt 1 using 1//定時中斷發生,運行中斷函數
{
ms++;//屏閃時基
if(ms>=500) ms=0;
if(i_k==1) //不閃屏時允許刷新讀寫信息
{
if(ms==0){if((++i)>8)i=0;}//延時8秒給mute鍵的寫時鐘芯片時間窗口,
ds_temp=i;
}
if(ds_temp==0)i_k=0;
if(((ok==1)&&(zuo_you<8))||(ds_temp>0))ds=1;//在全屏閃5秒內和位閃調時時不允許刷新顯存
else ds=0;//ds為何0時才允許刷新顯存
TL0=0x25;//12M 2ms(測試這個晶振誤差后的初值)
TH0=0xf8;
//以下9行消隱
dscs=1;//關掉時鐘片選讓數據接收口(74hc573數碼管的位碼和段碼鎖存器)得到純凈的數據信號
duan=0; // 關閉段選
wei=0; // 關閉位選
P0=0x00; // 消陷碼
wei=1; // 打開位選
wei=0; // 關閉位選,鎖存消隱碼
P0=0xff; // 消隱碼
duan=1; // 打開段選
duan=0; // 關閉段選,鎖存消隱碼
//數字顯示 在鎖存器的鎖存端出現下降沿時鎖存數據
P0=Led_Tab[Led_Buf_temp[Led_Index]];// 數模段碼送P0口
duan=1;// 打開段選
duan=0;// 關閉段選,鎖存段碼
P0=Led_Sel[Led_Index];// 位碼數據送P0口
wei=1;// 打開位選
wei=0;// 關閉位選,鎖存位碼
if(++Led_Index>7) Led_Index=0;
}
//初始化=============================================================================
void init()
{
//以下9行消隱 在開機瞬間消除屏閃
dscs=1;//關掉時鐘片選讓數據接收口(74hc573為數碼管的位碼和段碼鎖存器)得到純靜凈的數據信號
duan=0;// 關閉段選
wei=0;// 關閉位選
P0=0xff;// 消隱碼
duan=1;// 打開段選
duan=0;// 關閉段選,鎖存消隱碼
P0=0x00;// 消陷碼
wei=1;// 打開位選
wei=0;// 關閉位選,鎖存消隱碼
//定時器設置
TMOD=0x11;
TL0=0xc5;//重裝初值
TH0=0xf1;//數碼管的刷新頻率2ms
EA=1;//開定時總中斷
ET0=1;//開定時器0中斷 用于遙控高低電平時間采集
ET1=1;//開定時器1中斷
TR0=1;//啟動定時器1 用于數碼管定時中斷掃描
//以下是初始化時鐘芯片的控制寄存器A和B
write_ds(0x0A,47); //寫時鐘芯片DS12C887+A寄存器,打開振蕩器,啟動記時 輸出2HZ方波
write_ds(0x0B,126); //寫時鐘芯片B
}
//寫時鐘芯片DS12C887+時序========(請參考DS12C887芯片手冊)
void write_ds(uchar add,uchar date)
{dscs=0;dsas=0;dsas=1;dsrw=1;dsds=1;P0=add;dsas=0;dsrw=0;P0=date;dsrw=1;dsas=1;dscs=1;}
//讀時鐘芯片DS12C887+時序========(請參考DS12C887芯片手冊)
uchar read_ds(uchar add)
{uchar ds_date;dscs=0;dsas=0;dsas=1;dsrw=1;dsds=1;P0=add;dsas=0;
dsds=0;P0=0xff;ds_date=P0;dsds=1;dsas=1;dscs=1;return ds_date;}
//根據具體內容格式化輸出函數
void led_out(uchar add_1,uchar add_2,uchar add_3,uchar add_4)
{
uchar a,b,c,d=add_4,i;
for(i=0;i<4;i++)
{
if(i==0) a=read_ds(add_1);
if(i==1) b=read_ds(add_2);
if(i==2) c=read_ds(add_3);
if(i==3) d=read_ds(add_4);
}
if(add_1==4)d=18;//時鐘間隔位
if(add_1==5)d=16;//鬧鐘間隔位
if(add_1==4||add_1==5)//按不同的內容用不同的格式輸出(參數特征決定輸出內容)
{
Led_Buf[7]=a/10;//分離小時位數據
Led_Buf[6]=a%10;
Led_Buf[4]=b/10;//分離分鐘位數據
Led_Buf[3]=b%10;
Led_Buf[1]=c/10;//分離秒鐘位數據
Led_Buf[0]=c%10;
Led_Buf[5]=d; //間隔位
Led_Buf[2]=d;
}
else if(add_1==9)
{
Led_Buf[7]=2; //分離小時位數據
Led_Buf[6]=0;
Led_Buf[5]=a/10;
Led_Buf[4]=a%10;//分離分鐘位數據
Led_Buf[3]=b/10;
Led_Buf[2]=b%10;
Led_Buf[1]=c/10;//分離秒鐘位數據
Led_Buf[0]=c%10;
}
else for(i=0;i<8;i++) Led_Buf[i]=a;
}
//遙控碼顯示========================================================================
void ykm_out()
{
uchar y;//由于使用過的鍵會對用戶碼全置1操作,所以在此根據用戶反碼取反操作還原用戶碼
if(Ir_Buf[0]==0x02)y=(~Ir_Buf[3]);
else y=Ir_Buf[2];
Led_Buf[0]=Ir_Buf[3]&0xf;//結果裝入顯示緩沖區
Led_Buf[1]=(Ir_Buf[3]/16)&0xf;//數據反碼
Led_Buf[2]=y&0xf;
Led_Buf[3]=(y/16)&0xf;//數據碼
Led_Buf[4]=Ir_Buf[1]&0xf;
Led_Buf[5]=(Ir_Buf[1]/16)&0xf;//用戶反碼
Led_Buf[6]=Ir_Buf[0]&0xf;
Led_Buf[7]=(Ir_Buf[0]/16)&0xf;//用戶碼
}
//遙控數字鍵直接預調時==================================================================================
void ykm_set()//從最左第一位開始直接輸入一個0--9的數時顯示出來后自動右移一位,當到最右邊時轉到最左邊
{
if((ok==1)&&((Ir_Buf[0]==0x02)&&(Ir_Buf[2]<10)))
{
if(zuo_you>7){zuo_you=7;ds=1;}//ds=1;保證此函數結束后不從寫 Led_Buf[7]
while(Led_Buf[zuo_you]>9){if((--zuo_you)==255) zuo_you=7;}//閃動的第7位不是十進制數則一直移動
if(Ir_Buf[2]<9)Led_Buf[zuo_you]=Ir_Buf[2]+1;//因為我的遙控器按1時數據碼是0x00,按2是0x01...,按0是0x09
else Led_Buf[zuo_you]=0;
if((--zuo_you)==255) {zuo_you=8;i_k=1;i=1;}//先右移,如果到最右邊一位則轉到最左邊一位
while(Led_Buf[zuo_you]>9){if((--zuo_you)==255)zuo_you=8;}//正在閃動的位不是十進制數則一直移動
Ir_Buf[2]=0xff;
}
if((ok==0)&&((Ir_Buf[0]==0x02)&&(Ir_Buf[2]<10)))
{
if(Ir_Buf[2]<6)shan_xia=Ir_Buf[2];
}
}
//調時閃動函數========================================================================
void led_flash(uchar k,uchar z)//K為閃動開關,Z為閃動內容
{
uchar x,y,a=k;
if(z==1)y=17;
else if(z==2)y=18;
else y=19;
if(a==0)for(x=0;x<8;x++)Led_Buf_temp[x]=Led_Buf[x];//正常狀態不閃動
else//當K值不為0里閃動
{
if(ms>220)for(x=0;x<8;x++){Led_Buf_temp[x]=Led_Buf[x];}//MS為閃動時基
else
{
if(zuo_you<=7)Led_Buf_temp[zuo_you]=y;
else for(x=0;x<8;x++)Led_Buf_temp[x]=y;
}
}
}
//延時void delay(uint z)
{ uint x,y;for(x=z;x>0;x--)for(y=500;y>0;y--);}
//紅外遙控=========================================================================
void hyyk()
{
uint temp;
uchar i,j;
temp=Ir_Get_Low();//低電平時間采集
if(temp<c(8500) || temp>c(9500)) goto restart;//引導脈沖低電平在9ms 附近
temp=Ir_Get_High();//高電平時間采集
if(temp<c(4000) || temp>c(5000)) goto restart;//引導脈沖高電平在4。5ms 附近
for(i=0;i<4;i++)//4個字節
for(j=0;j<8;j++)//每個字節8位 共32bit裝入Ir_Buf[4]
{
temp=Ir_Get_Low();
if(temp<c(200) || temp>c(800)) goto restart;//低電平時間符合
temp=Ir_Get_High();
if(temp<c(200) || temp>c(2000)) goto restart;//高電平時間符合
Ir_Buf[i]>>=1;//數據右移一位
if(temp>c(1120)) Ir_Buf[i]|=0x80;//高電平時間分析,大于1120us為1否則為0
}
if(mute==0)//靜音功能,默認打開
{
beep=0;
delay(15);
beep=1;
}
restart://無效信號勻跳轉至此 加速循環提高程式運行效率
TR1=0;//關定時器1中斷
}
//紅外低電平時間采集=======================================================================
uint Ir_Get_Low()
{ //定時器清0
TL1=0;
TH1=0;//開始記數
TR1=1;//完成一次記數
while(!Ir_Pin && (TH1&0x80)==0);
TR1=0;//關定時器
return TH1*256+TL1;//反回記數值
}
//紅外高電平時間采集uint Ir_Get_High()
{
TL1=0;
TH1=0;
TR1=1;
while(Ir_Pin && (TH1&0x80)==0);
TR1=0;
return TH1*256+TL1;
}
//時間調整數據采集分析寫調時緩沖區函數
void time_set()
{
uchar write[3]//write[3]為預寫緩沖區
ok=0;//當寫時鐘芯片后不閃,并可以馬上刷新屏幕
if((Led_Buf[2]==16)||(Led_Buf[2]==18))//此時顯示的是鬧鐘或時間,那么預寫緩沖區的數到顯示緩沖區相應的數
{
write[0]=Led_Buf[0]+Led_Buf[1]*10; //預寫秒位
write[1]=Led_Buf[3]+Led_Buf[4]*10; //預寫分位
write[2]=Led_Buf[6]+Led_Buf[7]*10; //預寫時位
if(Led_Buf[2]==18) //是時間格式特征
{
write_ds(0x04,write[2]); //寫時 向時鐘芯片ds12c887+寫信息
write_ds(0x02,write[1]); //寫分
write_ds(0x00,write[0]); //寫秒
}
if(Led_Buf[2]==16) //是鬧鐘格式特征
{
write_ds(0x05,write[2]); //寫時(鬧鐘) 向時鐘芯片ds12c887+寫信息
write_ds(0x03,write[1]); //寫分(鬧鐘)
write_ds(0x01,write[0]); //寫秒(鬧鐘)
}
}
if((Led_Buf[7]==2)&&(Led_Buf[6]==0)&&(Led_Buf[3]<2)&&(Led_Buf[1]<4))//是日期的格式特征
{
write[0]=Led_Buf[0]+Led_Buf[1]*10;//預寫日
write[1]=Led_Buf[2]+Led_Buf[3]*10;//預寫月
write[2]=Led_Buf[4]+Led_Buf[5]*10;//預寫年
write_ds(0x09,write[2]); //寫年 向時鐘芯片ds12c887+寫信息
write_ds(0x08,write[1]); //寫月
write_ds(0x07,write[0]); //寫日
}
if((Led_Buf[1]==Led_Buf[2])&&(Led_Buf[6]==Led_Buf[7]))//是星期格式特征(先排除時間與鬧鐘格式再排除日期格式)
{
write[0]=Led_Buf[7];
// if(write[0]>7)write[0]=0;
write_ds(0x06,write[0]); //寫星期 向時鐘芯片ds12c887+寫信息
}
}
//以下全為溫度傳感函數
//延時
void delay_18b20(uint i)
{while(i--);}
//初始化函數
Init_DS18B20(void)
{
uchar x=0;
DQ = 1; //DQ復位
delay_18b20(8); //稍做延時
DQ = 0; //單片機將DQ拉低
delay_18b20(80); //精確延時 大于 480us
DQ = 1; //拉高總線
delay_18b20(14);
x=DQ; //稍做延時后 如果x=0則初始化成功 x=1則初始化失敗
delay_18b20(20);
}
//讀一個字節
ReadOneChar(void)
{
uchar i=0;
uchar dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; //給脈沖信號
dat>>=1;
DQ = 1; //給脈沖信號
if(DQ)
dat|=0x80;
delay_18b20(4);
}
return(dat);
}
//寫一個字節
WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
delay_18b20(5);
DQ = 1;
dat>>=1;
}
delay_18b20(4);
}
//讀取溫度
ReadTemperature(void)
{
unsigned char a=0;
unsigned char b=0;
unsigned char t=0;
Init_DS18B20();
WriteOneChar(0xCC);// 跳過讀序號列號的操作
WriteOneChar(0x44);// 啟動溫度轉換
Init_DS18B20();
WriteOneChar(0xCC);//跳過讀序號列號的操作
WriteOneChar(0xBE);//讀取溫度寄存器等(共可讀9個寄存器)前兩個就是溫度
a=ReadOneChar();//讀取溫度值低位
b=ReadOneChar();//讀取溫度值高位
a=a>>4;//低位右移4位,舍棄小數部分
t=b<<4;//高位左移4位,舍棄符號位
t=t|a;
return(t);
}
void out_18b20()//溫度顯示函數
{
int temp_18b20;
temp_18b20=ReadTemperature();
Led_Buf[7]=16;
Led_Buf[6]=16;
Led_Buf[5]=16;
Led_Buf[4]=16;
Led_Buf[3]=temp_18b20/10;
Led_Buf[2]=temp_18b20%10;
Led_Buf[1]=20;
Led_Buf[0]=21;
}
復制代碼
歡迎光臨 (http://www.zg4o1577.cn/bbs/)
Powered by Discuz! X3.1
主站蜘蛛池模板:
久在线观看
|
操到爽
|
国产精品福利视频
|
亚洲国产精品99久久久久久久久
|
色视频在线免费观看
|
亚洲一二三在线观看
|
欧美成人精品二区三区99精品
|
欧美一级电影免费观看
|
天天操夜夜操
|
99国产精品久久久
|
日韩亚洲一区二区
|
亚洲激情综合
|
久久精品国产亚洲一区二区三区
|
午夜影院在线观看
|
国产精品亚洲成在人线
|
久久一久久
|
美女三区
|
日韩欧美在线播放
|
午夜在线免费观看视频
|
日本韩国电影免费观看
|
免费视频99
|
欧美视频1区
|
欧美日韩国产一区二区三区不卡
|
欧美一区二区视频
|
久久国产精品-国产精品
|
久久久久久一区
|
在线国产一区
|
日韩高清黄色
|
欧美日韩在线一区二区
|
亚洲 欧美 日韩在线
|
一区二区三区av
|
www.狠狠操
|
高清一区二区三区
|
国产成人精品久久二区二区91
|
自拍偷拍3p
|
久久久免费观看视频
|
精品99在线
|
可以免费观看的av
|
欧美一级在线观看
|
国产在线视频在线观看
|
影音先锋中文字幕在线观看
|