PIC单片机课程设计报告

NORTH CHINA UNIVERSITY OF SCIENCE AND TECHNOLOGY

单片机课程设计报告

学生姓名: 学 号: 学 院: 信息工程学院 专业班级: 12电信4班 指导教师:

2015年6月21日

一、课程设计目的

PIC单片机课程设计报告

本课程设计是在《PIC单片机原理及应用》及《单片机C语言编程》课程的基础上,通过硬件设计、软件编程及仿真调试的实践,进一步掌握PIC单片机的应用方法,熟练掌握PICC C语言程序的编写与调试,是毕业设计前的一次重要实践,为今后走上工作岗位打下坚实的单片机应用基础。

二、设计题目及要求

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,如此循环显示。

按键用来作为时间调整。要求至少设计4个按键,按键1作为设置键;按键2、按键3分别为增加、减少键,在设置键按下时,此两个按键方有效;按键4是确定键,在设置键按下时方才有效。 3.4 温度采集模块

DS18B20是美国DALLAS公司推出的单总线数字温度传感器。DS18B20内部集成了温敏元件、数据转换芯片、存储器芯片和计算机接口芯片等多功能模块。其主要技术特点有:具有独特的单线接口方式;可以通过数据线供电,具有超低功耗工作方式;测温范围为-55℃~125℃,测温精度为0.5℃;温度转换精度9~12位可编程,直接将温度转换值以二进制数码的方式串行输出。

四、硬件原理图

4.1电子时钟原理图

4.3显示模块

4.5温度采集模块

4.6电路仿真图 4.6.1开机动画

4.6.2实时时钟显示,实时温度显示

4.6.3时间可调,报警温度可调

4.6.4闹钟功能

4.6.5超限报警

五、软件设计

PIC单片机课程设计报告

5.1流程图

5.2源程序 5.2.1程序清单

5.2.2主程序代码 5.2.2.1主函数.c文件

PIC单片机课程设计报告

#include #include"main.h"

uchar line1_data[]={"Electronic Clock"}; uchar line2_data[]={" Powered By Me "};

void main(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;} PIC单片机课程设计报告

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清屏函数******/

void LCD_clr()

{

LCD1602_write_com(0x01);

__delay_ms(5);

}

/*********光标定位函数。x为显示列,y为显示行********/

void LocateXY(uchar x,uchar y)

{

if(y==0)

{

LCD1602_write_com(0x80+x);

}

else

{

LCD1602_write_com(0xC0+x);

}

}

//***************特定位置写字符*********************

void LCD_write_str(uchar x,uchar y,uchar *s)

{

LocateXY(x,y);

while(*s)

{

LCD1602_write_dat(*s);

s++;

}

}

//****************特定位置显示数值********************

void LCD_write_data(uchar x,uchar y,uchar data)

{

LocateXY(x,y);

LCD1602_write_dat(data/10 +48); //将数值转换成其对应的ASIC码值,相当于以字符形式输出

LCD1602_write_dat(data%10+ 48); //因为0的ASIC码值为48

}

//****************LCD1602初始化函数********************

void LCD_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读忙状态**********************

void LCD1602_check_busy(void)

{

uint i=20000;

dport_in; //端口设为输入

rs=0;

rw=1;

en=1;

while((0x80&dport)&&(i>0))

{

i--;

}

en=0;

dport_out;

}

//******************向1602写数据**********************

void LCD1602_write_dat(uchar lcd_dat)

{

LCD1602_check_busy();

rs=1;

rw=0;

en=1;

dport=lcd_dat;

en=0;

}

//****************向1602写string数据******************

void LCD1602_write_string(const uchar *cy)

{

while(*cy)

{

LCD1602_check_busy();

rs=1;

rw=0;

en=1;

dport=*cy;

en=0;

cy++;

}

}

//******************向1602写指令**********************

void LCD1602_write_com(uchar lcd_com)

{

LCD1602_check_busy();

rs=0;

rw=0;

en=1;//下降沿把数据写进出

dport=lcd_com;

en=0;

}

5.2.3.1液晶显示屏LCD1602.H文件 PIC单片机课程设计报告

#ifndef _LCD1602_H_

#define _LCD1602_H_

#include

#include"all.h"

#define dport PORTD //定义数据口

#define dport_in TRISD=0xff //PD端口设为输入

#define dport_out TRISD=0x00 //PD端口设为输出

#define rs RE0 //并行数据/控制字选择 H:数据 L:控制字 串行片选信号

#define rw RE1 //并行读/写选择 H:读 L:写 串行数据信号

#define en RE2 //并行读写使能 H有效,下降沿锁定数据 串行时钟信号

//*************** 函数定义 ******************

void LCD1602_check_busy(void); //读1602读忙状态

void LCD1602_write_dat(uchar lcd_dat);//向1602写数据********

void LCD1602_write_string(const uchar *cy);//向1602写string数据

void LCD1602_write_com(uchar lcd_com);//向1602写指令

void LocateXY(uchar x,uchar y);//光标定位函数。x为显示列,y为显示行

void LCD_init(void); //LCD1602初始化函数***********

void LCD_write_data(uchar x,uchar y,uchar data);//特定位置显示数值****** void LCD_write_str(uchar x,uchar y,uchar *s);//特定位置写字符********

void LCD_clr(); //lcd清屏函数*************

#endif

5.2.4时钟芯片DS1302代码

5.2.4.1时钟芯片DS1302.C文件

#include"ds1302.h"

//***********延时函数*************

void delay1()

{

int i;

for(i=100;i--;);

}

/******** 从ds1302读一个字节数据******/

uchar read_byte(void)

