版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、<p> 課程設計(論文)任務書</p><p> 課程設計(論文)題目 計算器設計 </p><p> 課程設計(論文)工作自 2016 年 1 月 5 日起至 2016 年 1 月 15 日止。</p><p> 課程設計(論文)的內容要求:&l
2、t;/p><p> 實現(xiàn)五位數(shù)(可為帶小數(shù)數(shù))的加減乘除運算,通過按鍵輸入十進制數(shù)據(jù)。利用八位數(shù)碼管顯示運算結果。 </p><p><b> 目錄</b></p><p> 第一章課程設計題目分析1</p
3、><p> 1.1 課程設計題目要求1</p><p> 1.2 課程設計題目要求分析1</p><p> 第二章設計思想和設計說明2</p><p> 2.1 設計思想2</p><p> 2.2 設計說明2</p><p> 第三章硬件選型3</p>&
4、lt;p> 3.1 單片機選型3</p><p> 3.2 LCD選型3</p><p> 3.3 其他器件選型3</p><p> 3.4 使用軟件說明4</p><p> 第四章硬件原理4</p><p> 4.1 硬件整體框圖4</p><p> 4.2
5、矩陣鍵盤電路5</p><p> 4.3 復位電路5</p><p> 4.4 晶振電路6</p><p> 4.5 LCD電路6</p><p> 第五章程序設計原理7</p><p> 5.1 程序設計流程7</p><p> 5.2 按鍵掃描程序8</p&
6、gt;<p> 5.3 輸入數(shù)據(jù)存儲與轉換算法8</p><p> 5.4 LCD驅動8</p><p> 第六章系統(tǒng)功能描述9</p><p> 第七章設計總結和心得體會10</p><p> 附錄1 STC89C52RC資料12</p><p> 附錄2 器件選型13<
7、;/p><p> 附錄3 硬件原理圖14</p><p> 附錄4 程序清單15</p><p><b> 參考文獻21</b></p><p><b> 課程設計題目分析</b></p><p> 1.1 課程設計題目要求</p><p>
8、; 本次課程設計要求設計一個能實現(xiàn)五位數(shù)(可為帶小數(shù)數(shù))的加減乘除運算的計算器,通過按鍵輸入十進制數(shù)據(jù)。利用八位數(shù)據(jù)碼管顯示運算結果。在經(jīng)過指導老師的批準后,將題目要求改為用LCD顯示運算的結果。</p><p> 1.2 課程設計題目要求分析</p><p> 分析題目要求可知,本次設計要用到的知識有鍵盤的設計、單片機I/O口的操作、數(shù)制的轉換與數(shù)值的運算、LCD的驅動顯示。<
9、;/p><p> 鍵盤設計部分的主要任務是設計一個用來輸入數(shù)值、運算符以及結果顯示操作的鍵盤。</p><p> 單片機的I/O口一是用來接收外部輸入的數(shù)據(jù),主要是鍵盤輸入的數(shù)據(jù),并對這些數(shù)據(jù)進行判斷和處理,第二是用來輸出處理過后的數(shù)據(jù),主要是將數(shù)據(jù)輸出到LCD上以驅動LCD顯示相應的內容。</p><p> 數(shù)制轉換與數(shù)值運算部分的主要任務有:將鍵盤輸入的十進制
10、數(shù)據(jù)進行十六進制以及二進制的轉換,這些操作由單片機內部自動完成;輸入數(shù)值的整型以及浮點型的處理,這部分需要通過編程實現(xiàn);運算結果的整型以及浮點型的控制,這部分需要通過編程實現(xiàn),LCD驅動數(shù)據(jù)的整型和浮點型向字符型的轉換,這部分需要通過編程實現(xiàn)。</p><p> LCD驅動顯示部分主要用來顯示輸入的兩個操作數(shù)、一個操作運算符及一個運算結果。</p><p> 通過以上分析可知,本次課程
11、設計的難點在于數(shù)制轉換與數(shù)值運算部分以及LCD驅動顯示部分。在進行課程設計之前需要準備的知識有:Keil軟件的使用,Altium Designer軟件的使用,數(shù)值轉換與數(shù)值運算相關算法的了解,LCD接口以及驅動的了解。</p><p><b> 設計思想和設計說明</b></p><p><b> 2.1 設計思想</b></p>
12、<p> 從以上的分析可知,本次課程設計可分為兩大部分,第一部分是鍵盤數(shù)據(jù)的輸入及處理,第二部分是LCD部分的輸出驅動及顯示。按照上述分類,本次設計的硬件部分采用先分開調試后聯(lián)合調試的方法,即先分開調試鍵盤部分和LCD部分的硬件電路,待各部分的電路都調試通過后,再將兩部分電路聯(lián)合調試,采用這種調試方法,不僅能提高設計的效率,降低出錯率,還能在出現(xiàn)問題時快速找到問題的所在??紤]到LCD底層驅動程序較為復雜,以及本人對匯編語
13、言的掌握不是太好,本次課程設計的程序語言采用C語言進行編寫,并采用模塊化編程的思想,將LCD的驅動以及鍵盤部分的驅動分為兩個模塊進行編寫,同樣采用先獨立調試再聯(lián)合調試的方法。</p><p><b> 2.2 設計說明</b></p><p> 本次設計的詳細軟硬件資料見附錄。</p><p> 設計報告中使用的簡寫如下:</p&g
14、t;<p> LCD:Liquid Crystal Display(液晶顯示器);</p><p> ROM:Read only memory(只讀存儲器);</p><p> RAM:Random access memory(隨機存取存儲器);</p><p> SRAM:Static random access memory(靜態(tài)隨機存取存
15、儲器);</p><p> PCB:Printed circuit board(印制電路板)。</p><p><b> 硬件選型</b></p><p><b> 3.1 單片機選型</b></p><p> 在設計初期采用AT89C51單片機進行調試,發(fā)現(xiàn)在LCD的驅動調試好以后占用的R
16、OM已經(jīng)接近4K,考慮到鍵盤部分的程序還未編寫,所以最終的程序大小可能會超過4K,因此就需要擴展片外的ROM,為了節(jié)約設計的制作成本和簡化設計的硬件電路,于是采用STC89C52RC單片機進行調試,STC89C52RC單片機擁有8K的Flash RAM以及512B的SRAM和5K的EEPROM,RAM大大小以及ROM的大小完全足夠本次設計使用,而且價格適中。STC89C52RC的具體特性見附錄1。</p><p>
17、;<b> 3.2 LCD選型</b></p><p> 根據(jù)以往做項目的經(jīng)驗,LCD的驅動芯片選用SSD1306 128×64液晶顯示屏驅動芯片,芯片接口支持SPI協(xié)議和IIC協(xié)議,通過單片機I/O口的模擬配置就可以驅動顯示。LCD模塊選擇中景園電子的0.96寸LCD模塊,其內部集成SSD1306驅動芯片,支持3.3~5V電源輸入,符合本次設計的要求。</p>
18、<p> 3.3 其他器件選型</p><p> 考慮到PCB制作成本的問題,本次設計的電路板使用萬能板進行焊制。由于LCD的驅動代碼較多,為了加快系統(tǒng)的運行速度,晶振采用11.0592MHz的頻率,同時也為了方便串口調試時的使用。其他器件的選型見附錄2。</p><p> 3.4 使用軟件說明</p><p> 本次課程設計的軟硬件設計在wind
19、ows 7系統(tǒng)下進行。程序編寫使用Keil uVision4軟件;硬件電路圖的繪制使用Altium Designer軟件;原理框圖的繪制使用Microsoft Viso軟件;使用stc-isp-15xx-v6.85I軟件進行程序的仿真調試與下載。</p><p><b> 硬件原理</b></p><p> 4.1 硬件整體框圖</p><p&
20、gt; 硬件整體框圖如圖1所示。</p><p><b> 圖1 硬件整體框圖</b></p><p> 本設計硬件整體分為六個小部分,分別為:矩陣鍵盤電路、復位電路、晶振電路、LCD電路、電源電路和STC89C52RC電路,下面對前四部分進行詳細說明。</p><p> 4.2 矩陣鍵盤電路</p><p>
21、 矩陣鍵盤電路如圖2所示,采用4×4矩陣鍵盤,共四行四列十六個按鍵,占用八個I/O口。</p><p><b> 圖2 矩陣鍵盤電路</b></p><p> 矩陣鍵盤的四個行分別與單片機的P1.0~P1.3相連接,四個列分別與單片機的P3.4~P3.7相連接,采用行列掃描的方法來檢測按下的按鍵,具體的做法是:檢測時先讓一列為低電平(此時確定了列),其余
22、幾列為高電平,然后立即輪流檢測各個行是否有低電平出現(xiàn),如果檢測到了某一行有低電平(此時確定了行),就可以確定是那個按鍵被按下了。圖中的S1~S10分別對用十進制數(shù)0~9,S11代表小數(shù)點,S12代表等號,S13~S16分別代表加、減、乘、除四個運算符。</p><p><b> 4.3 復位電路</b></p><p> 復位電路如圖3所示。</p>
23、<p><b> 圖3 復位電路</b></p><p> 在復位按鍵沒有按下時,復位引腳通過下拉電阻和地GND相連接,為低電平,當復位按鍵按下時,復位引腳和VCC接通,使單片機復位。</p><p><b> 4.4 晶振電路</b></p><p> 晶振電路如圖4所示。11.0592MHz的晶振兩
24、端通過兩個33皮法的電容接地,組成時鐘電路,通過引腳輸入到單片機內部以提供時鐘。</p><p><b> 圖4 晶振電路</b></p><p><b> 4.5 LCD電路</b></p><p> LCD電路如圖5所示。</p><p><b> 圖5 LCD電路</b
25、></p><p> LCD與STC89C52RC之間通過J1相連接,由單片機的I/O口模擬SPI接口驅動LCD進行工作。接口引腳CLK、MOSI、D/C、CS1、FSO、CS2分別與單片機的P0.0~P0.5通過上拉電阻相連接。</p><p><b> 程序設計原理</b></p><p> 5.1 程序設計流程 </p&
26、gt;<p> 程序的設計流程圖如圖6所示。</p><p> 下面對程序的幾個主要部分進行說明。</p><p> 圖6 程序設計流程圖</p><p> 5.2 按鍵掃描程序 </p><p> 鍵盤掃描函數(shù)的定義為void keyScan();在程序中依次給PO口賦值0XFE、0XFD、0XFB、0XF7來依次使
27、鍵盤的四個行線為0,然后用temp=P0來讀取P0口的狀態(tài)以用于后面的計算,然后將temp的值與0XF0相“與“判斷temp的高四位是否有0,如果temp的高四位沒有0,那么與0XF0相與的結果必然等于0XF0,就說明沒有按鍵被按下,如果temp的高四位有0,那么與0XF0相與的結果必然不等于0XF0,就說明有按鍵被按下,然后再通過P0口的值來判斷具體是那個按鍵被按下。</p><p> 5.3 輸入數(shù)據(jù)存儲與
28、轉換算法</p><p> 輸入的數(shù)據(jù)用兩個整型變量和兩個字符串來存儲其定義分別為:</p><p> int BP_dat,AP_dat</p><p> unsigned char BP_str[]=“”,AP_str[]=“” 。</p><p> 輸入的數(shù)字用變量key表示 ,小數(shù)點前的整數(shù)部分的計算方式為</p>
29、<p> BP_dat=BP_dat*10+key。</p><p> 小數(shù)點后小時部分的計算方式為((float)(AP_dat))/(10^(strlen(AP_str))),然后使用語句BP_dat+((float)(AP_dat))/(10^(strlen(AP_str)))便可得到輸入的操作數(shù)。</p><p> 由于LCD顯示函數(shù)的輸入只能是字符型的數(shù)據(jù),因
30、此使用sprintf(BP_str,"%d",BP_dat)函數(shù)將整型的數(shù)據(jù)轉換成字符型。</p><p> 其他部分程序見附錄4。</p><p><b> 5.4 LCD驅動</b></p><p> LCD的底層驅動使用SSD1306的開源驅動程序,在此底層驅動的基礎上自己編寫顯示函數(shù)。</p>&
31、lt;p><b> 系統(tǒng)功能描述</b></p><p> 本次課程設計的作品實物圖如圖7所示。</p><p><b> 圖7 作品實物圖</b></p><p> 按鍵的對應關系如圖8所示。</p><p> 圖8 按鍵功能對應關系</p><p> 作
32、品可實現(xiàn)四個浮點數(shù)的加減乘除四則運算,但在計算乘除法,特別是兩個浮點數(shù)的乘除法時會會產(chǎn)生數(shù)據(jù)精度被削減的問題,此問題暫時沒有找到解決的方法,有待日后改進。</p><p><b> 設計總結和心得體會</b></p><p> 本次課程設計歷時兩周,在課程設計的過程中遇到了許多的問題,同時也學到了許多知識。</p><p> 在最初的硬件
33、調試時總是遇到下載器檢測不到單片機的情況,為了找出問題所在,我首先檢查單片機的最小系統(tǒng)是否正常工作,檢查發(fā)現(xiàn)電源供電正常,復位電路連接正常,晶振電路能正常起振,最后仔細查閱數(shù)據(jù)手冊才知道,STC89C52RC單片機和以前使用的其他類型的單片機不同,它采用的是高電平復位,而以前自己使用的單片機是低電平復位,在修改了復位電路后,下載器便能正常檢測到單片機。</p><p> 在調試LCD的驅動時總是遇到顯示亂碼和錯
34、位的問題,通過在程序中設置斷點的調試方法發(fā)現(xiàn)是數(shù)據(jù)格式轉換是出現(xiàn)了問題,主要是在整型數(shù)據(jù)和浮點數(shù)轉為字符型時出現(xiàn)的問題,通過查閱C語言的相關書籍發(fā)現(xiàn),使用sprintf()函數(shù)可以很好地實現(xiàn)數(shù)值向字符串的轉換,但是8051內核運行這個函數(shù)總是顯得有些吃力,為了到達較好的顯示效果,只能舍棄了運行速度。</p><p> 在對兩個數(shù)進行運算時,特別是浮點數(shù)的運算時,運算結果有時出現(xiàn)精度降低或者是數(shù)值溢出的問題,通過
35、查閱開發(fā)手冊得知,在Keil C51中unsigned int型數(shù)據(jù)占兩個字節(jié),數(shù)據(jù)范圍為0~65535,signed int型數(shù)據(jù)占兩個字節(jié)數(shù)據(jù)范圍為-32768~+32767,float類型數(shù)據(jù)占四個字節(jié),數(shù)據(jù)范圍為:±1.175494E-38~±3.402823E+38,而自己輸入的數(shù)據(jù)或運算的結果可能超出了上述的范圍值,因此造成數(shù)據(jù)溢出并顯示錯誤,在修改了數(shù)據(jù)的存儲類型后,上述的問題得到了有效的解決,但是輸入
36、的數(shù)值和運算的結果卻有了一定的范圍限制。</p><p> 本次課程設計的作品到目前位置仍有一些缺陷,比如輸入數(shù)據(jù)位數(shù)的問題和計算結果精度降低的問題,由于時間的原因,只能在以后的時間里慢慢完善。</p><p> 通過本次課程設計,不僅讓我在課堂上學到的東西學以致用,更重要的是提高了我的動手能力和解決問題的能力,為以后的工作打下了很好的基礎。</p><p>
37、 附錄1 STC89C52RC資料</p><p> STC89C52RC單片機是宏晶科技推出的新一代高速/低功耗/超強抗干擾的8051內核單片機,指令代碼完全兼容傳統(tǒng)8051單片機,12時鐘/機器周期和6時鐘/機器周期可以任意選擇。</p><p><b> 其主要特性如下:</b></p><p> 增強型8051單片機,12時鐘/機
38、器周期和6時鐘/機器周期可以任意選擇,指令代碼完全兼容傳統(tǒng)8051。</p><p> 工作電壓:5.5V~3.3V。</p><p> 工作頻率范圍:0~40MHz。</p><p> 用戶應用程序存儲空間為8K。</p><p> 片上集成512B的RAM。</p><p> 32個I/O口,復位后P1/
39、P2/P3為準雙向口/弱上拉,PO口為漏極開路,作為總線擴展時不用加上拉電阻,作為I/O口時需要加上拉電阻。</p><p><b> ISP/IAP。</b></p><p> 3個16為定時/計數(shù)器。</p><p> 4路外部中斷,下降沿或低電平觸發(fā)。</p><p> STC89C52RC的引腳圖如圖9所
40、示。</p><p> 圖9 STC89C52RC引腳圖</p><p><b> 附錄2 器件選型</b></p><p><b> 附錄3 硬件原理圖</b></p><p><b> 附錄4 程序清單</b></p><p> 源文件1:
41、calculator.c</p><p> #include <reg52.H></p><p> #include <intrins.h></p><p> #include<stdio.h></p><p> #include<string.h></p><p&g
42、t; #include"user_define.h"</p><p> uchar point[]='.';</p><p> float op1;</p><p> float op2;</p><p> float ans;</p><p> int BP_dat
43、=0; //小數(shù)點之前的數(shù)據(jù)</p><p> int AP_dat=0; //小數(shù)點之后的數(shù)據(jù)</p><p> uint en89=1;</p><p> uint pFlag=0; //小數(shù)點輸入標志</p><p> uint asf=0; //等號按鍵標志</p><p&
44、gt; uint optCS; //輸入運算符類型</p><p> uint line_f=0; //行控制</p><p> uint bplen; //整數(shù)部分長度</p><p> uchar BP_str[]=""; //整數(shù)部分存放數(shù)組</p><p> uchar AP_
45、str[]=""; //小數(shù)部分存放數(shù)組</p><p> uchar ansCode[]=""; //運算結果存放數(shù)組</p><p> /************初始化顯示****************/</p><p> void init_dis()</p><p><b>
46、; {</b></p><p> oledDisp(0,0,">>");</p><p> oledDisp(4,0,">>");</p><p> oledDisp(6,0,"ans:");</p><p><b> }&l
47、t;/b></p><p> /**********數(shù)值計算函數(shù)*************/</p><p> void numSelc(int key)</p><p><b> { </b></p><p> if(pFlag==0)</p><p><b> {
48、</b></p><p> BP_dat=BP_dat*10+key;</p><p> sprintf(BP_str,"%d",BP_dat);</p><p> bplen=strlen(BP_str)*8+24;</p><p> oledDisp(line_f,16,BP_str);</p
49、><p><b> }</b></p><p><b> else</b></p><p><b> {</b></p><p> AP_dat=AP_dat*10+key;</p><p> sprintf(AP_str,"%d&quo
50、t;,AP_dat);</p><p> oledDisp(line_f,bplen,AP_str);</p><p><b> } </b></p><p><b> }</b></p><p> /**********延時函數(shù),毫秒級************/</p&g
51、t;<p> void delay_ms(uint a)</p><p><b> {</b></p><p><b> uint i,j;</b></p><p> for(i=a;i>0;i--)</p><p> for(j=110;j>0;j--);<
52、;/p><p><b> } </b></p><p> /*************鍵盤掃描*****************/</p><p> void keyScan() </p><p><b> { </b></p><p>
53、 uchar temp;</p><p><b> int key;</b></p><p><b> P1=0XFE;</b></p><p><b> temp=P1;</b></p><p> temp=temp&0XF0;</p><
54、p> if(temp!=0XF0)</p><p><b> {</b></p><p> delay_ms(10);</p><p><b> temp=P1;</b></p><p> temp=temp&0XF0;</p><p> if(te
55、mp!=0XF0)</p><p><b> {</b></p><p><b> temp=P1;</b></p><p> switch(temp)</p><p><b> {</b></p><p> case 0XEE: key=0;
56、break;</p><p> case 0XDE: key=1;break;</p><p> case 0XBE: key=2;break;</p><p> case 0X7E: key=3;break;</p><p><b> }</b></p><p> while(temp
57、!=0XF0)</p><p><b> {</b></p><p><b> temp=P1;</b></p><p> temp=temp&0XF0;</p><p><b> }</b></p><p> numSelc(key)
58、; </p><p><b> }</b></p><p><b> }</b></p><p><b> P1=0XFD;</b></p><p><b> temp=P1;</b></p><
59、;p> temp=temp&0XF0;</p><p> if(temp!=0XF0)</p><p><b> {</b></p><p> delay_ms(10);</p><p><b> temp=P1;</b></p><p> temp
60、=temp&0XF0;</p><p> if(temp!=0XF0)</p><p><b> {</b></p><p><b> temp=P1;</b></p><p> switch(temp)</p><p><b> {</b&
61、gt;</p><p> case 0XED: key=4;break;</p><p> case 0XDD: key=5;break;</p><p> case 0XBD: key=6;break;</p><p> case 0X7D: key=7;break;</p><p><b> }
62、</b></p><p> while(temp!=0XF0)</p><p><b> {</b></p><p><b> temp=P1;</b></p><p> temp=temp&0XF0;</p><p><b> }&l
63、t;/b></p><p> numSelc(key); </p><p><b> }</b></p><p><b> } </b></p><p><b> P1=0XFB; </b></p><p><b>
64、 temp=P1;</b></p><p> temp=temp&0XF0;</p><p> if(temp!=0XF0)</p><p><b> {</b></p><p> delay_ms(10);</p><p><b> temp=P1;&l
65、t;/b></p><p> temp=temp&0XF0;</p><p> if(temp!=0XF0)</p><p><b> {</b></p><p><b> temp=P1;</b></p><p> switch(temp)</
66、p><p><b> {</b></p><p> case 0XEB: key=8;break;</p><p> case 0XDB: key=9;break;</p><p> case 0XBB: pFlag=1;break;</p><p> case 0X7B: asf=1;pF
67、lag=0;break;</p><p><b> }</b></p><p> while(temp!=0XF0)</p><p><b> {</b></p><p><b> temp=P1;</b></p><p> temp=temp
68、&0XF0;</p><p><b> }</b></p><p> if(pFlag==1&&en89==1)</p><p><b> { </b></p><p> oledDisp(line_f,strlen(BP_str)*8+16,point); //計算
69、小數(shù)點顯示的地址</p><p><b> en89=0;</b></p><p><b> }</b></p><p> else if(asf==1)</p><p><b> {</b></p><p> if(strlen(AP_str
70、)==0)</p><p> op2=BP_dat; </p><p><b> else</b></p><p> op2=BP_dat+((float)(AP_dat))/(10^(strlen(AP_str))); //得到第二個運算數(shù) </p><p> switch(optCS)</p>
71、;<p><b> {</b></p><p> case 0:ans=op1+op2;break;</p><p> case 1:ans=op1-op2;break;</p><p> case 2:ans=op1*op2;break;</p><p> case 3:ans=op1/op2;
72、break;</p><p><b> } </b></p><p> sprintf(ansCode,"%f",ans); //將浮點型數(shù)據(jù)轉換為字符串以顯示在LCD上</p><p> oledDisp(6,32,ansCode);</p><p><b> pFlag=0
73、;</b></p><p><b> BP_dat=0;</b></p><p> AP_dat=0; </p><p><b> }</b></p><p><b> else</b></p><p> numSelc(key
74、); </p><p><b> }</b></p><p><b> } </b></p><p><b> P1=0XF7;</b></p><p><b> temp=P1;</b></p><p>
75、; temp=temp&0XF0;</p><p> if(temp!=0XF0)</p><p><b> {</b></p><p> delay_ms(10);</p><p><b> temp=P1;</b></p><p> temp=temp
76、&0XF0;</p><p> if(temp!=0XF0)</p><p><b> {</b></p><p><b> temp=P1;</b></p><p> switch(temp)</p><p><b> {</b>&l
77、t;/p><p> case 0XE7: optCS=0;break;</p><p> case 0XD7: optCS=1;break;</p><p> case 0XB7: optCS=2;break;</p><p> case 0X77: optCS=3;break;</p><p><b>
78、 }</b></p><p> while(temp!=0XF0)</p><p><b> {</b></p><p><b> temp=P1;</b></p><p> temp=temp&0XF0;</p><p><b>
79、}</b></p><p> if(strlen(AP_str)==0)</p><p> op1=BP_dat;</p><p> else </p><p> op1=BP_dat+((float)(AP_dat))/(10^(strlen(AP_str))); //轉換得到第一個運算數(shù)</p>
80、<p><b> line_f=4;</b></p><p><b> AP_dat=0;</b></p><p> BP_dat=0; </p><p><b> pFlag=0;</b></p><p><b> en89=1;</b&
81、gt;</p><p> switch(optCS)</p><p><b> {</b></p><p> case 0:oledDisp(2,1,"+");break;</p><p> case 1:oledDisp(2,1,"-");break;</p>
82、<p> case 2:oledDisp(2,1,"*");break;</p><p> case 3:oledDisp(2,1,"/");break;</p><p> } </p><p><b> }</b></p><
83、p><b> } </b></p><p><b> }</b></p><p> void main(void)</p><p> { </p><p><b> CS2=1;</b></p><p><b
84、> CS1=0;</b></p><p> initLcd(); //初始化LCD</p><p> clr_SCR(); </p><p> init_dis(); //初始化顯示</p><p><b> P3=0X00;</b></p><p><b&g
85、t; while(1)</b></p><p><b> {</b></p><p> keyScan(); //循環(huán)按鍵掃描</p><p><b> }</b></p><p><b> }</b></p><p> 頭文件
86、: user_define.h</p><p> #ifndef __USER_DEFINE_H__</p><p> #define __USER_DEFINE_H__</p><p> #define uchar unsigned char </p><p> #define uint unsigned int</p>
87、<p> #define ulong unsigned long</p><p> sbit CLK=P0^0; //接口定義:CLK</p><p> sbit MOSI=P0^1; //接口定義:MOSI</p><p> sbit DC=P0^2; //接口定義:DC</p&g
88、t;<p> sbit CS1=P0^3; //接口定義:OLED的片選CS1</p><p> sbit FSO=P0^4; //字庫IC接口定義:FSO</p><p> sbit CS2=P0^5; //字庫IC接口定義:CS2</p><p> void oledDisp(uchar
89、 y,uchar x,uchar *text); //函數(shù)聲明</p><p> void clr_SCR();</p><p> void initLcd();</p><p> void delay_ms(uint a) ;</p><p><b> #endif</b></p><p&g
90、t; 源文件: oled_driver.c</p><p> #include<reg52.h></p><p> #include <intrins.h></p><p> #include"user_define.h"</p><p> /*******寫指令到LCD模塊*******
91、/</p><p> void wr_CMD(int data1) </p><p><b> {</b></p><p><b> char i;</b></p><p><b> DC=0;</b></p><p><b>
92、CLK=0;</b></p><p> for(i=0;i<8;i++)</p><p><b> {</b></p><p> if(data1&0x80)</p><p><b> MOSI=1;</b></p><p><b>
93、; else </b></p><p><b> MOSI=0;</b></p><p><b> CLK=1;</b></p><p><b> _nop_();</b></p><p><b> CLK=0;</b></p&
94、gt;<p> data1<<=1;</p><p><b> }</b></p><p><b> }</b></p><p> /*********寫數(shù)據(jù)到LCD模塊*********/</p><p> void wr_DAT(int data1)</
95、p><p><b> {</b></p><p><b> char i;</b></p><p><b> DC=1;</b></p><p><b> CLK=0;</b></p><p> for(i=0;i<8;
96、i++)</p><p><b> {</b></p><p> if(data1&0x80)</p><p><b> MOSI=1;</b></p><p><b> else </b></p><p><b> MOS
97、I=0;</b></p><p><b> CLK=1;</b></p><p><b> _nop_();</b></p><p><b> CLK=0;</b></p><p> data1<<=1;</p><p>
98、<b> }</b></p><p><b> }</b></p><p> /**************LCD模塊初始化***********/</p><p> void initLcd()</p><p><b> {</b></p><p
99、><b> CS1=0;</b></p><p><b> CS2 = 1;</b></p><p> delay_ms(20); </p><p> wr_CMD(0xAE);//關閉顯示</p><p> wr_CMD(0x20);//設置存儲器尋址模式</p
100、><p> /*00,Horizontal Addressing Mode;01,Vertical Addressing Mode;</p><p> 10,Page Addressing Mode (RESET);11,Invalid*/</p><p> wr_CMD(0x10);</p><p> wr_CMD(0xb0);<
101、;/p><p> wr_CMD(0xc8);//設置輸出掃描方向</p><p> wr_CMD(0x00);//設置低列地址</p><p> wr_CMD(0x10);//設置高列地址</p><p> wr_CMD(0x40);//設置起始線地址</p><p> wr_CMD(0x81);//設置對比度控
102、制寄存器</p><p> wr_CMD(0x7f);</p><p> wr_CMD(0xa1);</p><p> wr_CMD(0xa6);//設置正常顯示</p><p> wr_CMD(0xa8);//設置復用率(1到64)</p><p> wr_CMD(0x3F);</p><
103、;p> /*0xa4,Output follows RAM content;0xa5,Output ignores RAM content*/</p><p> wr_CMD(0xa4);</p><p> wr_CMD(0xd3);//設置顯示偏移</p><p> wr_CMD(0x00);//設置無偏移</p><p>
104、 wr_CMD(0xd5);//設置時鐘分頻</p><p> wr_CMD(0xf0);//設置分辨率</p><p> wr_CMD(0xd9);//設置電源周期</p><p> wr_CMD(0x22); </p><p> wr_CMD(0xda);//設置硬件配置</p><p> wr_CMD(
105、0x12);</p><p> wr_CMD(0xdb);//設置vcomh</p><p> wr_CMD(0x20);//0x20,0.77xVcc</p><p> wr_CMD(0x8d);//設置DC-DC使能</p><p> wr_CMD(0x14);</p><p> wr_CMD(0xaf)
106、;//打開OLED控制面板 </p><p><b> CS1=1;</b></p><p><b> }</b></p><p> void lcd_Add(uchar page,uchar column)</p><p><b> {</b></p>
107、<p> wr_CMD(0xb0 + column); //設置頁地址</p><p> wr_CMD(((page & 0xf0) >> 4) | 0x10);//設置列地址的高4位</p><p> wr_CMD((page & 0x0f) | 0x00);//設置列地址的低4位</p><p><b&
108、gt; }</b></p><p> /********全屏清屏************/</p><p> void clr_SCR()</p><p><b> {</b></p><p> unsigned char i,j;</p><p><b> CS
109、1=0;</b></p><p><b> CS2 = 1;</b></p><p> for(i=0;i<8;i++)</p><p><b> {</b></p><p> wr_CMD(0xb0+i);</p><p> wr_CMD(0x
110、00);</p><p> wr_CMD(0x10);</p><p> for(j=0;j<128;j++)</p><p><b> {</b></p><p> wr_DAT(0x00);</p><p><b> }</b></p>&l
111、t;p><b> }</b></p><p><b> CS1=1;</b></p><p><b> }</b></p><p> /**顯示16x16點陣圖像、漢字、生僻字或16x16點陣的其他圖標**/</p><p> void disp_16X16(u
112、int page,uint column,uchar *dp)</p><p><b> {</b></p><p><b> uint i,j;</b></p><p><b> CS1=0;</b></p><p> CS2 = 1; </p>&l
113、t;p> for(j=2;j>0;j--)</p><p><b> {</b></p><p> lcd_Add(column,page);</p><p> for (i=0;i<16;i++)</p><p><b> {</b></p><p
114、> wr_DAT(*dp);//寫數(shù)據(jù)到LCD,每寫完一個8位的數(shù)據(jù)后列地址自動加1</p><p><b> dp++;</b></p><p><b> }</b></p><p><b> page++;</b></p><p><b> }&l
115、t;/b></p><p><b> CS1=1;</b></p><p><b> }</b></p><p> /**顯示8x16點陣圖像、ASCII, 或8x16點陣的自造字符、其他圖標**/</p><p> void disp_8X16(uint page,uchar col
116、umn,uchar *dp)</p><p><b> {</b></p><p><b> uint i,j;</b></p><p><b> CS1=0;</b></p><p> for(j=2;j>0;j--)</p><p>
117、<b> {</b></p><p> lcd_Add(column,page);</p><p> for (i=0;i<8;i++)</p><p><b> {</b></p><p> wr_DAT(*dp);//寫數(shù)據(jù)到LCD,每寫完一個8位的數(shù)據(jù)后列地址自動加1<
118、/p><p><b> dp++;</b></p><p><b> }</b></p><p><b> page++;</b></p><p><b> }</b></p><p><b> CS1=1;<
119、/b></p><p><b> }</b></p><p> /****送指令到晶聯(lián)訊字庫IC***/</p><p> void wrCMD_ROM( uchar datu )</p><p><b> {</b></p><p><b> uc
120、har i;</b></p><p> for(i=0;i<8;i++ )</p><p><b> {</b></p><p> if(datu&0x80)</p><p><b> MOSI = 1;</b></p><p><b&
121、gt; else</b></p><p><b> MOSI = 0;</b></p><p> datu = datu<<1;</p><p><b> CLK=0;</b></p><p><b> CLK=1;</b></p>
122、<p><b> }</b></p><p><b> }</b></p><p> /****從晶聯(lián)訊字庫IC中取漢字或字符數(shù)據(jù)(1個字節(jié))***/</p><p> static uchar rdDat_ROM( )</p><p><b> {</b&
123、gt;</p><p><b> uchar i;</b></p><p> uchar ret_data=0;</p><p><b> CLK=1;</b></p><p> for(i=0;i<8;i++)</p><p><b> {<
124、/b></p><p><b> FSO=1;</b></p><p><b> CLK=0;</b></p><p> ret_data=ret_data<<1;</p><p><b> if( FSO )</b></p><p
125、> ret_data=ret_data+1;</p><p><b> else</b></p><p> ret_data=ret_data+0;</p><p><b> CLK=1;</b></p><p><b> }</b></p>&l
126、t;p> return(ret_data);</p><p><b> }</b></p><p> /*從相關地址(addrHigh:地址高字節(jié),addrMid:地址中字節(jié),addrLow:地址低字節(jié))</p><p> **中連續(xù)讀出DataLen個字節(jié)的數(shù)據(jù)到 pBuff的地址*/</p><p>
127、 void gnBD_rom(uchar addrHigh,uchar addrMid,uchar addrLow,uchar *pBuff,uchar DataLen )</p><p><b> {</b></p><p><b> uchar i;</b></p><p><b> CS2 = 0;&
128、lt;/b></p><p><b> CS1=1;</b></p><p><b> CLK=0;</b></p><p> wrCMD_ROM(0x03);</p><p> wrCMD_ROM(addrHigh);</p><p> wrCMD_ROM
129、(addrMid);</p><p> wrCMD_ROM(addrLow);</p><p> for(i = 0; i < DataLen; i++ )</p><p> *(pBuff+i) =rdDat_ROM();</p><p><b> CS2 = 1;</b></p><
130、p><b> }</b></p><p> /**********************顯示GB字符****************************/</p><p> ulong fontaddr=0;</p><p> void oledDisp(uchar y,uchar x,uchar *text)</p
131、><p><b> {</b></p><p> uchar i= 0;</p><p> uchar addrHigh,addrMid,addrLow ;</p><p> uchar fontbuf[32];</p><p> while((text[i]>0x00))<
132、;/p><p><b> {</b></p><p> if(((text[i]>=0xb0) &&(text[i]<=0xf7))&&(text[i+1]>=0xa1))</p><p><b> {</b></p><p> fontaddr
133、 = (text[i]- 0xb0)*94; </p><p> fontaddr += (text[i+1]-0xa1)+846;</p><p> fontaddr = (ulong)(fontaddr*32);</p><p> addrHigh = (fontaddr&0xff0000)>>16; //地址的高8位,共24位<
134、/p><p> addrMid = (fontaddr&0xff00)>>8; //地址的中8位,共24位</p><p> addrLow = fontaddr&0xff; //地址的低8位,共24位</p><p> /*取32個字節(jié)的數(shù)據(jù),存到"fontbuf[32]"*/</p&
135、gt;<p> gnBD_rom(addrHigh,addrMid,addrLow,fontbuf,32 );</p><p> /*顯示漢字到LCD上,y為頁地址,x為列地址,fontbuf[]為數(shù)據(jù)*/</p><p> disp_16X16(y,x,fontbuf);</p><p><b> i+=2;</b>&l
136、t;/p><p><b> x+=16;</b></p><p><b> }</b></p><p> else if(((text[i]>=0xa1) &&(text[i]<=0xa3))&&(text[i+1]>=0xa1))</p><p>
137、;<b> {</b></p><p> /*Address = ((MSB - 0xa1) * 94 + (LSB - 0xA1))*32+ BaseAdd;BaseAdd=0*/</p><p> fontaddr = (text[i]- 0xa1)*94; </p><p> fontaddr += (text[i+1
138、]-0xa1);</p><p> fontaddr = (ulong)(fontaddr*32);</p><p> addrHigh = (fontaddr&0xff0000)>>16; //地址的高8位,共24位</p><p> addrMid = (fontaddr&0xff00)>>8; //地址的中
139、8位,共24位</p><p> addrLow = fontaddr&0xff; //地址的低8位,共24位</p><p> /*取32個字節(jié)的數(shù)據(jù),存到"fontbuf[32]"*/</p><p> gnBD_rom(addrHigh,addrMid,addrLow,fontbuf,32 );</p&g
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
評論
0/150
提交評論