通过比较器比较U2、U3,U3U2时输出1,控制背景灯开。
2.DS18b20温度传感器
DSl820数字温度计提供9位(二进制)温度读数,指示器件的温度。
信息经过单线接口送入DSl820或从DSl820送出,因此从主机CPU到DSl820仅需一条线(和地线),DSl820的电源可以由数据线本身提供而不需要外部电源。
DSl820的测量范围从-55到+125增量值为0.5可在ls(典型值)内把温度变换成数字。
每一个DSl820包括一个唯一的64位长的序号,该序号值存放在DSl820内部的ROM(只读存贮器)中,开始8位是产品类型编码(DSl820编码均为10H)接着的48位是每个器件唯一的序号,最后8位是前面56位的CRC(循环冗余校验)码DSl820中还有用于贮存测得的温度值的两个8位存贮器RAM,编号为0号和1号,1号存贮器存放温度值的符号如果温度为负,则1号存贮器8位全为1,否则全为0,0号存贮器用于存放温度值的补码LSB(最低位)的1表示0.5摄氏度,将存贮器中的二进制数求补再转换成十进制数,并除以2就得到被测温度值(-55~125摄氏度)。
3.L298芯片驱动电机
L298N为SGS-THOMSONMicroelectronics所出产的双全桥步进电机专用驱动芯片(DualFull-BridgeDriver),内部包含4信道逻辑驱动电路,可同时驱动2个减速直流电机,内含二个H-Bridge的高电压、大电流双全桥式驱动器,接收标准TTL逻辑准位信号,可驱动46V、2A以下的步进电机,且可以直接透过电源来调节输出电压;此芯片可直接由单片机的IO端口来提供模拟时序信号,控制转速。
OUTl、OUT2和OUT3、OUT4之间分别接2个电机;input1~input4输入控制电位来控制电机的正反转;Enable则控制电机停转。
4.四位共阴极数码管的驱动
74HC573芯片驱动数码管显示接口,通过单片机I/O接口直接控制数码管位选。
共阴极数码管真值表
十六
进制
0x3f
0x06
0x5b
0x4f
0x66
0x6d
0x7d
0x07
0x7f
0x6f
0x00
0x40
显示符号
0
1
2
3
4
5
6
7
8
9
空
-
74HC573为八进制3态非反转透明锁存器,输入是和标准CMOS输出兼容的;加上拉电阻,他们能和LS/ALSTTL输出兼容。
当锁存使能端LE为高时,这些器件的锁存对于数据是透明的(也就是说输出同步)。
当锁存使能变低时,符合建立时间和保持时间的数据会被锁存。
5.独立按键模块
按键一端接地,另一端与单片机I/O口相连并外接上拉电阻。
按键按下时I/O口由高电位转为低点位,经单片机读取引脚信号,将按键状态输入。
6.外部晶振电路
51单片机
单片机内部有一个用于构成振荡器的高增益反向放大器,引脚XTAL1为输入端,XTAL2为输出端。
两个引脚间跨接晶体振荡器与微调电容组成并联谐振电路,构成一个自激振荡器为内部时钟提供振荡时钟。
振荡期的频率主要取决于晶体的振荡频率,一般晶体可在1.2MHz~12MHz之间任选。
电容C1,C2通常取30pF左右。
7.复位电路
51单片机
51系列单片机系统通常有上电复位和按键复位两种方式。
最简单的一种上电复位及按键复位电路图如上图所示。
上电后,由于电容充电,使RST持续一段时间的高电平,完成复位操作;当单片机处于运行中或者死锁时,按下“复位”按钮,也可以使单片机进入复位状态。
程序模块
1.数码管动态扫描函数
voidrefresh_led()
{
P2=Disp_Tab[a[0]];P1=dispbit[0];P1=0xff;//每个数码管按负值、打开、关闭的顺序
P2=Disp_Tab[a[1]];P1=dispbit[1];P1=0xff;
P2=Disp_Tab[a[2]]|0x80;P1=dispbit[2];P1=0xff;
P2=Disp_Tab[a[3]];P1=dispbit[3];P1=0xff;
}
每个数码管依次按负值、打开、关闭的顺序受控,从而实现动态扫描。
2.温度转换模块程序
voidstart_temp_sensor(void)
{
DS18b20_reset();
write_byte(0xCC);//发SkipROM命令
write_byte(0x44);//发转换命令
}
/**读存温度*/
voidread_temp()
{
uint8temp_data[2];//读出温度暂放
uint16temp=0,c;
doublewd;
start_temp_sensor();
delay_ms(100);
DS18b20_reset();//复位
write_byte(0xCC);//发SkipROM命令
write_byte(0xBE);//发读命令
temp_data[0]=read_byte();//温度低8位
temp_data[1]=read_byte();//温度高8位
temp=temp_data[1];//一下三步将温度高八位低八位整合
temp<<=8;
temp|=temp_data[0];
if(temp_data[1]&0xf0)//判断温度是否为负
{
temp=(~temp)+1;//为负时,取反加一
wd=temp*0.0625;//转为摄氏温度,0.0625为温感芯片储存精度
a[0]=11;//为负时,第一个数码管显示负号
}
else
{
wd=temp*0.0625;
a[0]=10;//为正时,第一个数码管不显示
}
c=wd;//将摄氏温度转为整型
a[2]=c%10;//第三个数码管显示个位
a[1]=c/10%10;//第二个数码管显示十位
c=wd*10;
a[3]=c%10;//第四个数码管显示小数位
}
3.背景灯控制模块程序
voidbeijingdeng()
{
if(ggxh)led_bjd=1;
elseled_bjd=0;
}
光感信号为高电平时,背景灯控制引脚输出高电平,控制背景灯关;光感信号为低电平时,背景灯控制引脚输出低电平,控制背景灯亮。
4.自动控制模块程序
voidzidong()
{
led_zs=0;//点亮自动/手动指示灯
while
(1)
{
if(i)//判断电机正反转状态,并控制电机正反转
{
dj_zz=1;
dj_fz=0;
}
else
{
dj_zz=0;
dj_fz=1;
}
if(kg1==0)//监测行程开关1状态
{
dj_zz=0;//关闭电机并延时
dj_fz=0;
delay_ms(100);
i++;//控制电机下次启动换向
read_temp();//读存温度信息
}
if(kg2==0)//监测行程开关2状态
{
dj_zz=0;
dj_fz=0;
delay_ms(100);
read_temp();
}
if(kg3==0)//监测行程开关3状态
{
dj_zz=0;
dj_fz=0;
delay_ms(100);
read_temp();
}
if(kg4==0)//监测行程开关4状态
{
dj_zz=0;
dj_fz=0;
delay_ms(100);
i--;//控制电机下次启动换向
read_temp();
}
beijingdeng();//调入背景灯控制函数,监测感光信号
refresh_led();//显示温度信息
if(aj_qh==0)//监测自动/手动切换_按键状态
{
dj_zz=0;//监测到切换到手动状态时,电机停转
dj_fz=0;
break;//跳出自动控制循环,进入主函数
}
}
}
自动控制状态下,手动/自动指示灯控制引脚输出为低电平,指示灯亮;判断电机正反转状态,并控制电机正反转;监测行程开关1状态,若为低电平,则关闭电机,延时并控制电机下次启动换向;若为高电平,则不变。
然后读存温度信息并依次监测行程开关2、3状态,若为低电平,则关闭电机,延时并读存温度信息。
然后监测行程开关4状态,若为低电平,则关闭电机,延时并控制电机下次启动换向。
最后监测自动/手动切换_按键状态,若为低电平,则电机停转,跳出自动控制循环,进入主函数。
5.手动控制模块程序
voidshoudong()//手动控制子函数
{
led_zs=1;//关闭自动/手动指示灯
while
(1)
{
if(aj_zz==0)//按下正转按键时,电机正转
{
dj_zz=0;
dj_fz=1;
}
if(aj_fz==0)//按下反转按键时,电机反转
{
dj_zz=1;
dj_fz=0;
}
if(aj_fz==1&&aj_zz==1)//无按键按下,电机停转
{
dj_zz=0;
dj_fz=0;
}
if(aj_qh==1)//监测自动/手动切换_按键状态
{
break;//监测到切换到自动状态时,跳出手动控制循环,
}//进入主函数
refresh_led();//显示温度信息
beijingdeng();//调入背景灯控制函数,监测感光信号
}
}
手动控制状态下,手动/自动指示灯控制引脚输出为高电平,指示灯灭;若按下正转按键,则L298芯片OUT1输出+12V,OUT2输出0V,电机正转;若按下反转按键,则L298芯片OUT1输出0V,OUT2输出+12V,电机反转;若无按键按下,则L298芯片OUT1输出0V,OUT2输出0V,电机停转。
6.主程序模块程序
main()
{
while
(1)
{
if(aj_qh==0)//监测自动/手动切换_按键状态,
{//并控制进入相应子函数
shoudong();
}
else
{
zidong();
}
}
}
若自动/手动切换_按键按下时,控制引脚输出为低电平,电机状态为手动控制;若自动/手动切换_按键无按下时,控制引脚输出为高电平,电机状态为自动控制。
四、程序框图
五、程序清单
#include
externvoid_nop_(void);
typedefunsignedcharuint8;
typedefunsignedintuint16;
typedefunsignedlonguint32;
typedefcharint8;
typedefintint16;
codeuint8Disp_Tab[]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x00,0x40};
codeuint8dispbit[4]={0xfe,0xfd,0xfb,0xf7};//数码管位选控制变量
uint8a[4];//数码管显示控制变量
uint8i=0;//电机正反转控制变量
#definenops();{_nop_();_nop_();_nop_();_nop_();}//定义空指令,调整控制温感驱动时序
sbitdj_zz=P3^0;//定义电机正反转控制引脚
sbitdj_fz=P3^1;
sbitled_bjd=P3^2;//定义背景灯控制引脚
sbitled_zs=P3^3;//定义指示灯控制引脚
sbitDQ=P3^6;//温度输入口
sbitggxh=P3^7;//定义感光信号引脚
sbitkg1=P0^0;//定义行程开关1信号引脚
sbitkg2=P0^1;//定义行程开关2信号引脚
sbitkg3=P0^2;//定义行程开关3信号引脚
sbitkg4=P0^3;//定义行程开关4信号引脚
sbitaj_fz=P0^4;//定义电机正反转_按键信号引脚
sbitaj_zz=P0^5;
sbitaj_qh=P0^6;//定义自动/手动切换_按键信号引脚
/*数码管动态扫描函数*/
voidrefresh_led()
{
P2=Disp_Tab[a[0]];P1=dispbit[0];P1=0xff;//每个数码管按负值、打开、关闭的顺序
P2=Disp_Tab[a[1]];P1=dispbit[1];P1=0xff;
P2=Disp_Tab[a[2]]|0x80;P1=dispbit[2];P1=0xff;
P2=Disp_Tab[a[3]];P1=dispbit[3];P1=0xff;
}
/*两个延时函数*/
voiddelay(uint16n)
{
while(n--);
}
voiddelay_ms(uint16n)
{
uint8m=120;
while(n--)
while(m--)
refresh_led();//刷新显示温度信息
}
/*18B20复位函数*/
voidDS18b20_reset(void)
{
bitflag=1;
while(flag)
{
while(flag)
{
DQ=1;
delay
(1);
DQ=0;
delay(50);//延时550us
DQ=1;
delay(6);//延时66us
flag=DQ;
}
delay(45);//延时500us
flag=~DQ;
}
DQ=1;
}
/**18B20写1个字节函数*/
voidwrite_byte(uint8val)
{
uint8i;
for(i=0;i<8;i++)
{
DQ=1;
_nop_();
DQ=0;
nops();//4us
DQ=val&0x01;//最低位移出
delay(6);//延时66us
val>>=1;//右移一位
}
DQ=1;
delay
(1);
}
/**18B20读1个字节函数*/
uint8read_byte(void)
{
uint8i,value=0;
for(i=0;i<8;i++)
{
DQ=1;
_nop_();
value>>=1;
DQ=0;
nops();//延时4us
DQ=1;
nops();//延时4us
if(DQ)
value|=0x80;
delay(6);//延时66us
}
DQ=1;
return(value);
}
/**启动温度转换*/
voidstart_temp_sensor(void)
{
DS18b20_reset();
write_byte(0xCC);//发SkipROM命令
write_byte(0x44);//发转换命令
}
/**读存温度*/
voidread_temp()
{
uint8temp_data[2];//读出温度暂放
uint16temp=0,c;
doublewd;
start_temp_sensor();
delay_ms(100);
DS18b20_reset();//复位
write_byte(0xCC);//发SkipROM命令
write_byte(0xBE);//发读命令
temp_data[0]=read_byte();//温度低8位
temp_data[1]=read_byte();//温度高8位
temp=temp_data[1];//一下三步将温度高八位低八位整合
temp<<=8;
temp|=temp_data[0];
if(temp_data[1]&0xf0)//判断温度是否为负
{
temp=(~temp)+1;//为负时,取反加一
wd=temp*0.0625;//转为摄氏温度,0.0625为温感芯片储存精度
a[0]=11;//为负时,第一个数码管显示负号
}
else
{
wd=temp*0.0625;
a[0]=10;//为正时,第一个数码管不显示
}
c=wd;//将摄氏温度转为整型
a[2]=c%10;//第三个数码管显示个位
a[1]=c/10%10;//第二个数码管显示十位
c=wd*10;
a[3]=c%10;//第四个数码管显示小数位
}
/*背景灯控制子函数*/
voidbeijingdeng()
{
if(ggxh)led_bjd=1;
elseled_bjd=0;
}
/*自动控制子函数*/
voidzidong()
{
led_zs=0;//点亮自动/手动指示灯
while
(1)
{
if(i)//判断电机正反转状态,并控制电机正反转
{
dj_zz=1;
dj_fz=0;
}
else
{
dj_zz=0;
dj_fz=1;
}
if(kg1==0)//监测行程开关1状态
{
dj_zz=1;//关闭电机并延时
dj_fz=1;