{

uchar i,dat=0;

IO_CLR;

for(i=0;i

{

SCK_CLR;

if(io)

{dat=dat|0x80;}

else

{dat=dat&0x7f;}

SCK_SET;

dat=dat>>1;

}

IO_OUT;

SCK_CLR;

return dat;

}

/***** 向ds1302写一个数据******/

void write_byte(uchar dat)

{

uchar i;

for(i=0;i

{

IO_CLR;

SCK_CLR;

if(dat&0x01)

{

IO_SET;

}

else

{

IO_CLR;

}

SCK_SET;

dat>>=1;

}

SCK_CLR;

}

/***** 从ds1302的指定地址读一个字节数据******/

uchar read_ds1302(uchar addr)

{

char data,data1,data2;

RST_CLR;

SCK_CLR;

delay1();

delay1();

write_byte(addr);

data=read_byte();

SCK_CLR;

RST_CLR;

data1=data/16;

data2=data%16;

data=data2+data1*10;

return data;

}

/***** 往ds1302的指定地址写一个字节数据******/

void write_ds1302(uchar addr,uchar data)

{

RST_CLR;

SCK_CLR;

delay1();

RST_SET;

delay1();

write_byte(addr);

SCK_CLR;

write_byte(data);

SCK_CLR;

RST_CLR;

}

/***** 初始化ds1302函数******/

void Init_ds1302()

{

RST_CLR;

SCK_CLR;

RST_OUT;

SCK_OUT;

}

/***** 写ds1302时间函数******/

void Set_Time(char year,char month,char day,char hour,char min,char sec,char week) {

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时间函数******/

void Get_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); //读取星期

}

/***** 显示时间函数******/

void Display_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); //显示秒

}

//**********星期显示函数***********

void Write_Week(int i,int j,uchar x)

