1? 系統(tǒng)方案設計
1.1 系統(tǒng)整體設計
電子智能補光器的設計思路:首先通過單片機判斷特殊天氣模式是否啟用,如果啟用則直接亮黃燈并在手機上顯示出來。確定特殊天氣模式沒有啟用時,通過季節(jié)模塊判斷當前月份對應的季節(jié)來確定補光模式。通過光照傳感器將外界光照強度與對應季節(jié)設定光照閾值進行比較,當外界光照強度大于設定閾值時進行補光操作,并通過藍牙連接在手機上顯示當前補光模式以及光照強度。
1.2 設計任務
主要任務簡述:以單片機為核心,設計電子智能補光器,以滿足各種不同情境下對光照需求的差異。
要求簡述:
(1)在外界光照強度大于所設定閾值時補光器保持不工作狀態(tài),光照強度小于設定閾值時開始補光;
(2)可選擇春、夏、秋、冬四種模式,分別對應四種不同的閾值電壓;
(3)設置特殊天氣模式,開啟特殊天氣模式后亮起黃色霧燈;
(4)通過藍牙連接手機,顯示當前的模式和光照強度。
1.3 模塊方案選型
1.3.1主控方案選型
STC89C52單片機是宏晶科技推出的高反應速度、低功率消耗、有著很強抵的擋外界干擾能力的單片機,而且該單片機的指令代碼非常切合傳統(tǒng)的8051單片機,并且與傳統(tǒng)51單片機對比而言,該單片機速度更快,是傳統(tǒng)51單片機的8~12倍。除此之外,該單片機還有6時鐘周期和12時鐘周期可以任意選擇。
主要特性如下:
(1)新一代8051單片機,6時鐘機器周期和12時鐘機器周期可以任意選擇,指令代碼非常契合傳統(tǒng)8051單片機。
(2)工作電壓:5.5V~3.3V(5V單片機)。
(3)工作頻率范圍處于0~40MHz之間,相當于普通8051單片機工作頻率的0~80MHz范圍,而且新一代單片機的實際工作頻率可達48MHz。
(4)一共具有3個16位定時器,也就是定時器T0、T1、T2。
(5)外部中斷4路,低電平觸發(fā)或下降沿中斷電路,PowerDown模式可通過外部中斷低電平觸發(fā)中斷的方式觸發(fā)。
1.3.2光電轉換器的選擇
ADC0832是NS(National Semiconductor)公司生產的串行接口8位A/D轉換器,通過三線接口與單片機連接,功耗低,性能價格比較高,合適使用在袖珍式的智能儀器儀表中。ADC0832為8位分辨率A/D轉換芯片,其最高分辨可達256級,可以適應一般的模擬量轉換要求。芯片具有雙數(shù)據(jù)輸出可作為數(shù)據(jù)校驗,以減少數(shù)據(jù)誤差,轉換速度快且穩(wěn)定性能強。獨立的芯片使能輸入,使多器件連接和處理器控制變得更加方便。通過DI 數(shù)據(jù)輸入端,可以輕易的實現(xiàn)通道功能的選擇。其主要特點如下:
(1)8位分辨率,其最高分辨可達256級;
(2)雙通道A/D轉換;
選擇該A/D轉換芯片,不僅因為其體積小、功耗低,而且可以適應一般的模擬量轉換要求,完全滿足系統(tǒng)的要求。另外,其內部電源輸入與參考電壓的復用,使得轉換芯片的模擬電壓輸入在0~5V之間,電源電路供電可以同時滿足51單片機和該芯片的共同使用。除此之外該芯片的轉換時間極短,僅為32μS,反應非常迅速,另外該芯片具有雙數(shù)據(jù)輸出可作為數(shù)據(jù)校驗的工具,以此來減少實驗數(shù)據(jù)誤差,轉換速度快并且穩(wěn)定性能出色。單獨工作的芯片的使能輸入,可以更輕松地對多元件進行連接,同時也可以更加方便地控制處理器。通過DI 數(shù)據(jù)輸入端,使得實現(xiàn)通道功能的選擇變的易如反掌。除此之外,價格上的優(yōu)勢同樣也是選擇它的原因之一。
1.3.3顯示器的選擇
LCD1602液晶顯示器是廣泛使用的一種工業(yè)字符型液晶顯示模塊。由字符型液晶顯示器(LCD)、控制驅動主電路HD44780及其擴展驅動電路HD44100,以及少量電阻、電容元件和結構件等裝配在PCB板上而組成,能夠同時顯示16x02即32個字符。(16列2行)。但寄存器不止32個,有一些顯示效果,如字符一個個顯示、字符從左到右或從右到左顯示等等,顯示效果簡單。當然也有其他更好的選擇,例如12864液晶顯示器,它的顯示模塊是128×64點陣的漢字圖形型液晶顯示模塊,可顯示漢字及圖形,具有多種功能:光標顯示、畫面移位、睡眠模式等。
其實綜合來說,二者編程方面的難度差不多,原理方面也差不多,甚至12864液晶顯示器更勝一籌,因為該顯示器顯示更全面,字符也更多,需要進行更多操作的話自然是12864液晶顯示器能夠勝任。但是對比來說的話,1602液晶顯示器也能實現(xiàn)設計的要求,而且相對來說更重要的原因就是1602液晶顯示器比較廉價,網上購買也比較便宜,最低五六塊錢左右。而12864液晶顯示器網上購買最便宜的也要在二三十左右。所以從造價方面以及使用方面考慮,當然是價格低廉而且功能也不欠缺的優(yōu)先。因此選擇1602液晶顯示器作為顯示器件。
2? 硬件設計
2.1 單片機模塊
單片機的主要特點有:
(1)有出色的性能單價比,高效能、低電壓,易于制作便攜式產品。
(2)集成度高,體積小,有較高的穩(wěn)定性。而且單片機把各功能零件組合在一塊芯片上,內部結構使用的是總線結構,不僅減輕了各芯片彼此之間的連線,還大大增加了單片機的安全性和抗干擾能力。
(3)控制功能強。為求滿足工業(yè)控制的要求,通常單片機的指令系統(tǒng)中均有極多樣的轉移指令、I/O口的邏輯操作和位處理特性。單片機的邏輯控制功能及運轉速度均遠高于同一等級的微機。
(4)外部總線增加了I2C(Inter-Integrated Circuit)及SPI(Serial Peripheral Interface)等串行總線方式,逐步縮小了體積,精簡了構造。單片機的系統(tǒng)擴展、系統(tǒng)配置較典型、規(guī)范,容易構成各種規(guī)模的應用系統(tǒng)。
PORT0(P0.0~P0.7):端口0是一個8位寬的開路汲極雙向輸出入端口,共有8個位,P0.0表示位0,P0.1表示位1,依此類推。其他三個I/O端口(P1、P2、P3)則不具有此電路組態(tài),而是內部有一提升電路,P0在當做I/O用時可以推動8個LS的TTL負載。
PORT1(P1.0~P1.7):端口1也是具有內部提升電路的雙向I/O端口,其輸出緩沖器可以推動4個LSTTL負載,同樣地若將端口1的輸出設為高電平,便是由此端口來輸入數(shù)據(jù)。
PORT2(P2.0~P2.7):端口2是具有內部提升電路的雙向I/O端口,每一個引腳可以推動4個LS的TTL負載,若將端口2的輸出設為高電平時,此端口便能當成輸入端口來使用。P2除了當做一般I/O端口使用外,若是在STC89C52擴充外接程序存儲器或數(shù)據(jù)存儲器時,也提供地址總線的高字節(jié)A8~A15,這個時候P2便不能當做I/O來使用了。
PORT3(P3.0~P3.7):端口3也具有內部提升電路的雙向I/O端口,其輸出緩沖器可以推動4個TTL負載,同時還多工具有其他的額外特殊功能,包括串行通信、外部中斷控制、計時計數(shù)控制及外部數(shù)據(jù)存儲器內容的讀取或寫入控制等功能。單片機的引腳圖如圖3-1所示。
#include "51Lib_Configure.h"
#include "51Lib_Declaration.h"
#if _CONFIG_FUNC_LCD1602_ == CH_ENABLE
#define _NOP() _nop_()
#define DataPort P0
#define DataPIN P0
#define CLR_RS (lcd1602_RS=0)
#define SET_RS (lcd1602_RS=1)
#define CLR_RW (lcd1602_RW=0)
#define SET_RW (lcd1602_RW=1)
#define CLR_EN (lcd1602_EN=0)
#define SET_EN (lcd1602_EN=1)
/*
LcdReset(); //LCD1602初始化
DelayMs(10);
sprintf(temp,"1111111111111111");//更新顯示
DispStr(0,0,(unsigned char *)temp);//打印顯示
sprintf(temp,"1111111111111111");//更新顯示
DispStr(0,1,(unsigned char *)temp);//打印顯示
*/
/***********************************************
函數(shù)名稱:DispNum
功 能:讓液晶從某個位置起連續(xù)顯示一個數(shù)值,前面不會補0
參 數(shù):x--位置的列坐標
y--位置的行坐標
Dis_dat--需要顯示的數(shù)
Dis_Len--需要顯示的寬度
返回值 :無
***********************************************/
void DispNum(uchar x, uchar y, uint Dis_dat, uchar Dis_Len)
{
uchar i;
uint dat = 1;
Disp1Char(x+Dis_Len-1,y,Dis_dat%10+0x30);
if(Dis_Len == 1)
return;
for(i = 1;i < Dis_Len;i++)
dat*=10;
for(i = 1; i < Dis_Len ; i++)
{
//dat = pow(10, Dis_Len-i);
if(Dis_dat >= dat)
Disp1Char(x+i-1,y,Dis_dat/dat%10+0x30);
else
Disp1Char(x+i-1,y,' ');
dat/=10;
}
}
/***********************************************
函數(shù)名稱:DispStr
功 能:讓液晶從某個位置起連續(xù)顯示一個字符串
參 數(shù):x--位置的列坐標
y--位置的行坐標
ptr--指向字符串存放位置的指針
返回值 :無
***********************************************/
void DispStr(uchar x,uchar y,uchar *ptr)
{
uchar *temp;
uchar i,n = 0;
temp = ptr;
while(*ptr++ != '?') n++; //計算字符串有效字符的個數(shù)
for (i=0;i<n;i++)
{
Disp1Char(x++,y,temp[i]);
if (x == 0x10)
{
break;
}
}
}
/*******************************************
函數(shù)名稱:DispNchar
功 能:讓液晶從某個位置起連續(xù)顯示N個字符
參 數(shù):x--位置的列坐標
y--位置的行坐標
n--字符個數(shù)
ptr--指向字符存放位置的指針
返回值 :無
*******************************************
void DispNChar(uchar x,uchar y, uchar n,uchar *ptr)
{
uchar i;
for (i=0;i<n;i++)
{
Disp1Char(x++,y,ptr[i]);
if (x == 0x10)
{
x = 0;
y ^= 1;
}
}
}
*/
/*******************************************
函數(shù)名稱:LocateXY
功 能:向液晶輸入顯示字符位置的坐標信息
參 數(shù):x--位置的列坐標
y--位置的行坐標
返回值 :無
********************************************/
void LocateXY(uchar x,uchar y)
{
uchar temp;
temp = x&0x0f;
y &= 0x01;
if(y) temp |= 0x40; //如果在第2行
temp |= 0x80;
LcdWriteCommand(temp,1);
}
/*******************************************
函數(shù)名稱:Disp1Char
功 能:在某個位置顯示一個字符
參 數(shù):x--位置的列坐標
y--位置的行坐標
data--顯示的字符數(shù)據(jù)
返回值 :無
********************************************/
void Disp1Char(uchar x,uchar y,uchar data1)
{
LocateXY( x, y );
LcdWriteData( data1 );
}
/*******************************************
函數(shù)名稱:LcdReset
功 能:對1602液晶模塊進行復位操作
參 數(shù):無
返回值 :無
********************************************/
void LcdReset(void)
{
// DataDir = 0xFF; //數(shù)據(jù)端口設為輸出狀態(tài)
LcdWriteCommand(0x38, 0); //規(guī)定的復位操作
DelayMs(5);
LcdWriteCommand(0x38, 0);
DelayMs(5);
LcdWriteCommand(0x38, 0);
DelayMs(5);
LcdWriteCommand(0x38, 1); //顯示模式設置
LcdWriteCommand(0x08, 1); //顯示關閉
LcdWriteCommand(0x01, 1); //顯示清屏
LcdWriteCommand(0x06, 1); //寫字符時整體不移動
LcdWriteCommand(0x0c, 1); //顯示開,不開游標,不閃爍
}
/*------------------------------------------------
清屏函數(shù)
------------------------------------------------*/
void LcdClear(void)
{
LcdWriteCommand(0x01,1);
DelayMs(5);
}
/*******************************************
函數(shù)名稱:LcdWriteCommand
功 能:向液晶模塊寫入命令
參 數(shù):cmd--命令,
chk--是否判忙的標志,1:判忙,0:不判
返回值 :無
********************************************/
void LcdWriteCommand(uchar cmd,uchar chk)
{
if (chk) WaitForEnable(); // 檢測忙信號?
CLR_RS;
CLR_RW;
_NOP();
DataPort = cmd; //將命令字寫入數(shù)據(jù)端口
_NOP();
SET_EN; //產生使能脈沖信號
_NOP();
_NOP();
CLR_EN;
}
/*******************************************
函數(shù)名稱:LcdWriteData
功 能:向液晶顯示的當前地址寫入顯示數(shù)據(jù)
參 數(shù):data--顯示字符數(shù)據(jù)
返回值 :無
********************************************/
void LcdWriteData( uchar data1 )
{
WaitForEnable(); //等待液晶不忙
SET_RS;
CLR_RW;
SET_EN;
_NOP();
DataPort = data1; //將顯示數(shù)據(jù)寫入數(shù)據(jù)端口
_NOP();
//產生使能脈沖信號
_NOP();
_NOP();
CLR_EN;
}
/*******************************************
函數(shù)名稱:WaitForEnable
功 能:等待1602液晶完成內部操作
參 數(shù):無
返回值 :無
********************************************/
void WaitForEnable(void)
{
unsigned int later=0;
DataPort=0xff;
CLR_RS;
SET_RW;
_NOP();
SET_EN;
_NOP();
_NOP();
// while((DataPIN&Busy)!=0);
while(((DataPIN&0x80)!=0)&&(later<1000)) //檢測忙標志
{
DelayUs2x(2);
later++;
}
CLR_EN;
// DataDir|=0xFF; //將P4口切換為輸出狀態(tài)
}
#endif