单片机课程设计.docx
《单片机课程设计.docx》由会员分享,可在线阅读,更多相关《单片机课程设计.docx(30页珍藏版)》请在冰豆网上搜索。
单片机课程设计
2017届课程设计
《基于单片机步进电机温度控制系统》
塔里木大学教务处制
目录
摘要:
3
一、设计要求3
二、系统组成方框图3
三、电路设计说明3
3.1单片机AT89C513
3.2步进电机5
3.3DS18B20温度传感器5
3.4LCD1602液晶显示屏6
3.5工作原理7
四、总结7
4.1参考文献7
4.2仿真图7
4.3代码9
摘要:
本课题是一种基于单片机步进电机控制系统的软硬件设计。
本设计能实现出步进电机的正转,反转。
通过数字温度传感器DS18B20对温度进行监控实现超温报警提示,温度过高电机将会正转,温度过低将会反转。
该系统具有控制方便、结构简单、界面友好、和系统运行稳定等优点,具有一定的应用价值。
一、设计要求
1、设计一个基于单片机步进电机温度控制系统;
2、在LCD屏上显示温度控制的上下限和当前室温;
3、可以调节温度的上下限;
4、室温超过设定的上限时,步进电机将会正转,室温低于设定的下限时,步进电机将会反转;
二、系统组成方框图
如图:
三、电路设计说明
3.1单片机AT89C51
AT89C51是美国ATMEL公司生产的低电压,高性能CMOS8位单片机,片内含4kbytes的可反复擦写的只读程序存储器(PEROM)和128bytes的随机存取数据存储器(RAM),器件采用ATMEL公司的高密度、非易失性存储技术生产,兼容标准MCS-51指令系统,片内置通用8位中央处理器(CPU)和Flash存储单元,功能强大AT89C51单片机能提供许多高性价比的应用场合,可灵活应用于各种控制领域。
AT89C51
3.3DS18B20温度传感器
DS18B20单线数字温度传感器,即“一线器件”,其具有独特的优点:
a.采用单总线的接口方式与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯。
单总线具有经济性好,抗干扰能力强,适合于恶劣环境的现场温度测量,使用方便等优点,使用户可轻松地组建传感器网络,为测量系统的构建引入全新概念。
b.测量温度范围宽,测量精度高DS18B20的测量范围为-55℃~+125℃;在-10~+85°C范围内,精度为±0.5°C。
c.持多点组网功能多个DS18B20可以并联在惟一的单线上,实现多点测温。
d.供电方式灵活DS18B20可以通过内部寄生电路从数据线上获取电源。
因此,当数据线上的时序满足一定的要求时,可以不接外部电源,从而使系统结构更趋简单,可靠性更高。
f.测量结果以9~12位数字量方式串行传送
单线总线特点:
单总线即只有一根数据线,系统中的数据交换,控制都由这根线完成。
单总线通常要求外接一个约为4.7K—10K的上拉电阻,这样,当总线闲置时其状态为高电平。
DS18B20单总线的工作方式:
DS18B20的初始化:
主机首先发出一个480-960微秒的低电平脉冲,然后释放总线变为高电平,并在随后的480微秒时间内对总线进行检测,如果有低电平出现说明总线上有器件已做出应答。
若无低电平出现一直都是高电平说明总线上无器件应答。
做为从器件的DS18B20在一上电后就一直在检测总线上是否有480-960微秒的低电平出现,如果有,在总线转为高电平后等待15-60微秒后将总线电平拉低60-240微秒做出响应存在脉冲,告诉主机本器件已做好准备。
若没有检测到就一直在检测等待。
主机发出各种操作命令都是向DS18B20写0和写1组成的命令字节,接收数据时也是从DS18B20读取0或1的过程。
因此首先要搞清主机是如何进行写0、写1、读0和读1的。
写周期最少为60微秒,最长不超过120微秒。
写周期一开始做为主机先把总线拉低1微秒表示写周期开始。
随后若主机想写0,则将总线置为低电平,若主机想写1,则将总线置为高电平,持续时间最少60微秒直至写周期结束,然后释放总线为高电平至少1微秒给总线恢复。
而DS18B20则在检测到总线被拉底后等待15微秒然后从15us到45us开始对总线采样,在采样期内总线为高电平则为1,若采样期内总线为低电平则为0。
对于读数据操作时序也分为读0时序和读1时序两个过程。
读周期是从主机把单总线拉低1微秒之后就得释放单总线为高电平,以让DS18B20把数据传输到单总线上。
作为从机DS18B20在检测到总线被拉低1微秒后,便开始送出数据,若是要送出0就把总线拉为低电平直到读周期结束。
若要送出1则释放总线为高电平。
主机在一开始拉低总线1微秒后释放总线,然后在包括前面的拉低总线电平1微秒在内的15微秒时间内完成对总线进行采样检测,采样期内总线为低电平则确认为0。
采样期内总线为高电平则确认为1。
完成一个读时序过程,至少需要60微秒才能完成
3.4LCD1602液晶显示屏
1602采用标准的16脚接口,其中:
第1脚:
GND为电源地
第2脚:
VCC接5V电源正极
第3脚:
V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高(对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度)。
第4脚:
RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。
第5脚:
RW为读写信号线,高电平
(1)时进行读操作,低电平(0)时进行写操作。
第6脚:
E(或EN)端为使能(enable)端,高电平
(1)时读取信息,负跳
变时执行指令。
第7~14脚:
D0~D7为8位双向数据端。
第15~16脚:
空脚或背灯电
源。
15脚背光正极,16脚背光负极。
特性:
3.3V或5V工作电压,对比度可调,内含复位电路,提供各种控制命令,如:
清屏、字符闪烁、光标闪烁、显示移位等多种功能,有80字节显示数据存储器DDRAM,内建有192,5X7点阵的字型的字符发生器CGROM,8个可由用户自定义的5X7的字符发生器CGRAM
通信协议:
每次通信//写数据时RS=L
lcden=0;//使能端高电平无效
P0=date;//给端口送数据
delay(5);//延时5MS
lcden=1;//使能端高电平有效
delay(5);
lcden=0;
LCD1602液晶显示屏
3.524C02暂存器
CAT24WC01/02/04/08/16是一个1K/2K/4K/8K/16K位串行CMOSE2PROM内部含有
128/256/512/1024/2048个8位字节CATALYST公司的先进CMOS技术实质上减少了器件的功耗
CAT24WC01有一个8字节页写缓冲器CAT24WC02/04/08/16有一个16字节页写缓冲器该器件通过
I2C总线接口进行操作有一个专门的写保护功能
3.6工作原理
通过DS18B20温度传感器采集室温,传输给单片机;设定温度的上下限,用的是P3.0,P3.1,P3.2口来调节;P0.0~P0.7口来输出给LCD1062液晶显示器;P1.0~P1.3四个口来控制步进电机的转动;P2.7口是控制LCD的E端使能端,高电平
(1)时读取信息,负跳变时执行指令;P2.6控制LCD的RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器;P2.5口控制LCD的RW为读写信号线,高电平
(1)时进行读操作,低电平(0)时进行写操作。
当室温高于设定的温度时,步进电机会正转,当室温低于设定温度时,步进电机反转。
四、总结
4.1参考文献
[1]王静霞.单片机应用技术.电子工业出版社.2009。
[2]楼然苗.单片机课程设计指导.北京航空航天大学出版社..2007
[3]周润景.《Proteus在MCS-51&ARM7系统中的应用百例》.电子工业出版社.2006
4.2仿真图
4.3代码
主函数
#include
#include"i2c.h"
#defineuintunsignedint
#defineucharunsignedchar
//第4个引脚是RS,5是RW,,6是en
sbitlcdrs=P2^6;//数据命令端口
sbitlcdrw=P2^5;//读写端口.我们在这里只写/
sbitlcden=P2^7;//使能端口。
sbitDQ=P3^7;//ds18b20端口
sbitK1=P3^1;//温度的上线加
sbitK2=P3^2;//温度的下线减
sbitK3=P3^0;//上下线切换
sbitK4=P3^3;//温度的上线加
sbitK5=P3^4;//温度的下线减
sbitK6=P3^5;
sbitA1=P1^0;//定义步进电机连接端口
sbitB1=P1^1;
sbitC1=P1^2;
sbitD1=P1^3;
sbitLSA=P2^2;
sbitLSB=P2^3;
sbitLSC=P2^4;
voidAt24c02Write(unsignedchar,unsignedchar);
unsignedcharAt24c02Read(unsignedchar);
#defineCoil_A1{A1=1;B1=1;C1=0;D1=0;}//A相通电,其他相断电
#defineCoil_B1{A1=0;B1=1;C1=1;D1=0;}//B相通电,其他相断电
#defineCoil_C1{A1=0;B1=0;C1=1;D1=1;}//C相通电,其他相断电
#defineCoil_D1{A1=1;B1=0;C1=0;D1=1;}//D相通电,其他相断电
unsignedcharSpeed;
voidDelayUs2x(unsignedchart)
{
while(--t);
}
voidDelayMs(unsignedchart)
{
while(t--)
{
//大致延时1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
intHwendu=23,Lwendu=20,flag=1,qiehuan;
uinttemp,TempH,TempL;
ucharcodetable1[]="";
ucharcodetable2[]="";
unsignedinti;
voidAt24c02Write(unsignedcharaddr,unsignedchardat)
{
I2C_Start();
I2C_SendByte(0xa0,1);//发送写器件地址
I2C_SendByte(addr,1);//发送要写入内存地址
I2C_SendByte(dat,0);//发送数据
I2C_Stop();
}
unsignedcharAt24c02Read(unsignedcharaddr)
{
unsignedcharnum;
I2C_Start();
I2C_SendByte(0xa0,1);//发送写器件地址
I2C_SendByte(addr,1);//发送要读取的地址
I2C_Start();
I2C_SendByte(0xa1,1);//发送读器件地址
num=I2C_ReadByte();//读取数据
I2C_Stop();
returnnum;
}
voiddelay(uintz)
{
uintx,y;
for(x=0;xfor(y=0;y<110;y++);
}
voiddelay1(unsignedinti)//延时函数
{
while(i--);
}
voidInit_DS18B20(void)
{
unsignedcharx=0;
DQ=1;//DQ复位
delay1(8);//稍做延时
DQ=0;//单片机将DQ拉低
delay1(80);//精确延时大于480us
DQ=1;//拉高总线
delay1(10);
x=DQ;//稍做延时后如果x=0则初始化成功x=1则初始化失败
delay(5);
}
/******************************************************************/
/*读一个字节*/
/******************************************************************/
unsignedcharReadOneChar(void)
{
unsignedchari=0;
unsignedchardat=0;
for(i=8;i>0;i--)
{
DQ=0;//给脉冲信号
dat>>=1;
DQ=1;//给脉冲信号
if(DQ)
dat|=0x80;
delay1(5);
}
return(dat);
}
/******************************************************************/
/*写一个字节*/
/******************************************************************/
voidWriteOneChar(unsignedchardat)
{
unsignedchari=0;
for(i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
delay1(5);
DQ=1;
dat>>=1;
}
delay1(5);
}
/******************************************************************/
/*读取温度*/
/******************************************************************/
unsignedintReadTemperature(void)
{
unsignedchara=0;
unsignedintb=0;
unsignedintt=0;
Init_DS18B20();
WriteOneChar(0xCC);//跳过读序号列号的操作
WriteOneChar(0x44);//启动温度转换
delay1(200);
Init_DS18B20();
WriteOneChar(0xCC);//跳过读序号列号的操作
WriteOneChar(0xBE);//读取温度寄存器等(共可读9个寄存器)前两个就是温度
a=ReadOneChar();//低位
b=ReadOneChar();//高位
b<<=8;
t=a+b;
return(t);
}
voidwrite_com(ucharcom)
{
lcdrs=0;//写指令时RS=L
lcden=0;
P0=com;//给端口送指令
delay(5);//延时5MS
lcden=1;//使能端高电平有效
delay(5);
lcden=0;
}
voidwrite_date(uchardate)
{
lcdrs=1;//写数据时RS=L
lcden=0;
P0=date;//给端口送数据
delay(5);//延时5MS
lcden=1;//使能端高电平有效
delay(5);
lcden=0;
}
voidinit()
{
ucharnum;
lcdrw=0;//写信号拉低
lcden=0;//使能端拉低
write_com(0x38);//开显示
write_com(0x0c);//0e开显示不显示光标
write_com(0x06);//每写一个地址和光标加一
write_com(0x01);//显示清零
write_com(0x80);//第一行的初始地址为0x80
for(num=0;num<14;num++)//循环的数字要看上面的占多少个字符
{
write_date(table1[num]);//多了和少了都不会对的。
delay(5);
}
write_com(0x80+0x40);//第二行初始地址为0x80+0x40
for(num=0;num<14;num++)
{
write_date(table2[num]);
delay(5);
}
}
voidkey()
{
if(K3==0)//高低线切换
{
delay(20);
if(K3==0)
{
qiehuan=!
qiehuan;
while(!
K3);
}
}
if(qiehuan==0)//高上线
{
if(K1==0)//加
{
delay(20);
if(K1==0)
{
Hwendu++;
DelayMs
(1);
At24c02Write(2,Hwendu);
if(Hwendu>=99)
{
Hwendu=99;
}
while(!
K1);
}
}
if(K2==0)//减
{
delay(20);
if(K2==0)
{
Hwendu--;
DelayMs
(1);
At24c02Write(2,Hwendu);
if(Hwendu<=0)
{
Hwendu=0;
}
while(!
K1);
}
}
write_com(0x80+10);
write_date(0x40+8);
write_date(0x30+10);
write_date(0x30+Hwendu/10);
write_date(0x30+Hwendu%10);
write_date(0xd0+15);
write_date(0x40+3);
}
if(qiehuan==1)//下线
{
if(K1==0)//加按键
{
delay(20);
if(K1==0)
{
Lwendu++;
At24c02Write(3,Lwendu);
if(Lwendu>=99)
{
Lwendu=99;
}
while(!
K1);
}
}
if(K2==0)//减
{
delay(20);
if(K2==0)
{
Lwendu--;
DelayMs
(1);
At24c02Write(3,Lwendu);
if(Lwendu<=0)
{
Lwendu=0;
}
while(!
K1);
}
}
write_com(0x80+0x40+10);
write_date(0x40+12);
write_date(0x30+10);
write_date(0x30+Lwendu/10);
write_date(0x30+Lwendu%10);
write_date(0xd0+15);
write_date(0x40+3);
}
}
unsignedinti;
unsignedintnum0=4,num1=0,n;
charc;
voidmain()
{
init();
while
(1)
{
temp=ReadTemperature();//温度读取
if(temp&0x8000)//判断
{
flag=0;//负号标志
temp=~temp;//取反加1
temp+=1;
}
else
{
temp=temp;
flag=1;//温度为正标志位1
}
TempH=temp>>4;//温度高4位
write_com(0x80+0x40);
if(flag==0)
{write_date(0xB0);}//负号标志
else
{write_date(0x20+11);}//正号标志.
write_com(0x80+0x41);
write_date(0x30+TempH/10);//显示温度的十位
write_date(0x30+TempH%10);//显示温度的各位
TempL=temp&0x0F;
TempL=TempL*6;//小数近似处理
write_com(0x80+0x43);
write_date(0x2e);//显示小数点
write_date(0x30+TempL/10);//显示温度的小数
write_date(0xd0+15);
write_date(0x40+3);
key();//按键扫描
DelayMs
(1);
Hwendu=At24c02Read
(2);
DelayMs
(1);
Lwendu=At24c02Read(3);
write_com(0x80);
write_date(0x40+8);
write_date(0x40+5);
write_date(0x40+12);
write_date(0x40+12);
write_date(0x40+15);
write_com(0x80+7);
write_com(0x80+10);//高上线
write_date(0x40+8);
write_date(0x30+10);
write_date(0x30+Hwendu/10);
write_date(0x30+Hwendu%10);
write_date(0xd0+15);
write_date(0x40+3);
write_com(0x80+0x40+10);//低下线
write_date(0x40+12);
write_date(0x30+10);
write_date(0x30+Lwendu/10);
write_date(0x30+Lwendu%10);
write_date(0xd0+15);
write_date(0x40+3);
for(i=0;i<15;i++)
{
if((TempH*10+TempL/10)>(Hwendu*10)&&(flag==1))//温度判断
{
if(K3==0)//高低线切换
{
de