2015-05-21 20:25:09 tengweitw 阅读数 4430
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3414 人正在学习 去看看 朱有鹏

回头看我所写的文章,基本都是软件方面的,是个典型的“欺软怕硬”的人。然而,在最开始的时候,我学习的是硬件。在前面文章《我的2013–一起从心开始》一文中写道,我在大一暑假的时候开始了单片机的学习,在大二、大三期间做过些小东西。刚进入程序员的领域的时候,显然是单片机带我入了门。下面我将写写用单片机做过的一些东西,权当纪念。


本文介绍我大一暑假学完单片机后,在大二上学期为参加学校星火杯而完成的作品(最终没有参加比赛)。这个电子制作是关于用单片机显示时间的作品,其功能就用单片机控制LCD、LED来显示时间和温度。


功能描述

  • 显示精确度为0.1摄氏度的温度(低于0摄氏度和高于100摄氏度响铃)
  • 液晶时钟,断电后仍然继续走动,每月误差不到一分钟,无电源可工作10年左右,区分平年和闰年;
  • 指针式时钟(黄灯为时针,红色为分针,最小误差5分钟,整点报时)与考试计时器(计时2两小时)

电子元器件

  • 2个单片机最小系统 (单片机型号为STC89C52)
  • 双色发光二级管
  • 液晶显示屏
  • 按键
  • DS12C887时钟芯片
  • DS18b20温度传感器
  • 蜂鸣器(整点报时)
  • LED数码管(显示温度)

作品展示图

  • 由于所有电路都是由杜邦线连接,所以存在接触不良,导致有时不能正常显示,于是就没有参赛,下图为双色二极管的显示。
    这里写图片描述
    这里写图片描述
  • 下图为用1602液晶显示日期和时间
    这里写图片描述
    这里写图片描述
  • 下图为用数码管来显示温度
    这里写图片描述
  • 下图为作品的布线,简直是乱成一团,要是用PCB就好了。
    这里写图片描述

原文:http://blog.csdn.net/tengweitw/article/details/45895989
作者:nineheadedbird

附录:代码实现

对于硬件来说,给代码不给管脚图没啥意义,不过由于年代久远,我已经找不到当初设计的电路图了。但仍然给出代码图,希望能起到一点点的参考作用。

//--------------------------------温度显示程序 第一个芯片------------------------------------------------------------------//

#include<reg52.h>
#include<intrins.h>
#include<stdio.h>
#define uchar unsigned char 
#define uint unsigned int

sbit ds=P2^2;

unsigned int te;

unsigned char code tabledu[]=
{ 
0x3f0x060x5b0x4f
0x660x6d0x7d0x07 
0x7f0x6f0x770x7c
0x390x5e0x790x71
};
unsigned char code tabledu1[]=
{ 
0xbf0x860xdb0xcf
0xe60xed0xfd0x87 
0xff0xef0xf70xfc
0x390x5e0x790x71
};

unsigned char code tablewe[]=
{
0xfe0xfd0xfb0xf70xef0xdf
};


void delayxms(unsigned int x)
{
unsigned int ij; 
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}



void delayx2us(unsigned char t)
{ 
while(--t);
}


void dsreset() // 复位
{
ds=1;
_nop_();
ds=0;
delayx2us(200);//注意时间
ds=1;
delayx2us(20);

}


void writetemp(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
ds = 0;
ds = dat&0x01;
delayx2us(25);
ds = 1;
dat>>=1;
}
delayx2us(25);
}


unsigned char readtemp(void)
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
ds = 0; // 给脉冲信号
dat>>=1;
ds = 1; // 给脉冲信号
if(ds)
dat|=0x80;
delayx2us(25);
}
return(dat);
}

uint temp()
{
uint ab;
dsreset();
delayxms(1);
writetemp(0xcc);
writetemp(0x44);
delayxms(1);

dsreset();
delayxms(1);
writetemp(0xcc);
writetemp(0xbe);
delayx2us(50);
a=readtemp();
b=readtemp();
a=a*10;
te=b*160+a/16;

return te;
}

void disp(long int num)
{
uchar cde;
c=num/100;
d=num%100/10;
e=num%10;

P0=tabledu[c];
P1=0xfe;
delayxms(6);
P0=tabledu1[d];
P1=0xfd;
delayxms(6);
P0=tabledu[e];
P1=0xfb;
delayxms(6);
P0=0xcc;
P1=0xf7;
delayxms(2);

}


