PIC18f452LM35温度报警MCP4725正弦波发生器Word格式文档下载.docx
《PIC18f452LM35温度报警MCP4725正弦波发生器Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《PIC18f452LM35温度报警MCP4725正弦波发生器Word格式文档下载.docx(35页珍藏版)》请在冰豆网上搜索。
工作原理是利用电容在一定的交流信号频率下产生的容抗来限制最大工作电流
分类
线性稳压器、开关稳压器、充电泵
按整流电路分:
半波整流、桥式整流
半波整流、全波整流
组成
开关电源一般由脉冲宽度调制(PWM)控制IC和MOSFET构成
电源变压器
整流电路
滤波电路
稳压电路
降压电容器、半波整流二极管、稳压二极管、
电阻
优点
高效率,宽电压输入范围低功率耗散,提供隔离(利用变压器)
低噪声,低纹波,良好的负载调整率,高稳定度,高准确度。
低成本取得非隔离的小电流电源。
它的输出电压通常可在几伏到三几十伏
缺点
瞬态响应慢,加大设计难度,较高的输出纹波和噪声
效率低
电容降压式电源是一种非隔离电源,在应用上要特别注意隔离,防止触电。
三、温度检测
1、设计方案
用LM35温度传感器检测温度,输入单片机,经过AD转换,显示到LCD显示屏。
通过4*4矩阵键盘设定最高温度、最低温度,将检测到的温度值与设定温度比较,超过范围则蜂鸣器响起报警。
2、模块设计
1)4*4矩阵键盘的设计
键盘需用到k1~k10作为0~9数字输入,k15作为复位,k16作为开始。
键开关状态的可靠输入:
如果检测到有按键按下时,延时5到10ms进行消除按键抖动,再确认该键电平是否仍保持闭合状态电平,如保持闭合状态电平则确认为真正键按下状态,从而消除了抖动影响。
在这种行列式矩阵键盘非编码键盘的单片机系统中,键盘处理程序首先执行等待按键并确认有无按键按下的程序段。
当确认有按键按下后,下一步就要识别哪一个按键按下。
我们使用的是逐行扫描查询法。
按键部分由两种按键组成,一种是等待按键(除非有按键按下,否则等待按键);
另一种是无需等待按键;
前者用于输入温度和时间,后者用于判断完后的重新循环按键。
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灯会闪烁进行报警。
程序设计中用的是RB0接蜂鸣器,当达到条件时,蜂鸣器开始鸣叫。
3、代码设计
#include<
p18f452.h>
delays.h>
#include<
adc.h>
/*RB0接CN11-2蜂鸣器
RB1接CN11-3SCL
RB2接CN11-4SDA
RC0~RC7接CN18-0~7键盘
RB3~RB5LCD
RA0AD
*/
//宏定义
#defineRB0PORTBbits.RB0
#defineRSPINPORTBbits.RB5//DataorInstrumentSelect
#defineRWPINPORTBbits.RB4//WriteorRead
#defineEPINPORTBbits.RB3//6800modeEnablesingle
#defineSCLPORTBbits.RB1//SDA
#defineSDAPORTBbits.RB2//SCL
#defineRC0PORTCbits.RC0
#defineRC1PORTCbits.RC1
#defineRC2PORTCbits.RC2
//全局变量
unsignedcharL=0,H=0,T=0,N=0;
//定义高H低L温度T及实时温度的编写符号
unsignedinta;
//a为AD读出值
unsignedintt=10;
unsignedintTimeout;
intflag;
intresult;
intxh;
//函数声明
voidInterruptHandlerHigh(void);
////按键的识别码和编入码
romunsignedcharASC[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
romunsignedcharKEYCODE[]=
{
0XEE,//0
0XDE,//1
0XBE,//2
0X7E,//3
0XED,//4
0XDD,//5
0XBD,//6
0X7D,//7
0XEB,//8
0XDB,//9
0XBB,
0X7B,
0XE7,
0XD7,
0XB7,//14重置按键
0X77,//15输入完成后开始信号
};
Delay()
unsignedcharp;
for(p=0;
p<
100;
p++);
}
Delayus()
unsignedcharq;
for(q=0;
q<
10;
q++);
//IIC部分
voidIICstart(void)
SDA=1;
//先将SDA=1,以准备在SCL=1时,将SDA=0
SCL=1;
//时钟总线拉高
Delay();
//调用延时函数,略作延时
SDA=0;
//SCL=1时,将SDA拉低即产生启动信号
SCL=0;
//将SCL=0,完成启动信号操作
//---------------------------------------
//名称:
IIC停止信号函数
voidIICstop(void)
//先将SDA=0,以准备在SCL=1时,将SDA=1
//SCL=1时,将SDA拉高即产生停止信号
向IIC总线写入1个字节函数
voidWrite1Byte(unsignedcharBuf1)
unsignedchark;
//1个字节要分8次写入,需要定义一个寄存器用来计数
for(k=0;
k<
8;
k++)//做一个8次的循环,每次写入1位,需要写8次
if(Buf1&
0x80)//从最高位开始写
//如果欲写入数据为1,就将数据线置1
else
//如果欲写入数据为0,就将数据线写0
Delayus();
//时钟线做一个上升沿,将一位数据写入
Buf1=Buf1<
<
1;
//数据左移一位,将下次要写入的位数据移到最高位
//将SCL=0,以准备通过上升沿将数据写入
TRISBbits.TRISB2=1;
//将RC4(SDA)设置为输入状态
//Delayus();
////从时序图中读出来感觉这一步爱是真正ACK给低电平的时候,好像这个延迟又不用给了
//将SCL=1,做个上升沿准备读应答信号
//将SCL=0,结束应答信号读操作
TRISBbits.TRISB2=0;
//将RC4(SDA)恢复为输出状态
从IIC总线读入1个字节函数
unsignedcharRead1Byte(void)
//1个字节要分8次读出,需要定义一个寄存器用来计数
unsignedcharg=0;
//定义一个寄存器用保存读出数据
k++)//做一个8次的循环,每次读入1位,需要读8次
g=g<
//数据左移一位,空出最低位以准备保存读入的一位数据
//将SCL=1,做个上升沿准备读一位数据
if(SDA==1)//读一位数据,并判断
g=g|0x01;
//如果读入数据为1,就将接收缓冲区最低一位置1
g=g&
0xfe;
//如果读入数据为0,就将接收缓冲区最低一位写0
//SCL恢复为0,结束一位数据读操作
returng;
//将读入的一个字节返回
软件模拟IIC向AT24C02指定地址写一个字节函数
voidWriteAT24C02(unsignedcharAddress,unsignedcharDatabuf)
{//直接调用本函数即可对AT24C02的Address地址写Databuf
IICstart();
//IIC启动信号
Write1Byte(0xA0);
//发送AT24C02的器件地址和写信号
Write1Byte(Address);
//发送地址
Write1Byte(Databuf);
//发送数据
IICstop();
//产生IIC停止信号//***在读数据的时候并没有主机向从机的应答,这是怎么回事***/
软件模拟IIC从AT24C02指定地址读一个字节函数
unsignedcharReadAT24C02(unsignedcharAddress)
{//直接调用本函数即可从AT24C02的Address地址读出数据返回
unsignedcharbuf;
//定义一个寄存器用来暂存读出的数据
Write1Byte(0xA1);
//发送AT24C02的器件地址和读信号
buf=Read1Byte();
//读一个字节数据
//产生IIC停止信号
return(buf);
//将读出数据返回
//名称:
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)
//选择指令寄存器
RWPIN=0;
//选择写
PORTD=combuf;
//把命令字送入RD
//使能线电平变化,命令送入1602的8位数据口
Delay1TCY();
//恢复使能线电平
1602写命令函数(带忙检测)
voidlcd_write_com_busy(unsignedcharcombuf)
lcd_wait_busy();
//调用忙检测函数
lcd_write_com(combuf);
//调用写命令函数
1602写数据函数(带忙检测)
voidlcd_write_data(unsignedchardatabuf)
//调用忙检测函数
RSPIN=1;
//选择数据寄存器
PORTD=databuf;
//把数据字送入P2
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(0x38);
Delay100TCYx(5);
lcd_write_com_busy(0x38);
//8位数据,双列,5*7字形
lcd_write_com_busy(0x08);
//显示功能关,无光标
lcd_write_com_busy(0x01);
//清屏指令
lcd_write_com_busy(0x06);
//写入新的数据后,光标右移,显示屏不移动
lcd_write_com_busy(0x0c);
//显示功能开,无光标,
}
指定地址写入函数
voidlcd_write_char(unsignedcharx,unsignedchary,unsignedcharbuf)
{
lcd_write_address(x,y);
//写入地址
lcd_write_data(buf);
//写入显示数据
读取按键对应数值函数
intanjian(void)//通过读取横排和竖排的识别按键
unsignedchari;
unsignedcharKeyTemp;
while
(1)
{
TRISC=0xf0;
LATC=0xf0;
if(0xf0!
=(PORTC&
0xf0))
{
Delay1KTCYx(10);
if(0xf0!
0XF0))
{
KeyTemp=PORTC&
0xF0;
TRISC=0x0F;
LATC=0x0f;
KeyTemp|=(PORTC&
0X0F);
for(i=0;
i<
sizeof(KEYCODE);
i++)
{
if(KeyTemp==KEYCODE[i])
{
KeyTemp=i;
i=sizeof(KEYCODE)+1;
}
}
while(0X0F!
0X0F));
if(KeyTemp==0)//0
return0;
if(KeyTemp==1)//1
return1;
if(KeyTemp==2)//2
return2;
if(KeyTemp==3)//3
return3;
if(KeyTemp==4)//4
return4;
if(KeyTemp==5)//5
return5;
if(KeyTemp==6)//6
return6;
if(KeyTemp==7)//7
return7;
if(KeyTemp==8)//8
return8;
if(KeyTemp==9)//9
return9;
if(KeyTemp==15)//开始判断
return15;
}
}
else
Nop();
}
//不需要等待的接收按键,按键编号接收14
intunwaitkey()
TRISC=0xf0;
LATC=0xf0;
if(0xf0!
Delay1KTCYx(10);
KeyTemp=PORTC&
TRISC=0x0F;
LATC=0