基于PIC16F887单片机的温度时钟显示以及闹钟功能.docx
《基于PIC16F887单片机的温度时钟显示以及闹钟功能.docx》由会员分享,可在线阅读,更多相关《基于PIC16F887单片机的温度时钟显示以及闹钟功能.docx(35页珍藏版)》请在冰豆网上搜索。
基于PIC16F887单片机的温度时钟显示以及闹钟功能
基于PIC16F887单片机的温度、时钟显示以及闹钟功能
基于PIC16F887单片机的温度、时钟
显示以及闹钟功能一、课程设计的目的
《PIC单片机课程设计》是电气工程及其自动化专业及相近专业的一门重要的专业实践课,本课程在《PIC单片机》课程的基础上,通过硬件设计与软件编程与调试的实践,进一步掌握PIC单片机的应用方法,熟练PIC单片机的C程序的编写与调试,是毕业设计前的一次重要的实践,为今后走上工作岗位打下坚实的单片机应用基础。
二、设计内容
1Proteus线路图绘制
根据所设计的线路图,绘制与之一致的,能用于仿真的Proteus线路图。
一致。
要求所绘的线路图美观、紧凑,参数要与课设
2、软件编制与调试
根据所设计的线路图制相应的单片机C程序,要求所制的程序符合C语言
译,有错及时修改,并先在Proteus上仿真,格式并加上注解。
每编一段即进行
基本正确后再用PICkit3在线调试,最后应脱机运行。
三、设计目标
1该设计包括数字钟及数字温度计:
按键的使用.LCD.蜂鸣器时钟芯片DS1307和温度传感器TC74。
2功能;此设计可以感测环境的温度,显示当前的时间,及闹钟。
温度与时间都显示在LCD显示屏上,以及如何调整闹钟界面
四硬件设计及说明
1复位按键
2时钟芯片DS1307及附属接线
时钟芯片DS1307用于产生时间,它提供了秒、分、时、日、年、和星期等数据,能算只瑞年2100年,时钟的晶振是典型的32.768Hz。
(1)其引脚作用如下:
2
(2)DS1307的读写如下;
1写DS1307的步骤如下:
a)发送启始位;
b)发送DS1307的7位地址+0(写),即0b11010000;
c)发送要写入DS1307的地址,地址见图16,如要修改分,此值为1;
d)发送要写入DS1307的数,如要把分修改为十进制数37,则此数为0x37;
e)发送停止位;
2读DS1307的步骤如下:
a)发送启始位;
b)发送DS1307的7位地址+0(写),即0b11010000;
c)发送要读的DS1307的起始地址,如要从秒读起,为0;
d)发送停止位;
e)发送重新开始位;
f)发送DS1307的7位地址+1(读),即0b11010001;
g)发送读使能位,接收一个数据,单片机发送应答位;
h)发送读使能,接收下一个数据(地址会自动+1),单片机发送应答位,直到读数完成,接收最后
一个数时单片机不发送应答位;
i)发送停止位;
注意在DS1307仿真的时候七位地址为0b1001101而实际为0b1001000;(3)功能是;提供时间通过pic16F877送入LCD中显示。
3振荡方式
4时钟控制按键及闹钟电路
(1)按键1可以再时钟界面和闹钟界面切换
(2)按键2可以通过光标移动设置时间和闹钟(3)按键3,4可以修改时机
(4)三极管用于电流的放大,以致驱动喇叭。
5LM016L液晶显示屏
LM016L是字符型的LCD液晶显示屏其内部控制芯片是HD44780或KS0066之类是16X2的字符型的LCD
对其使用时
(1)要初始化;
(2)在LCD显示前,要对显示位置进行定位,既写位置命令(3)把该命令写入到DDRAM中
(4)在用写数据命令,显示要显示的字符
五软件设计及说明
程序大体说明,
1.设单片机上电,屏幕上显示welcome~~和hello!
!
2.上述界面延迟一段时间后,自动进入时间界面,通过程序的运行,单片机自动同DS1307和TC74芯片中读取时间和温度并显示在LCD上
3.通过不断的按键扫面,当
(1)按键1可以再时钟界面和闹钟界面切换
(2)按键2可以通过光标移动设置时间和闹钟
(3)按键3,4可以修改时间,分别加减
4.当切换到闹钟界面,通过设置好时间后,在时间界面星期旁边会显示一个A提示我们闹钟已经开启,当到了设置的时间点,蜂鸣器会自动响,延迟一段时间
会自动关掉,或者我们可以用通过按键4人为关掉它#include
__CONFIG(0x20F1);
#defineucharunsignedchar#defineuintunsignedint#defineds13070b1101000
#defineTC740b1001000#defineRTR0b00000000#defineFMQRC1
#defineLCD_RSRD4
#defineLCD_RWRD5
#defineLCD_ERD6
#defineS1RB0
#defineS2RB1
#defineS3RB2
#defineS4RB3
#defineDAT1
#defineCOM0
#defineLINE10b10000000#defineLINE20b11000000#defineYEARLINE1+2#defineMONTHLINE1+5#defineDAYLINE1+8#defineWEEKDAY+3#defineHOURLINE2+1#defineMINUTELINE2+4#defineSECONDLINE2+7#defineWENDUSECOND+4//函数声明
voidDELAY(uintn);voidDELAY_A(uintn);voidDELAY_US(charn);voidCSH();
voidDS1307_CSH();
voidKEYSCAN();
voidLCD_CSH();
voidLCD_BUSY();
voidLCD_CLR();
voidLCD_GD();
voidREAD();
voidDSweek(char);
voidLCD_WRITE(char,char);
voidLCD_WRITE_4(char,char);voidTIME();
voidTIME_UP();
voidTIME_DOWN();
voidTIME_UPDATE();
voidDISL1();
voidDISL2();
voidDISL5();
voidBCD(uint);
voidDISP_T(signedchar);voidIIC_CSH();
voidIIC_SEND(charR);
voidIIC_WRITE(char,char);voidALARM_CLOCK();
voidALARM_KG();
charLCD_READ();
charIIC_READ(charaddr);charflag,flag_A,A;
charm=0,f=0,s=0,x,r,y,n;charA_m=0,A_f=0,A_s=0,A_x=0;charshi,ge;
charBW,SW,GW;
signedcharT_READ();
ucharnum1=0,num2=0,num3;constuchartable0[]={"WELCOME!
!
"};
constuchartable01[]={"HELLO!
!
"};
constuchartable04[]={"SETTIME"};
constuchartable[]={"20--"};
constuchartable1[]={":
:
"};//BCD码转换,R1双字节转换为十进制数
voidBCD(uintR1)
{BW=0;SW=0;GW=0;
while(R1>=100)
{R1-=100;BW++;}
while(R1>=10)
{R1-=10;SW++;}
GW=R1;
}
//清屏
voidLCD_CLR()
{LCD_WRITE(0b00000001,COM);
DELAY
(2);
}
//延时子程序
voidDELAY(uintn)
{uintj;
chark;
for(j=0;jfor(k=246;k>0;k--)NOP();
}
//关闹钟
voidDELAY_A(uintn)
{uintj;
chark;
for(j=0;j{if(S4==0)
{DELAY(20);
if(S4==0)
{break;}
}
for(k=246;k>0;k--)
{NOP();
if(S4==0)
{DELAY(20);
if(S4==0)
{break;}
}
}
}
}
voidDELAY_US(charn){charj;
j=n;
while(j>0)
{j--;
NOP();NOP();NOP();NOP();
}
}
//初始化
voidCSH()
{
TRISC=0b00011000;
TRISD=0X00;
ANSELH=0b000000;
TRISB=0b11111111;
RBPU=0;//B口上拉使能
WPUB=0b11111111;//887必须设置
PORTB=0XFF;
RC1=0;
RD7=1;
LCD_CSH();
IIC_CSH();
DISL1();
DISL2();
DELAY(500);
LCD_CLR();
LCD_GD();
DS1307_CSH();
}
//LCD模块初始化
voidLCD_CSH()
DELAY(20);//延时20ms{
LCD_WRITE_4(0b0011,COM);//发送控制序列
DELAY
(1);//延时1ms
LCD_WRITE_4(0b0011,COM);//发送控制序列
DELAY_US(10);//延时100us
LCD_WRITE_4(0b0011,COM);//发送控制序列
DELAY_US(10);//延时100us
LCD_WRITE_4(0b0010,COM);//4位数据格式
LCD_BUSY();//LCD忙检测
LCD_WRITE(0b00101000,COM);//4位数据格式,2行(实际上4行!
),5
×7点阵
LCD_WRITE(0b00001100,COM);//D(d2)=1:
打开显示,C(d1)=1:
光标打
开,B(d0)=1:
光标闪烁
LCD_CLR();
LCD_WRITE(0b00000110,COM);//输入模式,I/D(d1)=1:
地址加
1,S(d0)=1:
显示移位关闭
}
//LCD_GD//固定显示voidLCD_GD()
{chari;
LCD_WRITE(LINE1,COM);
for(i=0;i<11;i++)
{
LCD_WRITE(table[i],DAT);
DELAY
(1);
}
LCD_WRITE(LINE2+1,COM);
for(i=0;i<8;i++)
{
LCD_WRITE(table1[i],DAT);
}
}
//===========DISL1======voidDISL1()
{chari;
LCD_WRITE(0X80,COM);
for(i=0;i<15;i++)
{
LCD_WRITE(table0[i],DAT);
}
}
//===========DISL2======voidDISL2()
{chari;
LCD_WRITE(0Xc0,COM);
for(i=0;i<15;i++)
{
LCD_WRITE(table01[i],DAT);
}
}
//===========DISL5======voidDISL5()
{chari;
LCD_WRITE(0x80,COM);
for(i=0;i<15;i++)
{
LCD_WRITE(table04[i],DAT);
}
}
//LCD_READ//读LCD状态
charLCD_READ()
{unsignedcharR1;
LCD_RS=0;//寄存器选择
LCD_RW=1;NOP();//读为1
LCD_E=1;NOP();//使能
R1=0;//短延时
R1=PORTD;//读数据的高4位给R1的高4位,低4位清0
R1=(R1<<4)&0XF0;
LCD_E=0;NOP();//读数据结束
LCD_E=1;NOP();
R1|=(PORTD&0X0F);//读PORTD的低4位,R1的高4位不变
LCD_E=0;NOP();//读数据结束
LCD_RW=0;
return(R1);
}
//=======写R1的低4位,FLAG为寄存器选择,1为命令,0为数据==
voidLCD_WRITE_4(charR1,charFLAG)
{
NOP();NOP();//短延时
LCD_RW=0;NOP();//写模式
LCD_RS=FLAG;NOP();//寄存器选择
PORTD&=0XF0;NOP();//RD低4位先清0
LCD_E=1;NOP();//使能
R1=R1&0X0F;//低4位
PORTD|=R1;NOP();NOP();//送4位
NOP();NOP();//数据送入有效
LCD_E=0;
LCD_RS=0;NOP();
PORTD&=0XF0;//RD低4位清0}
//======写1B数R1,FLAG为写命令或数据选择,0为写命令,1为写数据
voidLCD_WRITE(charR1,charFLAG)
{charR2;
LCD_BUSY();//检测忙否
R2=R1&0XF0;//低4位清0
R2=R2>>4;//取高4位
LCD_WRITE_4(R2,FLAG);//先写高4位
R2=R1&0X0F;//高4位清0,取低4位
LCD_WRITE_4(R2,FLAG);//再送低4位
DELAY_US(10);//延时100us}
//检测LCD是否忙
voidLCD_BUSY()
{
unsignedcharR1;
do{
R1=LCD_READ();
}while(R1&0X80);
}
//发送数R并等待发送完成,收到从机的应答信号208voidIIC_SEND(charR){SSPBUF=R;//发送
while(RW==1);//在主动模式下,判断发送是否完成
while(SSPIF==0);//等待发送完成
while(ACKSTAT==1);//等待从机发送应答信号
}
//IIC初始化208
voidIIC_CSH()
{TRISC&=0b00011000;//SDA,SCL设置为输入~
SSPCON=0b00101000;//同步串口使能(SSPEN),主控方式
SMP=0;//使能高速模式(400kHz)的压摆率控制
SSPADD=4;//主控模式为波特率值,每位时间
T=(SSPADD+1)/Tcy=5us
}
//IIC_READ读
charIIC_READ(charaddr){
chariicr;
SEN=1;
while(SEN==1);//发送起始位
IIC_SEND(0b11010000);//DS1307在总线上的地址:
0b11010000
IIC_SEND(addr);//读取的首地址
RSEN=1;
while(RSEN==1);//发送重新起始位
IIC_SEND(0b11010001);//读数据
SSPIF=0;
RCEN=1;
while(SSPIF==0);//等待读完成
iicr=SSPBUF;
ACKDT=1;
ACKEN=1;
while(ACKEN==1);
PEN=1;//发送停止位
while(PEN==0);
return(iicr);}
//IIC_WRITE写
voidIIC_WRITE(charaddr,chardata)
{
SEN=1;
while(SEN==1);
IIC_SEND(0b11010000);
IIC_SEND(addr);
IIC_SEND(data);
PEN=1;
while(PEN==1);
}
//DS1307初始化时间并显示时间
voidDS1307_CSH()
{
IIC_WRITE(0,0x45);//00秒
IIC_WRITE(1,0x00);//00分
IIC_WRITE(2,0x10);//00时
IIC_WRITE(3,0x06);//星期日
IIC_WRITE(4,0x05);//1日
IIC_WRITE(5,0x05);//1月
IIC_WRITE(6,0x12);//12年
}
voidREAD()
{
LCD_WRITE(SECOND,COM);
shi=IIC_READ(0)>>4;
ge=IIC_READ(0)&0x0f;
LCD_WRITE(0x30+shi,DAT);
LCD_WRITE(0x30+ge,DAT);
LCD_WRITE(MINUTE,COM);
shi=IIC_READ
(1)>>4;
ge=IIC_READ
(1)&0x0f;
LCD_WRITE(0x30+shi,DAT);
LCD_WRITE(0x30+ge,DAT);
LCD_WRITE(HOUR,COM);
shi=IIC_READ
(2)>>4;
ge=IIC_READ
(2)&0x0f;
LCD_WRITE(0x30+shi,DAT);
LCD_WRITE(0x30+ge,DAT);
LCD_WRITE(DAY,COM);
shi=IIC_READ(4)>>4;
ge=IIC_READ(4)&0x0f;
LCD_WRITE(0x30+shi,DAT);
LCD_WRITE(0x30+ge,DAT);
DSweek(IIC_READ(3));
LCD_WRITE(MONTH,COM);
shi=IIC_READ(5)>>4;
ge=IIC_READ(5)&0x0f;
LCD_WRITE(0x30+shi,DAT);
LCD_WRITE(0x30+ge,DAT);
LCD_WRITE(YEAR,COM);
shi=IIC_READ(6)>>4;
ge=IIC_READ(6)&0x0f;
LCD_WRITE(0x30+shi,DAT);
LCD_WRITE(0x30+ge,DAT);
DELAY(100);
DISP_T(T_READ());
if(A==1)
{
LCD_WRITE(WEEK+4,COM);
LCD_WRITE('A',DAT);
}
if(A!
=1)
{
LCD_WRITE(WEEK+4,COM);
LCD_WRITE('',DAT);
}
}
voidDSweek(charnum)
{
LCD_WRITE(WEEK,COM);
switch(num)
{
case1:
LCD_WRITE('M',DAT);
LCD_WRITE('0',DAT);
LCD_WRITE('N',DAT);
break;
case2:
LCD_WRITE('T',DAT);
LCD_WRITE('U',DAT);
LCD_WRITE('E',DAT);
break;
case3:
LCD_WRITE('W',DAT);
LCD_WRITE('E',DAT);
LCD_WRITE('D',DAT);
break;
case4:
LCD_WRITE('T',DAT);
LCD_WRITE('H',DAT);
LCD_WRITE('U',DAT);
break;
case5:
LCD_WRITE('F',DAT);
LCD_WRITE('R',DAT);
LCD_WRITE('T',DAT);
break;
case6:
LCD_WRITE('S',DAT);
LCD_WRITE('A',DAT);
LCD_WRITE('T',DAT);
break;
case7:
LCD_WRITE('S',DAT);
LCD_WRITE('U',DAT);
LCD_WRITE('N',DAT);
break;
}
}
//**********温度模块*************//读温度值
signedcharT_READ(){
signedcharR1;
SEN=1;
while(SEN==1);//发送起始位
IIC_SEND(0b10010000);//TC74在总线上的地址:
0b10010000
IIC_SEND(RTR);
RSEN=1;
while(RSEN==1);//发送重新起始位
IIC_SEND(0b10010001);//读数据
RCEN=1;
while(RCEN==1);//等待读完成
R1=SSPBUF;
PEN=1;//发送停止位
while(PEN==0);
return(R1);
}
//显示温度
voidDISP_T(signedcharR1){charR2;
LCD_WRITE(0b00001100,COM);
if(R1>=0)
BCD(R1);
else
{R2=~R1+1;
BCD(R2);
}
LCD_WRITE(WENDU,COM);
if(R1<0)
LCD_WRITE('-',DAT);
if(R1>0)
LCD_WRITE(0x30+SW,DAT);
LCD_WRITE(0x30+GW,DAT);
LCD_WRITE(0xDF,DAT);
LCD_WRITE('C',DAT);
}
//闹钟
voidALARM_CLOCK()
{
PR2=249;
CCPR2L=0x25;
CCP2CON=0B00001100;
T2CO