void main()
{

while(1)
{
disp(temp());
if((temp()>=1000)||(temp()<=0))
beep=0;
else
beep=1;


}





//--------------------------------时钟显示程序 第二个芯片------------------------------------------------------------------//
#include<reg52.h>

#define uchar unsigned char 
#define uint unsigned int



//流水灯锁存器
sbit wela1=P2^0;//1
sbit wela2=P2^1;//2
sbit wela3=P2^2;//1
sbit wela4=P2^3;//2

//蜂鸣器
sbit beep=P2^4;

//按键
sbit key1=P2^5;//功能选择键
sbit key2=P2^6;//+(时间、日期加)
sbit key3=P2^7;//-(时间、日期减)
sbit key4=P3^7;//模式键(平时或考试)



//液晶接口
sbit lcden=P3^4;
sbit lcdrs=P3^5;
sbit lcdwr=P3^6;

//ds12c887接口
sbit dscs=P1^6;
sbit dsas=P1^7;
sbit dsrw=P3^0;
sbit dsds=P3^1;
sbit dsirq=P3^3;


//定义变量
uchar hour minseccountriweekyuenianj;
//uchar counthcountmcountycountkloop1;
uchar code table1[]=" - - ";
uchar code table2[]=" : : ";
uchar code table3[]="SUNMONTUEWEDTHUFRISAT";



//延迟函数
void delayxms(unsigned int x) 
{
unsigned int ij; 
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}



//--------------------1602液晶函数----------------------------------




//液晶写命令
void write_com(unsigned char com) 
{
lcdrs=0;
P0=com;
delayxms(5);
lcden=1;
delayxms(5); 
lcden=0;
}

//液晶写数据
void write_data(unsigned char date)
{
lcdrs=1;
P0=date;
delayxms(5); 
lcden=1;
delayxms(5);
lcden=0;
}

//液晶初始化
void lcdinit()
{
lcdwr=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06); 
write_com(0x01);

}

// 液晶显示
void disp() 
{
uchar i;

write_com(0x80);
for(i=0;i<15;i++)
{
write_data(table1[i]);
delayxms(5);
}
write_com(0x80+0x40);
for(i=0;i<12;i++)
{
write_data(table2[i]);
delayxms(5);
}
}


//写时间
void write_sfm(uchar addressuchar shu) 
{
uchar shige;
shi=shu/10;
ge=shu%10;
write_com(0x80+0x40+address);
write_data(0x30+shi);
write_data(0x30+ge);
}


//写日历
void write_calendar(uchar addressuchar shu) 
{
uchar shige;
shi=shu/10;
ge=shu%10;
write_com(0x80+address);
write_data(0x30+shi);
write_data(0x30+ge);
}


//-------------------------DS12C887程序----------------------------
//写时钟
void write_ds(uchar adduchar date)
{
dscs=0;
dsas=1;
dsds=1;
dsrw=1;
P0=add;
dsas=0;
dsrw=0;
P0=date;
dsrw=1;
dsas=1;
dscs=1;
}


//读时钟
uchar read_ds(uchar add)
{
uchar ds_date;
dsas=1;
dsds=1;
dsrw=1;
dscs=0;
P0=add;
dsas=0;
dsds=0;
P0=0xff;
ds_date=P0;
dsds=1;
dsas=1;
dscs=1;
return ds_date;
}

//写星期
void write_week(uchar date)
{

write_com(0x80+12);
write_data(table3[3*date]);
write_data(table3[3*date+1]);
write_data(table3[3*date+2]);
}




//键盘检测
void keyscan() //键盘检测 key1 为功能键 key2为加 key3为减 :时间与日期的改变
{

if(key1==0)
{
delayxms(10);
if(key1==0)
{
while(!key1);
count++;

if(count==1)
{

write_com(0x80+0x40+11);
write_com(0x0f);

}

if(count==2)
{

write_com(0x80+0x40+8);
write_com(0x0f);

}

if(count==3)
{

write_com(0x80+0x40+5);
write_com(0x0f);

}
if(count==4)
{
write_com(0x80+13);
write_com(0x0f);
}
if(count==7)
{
write_com(0x80+10);
write_com(0x0f);
}
if(count==6)
{
write_com(0x80+7);
write_com(0x0f);
}
if(count==5)
{
write_com(0x80+4);
write_com(0x0f);
}

if(count==8)
{

count=0;
write_com(0x0c);
write_ds(0sec);
write_ds(2min);
write_ds(4hour);
}
}
}


if(key2==0)
{
delayxms(10);
if(key2==0)
{
while(!key2);
if(count==1)
{
sec++;
if(sec==60)
sec=0;
write_ds(0sec);
write_sfm(10sec);
write_com(0x80+0x40+11);
}

if(count==2)
{
min++;
if(min==60)
min=0;
write_ds(2min);
write_sfm(7min);
write_com(0x80+0x40+8);
}


if(count==3)
{
hour++;

if(hour==24)
hour=0;
write_ds(4hour);
write_sfm(4hour);
write_com(0x80+0x40+5);
}

if(count==4)
{
week++;
if(week==7)
week=0;
write_week(week);
write_ds(6week);

}


if(count==5)
{
nian++;
if(nian==100)
nian=0;
write_ds(9nian);
write_calendar(3nian);
write_com(0x80+4);
}

if(count==6)
{
yue++;
if(yue==13)
yue=1;
write_ds(8yue);
write_calendar(6yue);
write_com(0x80+7);
}

if(count==7) // 判断闰年
{
ri++;
week++;
if(nian%4==0)
{
if((yue==4)||(yue==6)||(yue==9)||(yue==11))
{
if(ri==31)
ri=1;
}
else if(yue==2)
{
if(ri==30)
ri=1;
}
else
{
if(ri==32)
ri=1;
}
}

if(nian%4!=0)
{
if((yue==4)||(yue==6)||(yue==9)||(yue==11))
{
if(ri==31)
ri=1;
}
else if(yue==2)
{
if(ri>=29)
ri=1;
}
else
{
if(ri==32)
ri=1;
}
}
write_ds(7ri);
write_calendar(9ri);
write_com(0x80+10);
delayxms(2);
if(week==7) 
week=0;
write_week(week);
write_ds(6week);


}




}
}

if(key3==0)
{
delayxms(10);
if(key3==0)
{
while(!key3);
if(count==1)
{
if(sec==0)
sec=59;
else
sec--;
write_ds(0sec);
write_sfm(10sec);
write_com(0x80+0x40+11);
}

if(count==2)
{
if(min==0)
min=59;
else
min--;
write_ds(2min);
write_sfm(7min);
write_com(0x80+0x40+8);
}


if(count==3)
{
if(hour==0)
hour=23;
else
hour--;
write_ds(4hour);
write_sfm(4hour);
write_com(0x80+0x40+5);
}
if(count==5)
{

if(nian==0)
nian=99;
else
nian--;
write_ds(9nian);
write_calendar(3nian);
write_com(0x80+4);

}
if(count==6)
{

if(yue==1)
yue=12;
else
yue--;
write_ds(8yue);
write_calendar(6yue);
write_com(0x80+7);
}


if(count==7) // 判断闰年
{
ri--;
week--;
if(nian%4==0)
{
if((yue==4)||(yue==6)||(yue==9)||(yue==11))
{
if(ri==0)
ri=30;
}
else if(yue==2)
{
if(ri==0)
ri=29;
}
else
{
if(ri==0)
ri=31;
}
}

if(nian%4!=0)
{
if((yue==4)||(yue==6)||(yue==9)||(yue==11))
{
if(ri==0)
ri=30;
}
else if(yue==2)
{
if(ri==0)
ri=28;
}
else
{
if(ri==0)
ri=31;
}
}
write_ds(7ri);
write_calendar(9ri);
write_com(0x80+10);
delayxms(2);
if(week==-1) 
week=7;
write_week(week);
write_ds(6week);


}


}
}
}

