PIC单片机课程设计报告.docx

上传人:b****2 文档编号:1575706 上传时间:2023-05-01 格式:DOCX 页数:22 大小:369.84KB
下载 相关 举报
PIC单片机课程设计报告.docx_第1页
第1页 / 共22页
PIC单片机课程设计报告.docx_第2页
第2页 / 共22页
PIC单片机课程设计报告.docx_第3页
第3页 / 共22页
PIC单片机课程设计报告.docx_第4页
第4页 / 共22页
PIC单片机课程设计报告.docx_第5页
第5页 / 共22页
PIC单片机课程设计报告.docx_第6页
第6页 / 共22页
PIC单片机课程设计报告.docx_第7页
第7页 / 共22页
PIC单片机课程设计报告.docx_第8页
第8页 / 共22页
PIC单片机课程设计报告.docx_第9页
第9页 / 共22页
PIC单片机课程设计报告.docx_第10页
第10页 / 共22页
PIC单片机课程设计报告.docx_第11页
第11页 / 共22页
PIC单片机课程设计报告.docx_第12页
第12页 / 共22页
PIC单片机课程设计报告.docx_第13页
第13页 / 共22页
PIC单片机课程设计报告.docx_第14页
第14页 / 共22页
PIC单片机课程设计报告.docx_第15页
第15页 / 共22页
PIC单片机课程设计报告.docx_第16页
第16页 / 共22页
PIC单片机课程设计报告.docx_第17页
第17页 / 共22页
PIC单片机课程设计报告.docx_第18页
第18页 / 共22页
PIC单片机课程设计报告.docx_第19页
第19页 / 共22页
PIC单片机课程设计报告.docx_第20页
第20页 / 共22页
亲,该文档总共22页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

PIC单片机课程设计报告.docx

《PIC单片机课程设计报告.docx》由会员分享,可在线阅读,更多相关《PIC单片机课程设计报告.docx(22页珍藏版)》请在冰点文库上搜索。

PIC单片机课程设计报告.docx

PIC单片机课程设计报告

华北理工大学

NORTHCHINAUNIVERSITYOFSCIENCEANDTECHNOLOGY

单片机课程设计报告

学生姓名:

王文帅

学号:

2

学院:

信息工程学院

专业班级:

12级电信四班

指导教师:

崔博

2015年06月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位可编程,直接将温度转换值以二进制数码的方式串行输出。

四、硬件原理图

(含原理图、电路仿真图)

时间显示:

按下温度键temp后显示温度:

 

五、软件设计

(含流程图、带注释的程序清单)

#include

#include

#include

#define_XTAL_FREQ1000000UL

#definespeakRC3

#defineON0

#defineOFF1

#defineDQRB5

//设置数据方向

#defineDQ_IN()TRISB5=1//输入

#defineDQ_OUT()TRISB5=0//输出

//DS1302引脚定义

#defineIORA1

#defineSCLKRA0

#defineRSTRA2

//DS1302端口数据读写方向

#defineSET_IO_RD()TRISA1=1

#defineSET_IO_WR()TRISA1=0

#defineLCD_CLS0x01

#defineLCD_HOME0x02

#defineLCD_SETMODE0x04

#defineLCD_SETVISIBLE0x08

#defineLCD_SHIFT0x10

#defineLCD_SETFUNCTION0x20

#defineLCD_SETCGADDR0x40

#defineLCD_SETDDADDR0x80

#definePORT_LCD_DATPORTD

#definePORT_LCD_CTLPORTC

#defineTRIS_LCD_DATTRISD

#defineTRIS_LCD_CTLTRISC

#defineRSRC5

#defineRWRC6

#defineERC7

externunsignedcharDateTime[];

externcharWEEK[][4]={"SUN","MON","TUS","WEN","THU","FRI","SAT"};

//0,1,2,3,4,5,6分别对应周日,周一至周六

//所读取的日期时间(秒,分,时,日,月,星期,年)

unsignedinttemper;

unsignedintsettempe=570;

unsignedcharDateTime[7];

unsignedchartmp[]="0000";

//向DS1302写入一个字节

unsignedcharRB1_FLAG=0;

constunsignedchartone[]={108,102,91,86,77,68,61,57};//发声的频率常数

voiddelay18us(unsignedcharx)//18us,每次加1,增加9us

{

unsignedchari;

for(;x>0;x--)

{

for(i=0;i<1;i++);

}

}

voiddelay1ms(unsignedintx)

{

unsignedchari;

for(;x>0;x--)

for(i=0;i<165;i++);

}

voidwrite_byte_to_DS1302(unsignedcharx)

{

unsignedchari;SET_IO_WR();

for(i=0x01;i!

=0x00;i<<=1)

{

if(x&i)IO=1;elseIO=0;

SCLK=0;SCLK=1;__delay_us(10);

}

}

//从DS1302读取1字节

unsignedcharget_byte_form_DS1302()