{

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"

#define sclk RA1

#define io RA0

#define reset RA2

#define reset_IO TRISA2

#define sclk_IO TRISA1

#define io_IO TRISA0

/***** 复位脚******/

#define RST_CLR reset=0

#define RST_SET reset=1

#define RST_IN reset_IO=1

#define RST_OUT reset_IO=0

/***** 双向数据******/

#define IO_CLR io=0

#define IO_SET io=1

#define IO_IN io_IO=1

#define IO_OUT io_IO=0

/***** 时钟信号******/

#define SCK_CLR sclk=0

#define SCK_SET sclk=1

#define SCK_IN sclk_IO=1

#define SCK_OUT sclk_IO=0

int year,month,day,hour,min,sec,week;

int alarm_hour=13,alarm_min=30;//定义闹铃时间和闹铃分钟

uchar xinqi[8][4]={" ","SUN","MON","TUS","WED","THU","FRI","SAT"};

void delay1();//延时函数

void write_byte(uchar inbyte); //向ds1302写一个数据

uchar read_byte(void); //从ds1302读一个字节数据

void write_ds1302(uchar addr,uchar data);//往ds1302的指定地址写一个字节数据 uchar read_ds1302(uchar addr);//从ds1302的指定地址读一个字节数据

void Write_Week(int i,int j,uchar x);//星期显示函数

void Init_ds1302(void); //初始化ds1302函数**********

void Get_Time();//读ds1302时间函数******

void Set_Time(char year,char month,char day,char hour,char min,char sec,char week);//写ds1302时间函数******

void Display_Time();//显示时间函数******

#endif

5.2.5温度传感器DS18B20代码

5.2.5.1温度传感器DS18B20.C文件 PIC单片机课程设计报告

#include"ds18b20.h"

//---------------------------------------

//名称:复位DS18B20函数

//---------------------------------------

unsigned char Reset(void)

{

unsigned char k;

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的要求

return k; //k=0为复位成功,k=1为复位失败

}

//---------------------------------------

//名称:写字节函数

//---------------------------------------

void WriteByte(unsigned char dat)

{

unsigned char j;

for(j=0;j

{

if(dat&0x01) //如果写1

{

DQ_DIR=0; //设置RA4位输出口

DQ=0; //拉低

NOP(); //维持6US,符合大于1US小于15US的规范

NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范

NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范

NOP(); //维持6US,符合大于1US小于15US的规范

DQ_DIR=1; //设置RA4为输入口,以释放总线等电阻拉高总线 __delay_us(63); //维持约63US,符合不低于60US的要求

PIC单片机课程设计报告 }

else //如果写0

{

DQ_DIR=0; //设置RA4位输出口

DQ=0; //拉低

__delay_us(63); //维持约63US,符合不低于60US的要求 DQ_DIR=1; //设置RA4为输入口,以释放总线等电阻拉高总线

NOP(); //维持2US,符合大于1US的规范

NOP(); //维持2US,符合大于1US的规范 }

dat=dat>>1; //写入字节右移1位

}

}

//---------------------------------------

//名称:读字节函数

//---------------------------------------

unsigned char ReadByte(void)

{

unsigned char j,buf=0;

for(j=1;j

{

buf=buf>>1; //接收前,先将接收缓冲区右移

DQ_DIR=0; //设置RA4位输出口

DQ=0; //拉低

NOP(); //维持2US,符合大于1US小于15US的规范 NOP(); //维持2US,符合大于1US小于15US的规范

DQ_DIR=1; //设置RA4为输入口,以释放总线等电阻拉高总线 准备读

NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范

NOP(); //维持6US,符合大于1US小于15US的规范 if(DQ==1) buf|=0x80; //读出1位数据保存于buf中最高位

__delay_us(52); //维持约52US,符合总读时隙不低于60US的要求 }

return buf; //退出的同时将接收缓冲区参数返回 }

//---------------------------------------

//名称:温度转换函数

//---------------------------------------

unsigned char Convert(void)

{

if(Reset()==0) //如果复位成功

{

__delay_us(1000); //延时约1000US

WriteByte(0xcc); // 跳过多器件识别

WriteByte(0x44); // 启动温度转换

return 1;

}

else

{

return 0;

}

}

//*************读温度函数*************

void ReadFlash(void)

{

unsigned char Lsb,Msb;

if(Reset()==0)

{

__delay_us(1000); //延时约1000US

WriteByte(0xcc); // 跳过多器件识别

WriteByte(0xbe); // 读暂存器

Lsb=ReadByte(); // 低字节

Msb=ReadByte(); // 高字节

temp2=Lsb&0x0f; //LSB的低4位为小数部分

temp1=(Lsb>>4)|(Msb

}

else

{

temp1=0;

temp2=0;

}

}

//***********显示当前温度**************

void Display_wendu(void)

{

unsigned char buf;

if(Convert()==1) //启动转换

{

ReadFlash(); //读取温度

if(temp1>99) temp1=99;

if(temp2>15) temp2=0;

buf=temp1;

LCD_write_data(10,1,buf); //温度整数部分

LCD1602_write_dat('.'); //.

buf=table[temp2&0x0f];

buf+=0x30;

LCD1602_write_dat(buf); //温度小数部分

LCD1602_write_dat(0xdf); //.

LCD1602_write_dat(0x43); //C

}

}

//***********显示buf温度**************

void Display_temp(uchar buf)

{

LCD_write_data(10,1,buf); //温度报警温度整数部分

LCD1602_write_dat('.'); //.

LCD1602_write_dat(0x30); //温度小数部分0

LCD1602_write_dat(0xdf); //.

LCD1602_write_dat(0x43); //C

}

5.2.5.1温度传感器DS18B20.H文件

#ifndef _DS18B20_H_

#define _DS18B20_H_

#include

#include"all.h"

#include"lcd1602.h"

#define DQ_DIR TRISC0 //控制DS18B20的DQ端

#define DQ RC0 //控制DS18B20的DQ端

unsigned char temp1=0,temp2=0;//当前温度缓存

unsigned char warning_temp=50;//设置报警温度

const unsigned char table[16]={0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,9};

void Display_wendu(void); //显示当前温度函数*********

void Display_temp(uchar buf); //显示buf温度函数*********

void ReadFlash(void) ; //读温度函数

unsigned char Convert(void) ; //温度转换函数

unsigned char ReadByte(void); //读字节函数

void WriteByte(unsigned char dat); //写字节函数

unsigned char Reset(void); //复位DS18B20函数

#endif

5.2.6独立按键代码

5.2.6.1独立按键.C文件 #include"key.h"

//**********按键端口初始化***********

void Key_init()

{

TRISB=0B00011110; //初始化RB4-RB1为输入方向

PORTB=0B11111110; //初始化RA5-RA0数值

}

//**********按键扫描函数*************

void KeyScan()

{

uchar i=0;

int warning_temp_buf=0; //报警温度缓存

int alarm_hour_buf=0,alarm_min_buf=0; //闹钟时间缓存

int year_buf,month_buf,day_buf,hour_buf,min_buf,sec_buf,week_buf;//设置时间缓存

if(SET==0)

{

while(!SET);//松手检测

warning_temp_buf=warning_temp; //读回报警温度设置值

Display_temp(warning_temp_buf); //显示当前报警设置

year_buf=year; //读回当前时间

month_buf=month; //***********

day_buf=day; //***********

hour_buf=hour; //***********

min_buf=min; //***********

sec_buf=sec; //***********

week_buf=week; //***********

alarm_hour_buf=alarm_hour; //读回闹钟小时设置

alarm_min_buf=alarm_min; //读回闹钟分钟设置

LCD1602_write_com(0x0f);//显示光标并闪烁

LCD1602_write_com(0x80+2);//光标移动到年位置

i=0; //清零标志位

while(1)

{

if(SET==0)

{

while(!SET);//松手检测

i++; //标志加一

{ LCD1602_write_com(0x0c); //光标不显示 LCD_clr(); break; } switch(i) //检测标志位并移动光标 { case 0: LCD1602_write_com(0x80+2);//光标移动到年位置 break; case 1: LCD1602_write_com(0x80+5);//光标移动到月位置 break; case 2: LCD1602_write_com(0x80+8);//光标移动到日位置 break; case 3: LCD1602_write_com(0x80+13);//光标移动到星期位置 break; case 4: LCD1602_write_com(0xc0+2);//光标移动到小时位置 break; case 5: LCD1602_write_com(0xc0+5);//光标移动到分钟位置 break; case 6: LCD1602_write_com(0xc0+8);//光标移动到秒位置 break; case 7: LCD1602_write_com(0xc0+11);//光标移动到温度位置 break; case 8: LCD_clr(); //清屏 LocateXY(0,0); LCD1602_write_string(" Alarm Clock "); LCD_write_data(5,1,alarm_hour_buf); //显示时 LCD1602_write_dat(':'); LCD_write_data(8,1,alarm_min_buf); //显示分 LCD1602_write_com(0xc0+6);//光标移动到小时位置 break; case 9: LCD1602_write_com(0xc0+9);//光标移动到分钟位置

default: LCD1602_write_com(0x80+2);//光标移动到年位置(出错复位) break; } } if(UP==0) { while(!UP);//松手检测 switch(i) //检测标志位并增加对应的值 { case 0: year_buf++; if(year_buf>99)year_buf=0; LCD_write_data(1,0,year_buf); //显示年 LCD1602_write_com(0x80+2);//光标移动到年位置 break; case 1: month_buf++; if(month_buf>12)month_buf=1; LCD_write_data(4,0,month_buf); //显示月 LCD1602_write_com(0x80+5);//光标移动到月位置 break; case 2: day_buf++; if(day_buf>31)day_buf=1; LCD_write_data(7,0,day_buf); //显示日 LCD1602_write_com(0x80+8);//光标移动到日位置 break; case 3: week_buf++; if(week_buf>7)week_buf=1; Write_Week(10,0,week_buf); //显示星期 LCD1602_write_com(0x80+13);//光标移动到星期位置 break; case 4: hour_buf++; if(hour_buf>23)hour_buf=0; LCD_write_data(1,1,hour_buf); //显示时 LCD1602_write_com(0xc0+2);//光标移动到小时位置 break; case 5: min_buf++; if(min_buf>59)min_buf=0;

LCD1602_write_com(0xc0+5);//光标移动到分钟位置 break; case 6: sec_buf++; if(sec_buf>59)sec_buf=0; LCD_write_data(7,1,sec_buf); //显示秒 LCD1602_write_com(0xc0+8);//光标移动到秒位置 break; case 7: warning_temp_buf++; if(warning_temp_buf>99)warning_temp_buf=0; Display_temp(warning_temp_buf); //显示报警温度 LCD1602_write_com(0xc0+11);//光标移动到温度位置 break; case 8: alarm_hour_buf++; if(alarm_hour_buf>23)alarm_hour_buf=0; LCD_write_data(5,1,alarm_hour_buf); //显示时 LCD1602_write_com(0xc0+6);//光标移动到小时位置 break; case 9: alarm_min_buf++; if(alarm_min_buf>59)alarm_min_buf=0; LCD_write_data(8,1,alarm_min_buf); //显示分 LCD1602_write_com(0xc0+9);//光标移动到分钟位置 break; default: break; } } if(DOWN==0) { while(!DOWN);//松手检测 switch(i) //检测标志位并增加对应的值 { case 0: year_buf--; if(year_buf

LCD_write_data(4,0,month_buf); //显示月 LCD1602_write_com(0x80+5);//光标移动到月位置 break; case 2: day_buf--; if(day_buf

PIC单片机课程设计报告 LCD1602_write_com(0xc0+6);//光标移动到小时位置 break;

case 9:

alarm_min_buf--;

if(alarm_min_buf

LCD_write_data(8,1,alarm_min_buf); //显示分 LCD1602_write_com(0xc0+9);//光标移动到分钟位置 break;

default:

break;

}

}

if(OK==0)

{

while(!OK);//松手检测

//********************长条件句*******************

//判断条件“时间被修改”或(“闹钟没被修改”且“温度也没改”)则更改时间。

//用以解决只更改闹钟不设置时间时,时间也被修改的问题。 //以及设置时间与当前时间相同的问题。

if(

(year_buf!=year)||(month_buf!=month)||(day_buf!=day)||(hour_buf!=hour)||(min_buf!=min)||(sec_buf!=sec)||(week_buf!=week)

||

((alarm_hour_buf==alarm_hour)&&(alarm_min_buf==alarm_min)&&(warning_temp_buf==warning_temp))

) //长条件句

{

Set_Time(year_buf,month_buf,day_buf,hour_buf,min_buf,sec_buf,week_buf);//写ds1302时间

}

//**************************************************************** warning_temp=warning_temp_buf; //存储报警温度

alarm_hour=alarm_hour_buf; //存储闹钟小时设置 alarm_min=alarm_min_buf; //存储闹钟分钟设置

LCD1602_write_com(0x0c); //光标不显示

LCD_clr();

break;

}

}

}

} PIC单片机课程设计报告

5.2.6.2独立按键.H代码

#ifndef _KEY_H_

#define _KEY_H_

#include

#include"all.h"

#include"lcd1602.h"

#include"ds1302.h"

#include"ds18b20.h"

#define SET RB1

#define UP RB2

#define DOWN RB3

#define OK RB4

void KeyScan();//按键扫描函数

void Key_init();//按键端口初始化

#endif

5.2.7全局变量及定义头文件

#ifndef __ALL_H__

#define __ALL_H__

#ifndef uchar

#define uchar unsigned char

#endif

#ifndef uint

#define uint unsigned int

#endif

#ifndef ulong

#define ulong unsigned long

#endif

#ifndef _XTAL_FREQ

#define _XTAL_FREQ 4000000

#endif

extern int year,month,day,hour,min,sec,week;

extern int alarm_hour,alarm_min;

extern unsigned char temp1,temp2,warning_temp;

#endif

六、设计总结 PIC单片机课程设计报告

通过此次PIC课程设计,使我进一步掌握PIC单片机的应用方法,并通过硬件设计、软件编程及仿真调试的实践,熟练掌握PICC C语言程序的编写与调试,使书本上的理论知识与实践相结合。丰富了知识体系,锻炼了动手能力,使我的实践能力得到了很大提高。这次课程设计是毕业设计前的一次重要实践,为今后走上工作岗位打下坚实的单片机应用基础。

设计成绩:

教师签名: 年 月 日

NORTH CHINA UNIVERSITY OF SCIENCE AND TECHNOLOGY

单片机课程设计报告

学生姓名: 学 号: 学 院: 信息工程学院 专业班级: 12电信4班 指导教师:

2015年6月21日

一、课程设计目的

PIC单片机课程设计报告

本课程设计是在《PIC单片机原理及应用》及《单片机C语言编程》课程的基础上,通过硬件设计、软件编程及仿真调试的实践,进一步掌握PIC单片机的应用方法,熟练掌握PICC C语言程序的编写与调试,是毕业设计前的一次重要实践,为今后走上工作岗位打下坚实的单片机应用基础。

二、设计题目及要求

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,如此循环显示。

按键用来作为时间调整。要求至少设计4个按键,按键1作为设置键;按键2、按键3分别为增加、减少键,在设置键按下时,此两个按键方有效;按键4是确定键,在设置键按下时方才有效。 3.4 温度采集模块

DS18B20是美国DALLAS公司推出的单总线数字温度传感器。DS18B20内部集成了温敏元件、数据转换芯片、存储器芯片和计算机接口芯片等多功能模块。其主要技术特点有:具有独特的单线接口方式;可以通过数据线供电,具有超低功耗工作方式;测温范围为-55℃~125℃,测温精度为0.5℃;温度转换精度9~12位可编程,直接将温度转换值以二进制数码的方式串行输出。

四、硬件原理图

4.1电子时钟原理图

4.3显示模块

4.5温度采集模块

4.6电路仿真图 4.6.1开机动画

4.6.2实时时钟显示,实时温度显示

4.6.3时间可调,报警温度可调

4.6.4闹钟功能

4.6.5超限报警

五、软件设计

PIC单片机课程设计报告

5.1流程图

5.2源程序 5.2.1程序清单

5.2.2主程序代码 5.2.2.1主函数.c文件

PIC单片机课程设计报告

#include #include"main.h"

uchar line1_data[]={"Electronic Clock"}; uchar line2_data[]={" Powered By Me "};

void main(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;} PIC单片机课程设计报告

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清屏函数******/

void LCD_clr()

{

LCD1602_write_com(0x01);

__delay_ms(5);

}

/*********光标定位函数。x为显示列,y为显示行********/

void LocateXY(uchar x,uchar y)

{

if(y==0)

{

LCD1602_write_com(0x80+x);

}

else

{

LCD1602_write_com(0xC0+x);

}

}

//***************特定位置写字符*********************

void LCD_write_str(uchar x,uchar y,uchar *s)

{

LocateXY(x,y);

while(*s)

{

LCD1602_write_dat(*s);

s++;

}

}

//****************特定位置显示数值********************

void LCD_write_data(uchar x,uchar y,uchar data)

{

LocateXY(x,y);

LCD1602_write_dat(data/10 +48); //将数值转换成其对应的ASIC码值,相当于以字符形式输出

LCD1602_write_dat(data%10+ 48); //因为0的ASIC码值为48

}

//****************LCD1602初始化函数********************

void LCD_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读忙状态**********************

void LCD1602_check_busy(void)

{

uint i=20000;

dport_in; //端口设为输入

rs=0;

rw=1;

en=1;

while((0x80&dport)&&(i>0))

{

i--;

}

en=0;

dport_out;

}

//******************向1602写数据**********************

void LCD1602_write_dat(uchar lcd_dat)

{

LCD1602_check_busy();

rs=1;

rw=0;

en=1;

dport=lcd_dat;

en=0;

}

//****************向1602写string数据******************

void LCD1602_write_string(const uchar *cy)

{

while(*cy)

{

LCD1602_check_busy();

rs=1;

rw=0;

en=1;

dport=*cy;

en=0;

cy++;

}

}

//******************向1602写指令**********************

void LCD1602_write_com(uchar lcd_com)

{

LCD1602_check_busy();

rs=0;

rw=0;

en=1;//下降沿把数据写进出

dport=lcd_com;

en=0;

}

5.2.3.1液晶显示屏LCD1602.H文件 PIC单片机课程设计报告

#ifndef _LCD1602_H_

#define _LCD1602_H_

#include

#include"all.h"

#define dport PORTD //定义数据口

#define dport_in TRISD=0xff //PD端口设为输入

#define dport_out TRISD=0x00 //PD端口设为输出

#define rs RE0 //并行数据/控制字选择 H:数据 L:控制字 串行片选信号

#define rw RE1 //并行读/写选择 H:读 L:写 串行数据信号

#define en RE2 //并行读写使能 H有效,下降沿锁定数据 串行时钟信号

//*************** 函数定义 ******************

void LCD1602_check_busy(void); //读1602读忙状态

void LCD1602_write_dat(uchar lcd_dat);//向1602写数据********

void LCD1602_write_string(const uchar *cy);//向1602写string数据

void LCD1602_write_com(uchar lcd_com);//向1602写指令

void LocateXY(uchar x,uchar y);//光标定位函数。x为显示列,y为显示行

void LCD_init(void); //LCD1602初始化函数***********

void LCD_write_data(uchar x,uchar y,uchar data);//特定位置显示数值****** void LCD_write_str(uchar x,uchar y,uchar *s);//特定位置写字符********

void LCD_clr(); //lcd清屏函数*************

#endif

5.2.4时钟芯片DS1302代码

5.2.4.1时钟芯片DS1302.C文件

#include"ds1302.h"

//***********延时函数*************

void delay1()

{

int i;

for(i=100;i--;);

}

/******** 从ds1302读一个字节数据******/

uchar read_byte(void)

{

uchar i,dat=0;

IO_CLR;

for(i=0;i

{

SCK_CLR;

if(io)

{dat=dat|0x80;}

else

{dat=dat&0x7f;}

SCK_SET;

dat=dat>>1;

}

IO_OUT;

SCK_CLR;

return dat;

}

/***** 向ds1302写一个数据******/

void write_byte(uchar dat)

{

uchar i;

for(i=0;i

{

IO_CLR;

SCK_CLR;

if(dat&0x01)

{

IO_SET;

}

else

{

IO_CLR;

}

SCK_SET;

dat>>=1;

}

SCK_CLR;

}

/***** 从ds1302的指定地址读一个字节数据******/

uchar read_ds1302(uchar addr)

{

char data,data1,data2;

RST_CLR;

SCK_CLR;

delay1();

delay1();

write_byte(addr);

data=read_byte();

SCK_CLR;

RST_CLR;

data1=data/16;

data2=data%16;

data=data2+data1*10;

return data;

}

/***** 往ds1302的指定地址写一个字节数据******/

void write_ds1302(uchar addr,uchar data)

{

RST_CLR;

SCK_CLR;

delay1();

RST_SET;

delay1();

write_byte(addr);

SCK_CLR;

write_byte(data);

SCK_CLR;

RST_CLR;

}

/***** 初始化ds1302函数******/

void Init_ds1302()

{

RST_CLR;

SCK_CLR;

RST_OUT;

SCK_OUT;

}

/***** 写ds1302时间函数******/

void Set_Time(char year,char month,char day,char hour,char min,char sec,char week) {

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时间函数******/

void Get_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); //读取星期

}

/***** 显示时间函数******/

void Display_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); //显示秒

}

//**********星期显示函数***********

void Write_Week(int i,int j,uchar x)

{

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"

#define sclk RA1

#define io RA0

#define reset RA2

#define reset_IO TRISA2

#define sclk_IO TRISA1

#define io_IO TRISA0

/***** 复位脚******/

#define RST_CLR reset=0

#define RST_SET reset=1

#define RST_IN reset_IO=1

#define RST_OUT reset_IO=0

/***** 双向数据******/

#define IO_CLR io=0

#define IO_SET io=1

#define IO_IN io_IO=1

#define IO_OUT io_IO=0

/***** 时钟信号******/

#define SCK_CLR sclk=0

#define SCK_SET sclk=1

#define SCK_IN sclk_IO=1

#define SCK_OUT sclk_IO=0

int year,month,day,hour,min,sec,week;

int alarm_hour=13,alarm_min=30;//定义闹铃时间和闹铃分钟

uchar xinqi[8][4]={" ","SUN","MON","TUS","WED","THU","FRI","SAT"};

void delay1();//延时函数

void write_byte(uchar inbyte); //向ds1302写一个数据

uchar read_byte(void); //从ds1302读一个字节数据

void write_ds1302(uchar addr,uchar data);//往ds1302的指定地址写一个字节数据 uchar read_ds1302(uchar addr);//从ds1302的指定地址读一个字节数据

void Write_Week(int i,int j,uchar x);//星期显示函数

void Init_ds1302(void); //初始化ds1302函数**********

void Get_Time();//读ds1302时间函数******

void Set_Time(char year,char month,char day,char hour,char min,char sec,char week);//写ds1302时间函数******

void Display_Time();//显示时间函数******

#endif

5.2.5温度传感器DS18B20代码

5.2.5.1温度传感器DS18B20.C文件 PIC单片机课程设计报告

#include"ds18b20.h"

//---------------------------------------

//名称:复位DS18B20函数

//---------------------------------------

unsigned char Reset(void)

{

unsigned char k;

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的要求

return k; //k=0为复位成功,k=1为复位失败

}

//---------------------------------------

//名称:写字节函数

//---------------------------------------

void WriteByte(unsigned char dat)

{

unsigned char j;

for(j=0;j

{

if(dat&0x01) //如果写1

{

DQ_DIR=0; //设置RA4位输出口

DQ=0; //拉低

NOP(); //维持6US,符合大于1US小于15US的规范

NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范

NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范

NOP(); //维持6US,符合大于1US小于15US的规范

DQ_DIR=1; //设置RA4为输入口,以释放总线等电阻拉高总线 __delay_us(63); //维持约63US,符合不低于60US的要求

PIC单片机课程设计报告 }

else //如果写0

{

DQ_DIR=0; //设置RA4位输出口

DQ=0; //拉低

__delay_us(63); //维持约63US,符合不低于60US的要求 DQ_DIR=1; //设置RA4为输入口,以释放总线等电阻拉高总线

NOP(); //维持2US,符合大于1US的规范

NOP(); //维持2US,符合大于1US的规范 }

dat=dat>>1; //写入字节右移1位

}

}

//---------------------------------------

//名称:读字节函数

//---------------------------------------

unsigned char ReadByte(void)

{

unsigned char j,buf=0;

for(j=1;j

{

buf=buf>>1; //接收前,先将接收缓冲区右移

DQ_DIR=0; //设置RA4位输出口

DQ=0; //拉低

NOP(); //维持2US,符合大于1US小于15US的规范 NOP(); //维持2US,符合大于1US小于15US的规范

DQ_DIR=1; //设置RA4为输入口,以释放总线等电阻拉高总线 准备读

NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范

NOP(); //维持6US,符合大于1US小于15US的规范 if(DQ==1) buf|=0x80; //读出1位数据保存于buf中最高位

__delay_us(52); //维持约52US,符合总读时隙不低于60US的要求 }

return buf; //退出的同时将接收缓冲区参数返回 }

//---------------------------------------

//名称:温度转换函数

//---------------------------------------

unsigned char Convert(void)

{

if(Reset()==0) //如果复位成功

{

__delay_us(1000); //延时约1000US

WriteByte(0xcc); // 跳过多器件识别

WriteByte(0x44); // 启动温度转换

return 1;

}

else

{

return 0;

}

}

//*************读温度函数*************

void ReadFlash(void)

{

unsigned char Lsb,Msb;

if(Reset()==0)

{

__delay_us(1000); //延时约1000US

WriteByte(0xcc); // 跳过多器件识别

WriteByte(0xbe); // 读暂存器

Lsb=ReadByte(); // 低字节

Msb=ReadByte(); // 高字节

temp2=Lsb&0x0f; //LSB的低4位为小数部分

temp1=(Lsb>>4)|(Msb

}

else

{

temp1=0;

temp2=0;

}

}

//***********显示当前温度**************

void Display_wendu(void)

{

unsigned char buf;

if(Convert()==1) //启动转换

{

ReadFlash(); //读取温度

if(temp1>99) temp1=99;

if(temp2>15) temp2=0;

buf=temp1;

LCD_write_data(10,1,buf); //温度整数部分

LCD1602_write_dat('.'); //.

buf=table[temp2&0x0f];

buf+=0x30;

LCD1602_write_dat(buf); //温度小数部分

LCD1602_write_dat(0xdf); //.

LCD1602_write_dat(0x43); //C

}

}

//***********显示buf温度**************

void Display_temp(uchar buf)

{

LCD_write_data(10,1,buf); //温度报警温度整数部分

LCD1602_write_dat('.'); //.

LCD1602_write_dat(0x30); //温度小数部分0

LCD1602_write_dat(0xdf); //.

LCD1602_write_dat(0x43); //C

}

5.2.5.1温度传感器DS18B20.H文件

#ifndef _DS18B20_H_

#define _DS18B20_H_

#include

#include"all.h"

#include"lcd1602.h"

#define DQ_DIR TRISC0 //控制DS18B20的DQ端

#define DQ RC0 //控制DS18B20的DQ端

unsigned char temp1=0,temp2=0;//当前温度缓存

unsigned char warning_temp=50;//设置报警温度

const unsigned char table[16]={0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,9};

void Display_wendu(void); //显示当前温度函数*********

void Display_temp(uchar buf); //显示buf温度函数*********

void ReadFlash(void) ; //读温度函数

unsigned char Convert(void) ; //温度转换函数

unsigned char ReadByte(void); //读字节函数

void WriteByte(unsigned char dat); //写字节函数

unsigned char Reset(void); //复位DS18B20函数

#endif

5.2.6独立按键代码

5.2.6.1独立按键.C文件 #include"key.h"

//**********按键端口初始化***********

void Key_init()

{

TRISB=0B00011110; //初始化RB4-RB1为输入方向

PORTB=0B11111110; //初始化RA5-RA0数值

}

//**********按键扫描函数*************

void KeyScan()

{

uchar i=0;

int warning_temp_buf=0; //报警温度缓存

int alarm_hour_buf=0,alarm_min_buf=0; //闹钟时间缓存

int year_buf,month_buf,day_buf,hour_buf,min_buf,sec_buf,week_buf;//设置时间缓存

if(SET==0)

{

while(!SET);//松手检测

warning_temp_buf=warning_temp; //读回报警温度设置值

Display_temp(warning_temp_buf); //显示当前报警设置

year_buf=year; //读回当前时间

month_buf=month; //***********

day_buf=day; //***********

hour_buf=hour; //***********

min_buf=min; //***********

sec_buf=sec; //***********

week_buf=week; //***********

alarm_hour_buf=alarm_hour; //读回闹钟小时设置

alarm_min_buf=alarm_min; //读回闹钟分钟设置

LCD1602_write_com(0x0f);//显示光标并闪烁

LCD1602_write_com(0x80+2);//光标移动到年位置

i=0; //清零标志位

while(1)

{

if(SET==0)

{

while(!SET);//松手检测

i++; //标志加一

{ LCD1602_write_com(0x0c); //光标不显示 LCD_clr(); break; } switch(i) //检测标志位并移动光标 { case 0: LCD1602_write_com(0x80+2);//光标移动到年位置 break; case 1: LCD1602_write_com(0x80+5);//光标移动到月位置 break; case 2: LCD1602_write_com(0x80+8);//光标移动到日位置 break; case 3: LCD1602_write_com(0x80+13);//光标移动到星期位置 break; case 4: LCD1602_write_com(0xc0+2);//光标移动到小时位置 break; case 5: LCD1602_write_com(0xc0+5);//光标移动到分钟位置 break; case 6: LCD1602_write_com(0xc0+8);//光标移动到秒位置 break; case 7: LCD1602_write_com(0xc0+11);//光标移动到温度位置 break; case 8: LCD_clr(); //清屏 LocateXY(0,0); LCD1602_write_string(" Alarm Clock "); LCD_write_data(5,1,alarm_hour_buf); //显示时 LCD1602_write_dat(':'); LCD_write_data(8,1,alarm_min_buf); //显示分 LCD1602_write_com(0xc0+6);//光标移动到小时位置 break; case 9: LCD1602_write_com(0xc0+9);//光标移动到分钟位置

default: LCD1602_write_com(0x80+2);//光标移动到年位置(出错复位) break; } } if(UP==0) { while(!UP);//松手检测 switch(i) //检测标志位并增加对应的值 { case 0: year_buf++; if(year_buf>99)year_buf=0; LCD_write_data(1,0,year_buf); //显示年 LCD1602_write_com(0x80+2);//光标移动到年位置 break; case 1: month_buf++; if(month_buf>12)month_buf=1; LCD_write_data(4,0,month_buf); //显示月 LCD1602_write_com(0x80+5);//光标移动到月位置 break; case 2: day_buf++; if(day_buf>31)day_buf=1; LCD_write_data(7,0,day_buf); //显示日 LCD1602_write_com(0x80+8);//光标移动到日位置 break; case 3: week_buf++; if(week_buf>7)week_buf=1; Write_Week(10,0,week_buf); //显示星期 LCD1602_write_com(0x80+13);//光标移动到星期位置 break; case 4: hour_buf++; if(hour_buf>23)hour_buf=0; LCD_write_data(1,1,hour_buf); //显示时 LCD1602_write_com(0xc0+2);//光标移动到小时位置 break; case 5: min_buf++; if(min_buf>59)min_buf=0;

LCD1602_write_com(0xc0+5);//光标移动到分钟位置 break; case 6: sec_buf++; if(sec_buf>59)sec_buf=0; LCD_write_data(7,1,sec_buf); //显示秒 LCD1602_write_com(0xc0+8);//光标移动到秒位置 break; case 7: warning_temp_buf++; if(warning_temp_buf>99)warning_temp_buf=0; Display_temp(warning_temp_buf); //显示报警温度 LCD1602_write_com(0xc0+11);//光标移动到温度位置 break; case 8: alarm_hour_buf++; if(alarm_hour_buf>23)alarm_hour_buf=0; LCD_write_data(5,1,alarm_hour_buf); //显示时 LCD1602_write_com(0xc0+6);//光标移动到小时位置 break; case 9: alarm_min_buf++; if(alarm_min_buf>59)alarm_min_buf=0; LCD_write_data(8,1,alarm_min_buf); //显示分 LCD1602_write_com(0xc0+9);//光标移动到分钟位置 break; default: break; } } if(DOWN==0) { while(!DOWN);//松手检测 switch(i) //检测标志位并增加对应的值 { case 0: year_buf--; if(year_buf

LCD_write_data(4,0,month_buf); //显示月 LCD1602_write_com(0x80+5);//光标移动到月位置 break; case 2: day_buf--; if(day_buf

PIC单片机课程设计报告 LCD1602_write_com(0xc0+6);//光标移动到小时位置 break;

case 9:

alarm_min_buf--;

if(alarm_min_buf

LCD_write_data(8,1,alarm_min_buf); //显示分 LCD1602_write_com(0xc0+9);//光标移动到分钟位置 break;

default:

break;

}

}

if(OK==0)

{

while(!OK);//松手检测

//********************长条件句*******************

//判断条件“时间被修改”或(“闹钟没被修改”且“温度也没改”)则更改时间。

//用以解决只更改闹钟不设置时间时,时间也被修改的问题。 //以及设置时间与当前时间相同的问题。

if(

(year_buf!=year)||(month_buf!=month)||(day_buf!=day)||(hour_buf!=hour)||(min_buf!=min)||(sec_buf!=sec)||(week_buf!=week)

||

((alarm_hour_buf==alarm_hour)&&(alarm_min_buf==alarm_min)&&(warning_temp_buf==warning_temp))

) //长条件句

{

Set_Time(year_buf,month_buf,day_buf,hour_buf,min_buf,sec_buf,week_buf);//写ds1302时间

}

//**************************************************************** warning_temp=warning_temp_buf; //存储报警温度

alarm_hour=alarm_hour_buf; //存储闹钟小时设置 alarm_min=alarm_min_buf; //存储闹钟分钟设置

LCD1602_write_com(0x0c); //光标不显示

LCD_clr();

break;

}

}

}

} PIC单片机课程设计报告

5.2.6.2独立按键.H代码

#ifndef _KEY_H_

#define _KEY_H_

#include

#include"all.h"

#include"lcd1602.h"

#include"ds1302.h"

#include"ds18b20.h"

#define SET RB1

#define UP RB2

#define DOWN RB3

#define OK RB4

void KeyScan();//按键扫描函数

void Key_init();//按键端口初始化

#endif

5.2.7全局变量及定义头文件

#ifndef __ALL_H__

#define __ALL_H__

#ifndef uchar

#define uchar unsigned char

#endif

#ifndef uint

#define uint unsigned int

#endif

#ifndef ulong

#define ulong unsigned long

#endif

#ifndef _XTAL_FREQ

#define _XTAL_FREQ 4000000

#endif

extern int year,month,day,hour,min,sec,week;

extern int alarm_hour,alarm_min;

extern unsigned char temp1,temp2,warning_temp;

#endif

六、设计总结 PIC单片机课程设计报告

通过此次PIC课程设计,使我进一步掌握PIC单片机的应用方法,并通过硬件设计、软件编程及仿真调试的实践,熟练掌握PICC C语言程序的编写与调试,使书本上的理论知识与实践相结合。丰富了知识体系,锻炼了动手能力,使我的实践能力得到了很大提高。这次课程设计是毕业设计前的一次重要实践,为今后走上工作岗位打下坚实的单片机应用基础。

设计成绩:

教师签名: 年 月 日


相关文章

  • 单片机原理与接口技术实验室方案
  • 单片机原理与接口技术实验室方案 一.前言 单片机是当今电子信息产业发展最迅速的领域,大学单晶片教学和实验应该适应这样的变化,本方 案是针对单片机原理课程为主的单片机原理与接口技术 单片机原理与接口技术实验室的设备配置,从基础课程建设开始,对 ...查看


  • 单片机实用技术
  • 单片机实用技术 作者:shenxq301 1 首先介绍经济使用的单片机AVR 使用学习板快速入门,尤其实用于在校学生和刚刚工作的工程技术人员. AVR mega16学习板 单价:240 元 该学习板可以从正规途径买到正版,当然也可从旧货市场 ...查看


  • 单片机培训课程
  • 单片机培训课程 本文介绍了广州单片机培训课程.嵌入式系统开发工程师课程.PCB 板设计培训课程的学习内容及广州单片机培训学校的基本情况. 单片机培训课程(1) 课程名称:单片机设计工程师 培训内容:以MCS-51单片机为学习对象,通过LED ...查看


  • 天大自动化智能课程设计报告
  • 智能装置课程设计 题 目:智能电机测速仪姓 名:晁平复班 级:自动化学 号:同组人:王平 4班 3008203263 一. 课程设计目的: a) 深入了解PIC16F877单片机的工作原理,熟练掌握汇编语言程序设计方法,熟练 使用MPLAB ...查看


  • 基于单片机的秒表设计
  • 题目:基于单片机的秒表设计 姓 名: 学 号: 专业班级: 指导老师: 所在学院: 年 月 日 摘要 本设计是一个利用单片机控制的多功能秒表系统,它是基于51系列的单片机进行的系统设计.它采用AT89C51单片机为中心器件,利用其定时器/计 ...查看


  • 单片机课程设计电子钟实验
  • 数字钟实验 一 实验目的与要求 进一步熟悉I∧2C总线,掌握时钟芯片的使用:掌握使用液晶显示器显示时间 二 实验内容 ⒈PGF8563: ⑴实时时钟芯片,可记时时间1900-2099年,不具有周调整功能. ⑵数据传输采用I∧2C总线,固定片 ...查看


  • 北邮单片机实验报告(电子密码锁)
  • xx 班 xx 号 xx 单片机设计实验报告 2015 年小学期单片机设计实验报告 题目:基于 PIC 单片机的电子密码锁 班 级: 班内序号: 实验组号: 学生姓名: 指导教师: xx 班 xx 号 xx 单片机设计实验报告 期中检查 教 ...查看


  • 2015单片机学习心得
  • 2015单片机学习心得 第1篇:单片机学习心得分享 学习使用单片机就是理解单片机硬件结构,以及内部资源的应用,在汇编或C语言中学会各种功能的初始化设置,以及实现各种功能的程序编制. 第一步:数字I/O的使用 使用按钮输入信号,发光二极管显示 ...查看


  • 智能捕鼠器
  • 摘 要 当今社会,人们的生活水平和生活方式都在不断的提高,智能化已经在我们 生活中得到了实施.随着科学技术的进步和人们生活条件的友好改善,各种智能设备在人们的生活中不断出现,使人们的生活越来越方便和舒适.其中以单片机为核心实现的智能捕鼠器因 ...查看


热门内容