PIC单片机课程设计报告Word文件下载.docx
《PIC单片机课程设计报告Word文件下载.docx》由会员分享,可在线阅读,更多相关《PIC单片机课程设计报告Word文件下载.docx(22页珍藏版)》请在冰点文库上搜索。
具有独特的单线接口方式;
可以通过数据线供电,具有超低功耗工作方式;
测温范围为-55℃~125℃,测温精度为0.5℃;
温度转换精度9~12位可编程,直接将温度转换值以二进制数码的方式串行输出。
四、硬件原理图
(含原理图、电路仿真图)
时间显示:
按下温度键temp后显示温度:
五、软件设计
(含流程图、带注释的程序清单)
#include<
pic.h>
#include<
string.h>
stdio.h>
#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)
165;
voidwrite_byte_to_DS1302(unsignedcharx)
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;
8;
i++)
SCLK=1;
SCLK=0;
if(IO)dat|=(0x01<
i);
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)
write_byte_to_DS1302(dat);
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;
60;
i++)
for(j=0;
j<
3;
j++)
{
speak=1;
delay18us(tone[x]);
speak=0;
//翻转发声
}
}
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;
Write_DS1302(0x82,b);
if(RB4==0)
song(3);
while(RB4==ON);
Write_DS1302(0x80,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;
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寄存器数据
PORT_LCD_DAT=dat;
RS=1;
E=0;
voidLCD_Initialize()
Write_LCD_Command(0x38);
__delay_ms
(2);
Write_LCD_Command(0x01);
Write_LCD_Command(0x06);
Write_LCD_Command(0x0C);
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;
16&
&
str[i]!
='
\0'
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)//设置显示起始位置
//********18B20子程序********//
//包括函数:
voidWait_18B20();
//
voiddelay15us(unsignedintx)//x必须大于0
{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;
8;
tmp=data&
0x01;
data>
=1;
if(tmp)//tmp=1时
DQ_OUT();
NOP();
DQ_IN();
delay15us(5);
//延时61us
unsignedcharread_one_byte()
unsignedchari,data;
NOP();
if(DQ==1)
data=data|0x80;
//延时61us
return(data);
unsignedintget_temperature()
unsignedchartmpA,tmpB;
//定义读出RAM的高低位变量
reset();
write_one_byte(0xcc);
//写跳过ROM命令,因为总线上只有一个DS18B20
write_one_byte(0x44);
//启动DS18B20温度转换命令
delay1ms(800);
//如果再写命令必须再次复位
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;
//负号
//高八位
//低八位
tmp[0]=results/100+0x30;
//百
tmp[1]=results/10%10+0x30;
//十
tmp[2]=results%10+0x30;
//个
tmpA<
tmpA>
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"
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);
speak=0;
voidmain()
//unsignedchari;
TRISA0=TRISA2=0;
port_init();
LCD_Initialize();
init_DS1302;
while
(1)
pro_key_scan();
Screen();
compare();
temp();
六、设计总结
通过这次课程设计,使我更加扎实的掌握了单片机方面的知识,再设计过程中虽然遇到了一些问题,但经过一次又一次的思考,一遍又一遍的检查终于找出了原因所