//----------------初始化---------------------------------//
void init()
{
lcdinit();

disp();
week=0;
nian=11;
yue=9;
ri=1;

}


//---------------------------流水灯-----------------------------------//
void lampinit()
{
P1=0xff;
wela1=1;
wela2=1;
wela3=1;
wela3=1;
wela1=0;
wela2=0;
wela3=0;
wela4=0;

}
//----------------时钟用黄灯显示程序-------------------------------//
void clock()
{
if((hour==1)&&(hour==13))
{
P1=0xfd;
wela3=1;
wela3=0;
}

if((hour==2)&&(hour==14))
{
P1=0xfb;
wela3=1;
wela3=0;
}

if((hour==3)&&(hour==15))
{
P1=0xf7;
wela3=1;
wela3=0;
}

if((hour==4)&&(hour==16))
{
P1=0xef;
wela3=1;
wela3=0;
}
if((hour==5)&&(hour==17))
{
P1=0xdf;
wela3=1;
wela3=0;
}
if((hour==6)&&(hour==18))
{
P1=0xfe;
wela4=1;
wela4=0;
}
if((hour==7)&&(hour==19))
{
P1=0xfd;
wela4=1;
wela4=0;
}
if((hour==8)&&(hour==20))
{
P1=0xfb;
wela4=1;
wela4=0;
}
if((hour==9)&&(hour=21))
{
P1=0xf7;
wela4=1;
wela4=0;
}
if((hour==10)&&(hour==22))
{
P1=0xef;
wela4=1;
wela4=0;
}
if((hour==11)&&(hour==23))
{
P1=0xdf;
wela4=1;
wela4=0;
}
if((hour==12)&&(hour==0))
{
P1=0xfe;
wela3=1;
wela3=0;
}


if(min<5)
{
if((hour!=12)&&(hour!=24))
{
P1=0xfe;
wela1=1;
wela1=0;
}
}
//----------------分钟用红灯显示------------------------//

if((min>=5)&&(min<10))
{
if((hour!=13)&&(hour!=1))
{
P1=0xfd;
wela1=1;
wela1=0;
}
}

if((min>=10)&&(min<15))
{
if((hour!=14)&&(hour!=2))
{
P1=0xfb;
wela1=1;
wela1=0;
}
}

if((min>=15)&&(min<20))
{
if((hour!=15)&&(hour!=3))
{
P1=0xf7;
wela1=1;
wela1=0;
}
}

if((min>=20)&&(min<25))
{
if((hour!=16)&&(hour!=4))
{
P1=0xef;
wela1=1;
wela1=0;
}
}


if((min>=25)&&(min<30))
{
if((hour!=17)&&(hour!=5))
{
P1=0xdf;
wela1=1;
wela1=0;
}
}

if((min>=30)&&(min<35))
{
if((hour!=18)&&(hour!=6))
{
P1=0xfe;
wela2=1;
wela2=0;
}
}

if((min>=35)&&(min<40))
{
if((hour!=19)&&(hour!=7))
{
P1=0xfd;
wela2=1;
wela2=0;
}
}


if((min>=40)&&(min<45))
{
if((hour!=20)&&(hour!=8))
{
P1=0xfb;
wela2=1;
wela2=0;
}
}

if((min>=45)&&(min<50))
{
if((hour!=21)&&(hour!=9))
{
P1=0xf7;
wela2=1;
wela2=0;
}
}

if((min>=50)&&(min<55))
{
if((hour!=22)&&(hour!=10))
{
P1=0xef;
wela2=1;
wela2=0;
}
}
if(min>=55)
{
if((hour!=23)&&(hour!=11))
{
P1=0xdf;
wela2=1;
wela2=0;
}
}

}
//---------------考试倒计时模式-----------------------//