{

unsignedchari,dat=0x00;SET_IO_RD();

for(i=0;i<8;i++)

{

SCLK=1;SCLK=0;

if(IO)dat|=(0x01<

}

return(dat>>4)*10+(dat&0x0F);

}

//从DS1302指定位置读数据

unsignedcharread_data(unsignedcharaddr)

{

unsignedchardat;

RST=1;

write_byte_to_DS1302(addr);

dat=get_byte_form_DS1302();

RST=0;

returndat;

}

//向DS1302指定地址写数据

voidWrite_DS1302(unsignedcharaddr,unsignedchardat)

{

RST=1;

write_byte_to_DS1302(addr);

write_byte_to_DS1302(dat);

RST=0;

}

voidport_init()

{

ADCON1=0X06;//RA设置为普通IO口

TRISA=0X00;//端口A设置为输出

OPTION=0X00;//端口B弱上拉使能

TRISB=0xFF;

PORTC=0X00;

TRISC=0X00;//端口C设置为输出

PORTD=0X00;

TRISD=0X00;//端口D设置为输出

speak=0;

}

voidsong(unsignedcharx)

{

unsignedchari,j;

for(i=0;i<60;i++)

{

for(j=0;j<3;j++)

{

speak=1;

delay18us(tone[x]);

speak=0;//翻转发声

delay18us(tone[x]);

}

}

}

voidkeyscan()

{

unsignedchara,b;

DateTime[0]=0;

Write_DS1302(0x8E,0x00);//

Write_DS1302(0x80,0x80);//

if(RB2==0)//小时+1

{

DateTime[2]=DateTime[2]+1;//第三个元素小时+1

if(DateTime[2]==24)DateTime[2]=0;//当变为24H时,小时位归零

a=DateTime[2]/10*16+DateTime[2]%10;//变成16进制数据

Write_DS1302(0x84,a);

}

if(RB3==0)

{

DateTime[1]=DateTime[1]+1;//第二个元素分钟+1

if(DateTime[1]==60)DateTime[1]=0;//当变为60min时,小时位归零

b=DateTime[1]/10*16+DateTime[1]%10;//变成16进制数据

Write_DS1302(0x82,b);

}

if(RB4==0)

{

song(3);

while(RB4==ON);

Write_DS1302(0x80,0x00);//调整完毕后启动时钟运行

Write_DS1302(0x8E,0x00);//禁止写

RB1_FLAG=0;//将RB1按下后产生的标志清除

}

}

//DS1302初始化

voidinit_DS1302()

{

unsignedcharsecond_REG;

second_REG=read_data(0x81);//读取秒寄存器当前值

//如果高位CH为1,则表示当前DS1302振荡器出于待机状态

//这时需要将CH(clockhaltflag)位设为0,打开振荡器使时钟运行

if((second_REG&0x80)==0x80)

{

Write_DS1302(0x8E,0x00);//写控制字节,取消写保护

Write_DS1302(0x80,second_REG&0x7F);//0x80地址不变,设高位CH=0

Write_DS1302(0x8E,0x80);//加保护

}

}

//读取当前日期

voidgetDateTime()

{

//Write_DS1302(0x8E,0x00);//允许写操作

unsignedchari,addr=0x81;

for(i=0;i<7;i++)

{

DateTime[i]=read_data(addr);

addr+=2;

}

}

//********LCD显示子函数***********************//

//**********结束LCD子函数********************//

voidLCD_BUSY_WAIT()//忙等待

{

unsignedcharstatus;

TRIS_LCD_DAT=0xFF;

RS=0;RW=1;

do

{

E=1;NOP();

status=PORT_LCD_DAT;

E=0;

}

while(status&0x80);

}

voidWrite_LCD_Command(unsignedcharcmd)//写LCD命令

{

TRIS_LCD_DAT=0x00;

PORT_LCD_DAT=cmd;

PORT_LCD_CTL=TRIS_LCD_CTL=0x00;

RS=0;

RW=0;

E=1;

NOP();

E=0;

LCD_BUSY_WAIT();

}

voidWrite_LCD_Data(unsignedchardat)//写LCD寄存器数据

{

TRIS_LCD_DAT=0x00;

PORT_LCD_DAT=dat;

RS=1;

RW=0;

E=1;

NOP();

E=0;

LCD_BUSY_WAIT();

}

voidLCD_Initialize()

{

Write_LCD_Command(0x38);

__delay_ms

(2);

Write_LCD_Command(0x01);

__delay_ms

(2);

Write_LCD_Command(0x06);

__delay_ms

(2);

Write_LCD_Command(0x0C);

__delay_ms

(2);

}

voidLCD_ShowString(unsignedcharr,unsignedcharc,char*str)

{

unsignedchari=0;

if(r==0)Write_LCD_Command(0x80|c);

else

if(r==1)Write_LCD_Command(0xC0|c);

for(i=0;i<16&&str[i]!

='\0';i++)

Write_LCD_Data(str[i]);

}

voiddisplay_str(unsignedcharline,unsignedcharlocation,unsignedcharstr)//line行,location列,str字符

{

RS=0;

RW=0;

E=1;

delay1ms

(1);

if(line==0)//line=0,第一行

PORT_LCD_DAT=0x80+location;

if(line==1)//line=1,第二行

PORT_LCD_DAT=0xC0+location;

E=0;

LCD_BUSY_WAIT();

Write_LCD_Data(str);

}

voidSet_LCD_POS(unsignedcharr,unsignedcharc)//设置显示起始位置

{

if(r==0)Write_LCD_Command(0x80|c);else

if(r==1)Write_LCD_Command(0xC0|c);

}

//********18B20子程序********//

//包括函数:

voidWait_18B20();//

//

voiddelay15us(unsignedintx)//x必须大于0

{

do

{x--;}

while(x);

}

voidreset()

{

unsignedcharstate_DQ=1;

while(state_DQ)

{

DQ_OUT();

delay15us(64);//延时721us

DQ_IN();

delay15us(5);//延时61us

if(DQ)

state_DQ=1;//若DS18B20无应答,循环检查

else

state_DQ=0;//检测到DS18B20应答低电平信号

delay15us(43);//延时490us

}

}

voidwrite_one_byte(unsignedchardata)

{

unsignedchari,tmp;

for(i=0;i<8;i++)

{

tmp=data&0x01;

data>>=1;

if(tmp)//tmp=1时

{

DQ_OUT();

NOP();NOP();

DQ_IN();

delay15us(5);//延时61us

}

else

{

DQ_OUT();

delay15us(5);//延时61us

DQ_IN();

NOP();NOP();

}

}

}

unsignedcharread_one_byte()

{

unsignedchari,data;

for(i=0;i<8;i++)

{

data>>=1;

DQ_OUT();

NOP();

DQ_IN();

NOP();NOP();

if(DQ==1)

data=data|0x80;

delay15us(5);//延时61us

}

return(data);

}

unsignedintget_temperature()

{

unsignedchartmpA,tmpB;//定义读出RAM的高低位变量

reset();

write_one_byte(0xcc);//写跳过ROM命令,因为总线上只有一个DS18B20

write_one_byte(0x44);//启动DS18B20温度转换命令

delay1ms(800);

reset();//如果再写命令必须再次复位

write_one_byte(0xcc);//写跳过ROM命令,因为总线上只有一个DS18B20

write_one_byte(0xbe);//读内部RAM中9字节的内容命令

tmpA=read_one_byte();//读内部RAM低八位温度

tmpB=read_one_byte();//读内部RAM高八位温度

temper=tmpB*256+tmpA;

return(temper);

}

voidtemp()

{

unsignedchartmpB,tmpA;

unsignedintresults;

display_str(1,10,tmp[0]);//在指定位置显示百位/负号

display_str(1,11,tmp[1]);//在指定位置显示十位

display_str(1,12,tmp[2]);//在指定位置显示个位

display_str(1,13,'.');//在指定位置显示小数点位

display_str(1,14,tmp[3]);//在指定位置显示十分位位

display_str(1,15,0XDF);//在指定位置显示°

display_str(1,16,'C');//在指定位置显示C

delay1ms(200);//tmp[21]...222325

results=get_temperature();

if(results>=0x1000)

{

results=results^0xFFFF;

results++;

tmpB=results/256;

tmpA=(unsignedchar)results;

results>>=4;

tmp[0]=0x2D;//负号

}

else

{

tmpB=results/256;//高八位

tmpA=(unsignedchar)results;//低八位

results>>=4;

tmp[0]=results/100+0x30;//百

}

tmp[1]=results/10%10+0x30;//十

tmp[2]=results%10+0x30;//个

tmpA<<=4;

tmpA>>=4;

results=625*tmpA;

tmp[3]=results/1000+0x30;

//if(results>40)

//speak=0;

//song(0);

}

charLCD_disp_buff[17];

voidpro_key_scan()

{

if(RB1==1)

{

getDateTime();

}

if(RB1==0)

{

song(0);

while(RB1==ON);

__delay_ms(10);

//if(RB1==0)

//{

while(!

RB1);

RB1_FLAG=1;

//}

}

if(RB1_FLAG==1)keyscan();

}

voidScreen()

{

sprintf(LCD_disp_buff,"%02d-%02d-%02d%3s",

DateTime[6],DateTime[4],DateTime[3],WEEK[DateTime[5]-1]);

LCD_ShowString(0,0,LCD_disp_buff);

sprintf(LCD_disp_buff,"%02d:

%02d:

%02d",

DateTime[2],DateTime[1],DateTime[0]);

LCD_ShowString(1,0,LCD_disp_buff);

__delay_ms(100);

}

voidcompare()

{

if(temper>settempe)//当温度超过35.7度,蜂鸣器便会报警。

{

speak=1;

song

(1);

}

else

{

speak=0;

}

}

voidmain()

{

//unsignedchari;

TRISA0=TRISA2=0;

port_init();

LCD_Initialize();

init_DS1302;

while

(1)

{

pro_key_scan();

Screen();

compare();

temp();

}

}

六、设计总结

通过这次课程设计,使我更加扎实的掌握了单片机方面的知识,再设计过程中虽然遇到了一些问题,但经过一次又一次的思考,一遍又一遍的检查终于找出了原因所

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 工作范文 > 行政公文

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2