PIC课程设计报告LM35温度报警器.docx
《PIC课程设计报告LM35温度报警器.docx》由会员分享,可在线阅读,更多相关《PIC课程设计报告LM35温度报警器.docx(16页珍藏版)》请在冰豆网上搜索。
PIC课程设计报告LM35温度报警器
PIC课程设计报告
LM35温度报警器
专业:
电子信息工程
组长:
组员:
学号:
指导教师:
一、设计要求:
1、4*4键盘设定,最高温度,最低温度限制(0-9数字+功能键);
2、LCD1602液晶显示当前温度,最高温度,最低温度限制值,报警检测周期;
3、LM35温度传感器输出(0-1.0V对应0-100℃);
4、24C02存储设定的最高温度,最低温度限制值;
5、低于设置的最低温度或高于最高温度LED会闪烁报警。
例如:
键盘输入最低温度20℃,最高温度30℃。
当传感器温度小于20或大于30℃,LED会闪烁报警;
2、系统组成及工作原理
1、系统框图
2、工作原理
(1)总体设计思想
本设计是以PIC18F452单片机作为控制核心,以LM35的温度传感器作为单片机的输入。
首先通过4*4矩阵键盘设定一个最高温度和最低温度作为报警器报警的条件,然后单片机通过实时监控温度的变化,通过LCD1602字符型液晶显示各节点温度的数值,当温度值超出所设定的值时,LED开始闪烁报警,从而实现对整个温度系统的管理和控制。
(2)各模块设计
1)、4*4矩阵键盘的设计
根据设计任务书中要求实现的功能,我选择了一个4*4矩阵键盘来设置最高温度、最低温度和检测周期,4*4键盘能够符合设计要求,其中10个键来设置具体的数值,另外六个键为功能键,具体设计后面详述。
①矩阵键盘结构:
键盘实际上是一组按键开关的集合,平时按键开关总是处于断开状态,当按下键时它才闭合。
键盘结构能够有效的提高单片机系统中I/O口的利用率。
它的结构和产生的波形如图2-4所示。
图2-4键盘结构及产生的波形图
单片机应用系统中除了复位按键有专门的复位电路,以及专一的复位功能外,其它的按键或键盘都是以开关状态来设置控制功能或输入数据。
键开关状态的可靠输入:
如果检测到有按键按下时,延时5到10ms进行消除按键抖动,再确认该键电平是否仍保持闭合状态电平,如保持闭合状态电平则确认为真正键按下状态,从而消除了抖动影响。
在这种行列式矩阵键盘非编码键盘的单片机系统中,键盘处理程序首先执行等待按键并确认有无按键按下的程序段。
当确认有按键按下后,下一步就要识别哪一个按键按下。
我们使用的是逐行扫描查询法。
由于考虑到后面I2C的写入要用到RC端口的3、4引脚,故我们这里用的是RB端口的RB0-2和RB6四个个引脚接行,RB7和RC5-7接列。
键盘共有16个按键,用于方便设定温度。
表5-1键盘的按键分布
0
1
2
3
4
5
6
7
8
9
复位
复位
无
无
无
无
2)、LCD1602液晶显示的设计
温度显示工作原理:
LCD1602可以采用两种方式与单片机连接,一种是采用8位数据总线D0—D7,和RS、R/W、EN三个控制端口;另一种是只用D4-D7作为四位数据分两次传送。
本实验将使用并采用八位数据方式来控制1602显示。
进行LCD设计主要是LCD的控制/驱动和外界的接口设计。
控制主要是通过接口与外界通信、管理内/外显示RAM,控制驱动器,分配显示数据;驱动主要是根据控制器要求,驱动LCD进行显示。
控制器还常含有内部ASCII字符库,或可外扩的大容量汉字库。
内部引线已经连接好,不用外接杜邦线。
3)、LM35温度传感器的设计
PIC18F452内置的是10位A/D转换器,但是一次只能读入8位,故要用到两个存储空间,根据采用A/D转换后结果的对齐方式不同而有不同的读取方法,一般是采用右对齐的。
在程序运行时,LM35温度传感器从零摄氏度输出零伏起每升高一摄氏度输出增加10mV。
由LM35温度传感器输入的电压经过A/D转换成10位的数字量转换成实际的电压值,并将实际的电压值的各个位分开装入显示缓冲区。
转换后的数字量为0--1023,而我们所需要的温度为0--100,这里有一个换算的过程,将AD转换而来的结果整除10,这样得到的结果刚好在0--100内。
然后将转换的结果显示在LCD上。
测量电压与编码值的关系式:
4)、24C02的应用
利用I2C进行对EEPROM进行写操作和读操作,将每次我们设定好的最高温度、最低温度,检测周期写入EEPROM,然后在每次上电复位时,将上一次存入的值显示为初始值,这样可以对上一次的操作保留记忆。
写操作必须要写入器件地址、存储区地址、存储的内容,以下是写操作的时序图:
5)、LED灯报警
如果当前温度超过最高设定或者低于最低设定,LED灯会闪烁进行报警。
程序设计中用的是RB0接蜂鸣器,当达到条件时,蜂鸣器开始鸣叫。
3、单片机程序
#include
#include
#include
#include
#defineRB0PORTBbits.RB0
#defineRB1PORTBbits.RB1
#defineRB2PORTBbits.RB2
#defineRB6PORTBbits.RB6
#defineRB7PORTBbits.RB7
#defineRC5PORTCbits.RC5
#defineRC6PORTCbits.RC6
#defineRC7PORTCbits.RC7
#definesclPORTCbits.RC3
#definesdaPORTCbits.RC4
#defineLEDPORTCbits.RC0
#defineRSPINPORTBbits.RB5//DataorInstrumentSelect
#defineRWPINPORTBbits.RB4//WriteorRead
#defineEPINPORTBbits.RB3//6800modeEnablesingle
voidkey(void);
voidchoose(void);
voidread_T(void);
voiddisplay(void);
voidlcdreset(void);
voidlcd_wait_busy(void);
voidlcd_write_com(unsignedcharcombuf);
voidlcd_write_com_busy(unsignedcharcombuf);
voidlcd_write_data(unsignedchardatabuf);
voidlcd_write_address(unsignedcharx,unsignedchary);
voidwrite_t(unsignedcharx,unsignedinty,unsignedintdata);
voidlcd_write_char(unsignedcharx,unsignedchary,unsignedcharbuf);
voidlcd_write_string(unsignedcharx,unsignedchary,unsignedchar*s);
unsignedinti,j;
unsignedintresult=0,T=0;
unsignedintlowt=100,hight=400;
unsignedintnumber=0,times=0;
//---------------------------------------
//名称:
主函数
//-----------------------------------------
voidmain(void)
{
OpenI2C(MASTER,SLEW_ON);//configureA/Dconvertor
TRISC=0B11111110;
TRISB=0B10000000;//RB3-5设置为输出
TRISD=0B00000000;//RD设置为输出
lcdreset();//复位1602
while
(1)
{
read_T();
if(EERandomRead(0xa0,0x0f0)==255)
{
lowt=EERandomRead(0xa0,0x0f1)*255+EERandomRead(0xa0,0x0f2);
hight=EERandomRead(0xa0,0x0f3)*255+EERandomRead(0xa0,0x0f4);
}
else
write_t(0xa0,0x0f0,255);
key();
if(times==1)lowt=lowt%100+number*100;
elseif(times==2)lowt=100*(int)(lowt/100)+lowt%10+number*10;
elseif(times==3)lowt=10*(int)(lowt/10)+number;
elseif(times==4)hight=hight%100+number*100;
elseif(times==5)hight=100*(int)(hight/100)+hight%10+number*10;
elseif(times==6)hight=10*(int)(hight/10)+number,times=0;
display();
if(Thight)
{
LED=1;
Delay10KTCYx(10);
}
LED=0;
write_t(0xa0,0x0f1,lowt/255);
write_t(0xa0,0x0f2,lowt%255);
write_t(0xa0,0x0f3,hight/255);
write_t(0xa0,0x0f4,hight%255);
}
}
//---------------------------------------
//名称:
设置最低温度和最高温度的函数
//-----------------------------------------
voidwrite_t(unsignedcharx,unsignedinty,unsignedintdata)
{
StartI2C();
Nop();
WriteI2C(x);
Nop();
WriteI2C(y);
Nop();
WriteI2C(data);
Nop();
StopI2C();
Delay10KTCYx
(1);
}
//---------------------------------------
//名称:
读取温度数的函数
//-----------------------------------------
voidread_T()
{
OpenADC(ADC_FOSC_32&ADC_RIGHT_JUST&ADC_7ANA_1REF,ADC_CH0&ADC_INT_OFF);
//A/D时钟源,晶振32分频率,A/D转换结果右对齐,A/D参考电压源,电源工作电压
//通道选择中断关闭,查询模式
Delay10TCYx(5);//Delayfor50TCY
ConvertADC();//Startconversion
while(BusyADC());//Waitforcompletion
result=ReadADC();//Readresult
CloseADC();//DisableA/Dconverter
Nop();
T=result*2908.0/1023;
}
//---------------------------------------
//名称:
显示函数
//-----------------------------------------
voiddisplay()
{
lcd_write_char(2,1,lowt/100+0x30);
lcd_write_char(3,1,lowt/10%10+0x30);
lcd_write_char(4,1,'.');
lcd_write_char(5,1,lowt%10+0x30);
lcd_write_char(10,1,hight/100+0x30);
lcd_write_char(11,1,hight/10%10+0x30);
lcd_write_char(12,1,'.');
lcd_write_char(13,1,hight%10+0x30);
lcd_write_char(10,0,T/100+0x30);
lcd_write_char(11,0,T/10%10+0x30);
lcd_write_char(12,0,'.');
lcd_write_char(13,0,T%10+0x30);
}
//---------------------------------------
//名称:
检测按键的状态函数
//-----------------------------------------
voidchoose()
{
if(RB7==0)
number=i,Delay10KTCYx(50),times++;
elseif(RC5==0)
number=i+1,Delay10KTCYx(50),times++;
elseif(RC6==0)
number=i+2,Delay10KTCYx(50),times++;
elseif(RC7==0)
number=i+3,Delay10KTCYx(50),times++;
Nop();
}
//---------------------------------------
//名称:
按键低电平输入
//-----------------------------------------
voidkey()
{
RB0=0,RB1=1,RB2=1,RB6=1;
i=0;
choose();
RB0=1,RB1=0,RB2=1,RB6=1;
i=4;
choose();
RB0=1,RB1=1,RB2=0,RB6=1;
i=8;
choose();
RB0=1,RB1=1,RB2=1,RB6=0;
i=12;
choose();
if(number>=10)
times=0;
Nop();
}
//---------------------------------------
//名称:
1602忙检测函数
//-----------------------------------------
voidlcd_wait_busy(void)
{
TRISDbits.TRISD7=1;//为读状态做准备
RSPIN=0;//选择指令寄存器
RWPIN=1;//选择读
EPIN=1;//使能线电平变化
while(PORTDbits.RD7==1);//读忙状态,不忙时退出
EPIN=0;//恢复使能线电平
TRISDbits.TRISD7=0;
}
//---------------------------------------
//名称:
1602写命令函数
//-----------------------------------------
voidlcd_write_com(unsignedcharcombuf)
{
RSPIN=0;//选择指令寄存器
RWPIN=0;//选择写
PORTD=combuf;//把命令字送入RD
EPIN=1;//使能线电平变化,命令送入1602的8位数据口
Delay1TCY();
EPIN=0;//恢复使能线电平
}
//---------------------------------------
//名称:
1602写命令函数(带忙检测)
//-----------------------------------------
voidlcd_write_com_busy(unsignedcharcombuf)
{
lcd_wait_busy();//调用忙检测函数
lcd_write_com(combuf);//调用写命令函数
}
//---------------------------------------
//名称:
1602写数据函数(带忙检测)
//-----------------------------------------
voidlcd_write_data(unsignedchardatabuf)
{
lcd_wait_busy();//调用忙检测函数
RSPIN=1;//选择数据寄存器
RWPIN=0;//选择写
PORTD=databuf;//把数据字送入P2
EPIN=1;//使能线电平变化,命令送入1602的8位数据口
Delay1TCY();
EPIN=0;//恢复使能线电平
}
//---------------------------------------
//名称:
1602显示地址写函数
//-----------------------------------------
voidlcd_write_address(unsignedcharx,unsignedchary)
{
x&=0x0f;//列地址限制在0-15
y&=0x01;//行地址限制在0-1
if(y==0x00)
lcd_write_com_busy(x|0x80);//第一行的列地址写入
else
lcd_write_com_busy((x+0x40)|0x80);//第二行的列地址写入
}
//---------------------------------------
//名称:
1602初始化函数
//-----------------------------------------
voidlcdreset(void)
{
Delay100TCYx(15);
lcd_write_com_busy(0x38);//8位数据,双列,5*7字形
lcd_write_com_busy(0x08);//显示功能关,无光标
lcd_write_com_busy(0x01);//写入新的数据后,光标右移,显示屏不移动
Delay10KTCYx
(1);
lcd_write_com_busy(0x0c);//显示功能开,无光标,
lcd_write_char(14,0,'C');
lcd_write_char(8,0,'T');
lcd_write_char(9,0,'=');
lcd_write_char(0,1,'L');
lcd_write_char(1,1,'=');
lcd_write_char(6,1,'C');
lcd_write_char(8,1,'H');
lcd_write_char(9,1,'=');
lcd_write_char(14,1,'C');
}
//--------------------------------------
//名称:
指定地址写入函数
//-----------------------------------------
voidlcd_write_char(unsignedcharx,unsignedchary,unsignedcharbuf)
{
lcd_write_address(x,y);//写入地址
lcd_write_data(buf);//写入显示数据
}
4、单片机仿真
5、心得与总结