void test()
{
uchar hour1min1min2shi;
hour1=hour+2;
if(hour==24)
hour1=0;
if(hour==25)
hour1=1;

min1=min+20;
if(min1>=60)
{
min1=min1-60;
hour1=hour1+1;
if(hour1==24)
hour1=0;
}

shi=min1/10;
min1=shi*10;



if((min==min1)&&(sec==0))
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xfe;
wela3=1;
wela3=0;

}



if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xfc;
wela1=1;
wela1=0;

}

if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xf8;
wela1=1;
wela1=0;

}

if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xf0;
wela1=1;
wela1=0;

}

if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xe0;
wela1=1;
wela1=0;

}

if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xc0;
wela1=1;
wela1=0;

}
//-------------------------------------------------//
if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xfe;
wela2=1;
wela2=0;

}

if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xfc;
wela2=1;
wela2=0;

}

if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xf8;
wela2=1;
wela2=0;

}

if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xf0;
wela2=1;
wela2=0;

}

if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xe0;
wela2=1;
wela2=0;

}

if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xc0;
wela2=1;
wela2=0;

}
//----------------------时间到后开始响铃------------------------------------------//
if(min==min2)
{

P1=0;
wela1=1;
wela1=0;
beep=0;
delayxms(1000);
beep=1;
delayxms(1000);
beep=0;
delayxms(1000);
beep=1;
beep=0;
delayxms(1000);
beep=1;
delayxms(1000);
beep=0;
delayxms(6000);
delayxms(6000);
beep=1;

lampinit();

}
}




//-----------------主函数--------------------------------------//
void main()
{
init();
while(1)
{

keyscan();


if(count==0)
{
sec=read_ds(0);
min=read_ds(2);
hour=read_ds(4);
week=read_ds(6);
nian=read_ds(9);
yue=read_ds(8);
ri=read_ds(7);
write_sfm(10sec);
write_sfm(7min);
write_sfm(4hour);
write_week(week);

write_calendar(3nian);
write_calendar(6yue);
write_calendar(9ri);
write_calendar(120);

}

}

}
2012-12-13 14:33:55 ap105638 阅读数 725
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3414 人正在学习 去看看 朱有鹏
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit lcdrs=P1^7;
sbit lcdrw=P1^6;
sbit le=P2^4;
sbit DQ=P3^5;
uchar num = 0;

uchar i;

uchar code tabel[]="0123456789.";
uchar tabel0[]="TEMPERATURE:";
uchar tabel1[]="THE TIME IS:";

 void delay8(uint ms)
{
 while(ms--);
}
void delay(uint s)
{
 uint x,y;
 for(x=s;x>0;x--)
   for(y=110;y>0;y--);
}
void init_1820()  //1820的复位
{
 uchar x;
 DQ=1;
 delay8(8);
 DQ=0;
 delay8(140);
 DQ=1;
 delay8(15);
 x=DQ;
 delay8(5);
}
void write_byte(uchar dat)   //写指令
{
 uchar i;
 for(i=0;i<8;i++)
 {
  DQ=0;     //这里是单片机
  DQ=dat&0x01;   //这还是单片机发的  所以不用释放
  delay8(4);
  DQ=1;
  dat>>=1;
 }
 delay(5);
}

  uchar read_byte()   //读数据
 {
 uchar i,value;
 for(i=0;i<8;i++)
 {
  DQ=0;
  value>>=1;
  DQ=1;   //一定要释放 因为DQ即将要被1820用到而不是单片机
  if(DQ) 
   value|=0x80;
  delay8(4);  
 }
 return value;
}
uint temper()       //就是由于把uint写成uchar导致无法显示小数点,浪费8个小时啊.....
{
 uchar a,b;
 uint temp;
   
 init_1820();
 write_byte(0xcc);   //跳过ROM
 write_byte(0x44);  //启动转换温度
 delay8(300);
  
    init_1820();   //每次操作都要init初始化才行
 write_byte(0xcc);
 write_byte(0xbe); //读取温度
 a=read_byte();
 b=read_byte();
 temp=(a+b*256)*(0.0625*10);  //保留一位小数,即百位实际是十位,十位是个位,个位是小数点后一位
 return temp;
}
void write_com(uchar com)
{
 lcdrs=0;
 //le=0;
 delay(5);
 P0=com;
 delay(5); 
 le=1;
 delay(5);
 le=0;
}

