pic单片机课程设计报告大学毕业设计论文.docx
《pic单片机课程设计报告大学毕业设计论文.docx》由会员分享,可在线阅读,更多相关《pic单片机课程设计报告大学毕业设计论文.docx(43页珍藏版)》请在冰豆网上搜索。
pic单片机课程设计报告大学毕业设计论文
NORTHCHINAUNIVERSITYOFSCIENCEANDTECHNOLOGY
单片机课程设计报告
学生姓名:
李恒
学号:
201214570408
学院:
信息工程学院
专业班级:
12电信4班
指导教师:
崔博
2015年6月21日
一、课程设计目的
本课程设计是在《PIC单片机原理及应用》及《单片机C语言编程》课程的基础上,通过硬件设计、软件编程及仿真调试的实践,进一步掌握PIC单片机的应用方法,熟练掌握PICCC语言程序的编写与调试,是毕业设计前的一次重要实践,为今后走上工作岗位打下坚实的单片机应用基础。
二、设计题目及要求
2.1设计题目:
基于PIC16F877单片机的多功能电子时钟
2.2功能实现:
实时时钟显示,时间可调;实时温度显示,并具有超限报警功能。
输出显示采用LCD1602或LED七段数码显示器。
2.3设计要求:
自己设计硬件和程序编程,画出完整的电路原理图,用Multisim或Proteus仿真,最终可实现脱机运行。
三、设计原理说明
3.1时钟模块
DS1307是美国DALLAS公司推出的I2C总线接口实时时钟芯片,它可独立于CPU工作,不受CPU主晶振及其电容的影响,且计时准确,月累积误差一般小于10秒。
芯片还具有主电源掉电情况下的时钟保护电路,DS1307的时钟靠后备电池维持工作,拒绝CPU对其读出和写入访问。
同时还具有备用电源自动切换控制电路,因而可在主电源掉电和其它一些恶劣环境场合中保证系统时钟的定时准确性。
DS1307具有产生秒、分、时、日、月、年等功能,且具有闰年自动调整功能。
同时,DS1307芯片内部还集成有一定容量、具有掉电保护特性的静态RAM,可用于保存一些关键数据。
3.2显示模块
如用LCD1602作为显示设备,要求显示屏分两行显示,第一行显示日期(年-月-日)和星期,第二行显示时间(时:
分:
秒)和温度。
显示秒由00一直加到59,分钟数也由00加到59,小时采用24小时制,由00加到23,如此循环显示。
3.3按键模块
按键用来作为时间调整。
要求至少设计4个按键,按键1作为设置键;按键2、按键3分别为增加、减少键,在设置键按下时,此两个按键方有效;按键4是确定键,在设置键按下时方才有效。
3.4温度采集模块
DS18B20是美国DALLAS公司推出的单总线数字温度传感器。
DS18B20内部集成了温敏元件、数据转换芯片、存储器芯片和计算机接口芯片等多功能模块。
其主要技术特点有:
具有独特的单线接口方式;可以通过数据线供电,具有超低功耗工作方式;测温范围为-55℃~125℃,测温精度为0.5℃;温度转换精度9~12位可编程,直接将温度转换值以二进制数码的方式串行输出。
四、硬件原理图
4.1电子时钟原理图
4.2时钟模块
4.3显示模块
4.4按键模块
4.5温度采集模块
4.6电路仿真图
4.6.1开机动画
4.6.2实时时钟显示,实时温度显示
4.6.3时间可调,报警温度可调
4.6.4闹钟功能
4.6.5超限报警
五、软件设计
5.1流程图
按下
无
超限/到时
无
5.2源程序
5.2.1程序清单
5.2.2主程序代码
5.2.2.1主函数.c文件
#include
#include"main.h"
ucharline1_data[]={"ElectronicClock"};
ucharline2_data[]={"PoweredByMe"};
voidmain(void)
{
ADCON1=0x06;//基本配置PORTA,PORTE设定为数字端口
TRISD=0;//PORTD设置为输出
TRISB0=0;//PORTB0设置为输出
RB0=0;//初始化蜂鸣器RB0(不响)
TRISE0=0;
TRISE1=0;
TRISE2=0;
__delay_ms(10);
LCD_init();
Init_ds1302();//初始化ds1302
Key_init();//按键端口初始化
LCD_write_str(0,0,line1_data);//在第0行显示字符串
LCD_write_str(0,1,line2_data);//在第一行显示字符串
__delay_ms(3000);
LCD_clr();
while
(1)
{
Display_Time();//显示时间
Display_wendu();//显示温度
KeyScan();//按键扫描函数
if(temp1>warning_temp)
{
RB0=1;
__delay_ms(400);
RB0=0;
__delay_ms(400);
}
else
{RB0=0;}
if((hour==alarm_hour)&&(min==alarm_min))
{
RB0=1;
__delay_ms(200);
RB0=0;
__delay_ms(200);
}
else
{RB0=0;}
}
}
5.2.2.2主函数.h文件
#ifndef__MAIN_H__
#define__MAIN_H__
#define__STAT_BACKWARD_COMPATIBILITY//兼容PICC低版本
#include
#include"all.h"
#include"lcd1602.h"
#include"ds1302.h"
#include"ds18b20.h"
#include"key.h"
__CONFIG(HS&WDTDIS&LVPDIS&PWRTEN);
#endif
5.2.3液晶显示屏LCD1602代码
5.2.3.1液晶显示屏LCD1602.C文件
#include"lcd1602.h"
/*******lcd清屏函数******/
voidLCD_clr()
{
LCD1602_write_com(0x01);
__delay_ms(5);
}
/*********光标定位函数。
x为显示列,y为显示行********/
voidLocateXY(ucharx,uchary)
{
if(y==0)
{
LCD1602_write_com(0x80+x);
}
else
{
LCD1602_write_com(0xC0+x);
}
}
//***************特定位置写字符*********************
voidLCD_write_str(ucharx,uchary,uchar*s)
{
LocateXY(x,y);
while(*s)
{
LCD1602_write_dat(*s);
s++;
}
}
//****************特定位置显示数值********************
voidLCD_write_data(ucharx,uchary,uchardata)
{
LocateXY(x,y);
LCD1602_write_dat(data/10+48);//将数值转换成其对应的ASIC码值,相当于以字符形式输出
LCD1602_write_dat(data%10+48);//因为0的ASIC码值为48
}
//****************LCD1602初始化函数********************
voidLCD_init(void)
{
rs=0;
rw=0;
en=0;
LCD1602_write_com(0x01);//清零
LCD1602_write_com(0x38);//设置为16位两行字符,8位数据总线
LCD1602_write_com(0x0c);//显示开关,关闭光标,没有闪烁
LCD1602_write_com(0x06);//设置增量方式,显示移位方式
}
//******************读1602读忙状态**********************
voidLCD1602_check_busy(void)
{
uinti=20000;
dport_in;//端口设为输入
rs=0;
rw=1;
en=1;
while((0x80&dport)&&(i>0))
{
i--;
}
en=0;
dport_out;
}
//******************向1602写数据**********************
voidLCD1602_write_dat(ucharlcd_dat)
{
LCD1602_check_busy();
rs=1;
rw=0;
en=1;
dport=lcd_dat;
en=0;
}
//****************向1602写string数据******************
voidLCD1602_write_string(constuchar*cy)
{
while(*cy)
{
LCD1602_check_busy();
rs=1;
rw=0;
en=1;
dport=*cy;
en=0;
cy++;
}
}
//******************向1602写指令**********************
voidLCD1602_write_com(ucharlcd_com)
{
LCD1602_check_busy();
rs=0;
rw=0;
en=1;//下降沿把数据写进出
dport=lcd_com;
en=0;
}
5.2.3.1液晶显示屏LCD1602.H文件
#ifndef_LCD1602_H_
#define_LCD1602_H_
#include
#include"all.h"
#definedportPORTD//定义数据口
#definedport_inTRISD=0xff//PD端口设为输入
#definedport_outTRISD=0x00//PD端口设为输出
#definersRE0//并行数据/控制字选择H:
数据L:
控制字串行片选信号
#definerwRE1//并行读/写选择H:
读L:
写串行数据信号
#defineenRE2//并行读写使能H有效,下降沿锁定数据串行时钟信号
//***************函数定义******************
voidLCD1602_check_busy(void);//读1602读忙状态
voidLCD1602_write_dat(ucharlcd_dat);//向1602写数据********
voidLCD1602_write_string(constuchar*cy);//向1602写string数据
voidLCD1602_write_com(ucharlcd_com);//向1602写指令
voidLocateXY(ucharx,uchary);//光标定位函数。
x为显示列,y为显示行
voidLCD_init(void);//LCD1602初始化函数***********
voidLCD_write_data(ucharx,uchary,uchardata);//特定位置显示数值******
voidLCD_write_str(ucharx,uchary,uchar*s);//特定位置写字符********
voidLCD_clr();//lcd清屏函数*************
#endif
5.2.4时钟芯片DS1302代码
5.2.4.1时钟芯片DS1302.C文件
#include"ds1302.h"
//***********延时函数*************
voiddelay1()
{
inti;
for(i=100;i--;);
}
/********从ds1302读一个字节数据******/
ucharread_byte(void)
{
uchari,dat=0;
IO_IN;
IO_CLR;
for(i=0;i<7;i++)
{
SCK_CLR;
if(io)
{dat=dat|0x80;}
else
{dat=dat&0x7f;}
SCK_SET;
dat=dat>>1;
}
IO_OUT;
SCK_CLR;
returndat;
}
/*****向ds1302写一个数据******/
voidwrite_byte(uchardat)
{
uchari;
for(i=0;i<8;i++)
{
IO_CLR;
SCK_CLR;
if(dat&0x01)
{
IO_SET;
}
else
{
IO_CLR;
}
SCK_SET;
dat>>=1;
}
SCK_CLR;
}
/*****从ds1302的指定地址读一个字节数据******/
ucharread_ds1302(ucharaddr)
{
chardata,data1,data2;
RST_CLR;
SCK_CLR;
delay1();
RST_SET;
delay1();
write_byte(addr);
data=read_byte();
SCK_CLR;
RST_CLR;
data1=data/16;
data2=data%16;
data=data2+data1*10;
returndata;
}
/*****往ds1302的指定地址写一个字节数据******/
voidwrite_ds1302(ucharaddr,uchardata)
{
RST_CLR;
SCK_CLR;
delay1();
RST_SET;
delay1();
write_byte(addr);
SCK_CLR;
write_byte(data);
SCK_CLR;
RST_CLR;
}
/*****初始化ds1302函数******/
voidInit_ds1302()
{
RST_CLR;
SCK_CLR;
RST_OUT;
SCK_OUT;
}
/*****写ds1302时间函数******/
voidSet_Time(charyear,charmonth,charday,charhour,charmin,charsec,charweek)
{
write_ds1302(0x8E,0x00);//根据写状态寄存器命令字,写入不保护指令
write_ds1302(0x80,sec/10*16+sec%10);//根据写秒寄存器命令字,写入秒的值
write_ds1302(0x82,min/10*16+min%10);//根据写分寄存器命令字,写入分的值
write_ds1302(0x84,hour/10*16+hour%10);//根据写小时寄存器命令字,写入小时的值
write_ds1302(0x86,day/10*16+day%10);//根据写日寄存器命令字,写入日的值
write_ds1302(0x88,month/10*16+month%10);//根据写月寄存器命令字,写入月的值
write_ds1302(0x8c,year/10*16+year%10);//根据写年寄存器命令字,写入年的值
write_ds1302(0x8a,week/10*16+week%10);//根据写星期寄存器命令字,写入星期的值
write_ds1302(0x8e,0x80);//根据写状态寄存器命令字,写入写保护指令
}
/*****读ds1302时间函数******/
voidGet_Time()
{
write_ds1302(0x8e,0x00);//控制命令。
wp=0,允许写操作
write_ds1302(0x90,0xab);//涓流充电控制
sec=read_ds1302(0x81);//读取秒
min=read_ds1302(0x83);//读取分
hour=read_ds1302(0x85);//读取时
day=read_ds1302(0x87);//读取日
month=read_ds1302(0x89);//读取月
year=read_ds1302(0x8D);//读取年
week=read_ds1302(0x8B);//读取星期
}
/*****显示时间函数******/
voidDisplay_Time()
{
Get_Time();
LCD_write_data(1,0,year);//显示年
LCD1602_write_dat('-');
LCD_write_data(4,0,month);//显示月
LCD1602_write_dat('-');
LCD_write_data(7,0,day);//显示日
Write_Week(10,0,week);//显示星期
LCD_write_data(1,1,hour);//显示时
LCD1602_write_dat(':
');
LCD_write_data(4,1,min);//显示分
LCD1602_write_dat(':
');
LCD_write_data(7,1,sec);//显示秒
}
//**********星期显示函数***********
voidWrite_Week(inti,intj,ucharx)
{
LCD_write_str(i,j,xinqi[x]);
}
5.2.4.1时钟芯片DS1302.H文件
#ifndef_DS1302_H_
#define_DS1302_H_
#include
#include"all.h"
#include"lcd1602.h"
#definesclkRA1
#defineioRA0
#defineresetRA2
#definereset_IOTRISA2
#definesclk_IOTRISA1
#defineio_IOTRISA0
/*****复位脚******/
#defineRST_CLRreset=0
#defineRST_SETreset=1
#defineRST_INreset_IO=1
#defineRST_OUTreset_IO=0
/*****双向数据******/
#defineIO_CLRio=0
#defineIO_SETio=1
#defineIO_INio_IO=1
#defineIO_OUTio_IO=0
/*****时钟信号******/
#defineSCK_CLRsclk=0
#defineSCK_SETsclk=1
#defineSCK_INsclk_IO=1
#defineSCK_OUTsclk_IO=0
intyear,month,day,hour,min,sec,week;
intalarm_hour=13,alarm_min=30;//定义闹铃时间和闹铃分钟
ucharxinqi[8][4]={"","SUN","MON","TUS","WED","THU","FRI","SAT"};
voiddelay1();//延时函数
voidwrite_byte(ucharinbyte);//向ds1302写一个数据
ucharread_byte(void);//从ds1302读一个字节数据
voidwrite_ds1302(ucharaddr,uchardata);//往ds1302的指定地址写一个字节数据
ucharread_ds1302(ucharaddr);//从ds1302的指定地址读一个字节数据
voidWrite_Week(inti,intj,ucharx);//星期显示函数
voidInit_ds1302(void);//初始化ds1302函数**********
voidGet_Time();//读ds1302时间函数******
voidSet_Time(charyear,charmonth,charday,charhour,charmin,charsec,charweek);//写ds1302时间函数******
voidDisplay_Time();//显示时间函数******
#endif
5.2.5温度传感器DS18B20代码
5.2.5.1温度传感器DS18B20.C文件
#include"ds18b20.h"
//---------------------------------------
//名称:
复位DS18B20函数
//---------------------------------------
unsignedcharReset(void)
{
unsignedchark;
DQ_DIR=0;//设置RA4位输出口
DQ=0;//拉低DQ总线开始复位
__delay_us(870);//保持DQ低大约870uS,符合不低于480US的要求
DQ_DIR=1;//设置RA4为输入口,以释放总线等电阻拉高总线
__delay_us(78);//大约78uS后,判断是否复位成功
if(DQ==0)//读出数据并保存
k=0;
else
k=1;
__delay_us(400);//维持约400US,符合总读时隙不低于480US的要求
returnk;//k=0为复位成功,k=1为复位失败
}
//---------------------------------------
//名称:
写字节函数
//---------------------------------------
voidWriteByte(unsignedchardat)
{
unsignedcharj;
for(j=0;j<8;j++)