亚洲春色中文字幕久久久-三上亚,一吻二脱三床四吻胸,国产真实伦对白视频全集,在线毛片观看,精品成品入口黄网,国产毛aⅴ片久久久,亚洲AV色香蕉一区二区三区老师,萧皇后A级艳片,色情日本视频更新,99久久亚洲精品日本无码
標題:
我的小制作基于51單片機的數字時鐘
[打印本頁]
作者:
liuda
時間:
2015-1-21 17:44
標題:
我的小制作基于51單片機的數字時鐘
通過幾天的調試用,單片機AT89C52,LCD液晶屏LC1602,溫度采集模塊DS18B20,時鐘模塊DS1302,和三個按鍵,以及一些電子元件完成了數字時鐘系統的設計。在一塊液晶顯示屏上
實現動態,時、分、秒、年、月、日、星期、溫度數據的顯
示, 通過三個按鍵,S1調時鍵、S2時間加鍵、S3時間減鍵、實現時鐘的年、月、日、星期、時、分、秒、的調整。本系統設計大部分功能有軟件來實現,使電路簡單明了。由于以前從沒有過單片機相關產品的制作經驗,所以這個設計共用了約30多個鐘。在做這設計之前軟件思路非常模糊代碼都是想到哪寫到哪,結果寫到最后調試時出現了大把錯誤,在調試程序中花了大把的時間,調程序真的是個考驗耐心的工作搞的我砸電腦的想法都有了。因為是自己一個人制作的出現了錯誤只好在網上找資料,閱讀別人寫過的代碼,經過長時間的修改終于完成了這次制作。設計因為是業余學習的單片機加上這斷時間工作比較忙,所以為了完成這個產品的制作可沒少睡過覺,幾乎每天都沒在2點鐘前睡過。
附原代碼
#include"reg52.h"
#include"12864.h"
#include"ds1302.h"
#include"ds18b20.h"
#include"intrins.h"//_nop_聲明
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P3^7;
sbit rs=P3^0;
sbit rw=P3^1;
sbit en=P3^2;
uchar tou;
sbit io=P3^6;
sbit rst=P3^4; //定義各芯片跟單片機連接的定義
sbit sck=P3^5;
sbit s1=P1^0; //定義各芯片跟單片機連接的定義
sbit s2=P1^4;
sbit s3=P1^7; //定義各芯片跟單片機的連接的定義
uchar tung=0; //定義
uchar tab4[]={0x82,0x85,0x88,0x8f,0xc0,0xc3,0xc6};//用來存放年月日星期時分秒的地址
char tab[]={13,5,4,5,00,59,33};//年 月 日 周 時 分 秒的初值
uchar tab1[]; //
uchar write_add[7]={0x8c,0x88,0x86,0x8a,0x84,0x82,0x80}; //寫寄存器地址
uchar read_add[7]={0x8d,0x89,0x87,0x8b,0x85,0x83,0x81};//存放從1302中讀數寄存器地址
void write_byte(uchar); //寫數據函數
uchar read_byte(void); //讀數據函數
uchar readtemperature(void);//一次性讀出溫度
void write_ds1302_byte(uchar); //單字節寫函數
void write_ds1302(uchar add,uchar dat);//寫 /寫地址數據+寫數據函數
uchar read_ds1302(uchar);// 單字節讀函數
void flx(uchar j); //
void key(void); //按鍵函數
void write_ds1302_byte(uchar dat)
{
uchar i;
for(i=0;i<8;i++) //單字節寫
{
sck=0;
io=dat&0x01;
dat=dat>>1;
sck=1;
}
}
void write_ds1302(uchar add,uchar dat)
{
rst=0;
_nop_();
sck=0;
_nop_();
rst=1; //寫地址數據+寫數據函數
_nop_();
write_ds1302_byte(add); //寫地址
write_ds1302_byte(dat); //寫數據
rst=0;
_nop_();
io=1;
sck=1;
}
uchar read_ds1302(uchar add)
{ uchar i,value;
rst=0; //
_nop_();
sck=0;
_nop_(); //單字節讀數據函數
rst=1;
_nop_();
write_ds1302_byte(add );
for(i=0;i<8;i++)
{
value=value>>1;
sck=0;
if(io) //因為是串口所以要分8次讀數據
value=value|0x80;
sck=1;
}
rst=0;
_nop_();
sck=0;
_nop_();
sck=1;
io=1;
return value;
}
void read_ds1302_1(void)//一次讀出年月日 時分秒函數
{
uchar i,shi,ge,tun;
write_ds1302(0x8e,0x00);//去除寫保護
for(i=0;i<7;i++)
{
tun=read_ds1302(read_add[i]); //一次將年月日從DS1302中讀出送到數組中
ge=tun%16;
shi=tun/16; //將BCD碼分成十位和個位
tab[i]=shi*10+ge; //再換成十進制存到數組tab中
}
write_ds1302(0x8e,0x00);//加寫保護
}
void write_ds1302_1(void)
{ //將10進制數送到1602;
write_com(0x80+0x40+6);//秒的位置
write_dat(tab[6]/10+0x30);
write_dat(tab[6]%10+0x30);
write_com(0x80+0x40+3);//
write_dat(tab[5]/10+0x30); //分的位置
write_dat(tab[5]%10+0x30);
//將十進制的數據換成1602的顯示碼送到顯示屏
write_com(0x80+0x40+0);// //時的地址
write_dat(tab[4]/10+0x30); //顯示屏的第二排要加0x80+40
write_dat(tab[4]%10+0x30);
write_com(0x80+2);//
write_dat(tab[0]/10+0x30);//年的地址
write_dat(tab[0]%10+0x30);
write_com(0x80+5);// 顯示屏 的第一排地址要加0x80;
write_dat(tab[1]/10+0x30);
write_dat(tab[1]%10+0x30); //月的地址
write_com(0x80+8);// 日的地址
write_dat(tab[2]/10+0x30);
write_dat(tab[2]%10+0x30);
write_com(0x80+15); //星期的地址
write_dat(tab[3]%10+0x30);
}
void set_rtc(void) //一次設置初始時間年月日函數
{
uchar i,j;
for(i=0;i<7;i++)
{
j=tab[i]/10; //將設置的年月日時間2013—4-25 00-14-00中分解出十位放入J中
tab1[i]=tab[i]%10; //將設置的年月日時間2013—4-25 00-14-00中分解出個位再放入time_data[]數組中
tab1[i]=tab1[i]+j*16;//將十進制的個位和十位轉換為BCD碼
}
write_ds1302(0x8e,0x00);//去除寫保護
for(i=0;i<7;i++)
{
write_ds1302(write_add[i],tab1[i]); //寫要設置初始時間日期的操作寄存器的地址
}
write_ds1302(0x8e,0x00);//加寫保護
}
void ds1302_init(void)
{
key(); //按鍵函數
read_ds1302_1();//一次讀出年月日 時分秒函數
write_ds1302_1(); //時間的顯示函數
}
void key(void)
{
//按鍵函數
if(s1==0) //如果S1按下
{
delay(3); //延時去抖
if(s1==0)
{
while(!s1); //
tung=0; //tung用來確定光標的位置
while(tung<=6) //循環7次 時分秒年月日星期
{
if(s2==0)
{
delay(3);
if(s2==0)//去抖動延時
{
while(!s2); // 檢測按鍵是否放開
tab[tung]++; //如果+鍵按下加1
}
}
if(s3==0)
{
delay(3); // 檢測按鍵是否放開
if(s3==0)
{
while(!s3); //按鍵是否松手
tab[tung]--; //如果—鍵按下減1
}
}
switch(tung)
{ //通過tung的值確定光標的位置
case 0:
if(tab[tung]<3) //如果tung=0;則表示正在調年讓年在2004到2098這個范圍內
tab[tung]=98;
if(tab[tung]>98)
tab[tung]=4;
break;
case 1:
if(tab[tung]<1)
tab[tung]=12;
if(tab[tung]>12) //如果tung=1;則表示正在調月讓月在1到12這個范圍內
tab[tung]=1;
break;
case 2:
if(tab[tung]==0)
tab[tung]=31;
if(tab[tung]==32) //如果tung=2;則表示正在調日讓在1到31這個范圍內
tab[tung]=1;
break;
case 3:
if(tab[tung]<1)
tab[tung]=7;
if(tab[tung]>7) //如果tung =3則表示下在調星期讓在1到7這個范圍內
tab[tung]=1;
break;
case 4:
if(tab[tung]<0)
tab[tung]=23;
if(tab[tung]>23) //如果tung=4則表示在調時讓時在1到23這個范圍內
tab[tung]=0;
break;
case 5:
if(tab[tung]<0)
tab[tung]=59;
if(tab[tung]>59) //如果tung=5;則表示正在調分讓分在1到59這個范圍內
tab[tung]=0;
break;
default:
if(tab[tung]<0)
tab[tung]=59;
if(tab[tung]>59) //如果tung=6;則表示正在調秒讓秒在1到59這個范圍內
tab[tung]=0;
break;
}
write_com(tab4[tung]); //顯示正在調的位置
flx(tab[tung]); //將數據分離成1602的顯示碼并送到1602顯示屏
if(s1==0)
{
while(!s1); //判斷是否調好了時間如果好了則跳出key
tung++; //每按一下S1調式模式鍵則加一次如果到了7次跳出KEY函數
}
}
}
write_com(0x0c);//調完了時間關閉光標
set_rtc(); //把調好的時間數據送到DS1302芯片中
}
}
void flx(uchar j)
{
uchar k,a;
write_com(0x0f); //開光標顯示指令
k=j/10; //分離十位跟個位
a=j%10;
if(tung!=3) //年月日時分秒分離
{
write_dat(k+0x30); //將分離的十位跟個位換成LC1602能顯示的碼
write_com(0x0c);//關光標指令
write_dat(a+0x30);
}
else
write_dat(a+0x30); //星期分離
}
void delay1(uchar i)
{
while(i--);
}
void init_ds18b20(void)
{
uchar n;
DQ=1;
delay1(8);
DQ=0;
delay1(80); //初始化函數
DQ=1;
delay1(8);
n=DQ;
delay(25);
}
void write_byte(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
DQ=0; //寫函數
DQ=dat&0x01;
delay(4);
DQ=1;
dat>>=1; //移一位
}
delay(4);
}
uchar read_byte(void)
{
uchar i,value;
for(i=0;i<8;i++)
{
DQ=0; //讀數據函數
value>>=1; //移1位
DQ=1;
if(DQ)
value|=0x80;
delay(4);
}
return value;
}
uchar readtemperature(void)//一次性讀出溫度
{
uchar a,b;
init_ds18b20();
write_byte(0xcc);//跳過ROM
write_byte(0x44);//啟動溫度測量
delay1(300);
init_ds18b20(); //初始化
write_byte(0xcc);
write_byte(0xbe);//讀取溫度
a=read_byte();//高8位
b=read_byte();//
b<<=4; //因不用小數部分所以移4位
b+=(a&0xf0)>>4; //將存放低8位的個位和高8位的十位合到一塊
return b;
}
void xianshi(void)
{
uchar temp,k,f;
temp=readtemperature();//將溫度保存到temp中
f=temp/10; //分離出十位跟個位
k=temp%10;
write_com(0x80+0x40+10);//溫度顯示的位置
write_dat(f+0x30); //
write_dat(k+0x30);
}
uchar tab1[]="20 - - week "; //屏上要固定顯示的字符
uchar tab2[]=" : : ";
void delay(uint x)
{
uint a,b;
for(a=x;a--;a>0) //延時函數
for(b=110;b>0;b--);
}
void write_com(uchar com)
{
rs=0;
rw=0; //寫數據指令函數
P2=com;
delay(4);
en=1;
delay(4);
en=0;
}
void write_dat(uchar dat)
{
rs=1;
rw=0;
P2=dat;
delay(4); //寫數據函數
en=1;
delay(4);
en=0;
}
void init(void)
{
write_com(0x38);
write_com(0x0c);// //1602初始化函數
write_com(0x06);
write_com(0x01);
write_com(0x80);
write_com(0x80); //第一行顯示的位置地址
for(tou=0;tou<16;tou++)
{
write_dat(tab1[tou]); //顯示固定字符
}
write_com(0x80+0x40); //第二行顯示的位置地址
for(tou=0;tou<8;tou++)
{
write_dat(tab2[tou]);
}
write_com(0x80+0x40+12);
write_dat(0xdf);//顯示溫度的小圓圈符號,0xdf是液晶屏字符庫的該符號地址碼
write_dat(0x43); //顯示"C"符號,0x43是液晶屏字符庫里大寫C的地址碼
}
main()
{
init();//初始化顯示屏
set_rtc(); //設置ds1302時鐘芯片時間
while(1)
{
ds1302_init();//初始化ds1302時鐘芯片
xianshi(); //溫度顯示函數
}
}
通過這次的制作讓我全面的了解單片機相關產品的開發流程,及一些常用芯片驅動程序的編寫。始我在單片機上的學習更上一層樓!
復制代碼
作者:
七円君
時間:
2017-12-11 15:58
666,有沒有整點提醒功能
歡迎光臨 (http://www.denmoz.com/bbs/)
Powered by Discuz! X3.1