void write_data(uchar dete)
{
 lcdrs=1;
 //le=0;
 delay(5);
 P0=dete;
 delay(5); 
 le=1;
 delay(5);
 le=0;
}
void init()
{
 le=0;
 lcdrw=0;    //时序图是低电平  而文档文字是高电平  
 write_com(0x01);  //清屏等操作
 write_com(0x38);
 write_com(0x0f);

 /////////////////////外部中断0
 EA = 1;
 EX0 = 1;
 IT0 = 1;

  
}

void main()
{
    uchar shi,ge,dot1;
    uint tt;
 init();
    while(1){
 write_com(0x80+0x40);
 for(i=0;i<12;i++)
 {
  write_data(tabel0[i]);
  delay(30);
 }

 write_com(0x80);
 for(i=0;i<12;i++)
 {
  write_data(tabel1[i]);
  delay(30);
 }
 write_com(0x80+0x4c);
  tt=temper();
 
  shi=tt/100;
  ge=tt%100/10;
  dot1=tt%10;
  
  
 write_data(tabel[shi]);
 
  delay(200);

 write_data(tabel[ge]&0x7f);  //突出小数点
 
  delay(200); 
   write_data(tabel[10]);
   delay(200); 
 
   
 write_data(tabel[dot1]);
 
  delay(200);



  
 } 
 
}

void int0() interrupt 0
{
 num++;
}

#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit lcdrs=P2^2;
sbit lcdrw=P2^3;
sbit le=P2^4;
sbit peng=P2^1;

uchar min1=1;
uchar min2=0;
uchar sex1=0;
uchar sex2=0;
int fage=1;
uchar i;

uchar code tabel[]="0123456789.";
uchar tabel0[]=":";
uchar tabel1[]="THE TIME IS:";

 void delay8(uint us)
{
	 while(us--);
}
void delay(uint ms)
{
 	 uint x,y;
	 for(x=ms;x>0;x--)
  	 for(y=110;y>0;y--);
}


void write_com(uchar com)
{
 	lcdrs=0;
 	//le=0;
 	delay(5);
 	P0=com;
 	delay(5); 
 	le=1;
 	delay(5);
 	le=0;
}

void write_data(uchar dete)
{
 	lcdrs=1;
 	//le=0;
 	delay(5);
 	P0=dete;
 	delay(5); 
 	le=1;
	delay(5);
 	le=0;
}
void init()
{
 	le=0;
 	lcdrw=0;    //时序图是低电平  而文档文字是高电平  
 	write_com(0x01);  //清屏等操作
 	write_com(0x38);
 	write_com(0x0f);

 	/////////////////////外部中断0
	EA = 1;
 	EX0 = 1;

 	EX1=1;    //开外部中断1 
	IT1=0;  //外部中断边沿触发,下降沿触发  
	IT0=0;  //外部中断0边沿触发,下降沿触发
	
	
 

  
}
void int0() interrupt 0
{
 	

	fage=0;

}
 void int1() interrupt 2
{ 
 
	
	fage=1;


}


void main()
{
 	init();
	peng=0;
    while(1)
	{
	
		if(fage==1)
		{
		 	
			
		
	 		write_com(0x80);
 			for(i=0;i<12;i++)
 			{
 				write_data(tabel1[i]);
  			 	delay(30);
		
 			}
		
			write_com(0x80+0x49);
			write_data(tabel[min1])	;
			delay(30);
			write_data(tabel[min2])	;
			delay(30);
			write_data(tabel0[0])	;
			delay(30);
			write_data(tabel[sex1]);
			delay(30);
			write_data(tabel[sex2]);
			delay(30) ;
			
				
			if((sex1==0)&&(sex2==1)&&(min2==0)&&(min1==0))
			{
			 	fage=0;
				peng=1;
			}
			if((sex1==0)&&(sex2==0)&&(min2==0)&&(min1==1))
			{
			  min1--;
			  min2=9;
			  sex1=5;
			  sex2=10;
			}
			if((sex1==0)&&(sex2==0)&&(min2!=0))
			{
			  min2--;
			  sex1=5;
			  sex2=10;
			}
			if(sex2==0&&(sex1!=0))
			{
			  sex1--;
			  sex2=10;
			}
			 delay(700) ;
			 sex2--;
			
		
		}
		else
		{
		
		 
			write_com(0x80);
 			for(i=0;i<12;i++)
 			{
 				write_data(tabel1[i]);
  			 	delay(30);
		
 			}
		
			write_com(0x80+0x49);
			write_data(tabel[min1])	;
			delay(30);
			write_data(tabel[min2])	;
			delay(30);
			write_data(tabel0[0])	;
			delay(30);
			write_data(tabel[sex1]);
			delay(30);
			write_data(tabel[sex2]);
			delay(30) ;
			delay(700) ;
			
		
		}

	} 
 
}


2019-11-30 18:55:55 naotherway 阅读数 108
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3414 人正在学习 去看看 朱有鹏

程序开发环境为IAR FOR STM8 1.40
主控MCU为STM8S103F3P6
温度采集芯片为TMP275,采用IIC接口
时钟芯片位高精度的DS3231,采用IIC接口
显示采用2个6位LED数码管显示,每个数码管均采用数码管驱动芯片TM1620控制,TM1620采用IIC接口,3线即可控制6位数码管显示。

