|
前兩天做了一個ds18b20+lcm1602溫度顯示報警系統,將報告及源代碼分享給大家學習,有什么問題還請指正
一、單片機簡介
二、項目任務和要求
三、項目設計方案的總體設計框圖
3.1硬件電路框圖
3.2硬件電路概述
3.3主控電路
3.4顯示電路
3.5報警溫度調節電路
1、蜂鳴器
2、跑馬燈
3.6溫度傳感器及DS18B20測溫基本原理
3.7單片機硬件連接實物圖
四、系統軟件算法設計
五、總結與體會
附錄
參考文獻
單片機簡介
1.實驗系統簡介
本次課設單片機實驗系統采用nKDE-51 單片機實驗系統,nKDE-51 單片機實驗教學系統采用模塊化設計,以方便學生自由組合功能,設計實驗。整個實驗系統包括六個功能模塊,分別為CPU板、基本IO板、模擬總線接口IO口、擴展總線接口IO板,字符點陣LCD/大容量 flash/GPRS 模塊板和uart/以太網及電話接口拓展板。本次課設需要CPU板,lcm1602模塊,溫度傳感器模塊,流水燈模塊、蜂鳴器模塊以及數碼管模塊,所以該實驗板完全滿足課設的需要,具體用的各部分圖如下:
CPU板部分如圖:
IO口板部分和模擬總線部分板如下圖
2.系統資源及功能簡介
(1) 單片機端口的引出
MCS-51 系列單片機共有 4 個獨立的 8 位并行 I/O 端口分別為 P0、P1、P2 和 P3在 CPU板上各通過兩個8 芯單排插針引出,可通過杜邦插座連接到其它模塊或器件。
(2) CPU 工作頻率的選擇
nKDE-51 系統提供了四種常用的晶振頻率分別是 11.0592MHz、12MHz、18.432MHz 和
22.1184MHz。用戶可通過跳線JP1 和 JP2來選擇系統晶振的頻率。如果用戶還需要其它的晶振頻率,本系統預留了一個焊接晶振的位置X5可供使用。
(3) CPU 工作模式的選擇
MCS-51 單片機的工作方式可分為端口工作方式不擴展總線和擴展總線模式。在擴展總線模式單片機的P0口通過ALE信號控制外部地址鎖存器復用為地址總線低8位地址和數據 總線,P2口提供高8位地址,同時P3.6和P3.7作為W R和R D信號。而當單片機工作在端口方式下時P0~P3的每一位都可以作為獨立的端口引腳使用。 在 nKDE-51 系統中當實驗中不使用擴展總線時,單片機的端口可通過表 1-1 所列出的插座引出。如果單片機實驗需要使用擴展總線用戶可使用系統提供的 40 芯連接電纜將J9和JX1連接起來。此時 P0、P2 和 P3.6、P3.7 等引腳已作為系統總線使用,不要再將它們用作普通的 I/O。JX2 和 JX3 的各引腳和 JX1 的對應引腳相連可以通過它們將總線連接到其它模塊上。
單片機的ISP及串行口
電路連接nKDE-51系統使用 STC 公司的STC 12C5A60S2 作為 CPU。該 CPU 兼容標準51內核自帶 64K字節的 Flash 程序存儲器支持通過串行口進行在系統編程ISP以及程序調試單片機的串行口通過雙向自鎖開關 SW2 選擇連接到 9 芯孔型插座 COM1 RS232 接口用于和 計算機通信進行 ISP 或程序調試或者連接到 J4、J8 及 J9用于進行 I/O 端口及 RS485 通信等實驗.計算機必須通過實驗系統提供的9 芯串口延長電纜和 COM1 相連。 當SW2 彈起時單片機的串行口連接到 COM1 , 當 SW2 按下時單片機串行口連接到 J4、J8 及J9。
項目任務及要求
1. 單片機P0.0和DS18B20的數據端相連;(實驗八)
2. 編寫單片機通過IO端口模擬單總線時序控制DS18B20的程序,讀出溫度;(實驗八)
3. 在1602字符點陣液晶顯示模塊上顯示實測溫度(實驗七)
4.蜂鳴器報警功能;(+5)
5.串口顯示功能;(+5)
6.發光二極管流水燈報警功能,隨著溫度超過警戒值范圍改變,流水燈的速率進行改變。(+5)
7.計數器功能記錄超過警戒值的次數,單個或者八位數碼管顯示 計數。(+5)
1-3為基本功能部分,4-6為增加功能部分
創新部分: 比如:音樂播放實現聲音報警等。
三、項目設計方案的總體設計框圖
3.1硬件電路框圖
3.2硬件電路概述
單片機P0.0和DS18B20的數據端相連,在1602字符點陣液晶顯示模塊上顯示實測溫度,P0.7和蜂鳴器相連,P0其余口接LED1-6。
3.3主控電路
主控電路主要使用 STC 公司的STC 12C5A60S2作為 CPU,控制整個系統的工作。
3.4顯示電路
LCD顯示器是一種用液晶材料制成的液晶顯示器,它具有體積小、功耗低、字跡清晰、無電磁輻射、壽命長等優點,1602 字符點陣式LCM共有兩個顯示行,每行可顯示16個字符,為最常用的一種字符式LCM,顯示控制器為HD44780,通過HD44100進行規模的擴展。
3.5報警溫度調節電路
1、蜂鳴器
當溫度超過30度時,蜂鳴器會發出間隔的報警聲響。
2、跑馬燈
在30度以上時,跑馬燈會常亮,28-30度時會隨著溫度的升高而加快。
3.6溫度傳感器及DS18B20測溫基本原理
DS18B20 數字溫度傳感器提供9位(二進制)溫度讀數指示器件的溫度數據經單線接口和CPU交互,因此CPU和DS18B20之間只需一條信號線和地址線即可進行通信。
原理圖如下:
3.7單片機硬件連接實物圖
四、系統軟件算法設計
主程序 main.c
#include <reg51.h>
#include <intrins.h>
#include <stdio.h>
#include "lcm16x2p.h"
#include "DS18B20.h"
#define OSC 11059200 //晶振頻率
#define BAUDRATE 9600 //波特率
#define LCM_DB P2
sbit BUZ_CON = P0^7;
sbit LED =P0;
sbit LCM_BLC=P1^3;
void main(void)
{
unsigned char ucTH,ucTL,Ticks; //中斷程序
unsigned int i;
unsigned char tmph,tmpl;
Temp t;
unsigned char strTemp[8]; //顯示到屏幕的溫度數據
LCM_BLC = 0; //開背光
TMOD = 0x21; //選擇方式2作為波特率發生
SCON = 0x50; //串口方式1,允許中斷
PCON |= 0x80; //SMOD=1
TL1 = 256 -(OSC/12/16/BAUDRATE);
TH1 = 256 -(OSC/12/16/BAUDRATE);
TR1 = 1; //啟動定時器
TI = 1; //TI有效
//檢測DS18B20溫度傳感器是否存在并復位傳感器
if(DSReset())
printf("\r\Temp sensor ResetOK!");
else printf("\r\Temp Sensor Notready!");
while(1){
DSReset(); //復位傳感器
Delay(12);
DSWriteByte(SkipROM); //跳讀 省時
DSWriteByte(StartConvert); //溫度轉換
for(i=0;i<40000;i++);
DSReset();
Delay(12);
DSWriteByte(SkipROM);
DSWriteByte(ReadMemory); //讀RAM程序
tmpl = DSReadByte();
tmph = DSReadByte();
printf("\r\nTemperature code HI=%02bX,LO=%02bX ",tmph,tmpl);
DSReadTemp(&t);
//準備輸出到顯示屏的數據
strTemp[0]=t.z/10+0x30; //十位
strTemp[1]=t.z%10+0x30; //個位
strTemp[2]='.'; //小數點
strTemp[3]=t.x/1000+0x30; //十分位
strTemp[4]=(t.x/100)%10+0x30; //百分位
strTemp[5]=(t.x/10)%10+0x30;//千分位
strTemp[6]=t.x%10+0x30; //萬分位
strTemp[7]='C';
if(t.z>=30)
printf("\nWarning!!!Temperature= %d.%04d ",t.z,t.x) ; //大于30度溫度警告
else
printf("\r\nTemperature = %d.%04d",t.z,t.x);
//小于26度LED燈全亮
if(t.z<26)
{
P0=0x00;
}
else
{
P0=0xff; //燈滅
}
//大于28度流水燈循環(慢)
if(t.z>=28)
{
BUZ_CON=1;
P0=0xfd;
LCMDelay(60);
P0=0xfb;
LCMDelay(60);
P0=0xf7;
LCMDelay(60);
P0=0xdf;
LCMDelay(60);
//大于29度流水燈循環(快)
if(t.z>=29)
{
P0=0xfd;
LCMDelay(10);
P0=0xfb;
LCMDelay(10);
P0=0xf7;
LCMDelay(10);
P0=0xdf;
LCMDelay(10);
P0=0xbf;
LCMDelay(10);
}
//大于30度燈全亮。蜂鳴器響
if(t.z>=30)
{
BUZ_CON=0;
LCMDelay(100);
P0=0x00;
}
}
else{
BUZ_CON=1;
}
//初始化
EA = 0; // 停止所有中斷
Ticks = 0;
ucTH =(65536-OSC/12/20)/256; // 計算 50ms 定時的時間常數
ucTL =(65536-OSC/12/20)%256;
TMOD = 0x21; // T0:模式 1,16 位定時器
TH0 = ucTH;
TL0 = ucTL;
ET0 = 1; // T0 允許中斷
TR0 = 1; // 啟動定時器
EA = 1; // 打開總中斷允許
//輸出數據到顯示屏
LCMInit(); //初始化LCM顯示器
LCMClear(); //清屏
if(t.z>=30){
LCMDisplayString(0,0,"TempWarning!!!"); //大于29度警告
LCMDisplayString(1,0,"Temp:");
LCMDisplayString(1,6,strTemp);
}
else{
LCMDisplayString(0,0,"Temperature:");
LCMDisplayString(1,0,strTemp);
}
//閃爍(刷新)
for(i = 0; i < 16;i++)
LCMBlink(0,i,BLINK);
for(i = 0; i < 16;i++)
LCMBlink(1,i,BLINK);
}
}
子程序ds18b20.h文件
#ifndef __DS18B20H__
#define __DS18B20H__
#define ReadROM 0x33
#define MatchROM 0x55
#define ReadMemory 0xBE
#define SkipROM 0xCC
#define SearchROM 0xF0
#define StartConvert 0x44 //變換指令
typedef struct{
int z; //整數部分
int x; //小數部分
}Temp;
extern unsigned char ucTH,ucTL,Ticks; //外部引用
void Delay(unsigned int);
bit DSReset(void);
void DSWriteByte(char);
unsigned char DSReadByte(void);
void DSReadTemp(Temp *t);
#endif
ds18b20.c文件
#include "DS18B20.h"
#include <reg51.h>
#include <intrins.h>
sbit DQ = P0^0;
/*
Delay
通過循環計時
參數:int,表示要延時的 毫秒 數
*/
void Delay(unsigned int i)
{ i=i*12;
while(i--);
}
/*
DSReset
復位DS18B20并返回是否存在
*/
bit DSReset(void)
{
bit x;
DQ = 1;
Delay(8);
DQ = 0; // 主機拉低總線
Delay(80); // 延時約 500 個機器周期
DQ = 1; // 主機釋放總線
Delay(8); // 延時 60 個機器周期
x = DQ;
Delay(20);
if(x == 0)
return 1;
else return 0;
}
/*
DSWriteByte
向 DS18820 寫入一個字節
*/
void DSWriteByte(unsigned char c)
{
unsigned char ic;
for( ic = 0; ic < 8;ic++ )
{
DQ = 0; //主機拉低總線,開始寫位
DQ = c&0x01;
Delay(5); //延時60個機器周期
DQ = 1; //釋放總線
c >>= 1;
}
}
/*
DSReadByte
從溫度傳感器讀出一個字節
返回:讀出的字節
*/
unsigned char DSReadByte(void)
{
unsigned char c,ic;
c = 0;
for(ic = 0; ic < 8;ic++)
{
DQ = 0;
c >>= 1; //右移
DQ = 1;
if(DQ )
c |= 0x80;
Delay(4);
}
return c;
}
/*
DSReadTemp
讀出溫度
參數:溫度(由整數和小數部分構成)
*/
void DSReadTemp(Temp *t)
{
unsigned char tmpl,tmph;
DSReset();
Delay(12);
DSWriteByte(SkipROM);
DSWriteByte(StartConvert);
DSReset();
Delay(12);
DSWriteByte(SkipROM);
DSWriteByte(ReadMemory);
tmpl = DSReadByte();
tmph = DSReadByte();
t->z =(int)((tmph&0x07)<<4 | (tmpl&0xf0)>>4);
t->x =(int)((tmpl&0x0f)*625);
}
/*
T0ISR
50ms中斷服務程序
*/
void T0ISR(void) interrupt 1
{
unsigned char ucTH,ucTL,Ticks;
TH0 = ucTH;
TL0 = ucTL;
TR0 = 1;
Ticks ++;
if(Ticks == 20)
{
Ticks = 0;
}
}
lcm16x2p.h文件
#ifndef LCM16X2_H
#define LCM16X2_H
#define BUSYFLAG 0x80
#define BLINK 0X01
#define NOBLINE 0X00
unsigned char LCMReadState(void);
void LCMDelay(int);
void LCMWriteData(unsigned char);
void LCMWriteCmd(unsigned char);
void LCMClear(void);
void LCMInit(void);
void LCMGotoXY(unsigned char,unsigned char);
void LCMDisplay(unsigned char,unsigned char,unsigned char);
void LCMDisplayString(unsigned char,unsigned char,unsigned char*);
void LCMBlink(unsigned char,unsigned char,unsigned char);
#endif
llcm16x2p.c文件
#include <reg51.h>
#include <intrins.h>
#include "LCM16X2P.H"
#define LCM_DB P2
sbit LCM_RS = P1^0;
sbit LCM_RW = P1^1;
sbit LCM_E = P1^2;
sbit LCM_BLC = P1^3;
unsigned int data DelayConst = 140;
// 延時程序
void LCMDelay (int ms)
{
unsigned int i,cnt;
cnt = DelayConst * ms*12;
for(i=0;i<cnt;i++);
}
//查詢LCM忙的標志
unsigned char LCMReadState(void)
{
unsigned char state;
LCM_E = 0;
LCM_RS = 0;
LCM_RW = 1;
LCM_E = 1;
_nop_();
_nop_();
state = LCM_DB;
LCM_E = 0;
return state;
}
//clear qingpin
void LCMClear(void)
{
LCMDelay(12);
LCM_E = 0;
LCM_RS = 0;
LCM_RW = 0;
LCM_DB = 0x01;
LCM_E = 1;
_nop_();
_nop_();
LCM_E = 0;
LCMDelay(12);
}
//writecmd xierukongzhizi
void LCMWriteCmd(unsigned char cmd)
{
LCMDelay(1);
LCM_E = 0;
LCM_RS = 0;
LCM_RW = 0;
LCM_DB = cmd;
LCM_E = 1;
_nop_();
_nop_();
LCM_E = 0;
}
//write data xierushuju
void LCMWriteData(unsigned char dc)
{
while (LCMReadState()&BUSYFLAG);
LCM_RS = 1;
LCM_RW = 0;
LCM_DB = dc;
LCM_E = 1;
_nop_();
_nop_();
LCM_E = 0;
}
// init chushihua
void LCMInit(void)
{
LCMDelay(720);
LCMWriteCmd(0x38);
LCMDelay(60);
LCMWriteCmd(0x38);
LCMDelay(12);
LCMWriteCmd(0x38);
while(LCMReadState()&BUSYFLAG);
LCMWriteCmd(0x08);
while(LCMReadState()&BUSYFLAG);
LCMWriteCmd(0x01);
while(LCMReadState()&BUSYFLAG);
LCMWriteCmd(0x06);
while(LCMReadState()&BUSYFLAG);
LCMWriteCmd(0x0e);
while(LCMReadState()&BUSYFLAG);
}
//gotoxy yidongguangbiaodao x hang y lie
void LCMGotoXY(unsigned char x, unsigned char y)
{
unsigned char cmd;
if(x==0)
{
cmd = 0x80|y;
}
else
{
cmd =0x80 | 0x40 |y ;
}
LCMWriteCmd(cmd);
while(LCMReadState() & BUSYFLAG);
}
//LCMDISPLAYchar zhidingweizhixianshizifu
void LCMDisplayChar(unsigned char x, unsigned char y,unsigned char ch)
{
LCMGotoXY(x,y);
LCMWriteData(ch);
}
//xianshizifuchan
void LCMDisplayString(unsigned char x,unsigned char y,unsigned char* str)
{
unsigned char ptr;
ptr=0;
while (*(str+ptr)!=0)
{
LCMDisplayChar(x,(y+ptr),*(str+ptr));
ptr++;
}
}
//LCMBLINK zifushanshuo
void LCMBlink(unsigned char x,unsigned char y, unsigned char cmd)
{
LCMGotoXY(x,y);
if(cmd == BLINK)
{
LCMWriteCmd(0x0d);
}
else
{
LCMWriteCmd(0x0c);
}
}
五、總結與體會
經過一周的學習與努力,溫度顯示系統的設計終于完成了,真正的學到了東西。學習了單片機這門,感覺是有點難。也不明白整個學習過程是怎樣過來得,但是時間不等人。但是在學習中,我才發現學習單片機不僅僅僅需要軟件的知識,還需要硬件的知識。沒有相應的硬件知識,我連單片機怎樣和電腦相連都不明白,我為我當初的想法感到羞愧。單片機是一門很好的學問,需要我去鉆研它。一轉眼,一個學期又進尾聲了,本學期的單片機綜合設計也在一周內完成了。
說起設計,我認為最重要的就是做好設計的預習,認真的研究老師給的題目,其次,老師對實驗的講解要一絲不茍的去聽去想,因為只有都明白了,做起設計就會事半功倍,如果沒弄明白,就迷迷糊糊的去做設計,到頭來一點收獲也沒有。最后,要重視程序的模塊化,修改的方便,也要注重程序的調試,掌握其方法。在享受我們成果之時,不得不感慨單片機的重要性與高難度性,所以為期一周的單片機設計沒有浪費我我們學到了很多知識,也讓我對單片機有了更深一步的了解,雖然最后結果是出來了,可這與老師的精心指導是分不開的她引導我們的思路,本來一竅不通的我經過老師的點撥基本上通了,所以老師是功不可沒的。總而言之,單片機設計對于我有很大的幫忙,我從中受益匪淺。
|
-
18b20及實物圖
-
顯示模塊
-
硬件框圖
-
io口及拓展
-
-
-
溫度顯示報警代碼及報告.zip
2019-6-25 08:28 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
3.52 MB, 下載次數: 28, 下載積分: 黑幣 -5
|