? 低功耗藍(lán)牙(BluetoothLow Energy),簡稱BLE。藍(lán)牙低能耗無線技術(shù)利用許多智能手段最大限度地降低功耗。
藍(lán)牙低能耗架構(gòu)共有兩種芯片構(gòu)成:單模芯片和雙模芯片。藍(lán)牙單模器件是藍(lán)牙規(guī)范中新出現(xiàn)的一種只支持藍(lán)牙低能耗技術(shù)的芯片——是專門針對ULP操作優(yōu)化的技術(shù)的一部分。藍(lán)牙單模芯片可以和其它單模芯片及雙模芯片通信,此時后者需要使用自身架構(gòu)中的藍(lán)牙低能耗技術(shù)部分進行收發(fā)數(shù)據(jù)。雙模芯片也能與標(biāo)準(zhǔn)藍(lán)牙技術(shù)及使用傳統(tǒng)藍(lán)牙架構(gòu)的其它雙模芯片通信。
TI用于感測應(yīng)用的藍(lán)牙低功耗裝置是真正的 SoC 解決方案。CC254x SoC 系列完美結(jié)合 TI 協(xié)議堆棧、基本軟件 (profile software) 以及樣品應(yīng)用 (sample application),是高彈性、低成本單模藍(lán)牙低功耗解決方案。接下來我們將結(jié)合CC254x,講解從環(huán)境的搭建到藍(lán)牙4.0協(xié)議棧的開發(fā)來深入學(xué)習(xí)藍(lán)牙4.0的開發(fā)過程。本教程共分為六部分,主要知識點如下所示:
第一部分知識點:
第一節(jié) BLE開發(fā)環(huán)境的搭建
第二節(jié) BLE快速體驗
第三節(jié) 創(chuàng)建IAR工程-點亮LED
第四節(jié) 控制LED
第五節(jié) LCD12864顯示
第二部分知識點:
第六節(jié) 獨立按鍵之查詢方式
第七節(jié) 獨立按鍵之中斷方式
第八節(jié) CC254x內(nèi)部溫度傳感器溫度采集
第九節(jié) 五向按鍵
第十節(jié) 蜂鳴器
第三部分知識點:
第十一節(jié) 串口通信
第十二節(jié) Flash的讀寫
第十三節(jié) BLE協(xié)議棧簡介
第十四節(jié) OSAL工作原理
第十五節(jié) BLE藍(lán)牙4.0協(xié)議棧啟動分析
第四部分知識點:
第十六節(jié) 協(xié)議棧LED實驗
第十七節(jié) 協(xié)議棧LCD顯示
第十八節(jié) 協(xié)議棧UART實驗
第十九節(jié) 協(xié)議棧五向按鍵
第二十節(jié) 協(xié)議棧Flash數(shù)據(jù)存儲
第五部分知識點:
第二十一節(jié) DHT11溫濕度傳感器
第二十二節(jié) 藍(lán)牙協(xié)議棧之從機通訊
第二十三節(jié) 藍(lán)牙協(xié)議棧主從一體之主機通訊
第二十四節(jié) OAD空中升級
第二十五節(jié) SBL串口升級
第六部分知識點:
第二十六節(jié) UBL-USB升級
第二十七節(jié) MT-iBeacon基站使用iPhone空中升級
第二十八節(jié) MT-iBeacon基站在PC端實現(xiàn)OAD空中升級
第二十九節(jié) MT-iBeacon基站關(guān)于LightBlue軟件的使用
第三十節(jié) 如何使用MT-USBDongle的透傳功能
?
有關(guān)TI 的CC254x芯片介紹,可點擊下面鏈接查看:
主流藍(lán)牙BLE控制芯片詳解(1):TI CC2540
?
BLE是藍(lán)牙4.0規(guī)范中的一種,其中master最多有7個外設(shè),低功耗,低延遲,低吞吐量。
六種設(shè)備狀態(tài)
待機狀態(tài)(standby):設(shè)備沒有傳輸和發(fā)送數(shù)據(jù),并且沒有連接到任何設(shè)備
廣播狀態(tài)(Advertiser):周期性廣播狀態(tài)
掃描狀態(tài)(Scanner):主動尋找正在廣播的設(shè)備
發(fā)起鏈接狀態(tài)(Initiator):主動向掃描設(shè)備發(fā)起連接。
主設(shè)備(Master):作為主設(shè)備連接到其他設(shè)備。
從設(shè)備(Slave):作為從設(shè)備連接到其他設(shè)備。
五種工作狀態(tài)
準(zhǔn)備(standby),廣播(advertising),監(jiān)聽掃描(Scanning),發(fā)起連接(Initiating),已連接(Connected)
四種設(shè)備類型
Cnetral主機(常作為client端):如手機,PC
Peripheral從機(常作為Service端):如心率計,血糖計
Observer觀察者:
Broadcast廣播者:
連接過程:
Peripheral開啟廣播-->Central掃描從機廣播-->Peripheral接收到Central的掃描請求,Peripheral向Central發(fā)送掃描回應(yīng)數(shù)據(jù)-->Central向Peripheral發(fā)起連接-->開始通信。
兼容性
第一節(jié) BLE開發(fā)環(huán)境的搭建
1.1 硬件準(zhǔn)備
要進行BLE的開發(fā),首先我們需要一個硬件環(huán)境。
?。?) MT254xBoard開發(fā)板(最好有兩塊,方便進行數(shù)據(jù)收發(fā)實驗);
(2) USBDongle-BLE抓包工具(多個固件,一個硬件多種用途),協(xié)議開發(fā)時輔助我們分析數(shù)據(jù)包;
?。?) 開發(fā)必備CC-Debug,用于下載和調(diào)試程序;
有關(guān)本文的工具下載,大家可以到以下這個地址:
朱兆祺ForARM1.2 BLE協(xié)議棧的安裝
我們使用的是最新版本的協(xié)議棧BLE-CC254x-1.4.0,首先在配套的資料文件夾中的tools文件夾下找到BLE-CC254x-1.4.0.exe文件。
我們提供了一個安裝包和一個免安裝的源碼,根據(jù)我的開發(fā)經(jīng)驗,建議使用安裝包安裝到C盤,直接使用免安裝源碼在后期的開發(fā)中會遇到一些莫名其妙的問題。下面開始安裝協(xié)議棧,安裝方式很簡單,記得選擇C盤安裝。在安裝的最后階段,默認(rèn)的會安裝Btool。
成功安裝了協(xié)議棧后,將會出現(xiàn)說明文件。在說明文件中我們可以看到,這個版本的協(xié)議棧需要使用IAR for 8051 8.20.2版本的軟件。
注:如果使用的是Win8以上的系統(tǒng)建議使用IAR for 8051 8.30.2版本的軟件,安裝方式和8.20.2是一樣的。
下面我們就開始安裝這個版本的軟件。
1.3 IAR安裝
在配套的文件目錄下找到如下文件。
安裝IAR,然后安裝Dongle驅(qū)動。
到這步,說明IAR已經(jīng)安裝完成,下面開始進行和諧,你懂得!
解壓此文件夾,得到如下文件:
將解壓得到的文件全部復(fù)制到IAR安裝目錄(如下圖),直接覆蓋原始文件。
這樣IAR的安裝就完成了。先開啟軟件來體驗一下安裝成果吧!
1.4 安裝燒寫軟件
至此,我們目前需要用到的開發(fā)軟件就安裝完成了。
第二節(jié) BLE快速體驗
經(jīng)過前面的安裝,我們的開發(fā)環(huán)境已經(jīng)搭建好了,現(xiàn)在我們先來體驗一下BLE,給自己點動力,comeon!使用SmartRFFlash Programmer燒寫從機固件:CC2540_SmartRF_SimpleBLEPeripheral.hex,燒寫方法見SmartRF Flash Programmer的使用章節(jié)。
協(xié)議棧默認(rèn)自帶了一些已經(jīng)編譯好的文件,可以直接燒寫,具體路徑如下圖:
從機固件路徑:
讀取設(shè)備的IEEE地址:
?
燒寫完成后,如果你有支持Ble的手機或平板就可以搜索到設(shè)備了,或者使用本公司開發(fā)的USBDongle(抓包固件或HostTestRelease固件)也可以搜索到設(shè)備,具體的使用可以閱讀相應(yīng)的產(chǎn)品使用手冊,我這里用andriod平板搜索:
?
通過MAC地址可以知道我們的設(shè)備已經(jīng)在正常的廣播了,我這里使用本公司開發(fā)的andriod端軟件TruthBlue可以正常搜索到我們的設(shè)備。如果用戶手上有支持BLE的設(shè)備并且系統(tǒng)在andriod4.3以上也可以安裝我們的這個軟件。
連接上設(shè)備后如圖,這里我們不要求大家能夠看懂這些,這里僅僅是為了體驗,后面的章節(jié)中我們會詳細(xì)的講述這些知識。
第三節(jié) 創(chuàng)建IAR工程-點亮LED
經(jīng)過前面的準(zhǔn)備工作,這章開始我們開始正式的開發(fā)過程。
這個教程是為有一定51基礎(chǔ)和C基礎(chǔ)的人準(zhǔn)備的,如果讀者這方面還欠缺,請找相關(guān)方面的書籍惡補一下。CC2540的本質(zhì)就是一個8051的單片機,所以我們裸機開發(fā)就可以作為一個51單片機來開發(fā),裸機開發(fā)的目的是為了讓大家熟悉整個硬件以及開發(fā)環(huán)境,這并不是我們的最終目的,但這是一個必須的過程,為后面開發(fā)協(xié)議棧奠定基礎(chǔ)。
打開我們前面安裝的IAR軟件,創(chuàng)建一個新的工程。
因為我們使用的CC2540是增強型51單片機,這里我們創(chuàng)建一個空的8051工程,具體配置選項如圖:
選擇目錄保存工程;
我們這里創(chuàng)建一個最簡單的例程,點亮一個LED,這個例程就像我們學(xué)習(xí)每種編程語言是都是先來個Hello World!。雖然簡單,但是能夠讓我們最快的掌握一個開發(fā)環(huán)境的使用。
新的工程為空工程,沒有任何文件,我們這里新建一個文件并且保存為C文件。
添加文件到工程:
保存WorkSpace,在IAR中每個工程都必須要有一個Workspace,而且一個Workspace中可以有多個工程,所以這里我也必須要保存一個Workspace,點擊file->save Workspace As就會彈出如下對話框,這里和保存文件一樣需要對這個WorkSpace命名,我們這里一樣取名LED。
接下來我們需要對工程進行一些配置,使它適應(yīng)我們的CPU。在工程處右擊,進入配置界面。
CPU配置:
這里我們第一個要做的就是選擇我們的CPU,我們使用的是TI公司生產(chǎn)的CC2540F256,所以這里選擇CC2540F256。配置好CPU后,我們還需要配置編譯輸出的文件格式,選擇到Linker選項,配置如下圖:
debug選項:
選項配置:
經(jīng)過這些配置后,我們可以開始編碼了,下面開始編寫我們的第一個代碼,功能是點亮2個LED,開發(fā)板上有兩個LED燈,分別對應(yīng)P1.0和P1.1。
代碼如下,可能覺得都是注釋,這里我還是建議大家有一個好的編碼風(fēng)格,在開發(fā)大項目時就能夠看到它的優(yōu)勢。
int main(void)
{
P1SEL &= ~0X03; // 將P1.1、0設(shè)置為IO功能
P1DIR |= 0X03; // 設(shè)置P1.1、0為輸出功能
while(1)
{
P1 = (P1 & 0XFC) | 0X01; // 設(shè)置P1.0輸出高電平
}
return 0;
}
編寫好代碼后,就可以編譯下載到開發(fā)板上了。點擊圖中所示圖標(biāo)全速運行。
根據(jù)原理圖,P1.0對應(yīng)的是LED2,這里我們能夠看到LED2處于點亮的狀態(tài)。
根據(jù)CC254X的數(shù)據(jù)手冊,我們可以很快知道P1SEL是設(shè)置IO功能,P1DIR是設(shè)置輸入輸出。至于為什么程序是這么寫,我們來看下,CC254X芯片的P1口一共有8個IO口,那就是說剛剛好由兩位十六進制進行控制:1111 1111(FF),這里僅僅是LED1和LED2,也就是P1.1和P1.0兩個IO口,為了不影響其他引腳的使用,我們這里巧妙使用與或控制其功能。比如:P1 = (P1 & 0XFC) | 0X01; P1與上1111 1100,這樣不影響其他引腳的基礎(chǔ)上,清除了P1.0和P1.1的輸出,再或上0X01,這樣將P1.0設(shè)置為高電平,根據(jù)原理圖,高電平是點亮LED2.
第四節(jié) 控制LED
上一節(jié)點亮了單個LED燈,我們這堂課接著控制LED燈。這堂課我們要完成的是LED閃爍10次,蜂鳴器響1s鐘。這里我們先使用延時函數(shù)進行。
我們的程序一定要做到結(jié)構(gòu)清晰,可移植性強,閱讀性高。程序設(shè)計不僅僅是實現(xiàn)了功能,如果那樣的代碼,那只有你自己可以看懂,是一手垃圾。真正的漂亮代碼具有閱讀性高、可移植性強、代碼規(guī)范性好。
delay.h:
#ifndef __DELAY_H__
#define __DELAY_H__
extern void Delay1ms(unsigned int uiDelay);
#endif
/* end file */
延時函數(shù)的執(zhí)行程序delay.c:
#include “delay.h”
void Delay1ms(unsigned int uiDelay)
{
unsigned int i;
for ( ; uiDelay > 0; uiDelay--)
{
/* 大約延時1ms */
for (i = 0; i <320; i++);
}
}
/* end file */
主函數(shù)其實也很簡單:
int main(void)
{
/* 控制LED燈閃爍 */
unsigned char i;
/* 驅(qū)動無源蜂鳴器 */
unsigned int j;
/* 將P1.0、P1.1設(shè)置為IO口 */
P1SEL &= ~0x03;
/* 將P1.0、P1.1設(shè)置為IO口的輸出 */
P1DIR |= 0x03;
/* 將P2.0設(shè)置為IO口 */
P2SEL &= ~0x01;
/* 將P2.0設(shè)置為IO口輸出 */
P2DIR |= 0x01;
/* 主循環(huán) */
while(1)
{
/* LED1,LED2閃爍10次 */
for (i = 0; i <10; i++)
{
/* P1.0----LED2,P1.1----LED1 */
/* P1.0,P1.1輸出高電平,即點亮LED2,LED1 */
/* FC : 1111 1100*/
P1 = (P1 & 0xFC) | 0x03;
Delay1ms(1000);
/* P1.0,P1.1輸出低電平,即熄滅LED2,LED1 */
/* FC : 1111 1100*/
P1 = (P1 & 0xFC) & (~0x03);
Delay1ms(1000);
}
/* 給出500HZ的方波驅(qū)動 */
for(j = 0; j <1000; j++)
{
/* P2.0----蜂鳴器 */
P2 = (P2 & 0xFE) & (~0x01);
Delay1ms(1);
P2 = (P2 & 0xFE) | 0x01;
Delay1ms(1);
}
}
}
/* end file */
這里需要注意的是,MT254X藍(lán)牙4.0開發(fā)板使用的無源蜂鳴器,那么我們需要產(chǎn)生一個方波來驅(qū)動。如這代碼:
/* 給出500HZ的方波驅(qū)動 */
for(j = 0; j <1000; j++)
{
/* P2.0----蜂鳴器 */
P2 = (P2 & 0xFE) & (~0x01);
Delay1ms(1);
P2 = (P2 & 0xFE) | 0x01;
Delay1ms(1);
}
如果是有緣蜂鳴器,則沒有那么麻煩,直接給出低電平驅(qū)動。為什么是低電平,我們看下原理圖:
使用的PNP三極管,并且使用續(xù)流二極管保護蜂鳴器。
第五節(jié) LCD12864顯示
上一節(jié)我們成功控制了LED和蜂鳴器,這一節(jié)我們馬不停蹄接著LCD12864的控制。
為了系統(tǒng)能夠穩(wěn)定的工作,首先我們將系統(tǒng)時鐘切換到32M的外部晶振,為了自由配置所需要的時鐘,主要借助于CLKCONCMD.OSC選擇系統(tǒng)主時鐘,而借助于CLKCONCMD.OSC32K則用于選擇芯片32K時鐘源!而低功耗模式設(shè)置時,需要借助于SLEEPCMD寄存器,在《CC253x- CC2540-41Applications User‘s Guide.pdf>中并沒有說明SLEEPCMD第二位功能,如下所示:
但是參考cc2430芯片的說明書可以發(fā)現(xiàn),對應(yīng)的SLEEP寄存器則有說明,如下所示,這個是TI有意隱藏芯片細(xì)節(jié),當(dāng)SLEEPCMD.OSC_PD為0時,32MHz晶振與16MHz RC振蕩器都會起振:
對于SLEEPSTA寄存器中BIT6/BIT5說明在cc2530說明書中也并沒有說明,可以參考cc2430說明書中內(nèi)容,其中第6位 XOSC_STB表明外部高速32M晶振是否上電并穩(wěn)定起振,當(dāng)穩(wěn)定時該位為1;同樣對于第5位HFRC_STB則表明內(nèi)部16MHz高速RC振蕩器是否起振,并是否穩(wěn)定,當(dāng)16MHz RC振蕩器穩(wěn)定時該位為1。
void SysStartXOSC(void)
{
SLEEPCMD &= ~0x04; // 啟動所有晶振
while (?。⊿LEEPSTA & 0x40)); // 等待晶振穩(wěn)定
CLKCONCMD = (CLKCONCMD & 0x80) | 0x49; // 使用16M晶振作為主時鐘
while ((CLKCONSTA & ~0x80) != 0x49 ); // 等待主時鐘切換到16M晶振
CLKCONCMD = (CLKCONCMD & ~0x80) ; // 使用外部32K晶振作為休眠時鐘
while ( (CLKCONSTA & 0x80) != 0 ); // 等待睡眠時鐘切換到外部32K晶振
CLKCONCMD = (CLKCONCMD & 0x80) ; // 使用32M晶振作為主時鐘
while ( (CLKCONSTA & ~0x80) != 0 ); // 等待主時鐘切換到32M晶振
SLEEPCMD |= 0x04; // 關(guān)閉未使用的晶振
}
按照上述方式配置后,我們就可以工作在外部的32M晶振上了,配置好系統(tǒng)時鐘和SPI后,剩下的工作只需要按照液晶屏的說明書發(fā)送相應(yīng)的指令就可以將液晶屏驅(qū)動起來了,具體的驅(qū)動代碼詳見下一堂課程。這里使用的是ASCII的點陣表,所以只能顯示英文,如果需要顯示中文,就需要中文字庫的支持了。
LCD12864的驅(qū)動程序:
P0.1 - LCD_MODE
P1.2 - LCD_CS
//spi
P1.5 - CLK
P1.6 - MOSI
/* LCD lines */
#define LCD12864_MAX_LINE 64
#define LCD12864_MAX_ROW 128
#define HAL_LCD_FONT_LINES 8
#define HAL_LCD_FONT_ROWS 6
/* LCD Max Chars and Buffer */
#define HAL_LCD_MAX_LINES (LCD12864_MAX_LINE/HAL_LCD_FONT_LINES) // 6*8點陣最大行數(shù)
#define HAL_LCD_MAX_CHARS (LCD12864_MAX_ROW/HAL_LCD_FONT_ROWS) // 6*8點陣最大列數(shù)
/* LCD Control lines */
#define HAL_LCD_RS_PORT 0
#define HAL_LCD_RS_PIN 1
#define HAL_LCD_CS_PORT 1
#define HAL_LCD_CS_PIN 2
/* LCD SPI lines */
#define HAL_LCD_CLK_PORT 1
#define HAL_LCD_CLK_PIN 5
#define HAL_LCD_MOSI_PORT 1
#define HAL_LCD_MOSI_PIN 6
// 12864 命令
#define LCD_CMD_DISPLAY_ON 0xAF
#define LCD_CMD_DISPLAY_OFF 0xAE
#define LCD_CMD_BEGIN_LINE 0x40
#define LCD_CMD_PAGE_LINE 0xB0
#define LCD_CMD_ROW_HIG 0x10
#define LCD_CMD_ROW_LOW 0x00
#define LCD_CMD_READ_STATE 0x00
#define LCD_CMD_ROW_ADDR_NORMAL 0xA0 // 從左到右
#define LCD_CMD_ROW_ADDR_REVERSE 0xA1 // 從右到左
#define LCD_CMD_DISPLAY_NORMAL 0xA6
#define LCD_CMD_DISPLAY_REVERSE 0xA7
#define LCD_CMD_DISPLAY_POINT_ALL 0xA5
#define LCD_CMD_DISPLAY_POINT_NORMAL 0xA4
#define LCD_CMD_BIAS_SET 0xA2 // 0XA2:BIAS=1/9 (常用) 0XA3:BIAS=1/7
#define LCD_CMD_SOFT_RESET 0xE2
#define LCD_CMD_LINE_NORMAL 0xC0 // 從上到下
#define LCD_CMD_LINE_REVERSE 0xC8 // 從下到上
#define LCD_CMD_POWER_ONE 0x2C
#define LCD_CMD_POWER_TWO 0x2E
#define LCD_CMD_POWER_THREE 0x2F
#define LCD_CMD_CONTRAST_ONE_LEVEL 0x22 // 0x20-0x27
#define LCD_CMD_CONTRAST_TWO_CMD 0x81 // 0x00-0x3F
#define LCD_CMD_STATIC_PICTURE_ON 0xAD
/* SPI interface control */
#define LCD_SPI_BEGIN() HAL_CONFIG_IO_OUTPUT(HAL_LCD_CS_PORT, HAL_LCD_CS_PIN, 0); /* chip select */
#define LCD_SPI_END()
{
asm(“NOP”);
asm(“NOP”);
asm(“NOP”);
asm(“NOP”);
HAL_CONFIG_IO_OUTPUT(HAL_LCD_CS_PORT, HAL_LCD_CS_PIN, 1); /* chip select */
}
/* clear the received and transmit byte status, write tx data to buffer, wait till transmit done */
#define LCD_SPI_TX(x) { U1CSR &= ~(BV(2) | BV(1)); U1DBUF = x; while( ?。║1CSR & BV(1)) ); }
/* Control macros */
#define LCD_DO_WRITE() HAL_CONFIG_IO_OUTPUT(HAL_LCD_RS_PORT, HAL_LCD_RS_PIN, 1);
#define LCD_DO_CONTROL() HAL_CONFIG_IO_OUTPUT(HAL_LCD_RS_PORT, HAL_LCD_RS_PIN, 0);
/*全體ASCII 列表:5x7點陣庫*/
const static uint8 aucAsciiTable5x7[][5]={
0x00,0x00,0x00,0x00,0x00,//space
0x00,0x00,0x4f,0x00,0x00,//!
0x00,0x07,0x00,0x07,0x00,//“
0x14,0x7f,0x14,0x7f,0x14,//#
0x24,0x2a,0x7f,0x2a,0x12,//$
0x23,0x13,0x08,0x64,0x62,//%
0x36,0x49,0x55,0x22,0x50,//&
0x00,0x05,0x07,0x00,0x00,//]
0x00,0x1c,0x22,0x41,0x00,//(
0x00,0x41,0x22,0x1c,0x00,//)
0x14,0x08,0x3e,0x08,0x14,//*
0x08,0x08,0x3e,0x08,0x08,//+
0x00,0x50,0x30,0x00,0x00,//,
0x08,0x08,0x08,0x08,0x08,//-
0x00,0x60,0x60,0x00,0x00,//。
0x20,0x10,0x08,0x04,0x02,///
0x3e,0x51,0x49,0x45,0x3e,//0
0x00,0x42,0x7f,0x40,0x00,//1
0x42,0x61,0x51,0x49,0x46,//2
0x21,0x41,0x45,0x4b,0x31,//3
0x18,0x14,0x12,0x7f,0x10,//4
0x27,0x45,0x45,0x45,0x39,//5
0x3c,0x4a,0x49,0x49,0x30,//6
0x01,0x71,0x09,0x05,0x03,//7
0x36,0x49,0x49,0x49,0x36,//8
0x06,0x49,0x49,0x29,0x1e,//9
0x00,0x36,0x36,0x00,0x00,//:
0x00,0x56,0x36,0x00,0x00,//;
0x08,0x14,0x22,0x41,0x00,//《
0x14,0x14,0x14,0x14,0x14,//=
0x00,0x41,0x22,0x14,0x08,//>
0x02,0x01,0x51,0x09,0x06,//?
0x32,0x49,0x79,0x41,0x3e,//@
0x7e,0x11,0x11,0x11,0x7e,//A
0x7f,0x49,0x49,0x49,0x36,//B
0x3e,0x41,0x41,0x41,0x22,//C
0x7f,0x41,0x41,0x22,0x1c,//D
0x7f,0x49,0x49,0x49,0x41,//E
0x7f,0x09,0x09,0x09,0x01,//F
0x3e,0x41,0x49,0x49,0x7a,//G
0x7f,0x08,0x08,0x08,0x7f,//H
0x00,0x41,0x7f,0x41,0x00,//I
0x20,0x40,0x41,0x3f,0x01,//J
0x7f,0x08,0x14,0x22,0x41,//K
0x7f,0x40,0x40,0x40,0x40,//L
0x7f,0x02,0x0c,0x02,0x7f,//M
0x7f,0x04,0x08,0x10,0x7f,//N
0x3e,0x41,0x41,0x41,0x3e,//O
0x7f,0x09,0x09,0x09,0x06,//P
0x3e,0x41,0x51,0x21,0x5e,//Q
0x7f,0x09,0x19,0x29,0x46,//R
0x46,0x49,0x49,0x49,0x31,//S
0x01,0x01,0x7f,0x01,0x01,//T
0x3f,0x40,0x40,0x40,0x3f,//U
0x1f,0x20,0x40,0x20,0x1f,//V
0x3f,0x40,0x38,0x40,0x3f,//W
0x63,0x14,0x08,0x14,0x63,//X
0x07,0x08,0x70,0x08,0x07,//Y
0x61,0x51,0x49,0x45,0x43,//Z
0x00,0x7f,0x41,0x41,0x00,//[
0x02,0x04,0x08,0x10,0x20,// 斜杠
0x00,0x41,0x41,0x7f,0x00,//]
0x04,0x02,0x01,0x02,0x04,//^
0x40,0x40,0x40,0x40,0x40,//_
0x01,0x02,0x04,0x00,0x00,//`
0x20,0x54,0x54,0x54,0x78,//a
0x7f,0x48,0x48,0x48,0x30,//b
0x38,0x44,0x44,0x44,0x44,//c
0x30,0x48,0x48,0x48,0x7f,//d
0x38,0x54,0x54,0x54,0x58,//e
0x00,0x08,0x7e,0x09,0x02,//f
0x48,0x54,0x54,0x54,0x3c,//g
0x7f,0x08,0x08,0x08,0x70,//h
0x00,0x00,0x7a,0x00,0x00,//i
0x20,0x40,0x40,0x3d,0x00,//j
0x7f,0x20,0x28,0x44,0x00,//k
0x00,0x41,0x7f,0x40,0x00,//l
0x7c,0x04,0x38,0x04,0x7c,//m
0x7c,0x08,0x04,0x04,0x78,//n
0x38,0x44,0x44,0x44,0x38,//o
0x7c,0x14,0x14,0x14,0x08,//p
0x08,0x14,0x14,0x14,0x7c,//q
0x7c,0x08,0x04,0x04,0x08,//r
0x48,0x54,0x54,0x54,0x24,//s
0x04,0x04,0x3f,0x44,0x24,//t
0x3c,0x40,0x40,0x40,0x3c,//u
0x1c,0x20,0x40,0x20,0x1c,//v
0x3c,0x40,0x30,0x40,0x3c,//w
0x44,0x28,0x10,0x28,0x44,//x
0x04,0x48,0x30,0x08,0x04,//y
0x44,0x64,0x54,0x4c,0x44,//z
0x08,0x36,0x41,0x41,0x00,//{
0x00,0x00,0x77,0x00,0x00,//|
0x00,0x41,0x41,0x36,0x08,//}
0x04,0x02,0x02,0x02,0x01,//~
};
const uint8 asciiTableSize = sizeof( aucAsciiTable5x7 ) / sizeof( aucAsciiTable5x7[0]);
static void LCD12864_Cmd(uint8 cmd)
{
LCD_SPI_BEGIN();
LCD_DO_CONTROL();
LCD_SPI_TX(cmd);
LCD_SPI_END();
}
static void LCD12864_Dat(uint8 data)
{
LCD_SPI_BEGIN();
LCD_DO_WRITE();
LCD_SPI_TX(data);
LCD_SPI_END();
}
void LCD12864_Init(void)
{
PERCFG |= 0x02; // 設(shè)置UART alt2 為 SPI
// 配置引腳為SPI功能
HAL_CONFIG_IO_PERIPHERAL(HAL_LCD_CLK_PORT, HAL_LCD_CLK_PIN);
HAL_CONFIG_IO_PERIPHERAL(HAL_LCD_MOSI_PORT, HAL_LCD_MOSI_PIN);
/* Configure SPI */
U1UCR = 0x80; // 清除原來的數(shù)據(jù)
U1CSR = 0x00; // SPI 主機模式
// 高位在前,第一個上升沿發(fā)送數(shù)據(jù),波特率為2M
U1GCR = HAL_SPI_TRANSFER_MSB_FIRST | HAL_SPI_CLOCK_PHA_0 | HAL_SPI_CLOCK_POL_LO | 0x0F;
U1BAUD = 0xFF;
// CS RS 配置為輸出
HAL_CONFIG_IO_OUTPUT(HAL_LCD_RS_PORT, HAL_LCD_RS_PIN, 1);
HAL_CONFIG_IO_OUTPUT(HAL_LCD_CS_PORT, HAL_LCD_CS_PIN, 1);
SoftWaitUs(15000); // 15 ms
LCD12864_Cmd(LCD_CMD_SOFT_RESET); //軟復(fù)位
SoftWaitUs(15000); // 15 ms
LCD12864_Cmd(LCD_CMD_POWER_ONE); //升壓步聚1
SoftWaitUs(15); // 15 us
LCD12864_Cmd(LCD_CMD_POWER_TWO); //升壓步聚2
SoftWaitUs(15); // 15 us
LCD12864_Cmd(LCD_CMD_POWER_THREE); //升壓步聚3
SoftWaitUs(150); // 15 us
LCD12864_Cmd(LCD_CMD_CONTRAST_ONE_LEVEL); //粗調(diào)對比度,可設(shè)置范圍0x20~0x27
LCD12864_Cmd(LCD_CMD_CONTRAST_TWO_CMD); //微調(diào)對比度
LCD12864_Cmd(0x3a); //0x1a,微調(diào)對比度的值,可設(shè)置范圍0x00~0x3f
LCD12864_Cmd(LCD_CMD_BIAS_SET); // 1/9偏壓比(bias)
LCD12864_Cmd(LCD_CMD_LINE_NORMAL); //行掃描順序:從上到下
LCD12864_Cmd(LCD_CMD_ROW_ADDR_REVERSE); //列掃描順序:從左到右
LCD12864_Cmd(LCD_CMD_BEGIN_LINE); //起始行:第一行開始
LCD12864_Cmd(LCD_CMD_DISPLAY_ON); //打開顯示
LCD12864_Cmd(LCD_CMD_DISPLAY_POINT_NORMAL);
LCD12864_Cmd(LCD_CMD_DISPLAY_NORMAL); //設(shè)置為正顯模式
SoftWaitUs(150); // 150 us
}
static void LCD12864_SetAddr(uint8 line, uint8 col)
{
uint8 ucLine, ucRow;
//line += 5;
col += 4;
if((line >= LCD12864_MAX_LINE) || (col >= LCD12864_MAX_ROW))
{
return;
}
ucLine = LCD_CMD_PAGE_LINE | (line&0x0f);
LCD12864_Cmd(ucLine);
SoftWaitUs(15);
ucRow = LCD_CMD_ROW_HIG | (col>>4);
LCD12864_Cmd(ucRow);
SoftWaitUs(15); // 15 us
ucRow = LCD_CMD_ROW_LOW | (col&0x0f);
LCD12864_Cmd(ucRow);
SoftWaitUs(15); // 15 us
}
static void LCD12864_Dis5X8(char ch)
{
uint8 ucCnt;
if((ch >= 0x20)&&(ch <0x7f))
{
uint8 ucChar = ch - 0x20;
for(ucCnt=0; ucCnt《5; ucCnt++)
{
LCD12864_Dat( aucAsciiTable5x7[ucChar][ucCnt]);
}
//LCD12864_Dat(0x00);
}
else if(ch==0x00) //不需要顯示,清空指定位置
{
for(ucCnt=0; ucCnt《5; ucCnt++)
{
LCD12864_Dat(0x00);
}
}
LCD12864_Dat(0x00);
}
void LCD12864_Clear(void)
{
uint8 ucLine, ucRow;
for(ucLine=0; ucLine《LCD12864_MAX_LINE; ucLine++)
{
LCD12864_SetAddr(ucLine, 0);
for(ucRow=0; ucRow《LCD12864_MAX_ROW; ucRow++)
{
LCD12864_Dat(0x00);
}
}
}
void LCD12864_DisChar(uint8 line, uint8 col, char ch)
{
if (( line
{
LCD12864_SetAddr(line, col*HAL_LCD_FONT_ROWS);
LCD12864_Dis5X8(ch);
}
}
void LCD12864_DisStr(uint8 line, char* pStr)
{
uint8 ucCnt = 0;
for ( ucCnt = 0 ; ucCnt
{
if ( ’
主站蜘蛛池模板:
国产一区二区三区夜色
|
国产精品永久免费自在线观看
|
国产欧美综合在线
|
99精品在免费线视频
|
国产天天射
|
年轻的护士3在线观看
|
аⅴ天堂 在线
|
午夜激情网站
|
色综合天天综合给合国产
|
h视频免费看
|
福利区在线观看
|
中国国产aa一级毛片
|
天天操天天舔天天射
|
美女张开腿露出尿口让男人桶
|
亚洲婷婷在线视频
|
亚洲一级毛片免观看
|
青草视频久久
|
亚洲一区二区在线
|
国产69精品久久久久9牛牛
|
se94se最新网站
|
人人干在线
|
福利社藏经阁
|
狠狠干夜夜
|
色批|
深夜视频在线播放视频在线观看免费观看
|
亚洲色图日韩
|
日本一本高清视频
|
亚洲国产成人精品久久
|
午夜日韩视频
|
色色色色色色网
|
免费午夜影片在线观看影院
|
国产亚洲美女精品久久久久狼
|
特级黄|
天天干在线观看
|
亚洲 欧美 动漫
|
天堂最新版中文网
|
国产成人精品视频一区二区不卡
|
成人免费精品视频
|
欧美式free群乱
|
老司机精品免费视频
|
国产精品三级a三级三级午夜
|