可显示时间和温度。时间和温度切换显示。均为6位共阴数码管

程序实时读取温度值,读取实时时间值,通过2个6位共阴位数码管实时显示。
温度值两位整数位,一位小数位。

板载3个标定按键,用于标定时间,年月日时分秒均可设置。

硬件带有时钟纽扣电池座,纽扣电池为CR2032。
14个IO引脚全部引出。
RST,PD1用于下载程序

同时按住KEY1和KEY3,
进入时钟的年标定模式,年后的小数点闪烁:按KEY2,年加1,加到99,不在加。按KEY3年减1,减到19不再减;
再按KEY1,进入月标定,月后的小数点闪烁;按KEY2,月加1,加到12,不在加。按KEY3年减1,减到1不再减;
再按KEY1,进入日标定,,,,
再按KEY1,进入时标定,,,,
再按KEY1,进入分标定,,,,
再按KEY1,进入分秒标定,所有小数点均不闪烁。
再按KEY1,第一个(上排)数码管显示全6:此时按KEY1继续从年开始标定。按KEY3退出标定,标定完成。

 

 

 

共同交流:q:     1425636507

 

 

 

 

 

2017-11-06 10:42:42 qq_26914291 阅读数 1995
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3414 人正在学习 去看看 朱有鹏

要求

(一)基本功能
1.  测温范围-50℃—110℃
2.  精度误差不大于0.1℃
3.  LED数码直读显示    
(二)扩展功能
1.实现语音报数(不开发)
2.可以任意设定温度的上下限报警功能
二.计划完成时间   三周
1.第一周完成软件和硬件的整体设计,同时按要求上交设计报告一份。
2.第二周完成软件的具体设计和硬件的制作。
3.第三周完成软件和硬件的联合调试。

准备工作

确定模块

1.温度传感器模块
2.数码管模块
3.转换模块

元件清单

1.STC89C52单片机
2.DS18B20温度传感器

开发工具

1.proteus(开发仿真图)

2.dxp(开发原理图,设计电路板)

安装教程

1.http://www.3d66.com/softhtml/softsetup_114.html

破解教程

破解文件在上文链接中

  • 破解方法:AD10KeyGen

  • 运行AD10KeyGen,点击“打开模板”,加载license.ini,如想修改注册名,只需修改:TransactorName=Your Name其中Your Name用你自己的名字替换,其它参数在单机版的情况下无需修改;

  • 点击“生成协议”,保存生成的alf文件(文件名任意,如“jack”),并将其放到你的安装目录下;

  • 将patch.exe放到你的安装目录下,运行patch,对安装目录下的dxp.exe文件补丁,注意运行破解时软件没有运行;

  • 启动DXP,运行菜单DXP->My Account,点击Add Standalone License file,加载前面生成的license(.alf)文件后即能正常使用了。

3.keil(开发程序)

1.点击”keil3.exe”直接安装直到结束.
不过这样只可以生产2k以下的代码,如果要生成2k以上的代码需要注册,
请按第2部操作.

2.第一次运行请先进入”文件”->“授权管理”弹出窗口下输入注册码,
注册码由”Keil注册.exe”生成,选择V2选项,生成后复制LIC内容到keil
弹出窗口的“新授权ID码(LIC)”中然后点击“添加授权”,
注意看看注册后的使用期限,如果太短可以用注册机重新生成,
一般都可以找到30年左右:-)

3.keil3注册失败(出现错误: ERROR R208: RENEW LICENSE ID CODE (LIC)):[解决方案]

keil3下载地址:http://www.xdowns.com/soft/38/39/2013/Soft_104885.html
注册机下载地址: http://www.51hei.com/f/Keil_lic_v2.exe

设计方案

数字温度计设计方案

电路结构

电路主要有控制模块,报警模块,显示模块,温度传感器模块以及核心模块单片机处理模块, 其系统原理框图如下图所示!

设计思路

DSl8B20作为单片机AT89C52的外部信号源,把所采集到的温度转换为数字信号,通过IO接口传给AT89C52,AT89C52启动ROM内的控制程序驱动LED数码管,通过IO接口和数据线(单片机和数码管的接口)把数据传送给数码管,将采集到的温度显示出来,通过控制模块控制测温的上下限,当达到限制时,则AT89C52通知报警模块,实现报警功能!

结构

开发仿真图

开发程序

十六进制数值翻转代码

