单片机原理与应用实验报告温度测量显示及设定.docx
《单片机原理与应用实验报告温度测量显示及设定.docx》由会员分享,可在线阅读,更多相关《单片机原理与应用实验报告温度测量显示及设定.docx(34页珍藏版)》请在冰豆网上搜索。
单片机原理与应用实验报告温度测量显示及设定
《单片机原理与应用》课程实验报告
院系:
班级:
学生:
学号:
指导教师:
设计时间:
哈尔滨工业大学
1实验的目的、内容和设备
1.1实验的目的
单片机综合实验的目的是训练单片机应用系统的编程及调试能力,通过对一个单片机应用系统进行系统的编程和调试,掌握单片机应用系统开发环境和仿真调试工具及仪器仪表的实用,掌握单片机应用程序代码的编写和编译,掌握利用单片机硬件仿真调试工具进行单片机程序的跟踪调试和排错方法,掌握示波器和万用表等杆塔工具在单片机系统调试中应用。
1.2实验内容
实验的内容是利用APP001开发板实现一个温度测量显示和控制的单片机应用系统,利用APP001开发板上的温度传感器测量温度,通过键盘输入一个稳定设定值,当测量温度高于设定温度时发出声音报警,开启散热风扇开关,并在LCD上显示实时温度值,设定温度值和散热风扇的开关状态,其中日期和时间利用单片机的定时器来产生,并能通过键盘来设定。
通过该实验学习和掌握以下的内容:
1)MPLAB开发环境的使用,程序编写和排错及软件仿真
2)利用MPLAB和ICD2对程序进行在线仿真和调试
3)使用万用表和示波器等仪器对硬件系统进行测量和调试
4)PIC18F452单片机的I/O和PWM驱动及编程方法
5)PIC18F452单片机LCD和键盘接口及编程方法
6)PIC18F452单片机的USART编程及与PC机的通讯方法
7)利用Timer1外接32.768kHz的晶振产生RTC
1.3实验设备
1)运行MPLAB的PC机
2)示波器、万用表
3)直流电源
4)ICD2仿真器
5)APP001多功能实验板
2总体设计
2.1硬件总体设计
系统组成方案
图1系统框图
2.2软件总体设计
图2主程序框图
图3中断程序框图
3硬件设计
1)散热风扇开发输出控制:
实验中我们利用一个LED来模拟风扇状态,当散热风扇开关打开时,LED被点亮发光,当散热风扇关闭时,LED不发光。
开发板上的指示灯D11由RB2,低电平亮,高电平灭。
在代码中通过TRISBbits.TRISB2=0/1来设置输出/输入,通过PORTBbits.RB2来控制RB2管脚输入高低电平。
2)字符LCDAPP001:
开发板配置了一个2X16的字符LCD,它和PIC18F452的接口图如下。
端口D的RD0-RD3连接到LCD模块的DB4-DB7,用来向LCD模块写入命令和数据,其中DB7可以用来作为LCD模块控制器的忙标志位:
RD5是读写控制位;RD4是命令和数据标志位,当RD4=0时,RD0-RD3是读取和写入数据到LCD的命令寄存器,RD4=1时,RD0-RD3读取和写入的是要显示的数据。
端口A的RA2位用来控制LCD的使能,当RA2是高电平时LCD开始工作,RA2是低电平时,LCD禁止写工作。
图中的电位器VR是用来调节LCD的显示辉度。
图4LCD电路图
3)TC74:
APP001开发板上配置了一个I2C接口的温度传感器TC74.要使用TC74温度传感器时,断开J9的5、6、7、8管脚,同时连接J10的5、6、7、8管脚。
图5TC74电路图
4)键盘:
APP001开发板上配置了2组按键,SW2和SW3连接到端口RB0和RA4上。
4软件设计
1)温度更新函数:
实现从TC47温度传感器中读取温度值,再将它显示到LCD上。
voidLCD_Temp_Update(void);
2)串口通讯函数:
将当前时间和温度通过串口发送到PC机。
voidsend_temperature(void);
3)按键处理函数:
判断按键是否按下,并根据相应的按键设定时间和报警值。
voidkey_response(void);
4)报警函数:
通过将当前温度值与报警值进行比较,判断是否需要报警。
voidalarm_response(void);
5系统操作说明
通过STATUS按键切换设置日期、时间、设置温度报警值和完成状态,状态标志会依次在LCD上显示“Y(year)、M(month)、D(day)、h(hour)、m(minute)、s(second)、T(tempture)”,提示操作者。
在相应的提示符号状态下,可以通过递增键来改变相应的值。
每按以此,值加1,数值由0~9,逢9化0。
.LCD上还会显示实时日期时钟、传感器测得的当前温度值及报警值。
温度设定值规定为10~50度。
同时单片机还会将实时时间和传感器测得的当前温度值发送到PC机。
当温度超过报警值时,打开蜂鸣器和风扇(LED代替)。
打开串口调试小助手,当程序处在运行状态时,通过串口线,单片机每隔一秒会像PC机发送包含时间和当前温度的字符串。
6调试过程和结束语
通过本次单片机实验,了解了单片机应用系统的整个设计过程,培养了设计单片机应用初步能力。
提高了综合运用单片机原理、C语言及电工电子技术等课程知识进行单片机应用系统设计的能力。
(1)在调试过程中,在状态变量的指针方面遇到了较大的难题。
因为年月日时分秒和温度报警值总共有7个设置量。
其中日期和时间存储在dt[6]数组中。
刚开始设定displaycount指针的初始值来使状态显示位依次变化,但调试结果并不按设定的顺序变化,总是相差一定的数值。
最后还是修改程序形式。
记录调试过程中的显示顺序,然后由显示内容找出状态提示对应的字母,将对应字母改成我们要显示的字母。
虽然表面上程序能够正常实现功能。
但这次尝试说明我们对指针还不是很理解,以至于不能控制指针的精确指向。
程序如下所示:
if(displaycount>=0&&displaycount<=2)
select_change=&dt[5-displaycount];
if(displaycount>=3&&displaycount<=5)
select_change=&dt[5-displaycount];
if(displaycount==6)
select_change=&alarm_value;
if(displaycount==7)
select_change=&nouse;
if(displaycount==0)
friendkey='Y';
if(displaycount==1)
friendkey='M';
if(displaycount==2)
friendkey='D';
if(displaycount==3)
friendkey='h';
if(displaycount==4)
friendkey='m';
if(displaycount==5)
friendkey='s';
if(displaycount==6)
friendkey='T';
if(displaycount==7)
friendkey='O';
}
(2)程序中关于年月日时分秒的RTC。
我们使用了一个6层for循环嵌套来实现。
先建立关于闰年和平年月份天数的表格,然后通过查表法知道每个月的天数。
unsignedchardays[12]={31,28,31,30,31,30,31,31,30,31,30,31};
unsignedchardays1[12]={31,29,31,30,31,30,31,31,30,31,30,31};
if(PIR1bits.TMR1IF=1)
TMR1H=timer1H;
TMR1L=timer1L;//Reload0.1SecondvaluetoTimer1
PIR1bits.TMR1IF=0;//CleartflagofTimer1
cp++;
if(cp>9)
{
cp=0;
dt[0]++;//second++
if(dt[0]>59)
{
dt[0]=0;
dt[1]++;
if(dt[1]>59)
{
dt[1]=0;
dt[2]++;
if(dt[2]>23)
{
dt[2]=0;
dt[3]++;
if(dt[5]%4==0||dt[5]%400==0)
{
daylimit=days1[k];
}
else
{
daylimit=days[k];
}
if(dt[3]>(daylimit-1))
{
dt[3]=0;
dt[4]++;
if(dt[4]>11)
{
dt[4]=0;
dt[5]++;
}
}
}
}
}
附件1(电路原理图)
附件2(部分源代码及注释)
**********************************************************************************************************************************************************
主程序:
时间产生和通信
#include"GROUPX_main.h"
unsignedcharcp;//100mS=T/(1/32768Hz),T=3276.8
unsignedchardt[6]={0};//定义储存年月日时分秒的六元素数组
unsignedchardays[12]={31,28,31,30,31,30,31,31,30,31,30,31};//定义平年的每月天数表
unsignedchardays1[12]={31,29,31,30,31,30,31,31,30,31,30,31};//定义闰年的每月天数表
unsignedchark=0;
unsignedchardaylimit=0;//定义每月天数上限值变量
unsignedchartimerflag_5s=1;
unsignedchartimer1H;
unsignedchartimer1L;
unsignedcharalarm_value;
unsignedcharnouse=0;
#pragmaudataaccessMy_RAM_1
nearunsignedcharStr_Len;
nearunsignedchari;
nearunsignedintT2_Buffer;
nearunion
{
intWord;
unsignedcharByte[2];
}Byte2Word;
#pragmaudata
charASCII_StringT1[10];
charASCII_StringT2[10];
#pragmaromdataRomData
constromcharLCD_ROM_MSG1[]="T1=";
//constromcharLCD_ROM_MSG2[]="T2=";
#pragmainterruptMyHighInt
#pragmacodehigh_vector=0x0008
voidhigh_direct(void)
{
_asm//beginin-lineassembly
gotoMyHighInt//gotoisr_highfunction
_endasm//endin-lineassembly
}
#pragmainterruptlowMyLowInt
#pragmacodelow_vector=0x0018
voidlow_direct(void)
{
_asm//beginin-lineassembly
gotoMyLowInt//gotoisr_highfunction
_endasm//endin-lineassembly
}
#pragmacode//startcodehere
voidMyHighInt(void)
{
;
}
voidMyLowInt(void)
{
if(PIR1bits.TMR1IF=1)
TMR1H=timer1H;
TMR1L=timer1L;//Reload0.1SecondvaluetoTimer1
PIR1bits.TMR1IF=0;//CleartflagofTimer1
cp++;
if(cp>9)
{
cp=0;
dt[0]++;//second++
if(dt[0]>59)//满1分钟?
{
dt[0]=0;
dt[1]++;
if(dt[1]>59)//满1小时?
{
dt[1]=0;
dt[2]++;
if(dt[2]>23)//满1天?
{
dt[2]=0;
dt[3]++;
if(dt[5]%4==0||dt[5]%400==0)//判断是否是闰年
{
daylimit=days1[k];//满1月?
}
else
{
daylimit=days[k];
}
if(dt[3]>(daylimit-1))
{
dt[3]=0;
dt[4]++;
if(dt[4]>11)//满一年?
{
dt[4]=0;
dt[5]++;
}
}
}
}
}
LCD_Set_Cursor(1,7);
WriteDataLCD(dt[5]/10+0x30);
WriteDataLCD(dt[5]%10+0x30);//显示年
LCD_Set_Cursor(1,10);
WriteDataLCD(dt[4]/10+0x30);
WriteDataLCD(dt[4]%10+0x30);//显示月
LCD_Set_Cursor(1,13);
WriteDataLCD(dt[3]/10+0x30);
WriteDataLCD(dt[3]%10+0x30);//显示日
LCD_Set_Cursor(0,0);
WriteDataLCD(dt[2]/10+0x30);
WriteDataLCD(dt[2]%10+0x30);//显示时
LCD_Set_Cursor(0,3);
WriteDataLCD(dt[1]/10+0x30);
WriteDataLCD(dt[1]%10+0x30);//显示分
LCD_Set_Cursor(0,6);
WriteDataLCD(dt[0]/10+0x30);
WriteDataLCD(dt[0]%10+0x30);//显示秒
timerflag_5s=1;
}
}
voidmain(void)
{
//======initializetheMCU======//
unsignedcharusartcount;
InitializePORT();
InitializeINTs();
InitializeAD();
InitializeTMR1();
Initialize_I2C_Master();
InitializeUSART();//初始化
alarm_value=30;//温度告警值初始值设定
select_change=&alarm_value;//指针设定
//======initializetheLCD======//
OpenLCD();
LCD_Set_Cursor(0,0);
WriteDataLCD(dt[2]/10+0X30);//sendhourtoLCD
WriteDataLCD(dt[2]%10+0X30);
WriteDataLCD(':
');
WriteDataLCD(dt[1]/10+0X30);//sendminutetoLCD
WriteDataLCD(dt[1]%10+0X30);
WriteDataLCD(':
');
WriteDataLCD(dt[0]/10+0X30);//sendsecondtoLCD
WriteDataLCD(dt[0]%10+0x30);
LCD_Set_Cursor(0,9);//sendstatustoLCD
WriteDataLCD('w');
LCD_Set_Cursor(0,11);
WriteDataLCD('!
');//sendalarm_valuetoLCD
WriteDataLCD(alarm_value/10+0x30);
WriteDataLCD(alarm_value%10+0x30);
putcLCD(0xDF);//Adddegreesymbol
putcLCD('C');
LCD_Set_Cursor(1,0);
putrsLCD(LCD_ROM_MSG1);//send"T1="toLCD
LCD_Set_Cursor(1,8);
dt[3]=1;
dt[4]=2;
dt[5]=11;
while
(1)
{
if(timerflag_5s==1)
{
timerflag_5s=0;
LCD_Temp_Update();//更新温度值
send_temperature();//发送数据
}
key_response();
alarm_response();
}
}
voidLCD_Temp_Update(void)
{
//***DisplayTC74-A7TemperatureonLCD***//
LCD_Set_Cursor(1,3);
Byte2Word.Word=Read_TC74_Temperature();//GetCurrentTemperatureformTC74-A7
T2_Buffer=Read_TC74_Temperature();
if(Byte2Word.Byte[1]==0)
{
btoa(Byte2Word.Byte[0],ASCII_StringT1);//ConvertTemp.HaxtoASCIIstring
putsLCD(ASCII_StringT1);//PrinttoLCD
putcLCD(0xDF);//Adddegreesymbol
}
elseif(Byte2Word.Byte[1]==-1)//ReadfailfromTC74-A7,Display"--"onLCD
{
putcLCD('-');
putcLCD('-');
}
}
voidalarm_response(void)
{
if((T2_Buffer)>=alarm_value)//TC74温度值超过告警值时报警
{
PORTCbits.RC2=1;//开蜂鸣器
PORTDbits.RD7=1;//点LEDD8
}
else
{
PORTCbits.RC2=0;//观蜂鸣器
PORTDbits.RD7=0;//关LEDD8
}
}
voidsend_temperature(void)
{
unsignedcharusartcount;
//======sendthetimetoPC======//
WriteUSART(dt[2]/10+0x30);
Delay1KTCYx(4);
WriteUSART(dt[2]%10+0x30);//sendhour
Delay1KTCYx(4);
WriteUSART(':
');
Delay1KTCYx(4);
WriteUSART(dt[1]/10+0x30);
Delay1KTCYx(4);
WriteUSART(dt[1]%10+0x30);//sendminute
Delay1KTCYx(4);
WriteUSART(':
');
Delay1KTCYx(4);
WriteUSART(dt[0]/10+0x30);
Delay1KTCYx(4);
WriteUSART(dt[0]%10+0x30);//sendsecond
Delay1KTCYx(4);
//======senddoublespacetoPC======//
WriteUSART('');
Delay1KTCYx(4);
WriteUSART('');
Delay1KTCYx(4);
//======sendTC74-A7TemperaturetoPC======//
usartcount=0;
while(LCD_ROM_MSG1[usartcount])
{
WriteUSART(LCD_ROM_MSG1[usartcount++]);
Delay1KTCYx(4);
}
usartcount=0;
while(ASCII_StringT1[usartcount])
{
WriteUSART(ASCII_StringT1[usartcount++]);
Delay1KTCYx(4);
}
//======senddoublespacetoPC======//
WriteUSART('');
Delay1KTCYx(4);
WriteUSART('');
Delay1KTCYx(4);
**************************************************************************************************************************************************************************************************************************
键盘程序
#inclu