int isTurn=0;
int turnAll(int a) {//切换全部
   if(isTurn)return a^0xff;
   return a;

}
int turnAfter(int a){//仅切换低位
    if(isTurn)return a^0x0f;
    return a;

全部代码

#include<reg52.h>
#include <intrins.h>
#define  uchar  unsigned  char 
#define  uint   unsigned  int
sbit  DATA = P1^1; //DS18B20接入口
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//共阳极字型码
//uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//共阴极字型码
int temp;  //温度值
int ss;     //中间的一个变量
int dd;
int j;
int isTurn=0;   //切换共阴极-共阳极
uchar data b;//定时器中断次数
uchar data buf[4];//字型显示中间变量
int alarmH=320;   //默认报警值
int alarmL=100;
//定义开关的接入口
sbit  k1=P2^5;//+
sbit  k2=P2^6;//-
sbit  k3=P2^7;//确认
sbit  k4=P2^4; //切换
sbit  bell=P1^0; //蜂鸣器
sbit  HLight=P1^2; //正温指示灯
sbit  LLight=P1^3; //负温度指示灯
sbit  warn=P1^4;  //报警指示灯
sbit  Red=P1^6;   //温度上限设置指示灯
sbit  Green=P1^7; //温度下限设置指示灯
bit set=0;  //初始化
bit Flag=0; //设置标志
int n,a;
//函数的声明区
void key_to1();
void key_to2();
void delay(uint); 
void key();
void Show();
int turnAll(int a) ;
int turnAfter(int a);
//函数的定义区
int turnAll(int a) {
   if(isTurn)return a^0xff;
   return a;

}
int turnAfter(int a){
    if(isTurn)return a^0x0f;
    return a;

}

/*延时子函数*/
void delay(uint num)
{
    while(num--) ;
}
  void delay2(void)        //延时函数,延时约0.6毫秒
{
   unsigned char i;
    for(i=0;i<200;i++)  
    ;//空循环 起延时作用
 }

//DS18b20温度传感器所需函数,分为初始化,读写字节,读取温度4个函数
Init_DS18B20(void)         //传感器初始化
{
    uchar x=0;
    DATA = 1;    //DQ复位
    delay(10);  //稍做延时
    DATA = 0;    //单片机将DQ拉低
    delay(80); //精确延时 大于 480us    //450
    DATA = 1;    //拉高总线
    delay(20);
    x=DATA;      //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
    delay(30);
}
ReadOneChar(void)  //读一个字节
{
    uchar i=0;
    uchar dat = 0;
    for (i=8;i>0;i--)
    {
        DATA = 0; // 给脉冲信号
        dat>>=1;
        DATA = 1; // 给脉冲信号
        if(DATA)
        dat|=0x80;
        delay(8);
    }
    return(dat);
}
WriteOneChar(unsigned char dat) //写一个字节
{
    uchar i=0;
    for (i=8; i>0; i--)
    {
        DATA = 0;
        DATA = dat&0x01;
    delay(10);
    DATA = 1;
    dat>>=1;
    }
    delay(8);
}
int ReadTemperature(void) //读取温度
{
    uchar a=0;
    uchar b=0;
    int t=0;
    float tt=0;
    Init_DS18B20();
    WriteOneChar(0xCC); // 跳过读序号列号的操作
    WriteOneChar(0x44); // 启动温度转换
    Init_DS18B20();
    WriteOneChar(0xCC); //跳过读序号列号的操作
    WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
    a=ReadOneChar();//低位
    b=ReadOneChar();//高位
    t=b;
    t<<=8;
    t=t|a;
    tt=t*0.0625;
    t= tt*10+0.5; 
    return(t);
}
void  display00()     //*********显示负值子函数
{   
    dd=-temp;
    buf[1]=dd/100;
    buf[2]=dd/100;
    buf[3]=dd%100/10;
    buf[0]=dd%10;
    //动态显示
    for(j=0;j<3;j++){
    P2=turnAfter(0xfd); //显示小数点
    P0=turnAll(0x7f); //显示小数点
     delay2();
     P2=turnAfter(0xfe);   //P2.0引脚输出低电平,DS0点亮
     P0=table[buf[0]];  //数字1的段码
     delay2();
     P2=turnAfter(0xfd) ;  //P2.1引脚输出低电平,DS1点亮
     P0=table[buf[3]]; //数字2的段码
     delay2();   
     P2=turnAfter(0xfb);   //P2.2引脚输出低电平,DS2点亮
     P0=table[buf[2]];  //数字3的段码
     delay2();
     P2=turnAfter(0xf7);   //P2.3引脚输出低电平,DS3点亮
     P0=0xbf;  //数字4的段码
     delay2();
     P2=turnAfter(0xff);
     }  
}
//显示正值子函数
void  display()
{       
    buf[1]=temp/1000;//显示百位
    buf[2]=temp/100%10;//显示十位
    buf[3]=temp%100/10;//显示个位
    buf[0]=temp%10; //小数位
    for(j=0;j<3;j++){
    P2=turnAfter(0xfd); //显示小数点
    P0=turnAll(0x7f); //显示小数点
     delay2();
     P2=turnAfter(0xfe);   //P2.0引脚输出低电平,DS0点亮
     P0=table[buf[0]];  //数字1的段码
     delay2();
     P2=turnAfter(0xfd) ;  //P2.1引脚输出低电平,DS1点亮
     P0=table[buf[3]]; //数字2的段码
     delay2();   
     P2=turnAfter(0xfb);   //P2.2引脚输出低电平,DS2点亮
     P0=table[buf[2]];  //数字3的段码
     delay2();
     P2=turnAfter(0xf7);   //P2.3引脚输出低电平,DS3点亮
     P0=table[buf[1]];  //数字4的段码
     delay2();
     P2=turnAfter(0xff);
     }  
}
void key()  //按键扫描子程序
{   if(k1!=1)
    {
       delay(20);
       if(k1!=1)
       {
        while(k1!=1)
          { key_to1();
            for(n=0;n<8;n++)
            Show();
           }
       }
    }
    if(k2!=1)
    {
        delay(20);
        if(k2!=1)
        {
          while(k2!=1)
            { key_to2(); 
              for(n=0;n<8;n++)
              Show();
            }

        }
    }    
    if(k3!=1)
    {   TR0=1; //复位,开定时
        temp=ReadTemperature();                                                                                                     
    }
    if(k4!=1)
    {  delay(20);
       if(k4!=1)
       {  while(k4!=1);
          set=!set;
           if(set==0)
           { Red=0;Green=1;}
           else { Green=0;Red=1;}
        }
     }
}
void key_to1()
{
        TR0=0;         //关定时器
        temp+=10;
        if(temp>=1100)
           {temp=-550;}
        if(set==0)
        {alarmH=temp;}
        else {alarmL=temp;} 
}
void key_to2()
{
        TR0=0;
       //关定时器
        temp-=10;
        if(temp<=-550)
            {temp=1100;}
        if(set==0)
        { alarmH=temp;}
        else { alarmL=temp;}
}

void alarm(void)
{
    if(temp>alarmH||temp<alarmL) 
    {   //bell=1;
        //delay(50);
        //bell=0;
        Flag=1;
     }
     else {Flag=0;}
}


logo()//开机的Logo  
{  


     P2=0xfe;   //P2.0引脚输出低电平,DS0点亮
     P0=0xbf;  //数字1的段码
     delay2();
     P2=0xfd ;  //P2.1引脚输出低电平,DS1点亮
     P0=0xbf;  //数字2的段码
     delay2();   
     P2=0xfb;   //P2.2引脚输出低电平,DS2点亮
     P0=0xbf;  //数字3的段码
     delay2();
     P2=0xf7;   //P2.3引脚输出低电平,DS3点亮
     P0=0xbf;  //数字4的段码
     delay2();
     P2=0xff;      
}


void Show()  //显示函数,分别表示温度正负值
{       if(temp>=0)
        {HLight=1;LLight=0;display();}
        if(temp<0)
        {HLight=0;LLight=1;display00();}
}
void  main()
{   
    TCON=0x01; //定时器T0工作在01模式下
    TMOD=0X01;  
    TH0=0XD8;//装入初值
    TL0=0XF0;
    EA=1;  //开总中断
    ET0=1; //开T0中断
    TR0=1; //T0开始运行计数
    EX0=1; //开外部中断0

    P0=0xff; //初始化端口
    P2=0xff;//初始化端口
    for(n=0;n<500;n++)//显示启动LOGo"- - - -"
    {bell=1;warn=1;logo();}

     Red=0;
    while(1)
    {
        key(); 
        ss=ReadTemperature();
        Show();
        alarm();   //报警函数
        if(Flag==1)
        {bell=!bell;
         warn=!warn;}  //蜂鸣器滴滴响
        else {bell=1;
              warn=1;}  
    }    
}
 void time0(void) interrupt 1 using 1  //每隔10ms执行一次此子程序
 {  TH0=0X56;
    TL0=0XDC;   
    temp=ss;
 }

开发程序注意事项

1.根据数码管是否加三极管驱动以及在反向三极管驱动的情况修改程序!

开发原理图

开发PCB板

焊接元器件

18B20

1.元件引脚识别https://zhidao.baidu.com/question/414867948.html

四位数码管

引脚图

这里写图片描述

共阴极-共阳极段码表

//uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//共阳极字型码
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//共阴极字型码

问题

1.数码管是否加驱动问题?
http://www.360doc.com/content/16/1204/05/3813620_611692234.shtml

开发报告

涉及技术

1.单片机最小系统设计
2.DS18B20读取程序
3.多位数码管动态扫描显示程序
4.单片机定时器中断程序
5.如何利用延时函数修复仿真与现实的差距

参考文章

1.自制mini数字温度计
2.51单片机电子温度计源程序+仿真+照片
3.51单片机实现电子温度计(c语言)
4.单片机数字温度计的 课程设计

总结

1.在PCB上设计双排引脚的元件时一定要标明第一引脚(可把第一引脚焊盘做成方形)!
2.在使用共阳极数码管时一定要加三极管驱动!
3.一定要准确标出插槽的正负极和各个指示灯所代表的含义!

2014-05-11 19:30:35 yangguangmeng 阅读数 1378
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3414 人正在学习 去看看 朱有鹏

1602具有8根数据线和三根控制线(E使能线   R/W读写线   RS表示数据还是指令

一般是先写地址再写数据即可



DS18b20为单线器件,数据在该线上一位一位传输的,向DS18b20写入命令之后,就可以一位一位读取温度数值了


DS1302主要是数据引脚和时钟引脚匹配使用的,写操作时候是先写入地址再写入数据 ,读操作时候是先写入地址再读数据,比如写时候给I/O引脚一位数据,CLK来个下降沿该数据就写成功了。


没有更多推荐了,返回首页