[嵌入式系統] mcs-51 實驗 - 使用 iar (3)

127
Chien-Jung Li Nov. 2013 MCS-51 基礎實習 使用IAR Embedded Workbench (III)

Upload: simenli

Post on 15-Aug-2015

163 views

Category:

Engineering


7 download

TRANSCRIPT

Page 1: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

Chien-Jung Li

Nov 2013

MCS-51 基礎實習 使用IAR Embedded Workbench (III)

Lab11 Real-Time Clock晶片

2

DS1302 RTC介紹

3

DS1302是美國DALLAS公司生產的即時時鐘電路 (Real-time clock RTC)它可對年月日周日時分秒進行計時並具有閏年補償功能而且也有24小時制與12小時制(AMPM)的選擇

工作電壓為20V~55V採用三線通訊介面 (3-wire interface)內部具有31 Bytes的SRAM

DS1302具有主電源備用電源的雙電源引腳(VCC1為後備電源VCC2為主電源由VCC1 或VCC2 兩者中的較大者供電)同時提供對備用電源進行涓流充電的能力

X1和X2外接32768 kHz的石英振盪器RST是重置晶片選擇腳對RST輸入Low重置晶片而將RST設為High可啟動所有資料傳送

DS1302 RTC的RSTCE接腳功能

4

RSTCE輸入有兩種功能

RST接至控制邏輯允許位址命令序列送入移位暫存器

RST提供終止資料傳送當RST為高電壓時所有的數據傳送被初始化允許對DS1302進行操作如果在傳送過程中RST置為低電壓則會終止此次資料傳送IO引腳變為高阻態

啟動運行時在VCCgt20V之前RST必須保持低電位只有在SCLK為低電位時才能將RST置為高電位IO為串列資料輸出端(雙向)SCLK為時鐘輸入端

40 kΩ pull-down

DS1302之指令 ndash Command Byte

5

Command Byte用於初始化每次的資料傳輸bit-0必定為input staring

3-Wire通訊介面的讀寫

6

Burst mode command byte bit1~5 = 11111rsquob = 31(decimal)

Reads or writes in burst mode start with bit 0 of address 0

RTC內部暫存器(儲存時間資訊)

7

Trickle Charger (涓流充電)

8

Timing Diagram

9

實習11

10

目標製作一個電子時鐘將日期與時間顯示在LCD上這是我們第一次要同時控制兩個較複雜的裝置它們的驅動程式如果寫在一個c檔程式檔會變很龐大現在我們要開始學習如何管理程式碼這是進入商用產品開發的第一站

DS1302 RTC使用3-wire介面與MCU通訊

LCD使用LCD1602A的訊號介面與MCU通訊

練習1 結構化你的程式碼

練習2 加入LCD的驅動程式

練習3 練習撰寫API手冊(以LCD驅動程式為例)

練習4 加入3-wire通訊介面與DS1302的驅動程式

練習5 完成電子時鐘

設計模式與驅動程式

11

在開始談論如何結構化程式碼之前我們先來討論幾種跟硬體相關的嵌入式程式設計模式

所講到的觀念以後會慢慢應用在我們的設計專案當中(有些觀念其實你已經不知不覺接觸很久了)

Adapter(或Wrapper)模式

12

Adapter是十分傳統的設計模式它將一個物件的介面轉換成另一個用戶(高階模組)較易使用的介面

通常adapter覆蓋在軟體API之上以蓋掉醜陋的介面

閃爍LED燈 ndash 最簡單的寫法

13

includeltioAT89C52hgt typedef unsigned char uint8 void delayms(uint8) void main(void) P1_bitP1_0 = 1 while(1) P1_bitP1_0 = 0 delayms(250) P1_bitP1_0 = 1 delayms(250)

includeltioAT89C52hgt define LED0 P1_bitP1_0 typedef unsigned char uint8 void delayms(uint8) void main(void) LED0 = 1 while(1) LED0 = 0 delayms(250) LED0 = 1 delayms(250)

閃爍LED燈 ndash 使用機板標頭檔

14

ioMappingh define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

閃爍LED燈 ndash 通用機板標頭檔

15

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

ioMappingh if COMPILING_BOARD_V1 include ioMapping_v1h elif COMPILING_BOARD_V2 include ioMapping_v2h else error No IO map selected for the board endif

ioMapping_v1h define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

ioMapping_v2h define LED_REGISTER P3 define LED_BIT (1 ltlt 4)

IO處理程式碼

16

閃爍LED燈 ndash Facade模式

17

LED的IO子系統介面與內容就是LED的驅動程式

隱藏子系統的細節是良好設計中十分重要的一環呼叫端的程式不會依賴子系統的細節

Main

加上按鈕

18

設定中斷

19

雖然為腳位設定中斷與設定輸入都是屬於初始化但這兩件事情通常會將實作分離只需要在使用中斷的程式碼中包含設定中斷的複雜度

三個中斷處理函式(有時會用巨集來做)

競賽情況(Race Condition)

在工作間共享記憶體十分危險必須十分小心

20

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 2: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

Lab11 Real-Time Clock晶片

2

DS1302 RTC介紹

3

DS1302是美國DALLAS公司生產的即時時鐘電路 (Real-time clock RTC)它可對年月日周日時分秒進行計時並具有閏年補償功能而且也有24小時制與12小時制(AMPM)的選擇

工作電壓為20V~55V採用三線通訊介面 (3-wire interface)內部具有31 Bytes的SRAM

DS1302具有主電源備用電源的雙電源引腳(VCC1為後備電源VCC2為主電源由VCC1 或VCC2 兩者中的較大者供電)同時提供對備用電源進行涓流充電的能力

X1和X2外接32768 kHz的石英振盪器RST是重置晶片選擇腳對RST輸入Low重置晶片而將RST設為High可啟動所有資料傳送

DS1302 RTC的RSTCE接腳功能

4

RSTCE輸入有兩種功能

RST接至控制邏輯允許位址命令序列送入移位暫存器

RST提供終止資料傳送當RST為高電壓時所有的數據傳送被初始化允許對DS1302進行操作如果在傳送過程中RST置為低電壓則會終止此次資料傳送IO引腳變為高阻態

啟動運行時在VCCgt20V之前RST必須保持低電位只有在SCLK為低電位時才能將RST置為高電位IO為串列資料輸出端(雙向)SCLK為時鐘輸入端

40 kΩ pull-down

DS1302之指令 ndash Command Byte

5

Command Byte用於初始化每次的資料傳輸bit-0必定為input staring

3-Wire通訊介面的讀寫

6

Burst mode command byte bit1~5 = 11111rsquob = 31(decimal)

Reads or writes in burst mode start with bit 0 of address 0

RTC內部暫存器(儲存時間資訊)

7

Trickle Charger (涓流充電)

8

Timing Diagram

9

實習11

10

目標製作一個電子時鐘將日期與時間顯示在LCD上這是我們第一次要同時控制兩個較複雜的裝置它們的驅動程式如果寫在一個c檔程式檔會變很龐大現在我們要開始學習如何管理程式碼這是進入商用產品開發的第一站

DS1302 RTC使用3-wire介面與MCU通訊

LCD使用LCD1602A的訊號介面與MCU通訊

練習1 結構化你的程式碼

練習2 加入LCD的驅動程式

練習3 練習撰寫API手冊(以LCD驅動程式為例)

練習4 加入3-wire通訊介面與DS1302的驅動程式

練習5 完成電子時鐘

設計模式與驅動程式

11

在開始談論如何結構化程式碼之前我們先來討論幾種跟硬體相關的嵌入式程式設計模式

所講到的觀念以後會慢慢應用在我們的設計專案當中(有些觀念其實你已經不知不覺接觸很久了)

Adapter(或Wrapper)模式

12

Adapter是十分傳統的設計模式它將一個物件的介面轉換成另一個用戶(高階模組)較易使用的介面

通常adapter覆蓋在軟體API之上以蓋掉醜陋的介面

閃爍LED燈 ndash 最簡單的寫法

13

includeltioAT89C52hgt typedef unsigned char uint8 void delayms(uint8) void main(void) P1_bitP1_0 = 1 while(1) P1_bitP1_0 = 0 delayms(250) P1_bitP1_0 = 1 delayms(250)

includeltioAT89C52hgt define LED0 P1_bitP1_0 typedef unsigned char uint8 void delayms(uint8) void main(void) LED0 = 1 while(1) LED0 = 0 delayms(250) LED0 = 1 delayms(250)

閃爍LED燈 ndash 使用機板標頭檔

14

ioMappingh define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

閃爍LED燈 ndash 通用機板標頭檔

15

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

ioMappingh if COMPILING_BOARD_V1 include ioMapping_v1h elif COMPILING_BOARD_V2 include ioMapping_v2h else error No IO map selected for the board endif

ioMapping_v1h define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

ioMapping_v2h define LED_REGISTER P3 define LED_BIT (1 ltlt 4)

IO處理程式碼

16

閃爍LED燈 ndash Facade模式

17

LED的IO子系統介面與內容就是LED的驅動程式

隱藏子系統的細節是良好設計中十分重要的一環呼叫端的程式不會依賴子系統的細節

Main

加上按鈕

18

設定中斷

19

雖然為腳位設定中斷與設定輸入都是屬於初始化但這兩件事情通常會將實作分離只需要在使用中斷的程式碼中包含設定中斷的複雜度

三個中斷處理函式(有時會用巨集來做)

競賽情況(Race Condition)

在工作間共享記憶體十分危險必須十分小心

20

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 3: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

DS1302 RTC介紹

3

DS1302是美國DALLAS公司生產的即時時鐘電路 (Real-time clock RTC)它可對年月日周日時分秒進行計時並具有閏年補償功能而且也有24小時制與12小時制(AMPM)的選擇

工作電壓為20V~55V採用三線通訊介面 (3-wire interface)內部具有31 Bytes的SRAM

DS1302具有主電源備用電源的雙電源引腳(VCC1為後備電源VCC2為主電源由VCC1 或VCC2 兩者中的較大者供電)同時提供對備用電源進行涓流充電的能力

X1和X2外接32768 kHz的石英振盪器RST是重置晶片選擇腳對RST輸入Low重置晶片而將RST設為High可啟動所有資料傳送

DS1302 RTC的RSTCE接腳功能

4

RSTCE輸入有兩種功能

RST接至控制邏輯允許位址命令序列送入移位暫存器

RST提供終止資料傳送當RST為高電壓時所有的數據傳送被初始化允許對DS1302進行操作如果在傳送過程中RST置為低電壓則會終止此次資料傳送IO引腳變為高阻態

啟動運行時在VCCgt20V之前RST必須保持低電位只有在SCLK為低電位時才能將RST置為高電位IO為串列資料輸出端(雙向)SCLK為時鐘輸入端

40 kΩ pull-down

DS1302之指令 ndash Command Byte

5

Command Byte用於初始化每次的資料傳輸bit-0必定為input staring

3-Wire通訊介面的讀寫

6

Burst mode command byte bit1~5 = 11111rsquob = 31(decimal)

Reads or writes in burst mode start with bit 0 of address 0

RTC內部暫存器(儲存時間資訊)

7

Trickle Charger (涓流充電)

8

Timing Diagram

9

實習11

10

目標製作一個電子時鐘將日期與時間顯示在LCD上這是我們第一次要同時控制兩個較複雜的裝置它們的驅動程式如果寫在一個c檔程式檔會變很龐大現在我們要開始學習如何管理程式碼這是進入商用產品開發的第一站

DS1302 RTC使用3-wire介面與MCU通訊

LCD使用LCD1602A的訊號介面與MCU通訊

練習1 結構化你的程式碼

練習2 加入LCD的驅動程式

練習3 練習撰寫API手冊(以LCD驅動程式為例)

練習4 加入3-wire通訊介面與DS1302的驅動程式

練習5 完成電子時鐘

設計模式與驅動程式

11

在開始談論如何結構化程式碼之前我們先來討論幾種跟硬體相關的嵌入式程式設計模式

所講到的觀念以後會慢慢應用在我們的設計專案當中(有些觀念其實你已經不知不覺接觸很久了)

Adapter(或Wrapper)模式

12

Adapter是十分傳統的設計模式它將一個物件的介面轉換成另一個用戶(高階模組)較易使用的介面

通常adapter覆蓋在軟體API之上以蓋掉醜陋的介面

閃爍LED燈 ndash 最簡單的寫法

13

includeltioAT89C52hgt typedef unsigned char uint8 void delayms(uint8) void main(void) P1_bitP1_0 = 1 while(1) P1_bitP1_0 = 0 delayms(250) P1_bitP1_0 = 1 delayms(250)

includeltioAT89C52hgt define LED0 P1_bitP1_0 typedef unsigned char uint8 void delayms(uint8) void main(void) LED0 = 1 while(1) LED0 = 0 delayms(250) LED0 = 1 delayms(250)

閃爍LED燈 ndash 使用機板標頭檔

14

ioMappingh define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

閃爍LED燈 ndash 通用機板標頭檔

15

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

ioMappingh if COMPILING_BOARD_V1 include ioMapping_v1h elif COMPILING_BOARD_V2 include ioMapping_v2h else error No IO map selected for the board endif

ioMapping_v1h define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

ioMapping_v2h define LED_REGISTER P3 define LED_BIT (1 ltlt 4)

IO處理程式碼

16

閃爍LED燈 ndash Facade模式

17

LED的IO子系統介面與內容就是LED的驅動程式

隱藏子系統的細節是良好設計中十分重要的一環呼叫端的程式不會依賴子系統的細節

Main

加上按鈕

18

設定中斷

19

雖然為腳位設定中斷與設定輸入都是屬於初始化但這兩件事情通常會將實作分離只需要在使用中斷的程式碼中包含設定中斷的複雜度

三個中斷處理函式(有時會用巨集來做)

競賽情況(Race Condition)

在工作間共享記憶體十分危險必須十分小心

20

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 4: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

DS1302 RTC的RSTCE接腳功能

4

RSTCE輸入有兩種功能

RST接至控制邏輯允許位址命令序列送入移位暫存器

RST提供終止資料傳送當RST為高電壓時所有的數據傳送被初始化允許對DS1302進行操作如果在傳送過程中RST置為低電壓則會終止此次資料傳送IO引腳變為高阻態

啟動運行時在VCCgt20V之前RST必須保持低電位只有在SCLK為低電位時才能將RST置為高電位IO為串列資料輸出端(雙向)SCLK為時鐘輸入端

40 kΩ pull-down

DS1302之指令 ndash Command Byte

5

Command Byte用於初始化每次的資料傳輸bit-0必定為input staring

3-Wire通訊介面的讀寫

6

Burst mode command byte bit1~5 = 11111rsquob = 31(decimal)

Reads or writes in burst mode start with bit 0 of address 0

RTC內部暫存器(儲存時間資訊)

7

Trickle Charger (涓流充電)

8

Timing Diagram

9

實習11

10

目標製作一個電子時鐘將日期與時間顯示在LCD上這是我們第一次要同時控制兩個較複雜的裝置它們的驅動程式如果寫在一個c檔程式檔會變很龐大現在我們要開始學習如何管理程式碼這是進入商用產品開發的第一站

DS1302 RTC使用3-wire介面與MCU通訊

LCD使用LCD1602A的訊號介面與MCU通訊

練習1 結構化你的程式碼

練習2 加入LCD的驅動程式

練習3 練習撰寫API手冊(以LCD驅動程式為例)

練習4 加入3-wire通訊介面與DS1302的驅動程式

練習5 完成電子時鐘

設計模式與驅動程式

11

在開始談論如何結構化程式碼之前我們先來討論幾種跟硬體相關的嵌入式程式設計模式

所講到的觀念以後會慢慢應用在我們的設計專案當中(有些觀念其實你已經不知不覺接觸很久了)

Adapter(或Wrapper)模式

12

Adapter是十分傳統的設計模式它將一個物件的介面轉換成另一個用戶(高階模組)較易使用的介面

通常adapter覆蓋在軟體API之上以蓋掉醜陋的介面

閃爍LED燈 ndash 最簡單的寫法

13

includeltioAT89C52hgt typedef unsigned char uint8 void delayms(uint8) void main(void) P1_bitP1_0 = 1 while(1) P1_bitP1_0 = 0 delayms(250) P1_bitP1_0 = 1 delayms(250)

includeltioAT89C52hgt define LED0 P1_bitP1_0 typedef unsigned char uint8 void delayms(uint8) void main(void) LED0 = 1 while(1) LED0 = 0 delayms(250) LED0 = 1 delayms(250)

閃爍LED燈 ndash 使用機板標頭檔

14

ioMappingh define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

閃爍LED燈 ndash 通用機板標頭檔

15

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

ioMappingh if COMPILING_BOARD_V1 include ioMapping_v1h elif COMPILING_BOARD_V2 include ioMapping_v2h else error No IO map selected for the board endif

ioMapping_v1h define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

ioMapping_v2h define LED_REGISTER P3 define LED_BIT (1 ltlt 4)

IO處理程式碼

16

閃爍LED燈 ndash Facade模式

17

LED的IO子系統介面與內容就是LED的驅動程式

隱藏子系統的細節是良好設計中十分重要的一環呼叫端的程式不會依賴子系統的細節

Main

加上按鈕

18

設定中斷

19

雖然為腳位設定中斷與設定輸入都是屬於初始化但這兩件事情通常會將實作分離只需要在使用中斷的程式碼中包含設定中斷的複雜度

三個中斷處理函式(有時會用巨集來做)

競賽情況(Race Condition)

在工作間共享記憶體十分危險必須十分小心

20

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 5: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

DS1302之指令 ndash Command Byte

5

Command Byte用於初始化每次的資料傳輸bit-0必定為input staring

3-Wire通訊介面的讀寫

6

Burst mode command byte bit1~5 = 11111rsquob = 31(decimal)

Reads or writes in burst mode start with bit 0 of address 0

RTC內部暫存器(儲存時間資訊)

7

Trickle Charger (涓流充電)

8

Timing Diagram

9

實習11

10

目標製作一個電子時鐘將日期與時間顯示在LCD上這是我們第一次要同時控制兩個較複雜的裝置它們的驅動程式如果寫在一個c檔程式檔會變很龐大現在我們要開始學習如何管理程式碼這是進入商用產品開發的第一站

DS1302 RTC使用3-wire介面與MCU通訊

LCD使用LCD1602A的訊號介面與MCU通訊

練習1 結構化你的程式碼

練習2 加入LCD的驅動程式

練習3 練習撰寫API手冊(以LCD驅動程式為例)

練習4 加入3-wire通訊介面與DS1302的驅動程式

練習5 完成電子時鐘

設計模式與驅動程式

11

在開始談論如何結構化程式碼之前我們先來討論幾種跟硬體相關的嵌入式程式設計模式

所講到的觀念以後會慢慢應用在我們的設計專案當中(有些觀念其實你已經不知不覺接觸很久了)

Adapter(或Wrapper)模式

12

Adapter是十分傳統的設計模式它將一個物件的介面轉換成另一個用戶(高階模組)較易使用的介面

通常adapter覆蓋在軟體API之上以蓋掉醜陋的介面

閃爍LED燈 ndash 最簡單的寫法

13

includeltioAT89C52hgt typedef unsigned char uint8 void delayms(uint8) void main(void) P1_bitP1_0 = 1 while(1) P1_bitP1_0 = 0 delayms(250) P1_bitP1_0 = 1 delayms(250)

includeltioAT89C52hgt define LED0 P1_bitP1_0 typedef unsigned char uint8 void delayms(uint8) void main(void) LED0 = 1 while(1) LED0 = 0 delayms(250) LED0 = 1 delayms(250)

閃爍LED燈 ndash 使用機板標頭檔

14

ioMappingh define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

閃爍LED燈 ndash 通用機板標頭檔

15

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

ioMappingh if COMPILING_BOARD_V1 include ioMapping_v1h elif COMPILING_BOARD_V2 include ioMapping_v2h else error No IO map selected for the board endif

ioMapping_v1h define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

ioMapping_v2h define LED_REGISTER P3 define LED_BIT (1 ltlt 4)

IO處理程式碼

16

閃爍LED燈 ndash Facade模式

17

LED的IO子系統介面與內容就是LED的驅動程式

隱藏子系統的細節是良好設計中十分重要的一環呼叫端的程式不會依賴子系統的細節

Main

加上按鈕

18

設定中斷

19

雖然為腳位設定中斷與設定輸入都是屬於初始化但這兩件事情通常會將實作分離只需要在使用中斷的程式碼中包含設定中斷的複雜度

三個中斷處理函式(有時會用巨集來做)

競賽情況(Race Condition)

在工作間共享記憶體十分危險必須十分小心

20

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 6: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

3-Wire通訊介面的讀寫

6

Burst mode command byte bit1~5 = 11111rsquob = 31(decimal)

Reads or writes in burst mode start with bit 0 of address 0

RTC內部暫存器(儲存時間資訊)

7

Trickle Charger (涓流充電)

8

Timing Diagram

9

實習11

10

目標製作一個電子時鐘將日期與時間顯示在LCD上這是我們第一次要同時控制兩個較複雜的裝置它們的驅動程式如果寫在一個c檔程式檔會變很龐大現在我們要開始學習如何管理程式碼這是進入商用產品開發的第一站

DS1302 RTC使用3-wire介面與MCU通訊

LCD使用LCD1602A的訊號介面與MCU通訊

練習1 結構化你的程式碼

練習2 加入LCD的驅動程式

練習3 練習撰寫API手冊(以LCD驅動程式為例)

練習4 加入3-wire通訊介面與DS1302的驅動程式

練習5 完成電子時鐘

設計模式與驅動程式

11

在開始談論如何結構化程式碼之前我們先來討論幾種跟硬體相關的嵌入式程式設計模式

所講到的觀念以後會慢慢應用在我們的設計專案當中(有些觀念其實你已經不知不覺接觸很久了)

Adapter(或Wrapper)模式

12

Adapter是十分傳統的設計模式它將一個物件的介面轉換成另一個用戶(高階模組)較易使用的介面

通常adapter覆蓋在軟體API之上以蓋掉醜陋的介面

閃爍LED燈 ndash 最簡單的寫法

13

includeltioAT89C52hgt typedef unsigned char uint8 void delayms(uint8) void main(void) P1_bitP1_0 = 1 while(1) P1_bitP1_0 = 0 delayms(250) P1_bitP1_0 = 1 delayms(250)

includeltioAT89C52hgt define LED0 P1_bitP1_0 typedef unsigned char uint8 void delayms(uint8) void main(void) LED0 = 1 while(1) LED0 = 0 delayms(250) LED0 = 1 delayms(250)

閃爍LED燈 ndash 使用機板標頭檔

14

ioMappingh define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

閃爍LED燈 ndash 通用機板標頭檔

15

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

ioMappingh if COMPILING_BOARD_V1 include ioMapping_v1h elif COMPILING_BOARD_V2 include ioMapping_v2h else error No IO map selected for the board endif

ioMapping_v1h define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

ioMapping_v2h define LED_REGISTER P3 define LED_BIT (1 ltlt 4)

IO處理程式碼

16

閃爍LED燈 ndash Facade模式

17

LED的IO子系統介面與內容就是LED的驅動程式

隱藏子系統的細節是良好設計中十分重要的一環呼叫端的程式不會依賴子系統的細節

Main

加上按鈕

18

設定中斷

19

雖然為腳位設定中斷與設定輸入都是屬於初始化但這兩件事情通常會將實作分離只需要在使用中斷的程式碼中包含設定中斷的複雜度

三個中斷處理函式(有時會用巨集來做)

競賽情況(Race Condition)

在工作間共享記憶體十分危險必須十分小心

20

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 7: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

RTC內部暫存器(儲存時間資訊)

7

Trickle Charger (涓流充電)

8

Timing Diagram

9

實習11

10

目標製作一個電子時鐘將日期與時間顯示在LCD上這是我們第一次要同時控制兩個較複雜的裝置它們的驅動程式如果寫在一個c檔程式檔會變很龐大現在我們要開始學習如何管理程式碼這是進入商用產品開發的第一站

DS1302 RTC使用3-wire介面與MCU通訊

LCD使用LCD1602A的訊號介面與MCU通訊

練習1 結構化你的程式碼

練習2 加入LCD的驅動程式

練習3 練習撰寫API手冊(以LCD驅動程式為例)

練習4 加入3-wire通訊介面與DS1302的驅動程式

練習5 完成電子時鐘

設計模式與驅動程式

11

在開始談論如何結構化程式碼之前我們先來討論幾種跟硬體相關的嵌入式程式設計模式

所講到的觀念以後會慢慢應用在我們的設計專案當中(有些觀念其實你已經不知不覺接觸很久了)

Adapter(或Wrapper)模式

12

Adapter是十分傳統的設計模式它將一個物件的介面轉換成另一個用戶(高階模組)較易使用的介面

通常adapter覆蓋在軟體API之上以蓋掉醜陋的介面

閃爍LED燈 ndash 最簡單的寫法

13

includeltioAT89C52hgt typedef unsigned char uint8 void delayms(uint8) void main(void) P1_bitP1_0 = 1 while(1) P1_bitP1_0 = 0 delayms(250) P1_bitP1_0 = 1 delayms(250)

includeltioAT89C52hgt define LED0 P1_bitP1_0 typedef unsigned char uint8 void delayms(uint8) void main(void) LED0 = 1 while(1) LED0 = 0 delayms(250) LED0 = 1 delayms(250)

閃爍LED燈 ndash 使用機板標頭檔

14

ioMappingh define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

閃爍LED燈 ndash 通用機板標頭檔

15

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

ioMappingh if COMPILING_BOARD_V1 include ioMapping_v1h elif COMPILING_BOARD_V2 include ioMapping_v2h else error No IO map selected for the board endif

ioMapping_v1h define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

ioMapping_v2h define LED_REGISTER P3 define LED_BIT (1 ltlt 4)

IO處理程式碼

16

閃爍LED燈 ndash Facade模式

17

LED的IO子系統介面與內容就是LED的驅動程式

隱藏子系統的細節是良好設計中十分重要的一環呼叫端的程式不會依賴子系統的細節

Main

加上按鈕

18

設定中斷

19

雖然為腳位設定中斷與設定輸入都是屬於初始化但這兩件事情通常會將實作分離只需要在使用中斷的程式碼中包含設定中斷的複雜度

三個中斷處理函式(有時會用巨集來做)

競賽情況(Race Condition)

在工作間共享記憶體十分危險必須十分小心

20

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 8: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

Trickle Charger (涓流充電)

8

Timing Diagram

9

實習11

10

目標製作一個電子時鐘將日期與時間顯示在LCD上這是我們第一次要同時控制兩個較複雜的裝置它們的驅動程式如果寫在一個c檔程式檔會變很龐大現在我們要開始學習如何管理程式碼這是進入商用產品開發的第一站

DS1302 RTC使用3-wire介面與MCU通訊

LCD使用LCD1602A的訊號介面與MCU通訊

練習1 結構化你的程式碼

練習2 加入LCD的驅動程式

練習3 練習撰寫API手冊(以LCD驅動程式為例)

練習4 加入3-wire通訊介面與DS1302的驅動程式

練習5 完成電子時鐘

設計模式與驅動程式

11

在開始談論如何結構化程式碼之前我們先來討論幾種跟硬體相關的嵌入式程式設計模式

所講到的觀念以後會慢慢應用在我們的設計專案當中(有些觀念其實你已經不知不覺接觸很久了)

Adapter(或Wrapper)模式

12

Adapter是十分傳統的設計模式它將一個物件的介面轉換成另一個用戶(高階模組)較易使用的介面

通常adapter覆蓋在軟體API之上以蓋掉醜陋的介面

閃爍LED燈 ndash 最簡單的寫法

13

includeltioAT89C52hgt typedef unsigned char uint8 void delayms(uint8) void main(void) P1_bitP1_0 = 1 while(1) P1_bitP1_0 = 0 delayms(250) P1_bitP1_0 = 1 delayms(250)

includeltioAT89C52hgt define LED0 P1_bitP1_0 typedef unsigned char uint8 void delayms(uint8) void main(void) LED0 = 1 while(1) LED0 = 0 delayms(250) LED0 = 1 delayms(250)

閃爍LED燈 ndash 使用機板標頭檔

14

ioMappingh define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

閃爍LED燈 ndash 通用機板標頭檔

15

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

ioMappingh if COMPILING_BOARD_V1 include ioMapping_v1h elif COMPILING_BOARD_V2 include ioMapping_v2h else error No IO map selected for the board endif

ioMapping_v1h define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

ioMapping_v2h define LED_REGISTER P3 define LED_BIT (1 ltlt 4)

IO處理程式碼

16

閃爍LED燈 ndash Facade模式

17

LED的IO子系統介面與內容就是LED的驅動程式

隱藏子系統的細節是良好設計中十分重要的一環呼叫端的程式不會依賴子系統的細節

Main

加上按鈕

18

設定中斷

19

雖然為腳位設定中斷與設定輸入都是屬於初始化但這兩件事情通常會將實作分離只需要在使用中斷的程式碼中包含設定中斷的複雜度

三個中斷處理函式(有時會用巨集來做)

競賽情況(Race Condition)

在工作間共享記憶體十分危險必須十分小心

20

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 9: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

Timing Diagram

9

實習11

10

目標製作一個電子時鐘將日期與時間顯示在LCD上這是我們第一次要同時控制兩個較複雜的裝置它們的驅動程式如果寫在一個c檔程式檔會變很龐大現在我們要開始學習如何管理程式碼這是進入商用產品開發的第一站

DS1302 RTC使用3-wire介面與MCU通訊

LCD使用LCD1602A的訊號介面與MCU通訊

練習1 結構化你的程式碼

練習2 加入LCD的驅動程式

練習3 練習撰寫API手冊(以LCD驅動程式為例)

練習4 加入3-wire通訊介面與DS1302的驅動程式

練習5 完成電子時鐘

設計模式與驅動程式

11

在開始談論如何結構化程式碼之前我們先來討論幾種跟硬體相關的嵌入式程式設計模式

所講到的觀念以後會慢慢應用在我們的設計專案當中(有些觀念其實你已經不知不覺接觸很久了)

Adapter(或Wrapper)模式

12

Adapter是十分傳統的設計模式它將一個物件的介面轉換成另一個用戶(高階模組)較易使用的介面

通常adapter覆蓋在軟體API之上以蓋掉醜陋的介面

閃爍LED燈 ndash 最簡單的寫法

13

includeltioAT89C52hgt typedef unsigned char uint8 void delayms(uint8) void main(void) P1_bitP1_0 = 1 while(1) P1_bitP1_0 = 0 delayms(250) P1_bitP1_0 = 1 delayms(250)

includeltioAT89C52hgt define LED0 P1_bitP1_0 typedef unsigned char uint8 void delayms(uint8) void main(void) LED0 = 1 while(1) LED0 = 0 delayms(250) LED0 = 1 delayms(250)

閃爍LED燈 ndash 使用機板標頭檔

14

ioMappingh define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

閃爍LED燈 ndash 通用機板標頭檔

15

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

ioMappingh if COMPILING_BOARD_V1 include ioMapping_v1h elif COMPILING_BOARD_V2 include ioMapping_v2h else error No IO map selected for the board endif

ioMapping_v1h define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

ioMapping_v2h define LED_REGISTER P3 define LED_BIT (1 ltlt 4)

IO處理程式碼

16

閃爍LED燈 ndash Facade模式

17

LED的IO子系統介面與內容就是LED的驅動程式

隱藏子系統的細節是良好設計中十分重要的一環呼叫端的程式不會依賴子系統的細節

Main

加上按鈕

18

設定中斷

19

雖然為腳位設定中斷與設定輸入都是屬於初始化但這兩件事情通常會將實作分離只需要在使用中斷的程式碼中包含設定中斷的複雜度

三個中斷處理函式(有時會用巨集來做)

競賽情況(Race Condition)

在工作間共享記憶體十分危險必須十分小心

20

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 10: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

實習11

10

目標製作一個電子時鐘將日期與時間顯示在LCD上這是我們第一次要同時控制兩個較複雜的裝置它們的驅動程式如果寫在一個c檔程式檔會變很龐大現在我們要開始學習如何管理程式碼這是進入商用產品開發的第一站

DS1302 RTC使用3-wire介面與MCU通訊

LCD使用LCD1602A的訊號介面與MCU通訊

練習1 結構化你的程式碼

練習2 加入LCD的驅動程式

練習3 練習撰寫API手冊(以LCD驅動程式為例)

練習4 加入3-wire通訊介面與DS1302的驅動程式

練習5 完成電子時鐘

設計模式與驅動程式

11

在開始談論如何結構化程式碼之前我們先來討論幾種跟硬體相關的嵌入式程式設計模式

所講到的觀念以後會慢慢應用在我們的設計專案當中(有些觀念其實你已經不知不覺接觸很久了)

Adapter(或Wrapper)模式

12

Adapter是十分傳統的設計模式它將一個物件的介面轉換成另一個用戶(高階模組)較易使用的介面

通常adapter覆蓋在軟體API之上以蓋掉醜陋的介面

閃爍LED燈 ndash 最簡單的寫法

13

includeltioAT89C52hgt typedef unsigned char uint8 void delayms(uint8) void main(void) P1_bitP1_0 = 1 while(1) P1_bitP1_0 = 0 delayms(250) P1_bitP1_0 = 1 delayms(250)

includeltioAT89C52hgt define LED0 P1_bitP1_0 typedef unsigned char uint8 void delayms(uint8) void main(void) LED0 = 1 while(1) LED0 = 0 delayms(250) LED0 = 1 delayms(250)

閃爍LED燈 ndash 使用機板標頭檔

14

ioMappingh define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

閃爍LED燈 ndash 通用機板標頭檔

15

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

ioMappingh if COMPILING_BOARD_V1 include ioMapping_v1h elif COMPILING_BOARD_V2 include ioMapping_v2h else error No IO map selected for the board endif

ioMapping_v1h define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

ioMapping_v2h define LED_REGISTER P3 define LED_BIT (1 ltlt 4)

IO處理程式碼

16

閃爍LED燈 ndash Facade模式

17

LED的IO子系統介面與內容就是LED的驅動程式

隱藏子系統的細節是良好設計中十分重要的一環呼叫端的程式不會依賴子系統的細節

Main

加上按鈕

18

設定中斷

19

雖然為腳位設定中斷與設定輸入都是屬於初始化但這兩件事情通常會將實作分離只需要在使用中斷的程式碼中包含設定中斷的複雜度

三個中斷處理函式(有時會用巨集來做)

競賽情況(Race Condition)

在工作間共享記憶體十分危險必須十分小心

20

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 11: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

設計模式與驅動程式

11

在開始談論如何結構化程式碼之前我們先來討論幾種跟硬體相關的嵌入式程式設計模式

所講到的觀念以後會慢慢應用在我們的設計專案當中(有些觀念其實你已經不知不覺接觸很久了)

Adapter(或Wrapper)模式

12

Adapter是十分傳統的設計模式它將一個物件的介面轉換成另一個用戶(高階模組)較易使用的介面

通常adapter覆蓋在軟體API之上以蓋掉醜陋的介面

閃爍LED燈 ndash 最簡單的寫法

13

includeltioAT89C52hgt typedef unsigned char uint8 void delayms(uint8) void main(void) P1_bitP1_0 = 1 while(1) P1_bitP1_0 = 0 delayms(250) P1_bitP1_0 = 1 delayms(250)

includeltioAT89C52hgt define LED0 P1_bitP1_0 typedef unsigned char uint8 void delayms(uint8) void main(void) LED0 = 1 while(1) LED0 = 0 delayms(250) LED0 = 1 delayms(250)

閃爍LED燈 ndash 使用機板標頭檔

14

ioMappingh define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

閃爍LED燈 ndash 通用機板標頭檔

15

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

ioMappingh if COMPILING_BOARD_V1 include ioMapping_v1h elif COMPILING_BOARD_V2 include ioMapping_v2h else error No IO map selected for the board endif

ioMapping_v1h define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

ioMapping_v2h define LED_REGISTER P3 define LED_BIT (1 ltlt 4)

IO處理程式碼

16

閃爍LED燈 ndash Facade模式

17

LED的IO子系統介面與內容就是LED的驅動程式

隱藏子系統的細節是良好設計中十分重要的一環呼叫端的程式不會依賴子系統的細節

Main

加上按鈕

18

設定中斷

19

雖然為腳位設定中斷與設定輸入都是屬於初始化但這兩件事情通常會將實作分離只需要在使用中斷的程式碼中包含設定中斷的複雜度

三個中斷處理函式(有時會用巨集來做)

競賽情況(Race Condition)

在工作間共享記憶體十分危險必須十分小心

20

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 12: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

Adapter(或Wrapper)模式

12

Adapter是十分傳統的設計模式它將一個物件的介面轉換成另一個用戶(高階模組)較易使用的介面

通常adapter覆蓋在軟體API之上以蓋掉醜陋的介面

閃爍LED燈 ndash 最簡單的寫法

13

includeltioAT89C52hgt typedef unsigned char uint8 void delayms(uint8) void main(void) P1_bitP1_0 = 1 while(1) P1_bitP1_0 = 0 delayms(250) P1_bitP1_0 = 1 delayms(250)

includeltioAT89C52hgt define LED0 P1_bitP1_0 typedef unsigned char uint8 void delayms(uint8) void main(void) LED0 = 1 while(1) LED0 = 0 delayms(250) LED0 = 1 delayms(250)

閃爍LED燈 ndash 使用機板標頭檔

14

ioMappingh define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

閃爍LED燈 ndash 通用機板標頭檔

15

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

ioMappingh if COMPILING_BOARD_V1 include ioMapping_v1h elif COMPILING_BOARD_V2 include ioMapping_v2h else error No IO map selected for the board endif

ioMapping_v1h define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

ioMapping_v2h define LED_REGISTER P3 define LED_BIT (1 ltlt 4)

IO處理程式碼

16

閃爍LED燈 ndash Facade模式

17

LED的IO子系統介面與內容就是LED的驅動程式

隱藏子系統的細節是良好設計中十分重要的一環呼叫端的程式不會依賴子系統的細節

Main

加上按鈕

18

設定中斷

19

雖然為腳位設定中斷與設定輸入都是屬於初始化但這兩件事情通常會將實作分離只需要在使用中斷的程式碼中包含設定中斷的複雜度

三個中斷處理函式(有時會用巨集來做)

競賽情況(Race Condition)

在工作間共享記憶體十分危險必須十分小心

20

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 13: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

閃爍LED燈 ndash 最簡單的寫法

13

includeltioAT89C52hgt typedef unsigned char uint8 void delayms(uint8) void main(void) P1_bitP1_0 = 1 while(1) P1_bitP1_0 = 0 delayms(250) P1_bitP1_0 = 1 delayms(250)

includeltioAT89C52hgt define LED0 P1_bitP1_0 typedef unsigned char uint8 void delayms(uint8) void main(void) LED0 = 1 while(1) LED0 = 0 delayms(250) LED0 = 1 delayms(250)

閃爍LED燈 ndash 使用機板標頭檔

14

ioMappingh define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

閃爍LED燈 ndash 通用機板標頭檔

15

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

ioMappingh if COMPILING_BOARD_V1 include ioMapping_v1h elif COMPILING_BOARD_V2 include ioMapping_v2h else error No IO map selected for the board endif

ioMapping_v1h define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

ioMapping_v2h define LED_REGISTER P3 define LED_BIT (1 ltlt 4)

IO處理程式碼

16

閃爍LED燈 ndash Facade模式

17

LED的IO子系統介面與內容就是LED的驅動程式

隱藏子系統的細節是良好設計中十分重要的一環呼叫端的程式不會依賴子系統的細節

Main

加上按鈕

18

設定中斷

19

雖然為腳位設定中斷與設定輸入都是屬於初始化但這兩件事情通常會將實作分離只需要在使用中斷的程式碼中包含設定中斷的複雜度

三個中斷處理函式(有時會用巨集來做)

競賽情況(Race Condition)

在工作間共享記憶體十分危險必須十分小心

20

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 14: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

閃爍LED燈 ndash 使用機板標頭檔

14

ioMappingh define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

閃爍LED燈 ndash 通用機板標頭檔

15

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

ioMappingh if COMPILING_BOARD_V1 include ioMapping_v1h elif COMPILING_BOARD_V2 include ioMapping_v2h else error No IO map selected for the board endif

ioMapping_v1h define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

ioMapping_v2h define LED_REGISTER P3 define LED_BIT (1 ltlt 4)

IO處理程式碼

16

閃爍LED燈 ndash Facade模式

17

LED的IO子系統介面與內容就是LED的驅動程式

隱藏子系統的細節是良好設計中十分重要的一環呼叫端的程式不會依賴子系統的細節

Main

加上按鈕

18

設定中斷

19

雖然為腳位設定中斷與設定輸入都是屬於初始化但這兩件事情通常會將實作分離只需要在使用中斷的程式碼中包含設定中斷的複雜度

三個中斷處理函式(有時會用巨集來做)

競賽情況(Race Condition)

在工作間共享記憶體十分危險必須十分小心

20

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 15: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

閃爍LED燈 ndash 通用機板標頭檔

15

includeltioAT89C52hgt include ioMappingh typedef unsigned char uint8 void delayms(uint8) void main(void) LED_REGISTER |= LED_BIT while(1) LED_REGISTER amp= ~LED_BIT delayms(250) LED_REGISTER |= LED_BIT delayms(250)

ioMappingh if COMPILING_BOARD_V1 include ioMapping_v1h elif COMPILING_BOARD_V2 include ioMapping_v2h else error No IO map selected for the board endif

ioMapping_v1h define LED_REGISTER P0 define LED_BIT (1 ltlt 0)

ioMapping_v2h define LED_REGISTER P3 define LED_BIT (1 ltlt 4)

IO處理程式碼

16

閃爍LED燈 ndash Facade模式

17

LED的IO子系統介面與內容就是LED的驅動程式

隱藏子系統的細節是良好設計中十分重要的一環呼叫端的程式不會依賴子系統的細節

Main

加上按鈕

18

設定中斷

19

雖然為腳位設定中斷與設定輸入都是屬於初始化但這兩件事情通常會將實作分離只需要在使用中斷的程式碼中包含設定中斷的複雜度

三個中斷處理函式(有時會用巨集來做)

競賽情況(Race Condition)

在工作間共享記憶體十分危險必須十分小心

20

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 16: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

IO處理程式碼

16

閃爍LED燈 ndash Facade模式

17

LED的IO子系統介面與內容就是LED的驅動程式

隱藏子系統的細節是良好設計中十分重要的一環呼叫端的程式不會依賴子系統的細節

Main

加上按鈕

18

設定中斷

19

雖然為腳位設定中斷與設定輸入都是屬於初始化但這兩件事情通常會將實作分離只需要在使用中斷的程式碼中包含設定中斷的複雜度

三個中斷處理函式(有時會用巨集來做)

競賽情況(Race Condition)

在工作間共享記憶體十分危險必須十分小心

20

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 17: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

閃爍LED燈 ndash Facade模式

17

LED的IO子系統介面與內容就是LED的驅動程式

隱藏子系統的細節是良好設計中十分重要的一環呼叫端的程式不會依賴子系統的細節

Main

加上按鈕

18

設定中斷

19

雖然為腳位設定中斷與設定輸入都是屬於初始化但這兩件事情通常會將實作分離只需要在使用中斷的程式碼中包含設定中斷的複雜度

三個中斷處理函式(有時會用巨集來做)

競賽情況(Race Condition)

在工作間共享記憶體十分危險必須十分小心

20

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 18: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

加上按鈕

18

設定中斷

19

雖然為腳位設定中斷與設定輸入都是屬於初始化但這兩件事情通常會將實作分離只需要在使用中斷的程式碼中包含設定中斷的複雜度

三個中斷處理函式(有時會用巨集來做)

競賽情況(Race Condition)

在工作間共享記憶體十分危險必須十分小心

20

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 19: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

設定中斷

19

雖然為腳位設定中斷與設定輸入都是屬於初始化但這兩件事情通常會將實作分離只需要在使用中斷的程式碼中包含設定中斷的複雜度

三個中斷處理函式(有時會用巨集來做)

競賽情況(Race Condition)

在工作間共享記憶體十分危險必須十分小心

20

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 20: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

競賽情況(Race Condition)

在工作間共享記憶體十分危險必須十分小心

20

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 21: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

避免競賽情況 ndash 使用mutex

21

任何工作間共享的記憶體不論是讀取或寫入都要在程式中建立臨界區域(critical section)表示正在存取共享資源(記憶體或設備)必須保護共享資源同一時間只能讓一個工作修改稱為互斥(mutual exclusion)簡寫為mutex

對於包含OS的系統當兩個非中斷工作同時執行時能夠透過mutex表示兩個工作共享相同的資源只需要簡單地透過變數表示資源(或全域變數)可以供其他工作使用就行了

當其中之一是中斷時資源所有權的改變必須是單元動作(atomic)單元動作是指無法被系統其他部分中斷的動作

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 22: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

結構化你的程式碼 Source Tree

22

Source Tree

擺放原始碼檔案的目錄結構基本原則是一個目錄可以對應到系統架構中的一個方塊

還記得我們在學C語言時可以藉由撰寫Makefile來幫助我們同時編譯多個原始碼嗎

在開發系統時你必須告訴寫Makefile的工程師那些要編譯的檔案放在哪裡source tree結構規範就是在告訴工程師這件事

寫Makefile這件事情有點麻煩幸好我們有IDE開發環境可以使用我們只要將各種原始碼檔案分門別類放好再告訴IDE這些東西的Path在哪裡剩下的就交給它吧

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 23: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

常見目錄名稱的意思

23

bull Driver 驅動程式目錄 (有時也會用hal) Boot-Loader 開機程式 Hardware 各種硬體裝置的驅動程式 Include 驅動程式的header files API 將所有驅動程式包裝成API Boot Boot程式 LCD LCD程式 SDRAM SDRAM驅動程式

bull System 系統程式 Include 系統程式的header files API 將所有系統程式包裝成API Common 系統中的通用功能 RTOS 嵌入式OS的目錄 Include RTOS的header Memory 記憶體管理 Sync Task間同步機制 IPC Task間通訊機制 Glib 圖形函式庫 Sub-System各種子系統 GUI 圖形用戶介面 TCPIP TCPIP通訊堆疊 FileSystem 檔案系統

bull AP 應用程式 (或APP) Include 應用程式的header files Source 應用程式的原始碼 Common 應用程式的通用功能 AP1 應用程式1 AP2 應用程式2 Resource 應用程式的圖形字串資源

bull Third_Party_Lib 第三方函式庫 HandWriting 手寫辨識函式庫 Fonts 字型 VoiceComp 聲音壓縮函式庫

bull Include header sys_configh(系統配置檔)

bull Build 製作映像檔(執行檔)的東西 如makefile跟link script

bull Tools 開發中所需的程式例如compiler

bull Documents 開發規範datasheetuser guide Spec API手冊等

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 24: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

練習1 結構化你的程式碼

24

在D槽新建一個目錄結構

DMySimpSystem

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 25: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

在IAR中New一個Worksapce

25

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 26: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

環境設定

26

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 27: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

New一個應用程式File

27

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 28: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

建立Groups

28

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 29: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

完成以下的Groups

29

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 30: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

先把幾個Header File歸入Group

30

DMySimpSystemhaltargetJC51B

DMySimpSystemhalinclude

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 31: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

hal_typesh Filename hal_typesh Revised $Date 2013-10-18 1520 $ Revision $Revision $ Description Some useful typedef and definitions ifndef _HAL_TYPES_H define _HAL_TYPES_H Types typedef signed char int8 typedef unsigned char uint8 typedef signed short int16 typedef unsigned short uint16 typedef signed long int32 typedef unsigned long uint32 typedef unsigned char bool Standard Defines ifndef TRUE define TRUE 1 endif ifndef FALSE define FALSE 0 endif

ifndef NULL define NULL 0 endif ifndef HIGH define HIGH 1 endif ifndef LOW define LOW 0 endif Memory Attributes ----------- IAR Compiler ----------- ifdef __IAR_SYSTEMS_ICC__ define CODE __code define XDATA __xdata ----------- GNU Compiler ----------- elif defined __KEIL__ define CODE code define XDATA xdata ------- Unrecognized Compiler ------ else error ERROR Unknown compiler endif endif

31

DMySimpSystemhaltargetJC51B

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 32: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

hal_mcuh

32

Filename hal_mcuh Revised $Date 2013-10-18 $ Revision $Revision $ Description Describe the purpose and contents of the file ifndef _HAL_MCU_H define _HAL_MCU_H Target AT89C52 (8051 core) Includes include hal_defsh include hal_typesh Target Defines define HAL_MCU_AT89C52 Compiler Abstraction ---------------------- IAR Compiler ---------------------- ifdef __IAR_SYSTEMS_ICC__ include ltioAT89C52hgt define HAL_COMPILER_IAR define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ define _PRAGMA(x) _Pragma(x) define HAL_ISR_FUNC_DECLARATION(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNC_PROTOTYPE(fv) _PRAGMA(vector=v) __near_func __interrupt void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ---------------------- Keil Compiler ---------------------- elif defined __KEIL__ include ltreg51hgt

DMySimpSystemhaltargetJC51B

define HAL_COMPILER_KEIL define HAL_MCU_LITTLE_ENDIAN() 0 define HAL_ISR_FUNC_DECLARATION(fv) void f(void) interrupt v define HAL_ISR_FUNC_PROTOTYPE(fv) void f(void) define HAL_ISR_FUNCTION(fv) HAL_ISR_FUNC_PROTOTYPE(fv) HAL_ISR_FUNC_DECLARATION(fv) ------------ Unrecognized Compiler ---------- else error ERROR Unknown compiler endif

pragma vector = extern0 __interrupt void Int_Extern0(void)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 33: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

33

Interrupt Macros define HAL_ENABLE_INTERRUPTS() st( IE_bitEA = 1 ) define HAL_DISABLE_INTERRUPTS() st( IE_bitEA = 0 ) define HAL_INTERRUPTS_ARE_ENABLED() (IE_bitEA) typedef unsigned char halIntState_t define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bitEA HAL_DISABLE_INTERRUPTS() ) define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bitEA = x ) define HAL_CRITICAL_STATEMENT(x) st( halIntState_t _s HAL_ENTER_CRITICAL_SECTION(_s) x HAL_EXIT_CRITICAL_SECTION(_s) ) ifdef __IAR_SYSTEMS_ICC__ This workaround should only be used with 8051 using IAR compiler When IAR fixes the problem of XCH instruction with EA compile the following macros to null to disable them define HAL_ENTER_ISR() halIntState_t _isrIntState = EA HAL_ENABLE_INTERRUPTS() define HAL_EXIT_ISR() IE_bitEA = _isrIntState else define HAL_ENTER_ISR() define HAL_EXIT_ISR() endif __IAR_SYSTEMS_ICC__ endif

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 34: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

hal_boardh amp hal_board_cfgh

34

DMySimpSystemhalinclude

DMySimpSystemhaltargetJC51B

include hal_board_cfgh

Filename hal_board_cfgh Revised $Date 2013-10-18 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------------------------------------ Includes ------------------------------------------ include hal_mcuh include hal_defsh include hal_typesh endif

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 35: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

hal_defsh

35

Filename hal_defsh Revised $Date 2013-10-18 1448 $ Revision $Revision $ Description This file contains useful macros and data types ifndef HAL_DEFS_H define HAL_DEFS_H Macros ifndef BV define BV(n) (1 ltlt (n)) endif takes a byte out of a uint32 var - uint32 ByteNum - byte to take out (0 - 3) define BREAK_UINT32( var ByteNum ) (uint8)((uint32)(((var) gtgt((ByteNum) 8)) amp 0x00FF)) define BUILD_UINT32(Byte0 Byte1 Byte2 Byte3) ((uint32)((uint32)((Byte0) amp 0x00FF) + ((uint32)((Byte1) amp 0x00FF) ltlt 8) + ((uint32)((Byte2) amp 0x00FF) ltlt 16) + ((uint32)((Byte3) amp 0x00FF) ltlt 24))) define BUILD_UINT16(loByte hiByte) ((uint16)(((loByte) amp 0x00FF) + (((hiByte) amp 0x00FF) ltlt 8))) define HI_UINT16(a) (((a) gtgt 8) amp 0xFF) define LO_UINT16(a) ((a) amp 0xFF)

This macro is for use by other macros to form a fully valid C statement define st(x) do x while (__LINE__ == -1) endif

DMySimpSystemhalinclude

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 36: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

hal_driversh

36

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 37: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

練習2 加入LCD的驅動程式

includeltioAT89C52hgt define BTN1 P3_bitP3_2 define BTN2 P3_bitP3_3 define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 define LCD_SEL_CMD 0 define LCD_SEL_DATA 1 define LCD_IO_WRITE 0 define LCD_IO_READ 1 typedef unsigned char uint8

DMySimpSystemhalinclude

HD44780 Commands define LCD_CMD_CLS 0x01 Clear display (also DDRAM) define LCD_CMD_FNCT_1 0x30 8-bits 1 line define LCD_CMD_FNCT_2 0x38 8-bits 2 line define LCD_CMD_FNCT_3 0x20 4-bits 1 line define LCD_CMD_FNCT_4 0x28 4-bits 2 line define LCD_CMD_ENTRY_MODE 0x06 Entry mode define LCD_CMD_DON_COFF 0x0C LCD ON Cursor OFF Blink OFF define LCD_CMD_DON_CON 0x0E LCD ON Cursor ON Blink OFF define LCD_CMD_DON_CON_BLN 0x0F LCD ON Cursor ON Blink ON define LCD_CMD_SHIFT_LEFT 0x18 Shift entire display left define LCD_CMD_SHIFT_RIGHT 0x1C Shift entire display right define LCD_CMD_CMOVE_LEFT 0x10 Cursor move left by one char define LCD_CMD_CMOVE_RIGHT 0x14 Cursor move right by one char DDRAM and CGRAM Initial Address define LCD_DDRAM_ADDR0 0x80 define LCD_DDRAM_ADDR1 0xC0 define LCD_CGRAM_ADDR0 0x40

37

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 38: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

38

static void LCD_CursorSet(uint8 row uint8 col) void LCD_DataWr(uint8 data) void LCD_CmdWr(uint8 cmd) extern void LCD_Init(uint8 maxrows uint8 maxcols) extern void LCD_DispChar(uint8 row uint8 col char c) extern void LCD_DispStr(uint8 row uint8 col char s) extern void LCD_ClrLine(uint8 line) extern void LCD_ClrScr(void) extern void LCD_DefChar(uint8 id uint8 pat) extern void LCD_DispHorBarInit(void) extern void LCD_DispHorBar(uint8 row uint8 col uint8 val) void delayms(uint8 time)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 39: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

39

DMySimpSystemhaltargetJC51B

Filename hal_lcdc Revised $Date 2013-10-19 1621 $ Revision $Revision $ Description INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_lcdh CONSTANTS define LCD_CMD_FNCT LCD_CMD_FNCT_2 8-bits 2 line if (HAL_LCD == TRUE) LOCAL VARIABLES char StrL1[]=LCD 1602 Test char StrL2[]=Start LCD OK static uint8 LCD_MaxCols static uint8 LCD_MaxRows Patterns of horizontal bar static uint8 LCD_DispBar1[] = 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 static uint8 LCD_DispBar2[] = 0x18 0x18 0x18 0x18 0x18 0x18 0x18 0x18 static uint8 LCD_DispBar3[] = 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C 0x1C static uint8 LCD_DispBar4[] = 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E 0x1E static uint8 LCD_DispBar5[] = 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F

FUNCTIONS ndash API LOCAL FUNCTIONS static void LCD_BusyCheck(void) static void LCD_DataWr(uint8 data) static void LCD_CmdWr(uint8 cmd) static void LCD_CursorSet(uint8 row uint8 col) endif

if (HAL_LCD == TRUE) hellip endif

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 40: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

40

fn LCD_Init brief LCD initialization param maxrows max line number maxcols max word numbers return None void LCD_Init(uint8 maxrows uint8 maxcols) if (HAL_LCD == TRUE) LCD_MaxCols = maxcols LCD_MaxRows = maxrows delayms(30) LCD_EN = LOW LCD_RS = LOW LCD_RW = LOW LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) delayms(5) LCD_CmdWr(LCD_CMD_FNCT) LCD_CmdWr(LCD_CMD_DON_COFF) LCD_CmdWr(LCD_CMD_ENTRY_MODE) LCD_CmdWr(LCD_CMD_CLS) delayms(2) endif

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 41: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

41

void LCD_DispChar(uint8 row uint8 col char c) if (HAL_LCD == TRUE) 略 endif void LCD_DispStr(uint8 row uint8 col char s) if (HAL_LCD == TRUE) 略 endif void LCD_ClrLine(uint8 line) if (HAL_LCD == TRUE) 略 endif void LCD_ClrScr(void) if (HAL_LCD == TRUE) 略 endif

void LCD_DefChar(uint8 id uint8 pat) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBarInit(void) if (HAL_LCD == TRUE) 略 endif void LCD_DispHorBar(uint8 row uint8 col uint8 val) if (HAL_LCD == TRUE) 略 endif

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 42: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

42

LOCAL FUNCTIONS if (HAL_LCD == TRUE) fn LCD_BusyCheck brief Check if LCD is busy by Busy Flag (BF) param data the data to be written return None void LCD_BusyCheck(void) LCD_DATA_PORT = 0xFF LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_READ LCD_EN = HIGH while(LCD_BF == HIGH) LCD_EN = LOW static void LCD_DataWr(uint8 data) LCD_BusyCheck() LCD_RS = LCD_SEL_DATA LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = data LCD_EN = HIGH asm(nop) LCD_EN = LOW

static void LCD_CmdWr(uint8 cmd) LCD_BusyCheck() LCD_RS = LCD_SEL_CMD LCD_RW = LCD_IO_WRITE LCD_DATA_PORT = cmd LCD_EN = HIGH asm(nop) LCD_EN = LOW static void LCD_CursorSet(uint8 row uint8 col) 略 endif

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 43: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

將delayms()放到common driver

43

Filename hal_driversh Revised $Date 2013-10-18 1452 $ Revision $Revision $ Description This file contains the interface to the Drivers service ifndef HAL_DRIVER_H define HAL_DRIVER_H FUNCTIONS - API extern void delayms(uint8 time) Initialize HW extern void HalDriverInit (void) endif

DMySimpSystemhalinclude

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 44: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

44

DMySimpSystemhalcommon

Filename hal_driversc Revised $Date 20103-10-19 1700 $ Revision $Revision $ Description This file contains the common functions used by the driver INCLUDES include hal_typesh include hal_driversh include hal_lcdh FUNCTIONS ndash API fn delayms brief delay with ms param time = 0 ~ 255 the maximum delay is 255 ms return None void delayms(uint8 time) uint8 n while(timegt0) n = 162 while(ngt0) n-- time --

fn HalDriverInit brief Initialize HW param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 45: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

修改hal_board_cfgh

45

Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif endif

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 46: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

準備加入按鍵驅動程式

46

先修改一下hal_board_cfgh的內容 Filename hal_board_cfgh Revised $Date 2013-10-19 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------------- Includes ------------ include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh ---- Push Button Configuration ---- define ACTIVE_LOW double negation forces result to be 1 define ACTIVE_HIGH BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW

BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 47: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

47

----- Macros ------ ---- Debounce ---- define HAL_DEBOUNCE(expr) int i for (i=0 ilt500 i++) if ((expr)) i = 0 ---- Push Buttons ---- define HAL_PUSH_BUTTON1() (PUSH1_POLARITY (PUSH1_SBIT)) define HAL_PUSH_BUTTON2() (PUSH2_POLARITY (PUSH2_SBIT)) define HAL_PUSH_BUTTON3() (PUSH3_POLARITY (PUSH3_SBIT)) define HAL_PUSH_BUTTON4() (PUSH4_POLARITY (PUSH4_SBIT)) -------- Driver Configuration -------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif endif

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 48: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

加入按鍵的驅動程式

48

Filename hal_keyh Revised $Date 2013-10-19 1751 $ Revision $Revision $ Description This file contains the interface to the KEY Service ifndef HAL_KEY_H define HAL_KEY_H INCLUDES include hal_boardh CONSTANTS Interrupt option - Enable or disable define HAL_KEY_INTERRUPT_DISABLE 0x00 define HAL_KEY_INTERRUPT_ENABLE 0x01 Switches (keys) define HAL_KEY_SW_1 0x01 Button 1 (INT0) define HAL_KEY_SW_2 0x02 Button 2 (INT1) define HAL_KEY_SW_3 0x04 Button 3 (T0) define HAL_KEY_SW_4 0x08 Button 4 (T1) GLOBAL VARIABLES extern bool Hal_KeyIntEnable

FUNCTIONS ndash API Initialize the Key Service extern void HalKeyInit(void) Configure the Key Service extern void HalKeyConfig(bool interruptEnable) Read the Key status extern uint8 HalKeyRead(void) endif

DMySimpSystemhalinclude

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 49: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

49

Filename hal_keyc Revised $Date 2013-10-19 2227 $ Revision $Revision $ Description HAL KEY Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_boardh include hal_driversh include hal_keyh if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) CONSTANTS define HAL_KEY_NO_EDGE 0 define HAL_KEY_FALLING_EDGE 1 define HAL_KEY_DEBOUNCE_VALUE 25 CPU port interrupt edge control and flag define HAL_KEY_CPU_TCON TCON CPU port interrupt enabledisable define HAL_KEY_CPU_IE IE

DMySimpSystemhaltargetJC51B

Key 1 SW_1 is at P32 define HAL_KEY_SW_1_PORT PUSH1_SBIT edge interrupt define HAL_KEY_SW_1_EDGEBIT BV(0) TCON =gt Bit0 define HAL_KEY_SW_1_EDGE HAL_KEY_FALLING_EDGE SW_1 interrupts INT0 IE bit and flag define HAL_KEY_SW_1_IEBIT BV(0) define HAL_KEY_SW_1_IFG TCON_bitIE0 Key 2 SW_2 is at P33 define HAL_KEY_SW_2_PORT PUSH2_SBIT edge interrupt define HAL_KEY_SW_2_EDGEBIT BV(2) TCON =gt Bit2 define HAL_KEY_SW_2_EDGE HAL_KEY_FALLING_EDGE SW_2 interrupts INT1 IE bit and flag define HAL_KEY_SW_2_IEBIT BV(2) define HAL_KEY_SW_2_IFG TCON_bitIE1 Key 3 SW_3 is at P34 Key3 has no interrupt define HAL_KEY_SW_3_PORT PUSH3_SBIT Key 4 SW_4 is at P35 Key4 has no interrupt define HAL_KEY_SW_4_PORT PUSH4_SBIT

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 50: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

GLOBAL VARIABLES static uint8 HalKeyConfigured interrupt enabledisable flag bool Hal_KeyIntEnable FUNCTIONS ndash API fn HalKeyInit brief Initialize Key Service param none return None void HalKeyInit( void ) HAL_KEY_SW_1_PORT = 1 make it as an input HAL_KEY_SW_2_PORT = 1 make it as an input HAL_KEY_SW_3_PORT = 1 make it as an input HAL_KEY_SW_4_PORT = 1 make it as an input Start with key is not configured HalKeyConfigured = FALSE void HalKeyConfig (bool interruptEnable) EnableDisable Interrupt Hal_KeyIntEnable = interruptEnable Hal_KeyIntEnable is a global var

Determine if interrupt is enable or not Interrupt is only for Key1 and Key2 if (Hal_KeyIntEnable) Key 1 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_1_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_1_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_1_IEBIT HAL_KEY_SW_1_IFG = 0 Key 2 RisingFalling edge configuration HAL_KEY_CPU_TCON amp= ~(HAL_KEY_SW_2_EDGEBIT) For falling edge the bit must be set if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE) HAL_KEY_CPU_TCON |= HAL_KEY_SW_2_EDGEBIT endif Interrupt configuration HAL_KEY_CPU_IE |= HAL_KEY_SW_2_IEBIT HAL_KEY_SW_2_IFG = 0 Key 3 Key3 has no interrupt Key 4 Key4 has no interrupt

50

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 51: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

else Interrupts NOT enabled HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_1_IEBIT) HAL_KEY_SW_1_IFG = 0 HAL_KEY_CPU_IE amp= ~(HAL_KEY_SW_2_IEBIT) HAL_KEY_SW_2_IFG = 0 Key now is configured HalKeyConfigured = TRUE fn HalKeyRead brief Read the current value of a key param None return keys - current keys status uint8 HalKeyRead ( void ) uint8 keys = 0 if (HAL_PUSH_BUTTON1()) HAL_DEBOUNCE(HAL_PUSH_BUTTON1()) keys |= HAL_KEY_SW_1 if (HAL_PUSH_BUTTON2()) HAL_DEBOUNCE(HAL_PUSH_BUTTON2()) keys |= HAL_KEY_SW_2

if (HAL_PUSH_BUTTON3()) HAL_DEBOUNCE(HAL_PUSH_BUTTON3()) keys |= HAL_KEY_SW_3 INTERRUPT SERVICE ROUTINE fn halKeySW1Isr brief SW1 ISR param return HAL_ISR_FUNCTION( halKeySW1Isr extern0 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_1_IFG = 0 HAL_EXIT_ISR() fn halKeySW2Isr brief SW2 ISR param return HAL_ISR_FUNCTION( halKeySW2Isr extern1 ) HAL_ENTER_ISR() Clear the CPU interrupt flag HAL_KEY_SW_2_IFG = 0 HAL_EXIT_ISR()

51

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 52: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

52

else void HalKeyInit(void) void HalKeyConfig(bool interruptEnable) uint8 HalKeyRead(void) return 0 endif HAL_KEY

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 53: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

加入Library Path

53

現在你已經準備好幾樣東西讓我們再複習一下

hal_mcuh hal_typesh hal_board_cfgh hal_defsh hal_driversh hal_boardh hal_lcdh hal_keyh hal_drviersc hal_lcdc hal_keyc

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 54: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

在進行RTC實驗之前

54

我們現在有按鍵跟LCD驅動程式何不寫一個應用程式完成如exercise4-03c的進度條顯示程式

DMySimpSystemProjectsMyAPP1Source

include hal_typesh include hal_driversh include hal_board_cfgh

include MyAPP1h void main() uint8 i percent_bar char num[4] char str1 = Dynamic Show HalDriverInit() LCD_DispHorBarInit() LCD_DispStr(0 0 str1) while(1) if (HalKeyRead()==HAL_KEY_SW_1) LCD_ClrLine(0) LCD_ClrLine(1)

for(i=0ilt101i++) num[0] = (i100)+0x30 num[1] = ((i10)10)+0x30 num[2] = (i10)+0x30 num[3] = 0x25 if(num[0]==0x30) LCD_DispChar(0 0 ) if(num[1]==0x30) LCD_DispChar(0 1 ) else LCD_DispChar(0 1 num[1])

else LCD_DispChar(0 0 num[0]) LCD_DispChar(0 1 num[1]) LCD_DispChar(0 2 num[2]) LCD_DispChar(0 3 num[3]) percent_bar = (i100125) LCD_DispHorBar(1 0 percent_bar) delayms(200)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 55: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

顯現電路板設定組態檔的威力

將driver與硬體IO相關的設定移到hal_borad_cfgh

define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0

Filename hal_board_cfgh ifndef HAL_BOARD_CFG_H 略 BTN1 define PUSH1_BV BV(2) define PUSH1_SBIT P3_bitP3_2 INT0 define PUSH1_POLARITY ACTIVE_LOW BTN2 define PUSH2_BV BV(3) define PUSH2_SBIT P3_bitP3_3 INT1 define PUSH2_POLARITY ACTIVE_LOW BTN3 define PUSH3_BV BV(4) define PUSH3_SBIT P3_bitP3_4 T0 define PUSH3_POLARITY ACTIVE_LOW BTN4 define PUSH4_BV BV(5) define PUSH4_SBIT P3_bitP3_5 T1 define PUSH4_POLARITY ACTIVE_LOW -- LCD IO Configuration -- define LCD_RW P1_bitP1_1 define LCD_EN P3_bitP3_4 define LCD_RS P3_bitP3_5 define LCD_BF P0_bitP0_7 define LCD_DATA_PORT P0 55

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 56: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

練習3 撰寫API手冊 (以LCD Driver為例)

56

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 57: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

57

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 58: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

58

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 59: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

59

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 60: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

60

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 61: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

61

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 62: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

為RTC準備什麼

62

3-wire通訊介面的驅動程式

DS1302的驅動程式

寫完後將他們一一加入project的group

修改hal_board_cfgh

寫出RTC的應用程式

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 63: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

練習4 加入3-wire通訊介面Driver

63

Filename hal_triwireh Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the interface to the 3-Wire Service ifndef HAL_TRIWIRE_H define HAL_TRIWIRE_H INCLUDES include hal_boardh CONSTANTS 3-Wire delay define TriWireDELAY 10 FUNCTIONS ndash API 3-wire interface write a byte to the bus extern void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus extern uint8 TriWire_ReadByte(void) 3-wire interface write data to the device register extern void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) 3-wire interface read data from the device register extern uint8 TriWire_Read(uint8 Reg_Addr) endif

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 64: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

加入3-wire的driver hal_triwirec

64

Filename hal_triwirec Revised $Date 2013-10-18 2107 $ Revision $Revision $ Description This file contains the interface to the 3-wire driver INCLUDES include hal_board_cfgh include hal_defsh include hal_typeshldquo include hal_driversh include hal_triwireh LOCAL FUNCTIONS 3-wire interface write a byte to the bus void TriWire_WriteByte(uint8 output_data) 3-wire interface read a byte from the bus uint8 TriWire_ReadByte(void)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 65: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

fn TriWire_WriteByte brief Write 1-byte data to the bus param output_data The data byte to write on the bus return None void TriWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) TriWire_SCLK = LOW if(output_data amp 0x01) Check LSB bit LSB goes first TriWire_IO = HIGH else TriWire_IO = LOW delay_time(TriWireDELAY) TriWire_SCLK = HIGH Write at this transition delay_time(TriWireDELAY) output_data = output_data gtgt 1

fn TriWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 TriWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) input_data = input_data gtgt 1 TriWire_SCLK = LOW Read at this transition delay_time(TriWireDELAY) if(TriWire_IO) Check LSB bit LSB comes first input_data |= 0x80 else input_data |= 0x00 TriWire_SCLK = HIGH delay_time(TriWireDELAY) return(input_data)

65

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 66: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

66

fn TriWire_Write brief Write data to the register on a 3-wire device param Reg_Addr Register address Reg_Data Data to write-to return None void TriWire_Write(uint8 Reg_Addr uint8 Reg_Data) TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr) TriWire_WriteByte(Reg_Data) TriWire_SCLK = HIGH TriWire_RST = LOW

fn TriWire_Read brief Read data from the register on a 3-wire device param Reg_Addr Register address return Data The read-in data byteReg_Addr uint8 TriWire_Read(uint8 Reg_Addr) uint8 Data TriWire_RST = LOW TriWire_SCLK = LOW TriWire_RST = HIGH delay_time(TriWireDELAY) TriWire_WriteByte(Reg_Addr|0x01) Command - Read Data = TriWire_ReadByte() TriWire_SCLK = HIGH TriWire_RST = LOW return(Data)

if (HAL_TRIWIRE == TRUE) hellip endif

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 67: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

Add file與修改hal_board_cfgh

67

---------------------------------------------- 3-Wire Port Configuration ---------------------------------------------- define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 68: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

測試驅動程式 (I)

68

寫一個應用程式測試3-wire的驅動程式 include MyAPP1h void main() uint8 read_keys HalDriverInit() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break case HAL_KEY_SW_2 TriWire_ReadByte() break case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break case HAL_KEY_SW_4 TriWire_Read(0x37) break

--------------------------------- Driver Configuration --------------------------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD FALSE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 69: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

測試驅動程式 (II)

69

case HAL_KEY_SW_1 TriWire_WriteByte(0x35) break

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 70: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

測試驅動程式 (III)

70

case HAL_KEY_SW_2 TriWire_ReadByte() break

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 71: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

測試驅動程式 (IV)

71

case HAL_KEY_SW_3 TriWire_Write(0xA2 0xB4) break

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 72: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

測試驅動程式 (V)

72

case HAL_KEY_SW_4 TriWire_Read(0x37) break

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 73: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

加入DS1302 RTC驅動程式 Filename hal_ds1302h Revised $Date 2013-10-18 $ Revision $Revision $ Description This file contains the driver of DS1302 RTC ifndef HAL_DS1302_H define HAL_DS1302_H INCLUDES include hal_boardh CONSTANTS DS1302 Register Address define DS1302_SECOND 0x80 define DS1302_MINUTE 0x82 define DS1302_HOUR 0x84 define DS1302_DATE 0x86 define DS1302_MONTH 0x88 define DS1302_WEEKDAY 0x8A define DS1302_YEAR 0x8C define DS1302_WP 0x8E define DS1302_TCS 0x90 DS1302 Register Mask define REG_MASK_SECOND 0x70 define REG_MASK_MINUTE 0x30 define REG_MASK_HOUR 0x30 define REG_MASK_DATE 0x30 define REG_MASK_MONTH 0x10 define REG_MASK_WEEKDAY 0x00 define REG_MASK_YEAR 0xF0 define REG_MASK_HOUR_MODE 0xA0 define REG_MASK_CH 0x80

DS1302 Write Protection define DS1302_WR_ON 0x00 define DS1302_WR_OFF 0x80 define DS1302_START 0x7F TYPEDEFS typedef struct __SYSTEMTIME__ uint8 Second uint8 Minute uint8 Hour uint8 Hourmode uint8 Date uint8 Weekday uint8 Month uint8 Year uint8 DateString[11] uint8 WeekdayString[4] uint8 TimeString[9] SYSTEMTIME FUNCTIONS ndash API extern void DS1302_Init(void) extern void DS1302_ReadTime(SYSTEMTIME Time) extern void DS1302_WriteTime(SYSTEMTIME Time) endif

73

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 74: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

74

Filename hal_ds1302c Revised $Date 2013-10-18 2136 $ Revision $Revision $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_triwireh include hal_ds1302h LOCAL FUNCTIONS uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 FormatDec2Reg(uint8 dec_data) void DateToStr(SYSTEMTIME Time) void TimeToStr(SYSTEMTIME Time) fn DS1302_Init brief Initialize DS1302 param None return None void DS1302_Init(void) delayms(2) uint8 Clock_halt = TriWire_Read(DS1302_SECOND+1) amp REG_MASK_CH if(Clock_halt) TriWire_Write(DS1302_WP DS1302_WR_ON) Allow write Write initial date and time 20131112 TUE 235955 TriWire_Write(DS1302_YEAR 0x13) TriWire_Write(DS1302_MONTH 0x11) month 07

TriWire_Write(DS1302_DATE 0x12) date 25 TriWire_Write(DS1302_WEEKDAY 0x02) weekday TriWire_Write(DS1302_HOUR 0x23) 23 (HR) TriWire_Write(DS1302_MINUTE 0x59) 59 (Min) TriWire_Write(DS1302_SECOND 0x55) 55 (Sec) TriWire_Write(DS1302_WP DS1302_WR_OFF) Write prohibited

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 75: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

fn DS1302_ReadTime brief Read current time from DS1302 the read values are stored in a SYSTIME struct variable param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_ReadTime(SYSTEMTIME Time) uint8 ReadValue ReadValue = TriWire_Read(DS1302_SECOND+1) When read use (defined address+1) Time-gtSecond = FormatReg2Dec(ReadValue REG_MASK_SECOND) ReadValue = TriWire_Read(DS1302_MINUTE+1) Time-gtMinute = FormatReg2Dec(ReadValue REG_MASK_MINUTE) ReadValue = TriWire_Read(DS1302_HOUR+1) Time-gtHour = FormatReg2Dec(ReadValue REG_MASK_HOUR) Time-gtHourmode = ReadValue amp REG_MASK_HOUR_MODE ReadValue = TriWire_Read(DS1302_DATE+1) Time-gtDate = FormatReg2Dec(ReadValue REG_MASK_DATE) ReadValue = TriWire_Read(DS1302_MONTH+1) Time-gtMonth = FormatReg2Dec(ReadValue REG_MASK_MONTH) ReadValue = TriWire_Read(DS1302_WEEKDAY+1) Time-gtWeekday = FormatReg2Dec(ReadValue REG_MASK_WEEKDAY) ReadValue = TriWire_Read(DS1302_YEAR+1) Time-gtYear = FormatReg2Dec(ReadValue REG_MASK_YEAR) DateToStr(Time) TimeToStr(Time)

75

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 76: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

76

fn DS1302_WriteTime brief Write time to DS1302 param SYSTEMTIME Time Pointer to the SYSTEMTIME struct variable return None void DS1302_WriteTime(SYSTEMTIME Time) TriWire_Write(DS1302_WP DS1302_WR_ON) TriWire_Write(DS1302_YEAR FormatDec2Reg(Time-gtYear) ) TriWire_Write(DS1302_MONTH FormatDec2Reg(Time-gtMonth) ) TriWire_Write(DS1302_DATE FormatDec2Reg(Time-gtDate) ) TriWire_Write(DS1302_WEEKDAY FormatDec2Reg(Time-gtWeekday)) TriWire_Write(DS1302_HOUR FormatDec2Reg(Time-gtHour) ) TriWire_Write(DS1302_MINUTE FormatDec2Reg(Time-gtMinute) ) TriWire_Write(DS1302_SECOND FormatDec2Reg(Time-gtSecond) ) DateToStr(Time) TimeToStr(Time) TriWire_Write(DS1302_WP DS1302_WR_OFF) LOCAL FUNCTIONS fn FormatReg2Dec brief Convert the register data into decimal param reg_data the stored data in DS1302 reg_mask mask of that value return DecValue The converted decimal value uint8 FormatReg2Dec(uint8 reg_data uint8 reg_mask) uint8 DecValue DecValue = ((reg_data amp reg_mask) gtgt 4)10 + (reg_data amp 0x0F) return(DecValue)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 77: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

fn FormatDec2Reg brief Convert the decimal value in to register data format param dec_data the decimal value to store return RegValue the formatted register data uint8 FormatDec2Reg(uint8 dec_data) uint8 RegValue RegValue = (dec_data10)16 + dec_data10 return(RegValue)

fn DateToStr brief Convert Date (year month date weekday) into string param Time Pointer to the struct of current time return None void DateToStr(SYSTEMTIME Time) uint8 WeekdayTable[7] = Mon Tue Wen Thu Fri Sat Sun Time-gtDateString[0] = 2 Time-gtDateString[1] = 0 Time-gtDateString[2] = Time-gtYear10 + 0x30 0 ASCII = 0x30 Time-gtDateString[3] = Time-gtYear10 + 0x30 Time-gtDateString[4]=- Time-gtDateString[5] = Time-gtMonth10 + 0x30 Time-gtDateString[6] = Time-gtMonth10 + 0x30 Time-gtDateString[7]=- Time-gtDateString[8] = Time-gtDate10 + 0x30 Time-gtDateString[9] = Time-gtDate10 + 0x30 Time-gtDateString[10] = 0 Time-gtWeekdayString[0] = (WeekdayTable[(Time-gtWeekday10)-1] + 0) Time-gtWeekdayString[1] = (WeekdayTable[(Time-gtWeekday10)-1] + 1) Time-gtWeekdayString[2] = (WeekdayTable[(Time-gtWeekday10)-1] + 2) Time-gtWeekdayString[3] = 0 77

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 78: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

78

fn TimeToStr brief Convert Time (hour minute second) into string param Time Pointer to the struct of current time return None void TimeToStr(SYSTEMTIME Time) Time-gtTimeString[0] = Time-gtHour10 + 0x30 0 ASCII = 0x30 Time-gtTimeString[1] = Time-gtHour10 + 0x30 Time-gtTimeString[2] = Time-gtTimeString[3] = Time-gtMinute10 + 0x30 Time-gtTimeString[4] = Time-gtMinute10 + 0x30 Time-gtTimeString[6] = Time-gtSecond10 + 0x30 Time-gtTimeString[7] = Time-gtSecond10 + 0x30 Time-gtTimeString[8] = 0

if (HAL_DS1302 == TRUE) hellip endif

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 79: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

修改hal_board_cfgh

79

Filename hal_board_cfgh Revised $Date 2013-11-2 $ Revision $Revision $ Description Declarations for the JC51B Development Board ifndef HAL_BOARD_CFG_H define HAL_BOARD_CFG_H ------- Includes --------- include hal_mcuh include hal_defsh include hal_typesh include hal_lcdh include hal_keyh include hal_triwireh include hal_ds1302h 略 ------ 3-Wire Port Configuration ------ define TriWire_SCLK P1_bitP1_4 define TriWire_IO P1_bitP1_2 define TriWire_RST P1_bitP1_3

--------- Driver Configuration -------------- Set to TRUE enable LCD usage FALSE disable it ifndef HAL_LCD define HAL_LCD TRUE endif Set to TRUE enable KEY usage FALSE disable it ifndef HAL_KEY define HAL_KEY TRUE endif Set to TRUE enable 3-wire usage FALSE disable it ifndef HAL_TRIWIRE define HAL_TRIWIRE TRUE endif

Set to TRUE enable DS1302 RTC usage FALSE disable it ifndef HAL_DS1302 define HAL_DS1302 TRUE endif

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 80: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

修改hal_driversc的HalDriverInit()

80

fn Hal_DriverInit brief Initialize HW - These need to be initialized before anyone param None return None void HalDriverInit (void) if (defined HAL_LCD) ampamp (HAL_LCD == TRUE) LCD_Init(2 16) endif if (defined HAL_KEY) ampamp (HAL_KEY == TRUE) HalKeyInit() HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE) endif if (defined HAL_DS1302) ampamp (HAL_DS1302 == TRUE) DS1302_Init() endif

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 81: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

練習5 寫一支電子時鐘應用程式

81

include MyAPP1h SYSTEMTIME currentTime SYSTEMTIME currentTime = Second = 30 Minute = 50 Hour = 22 Hourmode = 0 Date = 2 Weekday = 6 Month = 11 Year = 13 void main() HalDriverInit() DS1302_WriteTime(ampcurrentTime) while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 82: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

Lab12 DS18B20溫度感測器

82

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 83: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

DS18B20溫度感測器

83

DS18B20是一個數位溫度感測器它可以提供9~12位元的攝氏溫度輸出而且可以設定超溫警告閥值它使用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊

電壓範圍30~55V

溫度範圍-55oC~+125oC-10~+85oC時精度為plusmn05oC

解析度為9~12位元對應的可分辨溫度量為 05oC025oC0125oC和 00625oC在9位元解析度時最多在9375ms內能把溫度轉換為數位值在12位元解析度時最多在750ms內把溫度值轉換為數位值

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 84: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

DS18B20架構說明

84

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 85: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

DS18B20的記憶體配置

85

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 86: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

與DS18B20進行通訊

86

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 87: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

DS1820B的指令集

87

指令 指令碼 說 明

搜尋ROM 0xF0 確定掛在同一bus上 DS1820 的個數和識別 64 位元ROM地址為操作各裝置作好準備

讀ROM 0x33 讀取DS1820 ROM中的64位元ROM位址

匹配ROM 0x55 發出此命令後接著發出 64 位元ROM位址使對應的DS1820作出回應為下一步對該其讀寫作準備

跳過ROM 0xCC 忽略 64 位 ROM 地址直接向 DS1820 下達溫度變換命令

警告搜索 0xEC 執行後只有溫度超過設定值上限或下限的晶片才做出回應

指令 指令碼 說 明

溫度轉換 0x44 執行溫度轉換結果將存入內部9位元組RAM中

寫入暫存器 0x4E 向RAM的2 3 4位元組寫上下限溫度資料組態該命令之後緊接3位元組的資料

讀取暫存器 0xBE 讀取內部RAM中9位元組的內容

複製暫存器 0x48 將RAM中第3 4位元組的內容複製到EEPROM中

Recall EEPROM 0xB8 將EEPROM中的內容還原到RAM中的第3 4位元組

讀取供電方式 0xB4 寄生供電時DS1820發回 0外接電源發回 1

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 88: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

ReadWrite時序圖

88

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 89: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

使用注意事項

89

DS1820與MCU使用串列通訊因此對DS1820進行讀寫時必須嚴格

保證讀寫時序否則將無法讀取測溫結果

實際應用中1-Wire bus上所掛DS1820數量並非任意多個當數量超

過8個時就需要解決MCU的匯流排驅動問題

連接DS1820的匯流排電纜有長度限制經驗中使用一般電線長度

超過50m時讀取的測溫資料將發生錯誤使用雙絞線帶遮罩電

纜時正常通訊距離可達150m

DS1820測溫程式中向DS1820發出溫度轉換命令後程式總要等

待DS1820的返回訊號一旦某個DS1820接觸不好或斷線當程式

讀該DS1820時將沒有返回訊號程式進入閉迴路這一點在進

行DS1820硬體連接和軟體設計時也要給予一定的重視 測溫電纜

線建議採用遮罩4芯雙絞線其中一對線接地線與訊號線另一組

接VCC和地線遮罩層在源端單點接地

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 90: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

Filename hal_onewirec Revised $Date 2013-11-5 2107 $ INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_onewireh CONSTANTS 1-Wire delay define OneWireDELAY_Write 6 define OneWireDELAY_Read 4 fn OneWire_WriteByte brief Write 1-byte data to the bus void OneWire_WriteByte(uint8 output_data) uint8 index for(index = 0 index lt 8 index++) OneWire_DQ = LOW OneWire_DQ = output_data amp 0x01 5us delay_time(OneWireDELAY_Write) 76us OneWire_DQ = HIGH output_data = output_data gtgt 1

1-Wire通訊介面驅動程式

90

Filename hal_onewireh Revised $Date 2013-11-6 $ Revision $Revision $ Description This file contains the interface to the 1-Wire service ifndef HAL_ONEWIRE_H define HAL_ONEWIRE_H INCLUDES include hal_boardhldquo FUNCTIONS - API 1-wire interface write a byte to the bus extern void OneWire_WriteByte(uint8 output_data) 1-wire interface read a byte from the bus extern uint8 OneWire_ReadByte(void) 1-wire interface Reset devices on the bus extern void OneWire_BusReset(void) endif

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 91: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

91

fn OneWire_ReadByte brief Read 1-byte data from the bus param None return The read-in data byte uint8 OneWire_ReadByte(void) uint8 index uint8 input_data = 0x00 for(index = 0 index lt 8 index++) OneWire_DQ = LOW input_data = input_data gtgt 1 takes 5us OneWire_DQ = HIGH asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) asm(nop) if(OneWire_DQ) input_data |= 0x80 delay_time(OneWireDELAY_Read) return(input_data)

fn OneWire_BusReset brief Reset all devices on the bus param None return None void OneWire_BusReset(void) OneWire_DQ = LOW delay_time(100) OneWire_DQ = HIGH

if (HAL_ONEWIRE == TRUE) hellip endif

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 92: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

DS18B20溫度感測器驅動程式 Filename hal_ds18b20h Revised $Date 2013-11-05 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor ifndef HAL_DS18B20_H define HAL_DS18B20_H INCLUDES include hal_boardhldquo CONSTANTS DS18B20 ROM CMDs define DS18B20_CMD_SEARCH_ROM 0xF0 define DS18B20_CMD_READ_ROM 0x33 define DS18B20_CMD_MATCH_ROM 0x55 define DS18B20_CMD_SKIP_ROM 0xCC define DS18B20_CMD_ALARM_SEARCH 0xEC DS18B20 RAM CMDs define DS18B20_CMD_CONVERT_TEMP 0x44 define DS18B20_CMD_READ_SCRATCH 0xBE define DS18B20_CMD_WRITE_SCRATCH 0x4E define DS18B20_CMD_COPY_SCRATCH 0x48 define DS18B20_CMD_RECALL_EPROM 0xB8 define DS18B20_CMD_READ_PSUPPLY 0xB4

DS18B20 Resolution define DS18B20_RES_9BITS 0x1F define DS18B20_RES_10BITS 0x3F define DS18B20_RES_11BITS 0x5F define DS18B20_RES_12BITS 0x7F define DS18B20_CONV_TIME 752 TYPEDEFS typedef struct __TEMPCONFIG__ 2s complement +85C = 0101 0101 = 0x55 uint8 Alarm_TH 2s complement -10C = 1111 0110 = 0xF6 uint8 Alarm_TL uint8 Resolution TEMPCONFIG typedef struct __SENSEDTEMP__ bool Temp_Sign uint8 Temp_Integer uint8 Temp_Decimal uint8 Resolution char TempString[8] SENSEDTEMP FUNCTIONS - API extern void DS18B20_Init(void) extern void DS18B20_ReadTemp(SENSEDTEMP ttemp) extern void DS18B20_Config(TEMPCONFIG tconfig) endif

92

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 93: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

93

Filename hal_ds18b20c Revised $Date 2013-11-05 2136 $ Revision $Revision $ Description This file contains the interface to the ds18b20 temperature sensor INCLUDES include hal_board_cfgh include hal_defsh include hal_typesh include hal_driversh include hal_ds18b20h include hal_onewireh LOCAL FUNCTIONS void DS18B20_Wait_Conv(uint8 Resolution) fn DS18B20_Init brief Initialize the DS18B20 on the bus param None return None void DS18B20_Init(void) OneWire_DQ = HIGH delay_time(1) OneWire_BusReset() Master Send Reset delay_time(50)

fn DS18B20_Config brief DS18B20 configuration with temperature alarm and resolution settings param tconfig pointer to the TEMPCONFIG struct return None void DS18B20_Config(TEMPCONFIG tconfig) OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(tconfig-gtAlarm_TH) OneWire_WriteByte(tconfig-gtAlarm_TL) OneWire_WriteByte(tconfig-gtResolution) OneWire_ReadByte() OneWire_ReadByte()

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 94: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

fn DS18B20_ReadTemp brief Read temperature from DS18B20 param ttemp pointer to SENSEDTEMP struct return None void DS18B20_ReadTemp(SENSEDTEMP ttemp) uint8 temp_low_byte = 0 uint8 temp_high_byte = 0 uint8 temp_sign = 0 send command 1Initialize 2ROM CMD 3RAM CMD DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP) DS18B20_Wait_Conv(ttemp-gtResolution) DS18B20_Init() OneWire_WriteByte(DS18B20_CMD_SKIP_ROM) OneWire_WriteByte(DS18B20_CMD_READ_SCRATCH) temp_low_byte = OneWire_ReadByte() temp low byte temp_high_byte = OneWire_ReadByte() temp high byte temp_sign = temp_high_byte amp 0xF8 if(temp_sign) ttemp-gtTemp_Sign = 1 negative ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Integer = ~(ttemp-gtTemp_Integer) + 1 ttemp-gtTemp_Decimal = LO_UINT8(~(temp_low_byte amp 0x0F)) else ttemp-gtTemp_Sign = 0 positive ttemp-gtTemp_Integer = ((LO_UINT8(temp_high_byte) ltlt 4) | HI_UINT8(temp_low_byte)) ttemp-gtTemp_Decimal = LO_UINT8(temp_low_byte amp 0x0F)

94

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 95: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

95

String construction if(temp_sign) ttemp-gtTempString[0] = - else ttemp-gtTempString[0] = if((ttemp-gtTemp_Integer)100) hundreds digit ttemp-gtTempString[1] = ((ttemp-gtTemp_Integer)100) + 0 else if(temp_sign) ttemp-gtTempString[0] = ttemp-gtTempString[1] = - else ttemp-gtTempString[1] = if(((ttemp-gtTemp_Integer)100)10) tens digit ttemp-gtTempString[2] = (((ttemp-gtTemp_Integer)100)10) + 0 else if(temp_sign) ttemp-gtTempString[1] = ttemp-gtTempString[2] = - else ttemp-gtTempString[2] = ttemp-gtTempString[3] = ((ttemp-gtTemp_Integer)10) + 0 ttemp-gtTempString[4] = ttemp-gtTempString[5] = (ttemp-gtTemp_Decimal6251000) + 0 ttemp-gtTempString[6] = C ttemp-gtTempString[7] = 0

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 96: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

96

fn DS18B20_Wait_Conv brief Waiting for temperature conversion param Resolution The DS18B20 resolution return None void DS18B20_Wait_Conv(uint8 Resolution) switch(Resolution) case DS18B20_RES_9BITS delayms(DS18B20_CONV_TIME8) break case DS18B20_RES_10BITS delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_11BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break case DS18B20_RES_12BITS delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) delayms(DS18B20_CONV_TIME4) break default break

if (HAL_DS18B20 == TRUE) hellip endif

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 97: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

1-Wire amp DS18B20 驅動程式測試

97

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 98: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

實習12

98

現在請綜合驅動程式寫一個應用程式讓LCD不只顯示出時間也可顯示目前溫度

步驟1 加入1-wrie驅動程式 1 加入hal_onewireh hal_onewirec

2 修改hal_board_cfgh

3 修改hal_driversc

步驟2 加入DS18B20溫度感測器驅動程式 1 加入hal_ds18b20h hal_ds18b20c

2 修改hal_board_cfgh

3 修改hal_driversc

步驟3 撰寫應用程式

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 99: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

含溫度顯示的電子時鐘應用程式

99

include MyAPP1h SYSTEMTIME currentTime SENSEDTEMP currentTemp TEMPCONFIG configTemp = 0x55 0xF6 DS18B20_RES_11BITS void main() HalDriverInit() DS18B20_Config(ampconfigTemp) OneWire_BusReset() currentTempResolution = configTempResolution while(1) DS1302_ReadTime(ampcurrentTime) LCD_DispStr(0 0 currentTimeDateString) LCD_DispStr(0 12 currentTimeWeekdayString) LCD_DispStr(1 0 currentTimeTimeString) DS18B20_ReadTemp(ampcurrentTemp) LCD_DispStr(1 9 currentTempTempString)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 100: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

Lab13 加入LED與Timer驅動程式

100

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 101: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

實習13 加入驅動程式並測試

101

練習1 加入LED驅動程式並完成設定

練習2 撰寫測試LED功能的應用程式

練習3 加入Timer驅動程式並完成設定

練習4 撰寫測試Timer功能的應用程式

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 102: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

練習1 加入LED驅動程式 (I)

102

------------------------------------------------------------------------------------------------ LED Configuration ------------------------------------------------------------------------------------------------ define HAL_NUM_LEDS 4 LED D0 define LED1_BV BV(0) define LED1_SBIT P1_bitP1_0 define LED1_POLARITY ACTIVE_LOW LED D5 define LED2_BV BV(5) define LED2_SBIT P1_bitP1_5 define LED2_POLARITY ACTIVE_LOW LED D6 define LED3_BV BV(6) define LED3_SBIT P1_bitP1_6 define LED3_POLARITY ACTIVE_LOW LED D7 define LED4_BV BV(7) define LED4_SBIT P1_bitP1_7 define LED4_POLARITY ACTIVE_LOW

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 103: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

103

------------------------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------------------------ ----------- LEDs ---------- define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0) ) define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0) ) define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0) ) define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0) ) define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1) ) define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1) ) define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1) ) define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1) ) define HAL_TOGGLE_LED1() st( if (LED1_SBIT) LED1_SBIT = 0 else LED1_SBIT = 1 ) define HAL_TOGGLE_LED2() st( if (LED2_SBIT) LED2_SBIT = 0 else LED2_SBIT = 1 ) define HAL_TOGGLE_LED3() st( if (LED3_SBIT) LED3_SBIT = 0 else LED3_SBIT = 1 ) define HAL_TOGGLE_LED4() st( if (LED4_SBIT) LED4_SBIT = 0 else LED4_SBIT = 1 ) define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT)) ------------------------------------------------------------------------------------------------ Driver Configuration ------------------------------------------------------------------------------------------------ 略 Set to TRUE enable LED usage FALSE disable it ifndef HAL_LED define HAL_LED TRUE endif

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 104: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

104

Filename hal_ledh Revised $Date 2013-11-06 $ Revision $Revision $ Description This file contains the interface to the LED Service ifndef HAL_LED_H define HAL_LED_H INCLUDES include hal_boardh CONSTANTS define HAL_LED_1 0x01 define HAL_LED_2 0x02 define HAL_LED_3 0x04 define HAL_LED_4 0x08 define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4) Modes define HAL_LED_MODE_OFF 0x00 define HAL_LED_MODE_ON 0x01 define HAL_LED_MODE_TOGGLE 0x02 Defaults define HAL_LED_DEFAULT_MAX_LEDS 4

Initialize LED Service extern void HalLedInit( void ) Set the LED ONOFF extern uint8 HalLedSet( uint8 led uint8 mode ) Put LEDs in sleep state - store current values extern void HalLedEnterSleep( void ) Retore LEDs from sleep state extern void HalLedExitSleep( void ) Return LED state extern uint8 HalLedGetState ( void ) endif

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 105: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

105

Filename hal_ledc Revised $Date 2013-11-06 $ Revision $Revision 29281 $ Description This file contains the interface to the HAL LED Service INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_driversh include hal_ledh include hal_boardh GLOBAL VARIABLES LED state at last setclr update static uint8 HalLedState if HAL_LED == TRUE LED state at last setclr update static uint8 HalSleepLedState endif

LOCAL FUNCTION if (HAL_LED == TRUE) void HalLedOnOff (uint8 leds uint8 mode) endif HAL_LED

FUNCTIONS - API fn HalLedInit brief Initialize LED Service param init - pointer to void that contains the initialized value return None void HalLedInit (void) if (HAL_LED == TRUE) Initialize all LEDs to OFF HalLedSet (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 106: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

fn HalLedSet brief Tun ONOFF given LEDs param led - bit mask value of leds to be turned ONOFFTOGGLE mode - TOGGLE ON OFF return None uint8 HalLedSet (uint8 leds uint8 mode) if (HAL_LED == TRUE) uint8 i if(mode == HAL_LED_MODE_TOGGLE) for(i=0iltHAL_LED_DEFAULT_MAX_LEDSi++) if (HalLedState amp (1ltlti)) HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_OFF) else HalLedOnOff(leds amp (1ltlti) HAL_LED_MODE_ON) else HalLedOnOff(leds mode) endif return ( HalLedState )

if (HAL_LED == TRUE) fn HalLedOnOff brief Turns specified LED ON or OFF param leds - LED bit mask mode - LED_ONLED_OFF return none void HalLedOnOff (uint8 leds uint8 mode) if (leds amp HAL_LED_1) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1() else HAL_TURN_OFF_LED1() if (leds amp HAL_LED_2) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2() else HAL_TURN_OFF_LED2()

106

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 107: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

107

if (leds amp HAL_LED_3) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3() else HAL_TURN_OFF_LED3() if (leds amp HAL_LED_4) if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED4() else HAL_TURN_OFF_LED4() Remember current state if (mode) HalLedState |= leds else HalLedState amp= (leds ^ 0xFF) endif HAL_LED

fn HalGetLedState brief Get LED state param none return led state uint8 HalLedGetState () if (HAL_LED == TRUE) return HalLedState else return 0 endif

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 108: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

108

fn HalLedEnterSleep brief Store current LEDs state before sleep param none return none void HalLedEnterSleep( void ) if (HAL_LED == TRUE) Save the state of each led HalSleepLedState = 0 HalSleepLedState |= HAL_STATE_LED1() HalSleepLedState |= HAL_STATE_LED2() ltlt 1 HalSleepLedState |= HAL_STATE_LED3() ltlt 2 HalSleepLedState |= HAL_STATE_LED4() ltlt 3 TURN OFF all LEDs to save power HalLedOnOff (HAL_LED_ALL HAL_LED_MODE_OFF) endif HAL_LED fn HalLedExitSleep brief Restore current LEDs state after sleep param none return none void HalLedExitSleep( void ) if (HAL_LED == TRUE) Load back the saved state HalLedOnOff(HalSleepLedState HAL_LED_MODE_ON) endif HAL_LED

void HalDriverInit (void) 略 if (defined HAL_LED) ampamp (HAL_LED == TRUE) HalLedInit() endif 略

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 109: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

練習2 測試LED的應用程式

109

測試時先關閉DS1302 RTC與DS18B20測溫功能

include MyAPP1h void main() uint8 read_keys HalDriverInit() uint8 sleep_flag = 0 while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs ON) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

case HAL_KEY_SW_2 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_ALL HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs OFF) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 110: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

110

case HAL_KEY_SW_3 if(sleep_flag) LCD_ClrLine(1) HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_2 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_3 HAL_LED_MODE_TOGGLE) HalLedSet(HAL_LED_4 HAL_LED_MODE_ON) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs TOGGLE) else LCD_ClrLine(1) LCD_DispStr(1 0 LEDs are sleeping) break case HAL_KEY_SW_4 if(sleep_flag) HalLedEnterSleep() sleep_flag = 1 LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Sleeping) else HalLedExitSleep() LCD_ClrLine(1) LCD_ClrLine(0) LCD_DispStr(0 0 LEDs Alive) sleep_flag = 0 break

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 111: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

練習3 加入Timer驅動程式並設定

111

Filename hal_timerh Revised $Date 2013-11-1 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented ifndef HAL_TIMER_H define HAL_TIMER_H INCLUDES include hal_boardh CONSTANTS Timer ID definitions define HAL_TIMER_0 0x00 8bit timer define HAL_TIMER_1 0x01 16bit timer define HAL_TIMER_INVALID 0x02 Invalid timer define HAL_TIMER_MAX 2 Max number of timer Operation Modes for timer define HAL_TIMER_MODE_13BITS 0x00 define HAL_TIMER_MODE_16BITS 0x01 define HAL_TIMER_MODE_8BITS_AUTO 0x02 define HAL_TIMER_MODE_8BITS_SPLIT 0x03 define HAL_TIMER_MODE_COUNT 0x04 define HAL_TIMER_MODE_GATE 0x08 define HAL_INT_ENABLE TRUE define HAL_INT_DISABLE FALSE

Error Code define HAL_TIMER_OK 0x00 define HAL_TIMER_NOT_OK 0x01 define HAL_TIMER_PARAMS_ERROR 0x02 define HAL_TIMER_NOT_CONFIGURED 0x03 define HAL_TIMER_INVALID_ID 0x04 define HAL_TIMER_INVALID_OP_MODE 0x05

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 112: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

112

TYPEDEFS typedef void (halTimerCBack_t) (uint8 timerId) FUNCTIONS - API Initialize Timer Service extern void HalTimerInit(void) Configure channel in different modes extern uint8 HalTimerConfig(uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cback ) Start a Timer extern uint8 HalTimerStart(uint8 timerId uint16 timePerTick) Stop a Timer extern uint8 HalTimerStop(uint8 timerId) Enable and disable particular timer extern uint8 HalTimerInterruptEnable(uint8 timerId bool enable) endif

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 113: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

113

Filename hal_timerc Revised $Date 2013-11-11 $ Revision $Revision $ Description This file contains the interface to the Timer Service Just for demo Timer2 is not implemented INCLUDES include hal_mcuh include hal_defsh include hal_typesh include hal_timerh include hal_ledh CONSTANTS IE BV define IE_T0_IntEn_Bit BV(1) define IE_T1_IntEn_Bit BV(3) IF BVTCON define TCON_T0_IntFlag_Bit BV(5) define TCON_T1_IntFlag_Bit BV(7) Timer Enable BVTCON define TCON_T0_START_BV BV(4) define TCON_T1_START_BV BV(6) Prescale settings and Clock settings define HAL_TIMER_PRESCALE_VAL 12 define HAL_TIMER_12MHZ 12 ISR Vector names define T0_VECTOR timer0 define T1_VECTOR timer1 Opmode Mask define OP_MODE_MASK 0x03 for checking mode0 1 2 3

TYPEDEFS typedef struct bool configured bool intEnable uint8 opMode uint8 prescaleVal uint8 clock uint8 TH uint8 TL halTimerCBack_t callBackFunc halTimerSettings_t GLOBAL VARIABLES static halTimerSettings_t halTimerRecord[HAL_TIMER_MAX] FUNCTIONS ndash Local uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) void halTimerSendCallBack (uint8 timerId) void halProcessTimer0 (void) void halProcessTimer1 (void) void halProcessTimer2 (void)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 114: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

fn HalTimerConfig brief Configure the Timer Serivce param timerId - Id of the timer opMode - Operation mode cBack - Pointer to callback function return Status of the configuration uint8 HalTimerConfig (uint8 timerId uint8 opMode bool intEnable halTimerCBack_t cBack) if (timerId lt HAL_TIMER_MAX) halTimerRecord[timerId]configured = TRUE halTimerRecord[timerId]opMode = opMode halTimerRecord[timerId]intEnable = intEnable halTimerRecord[timerId]TH = 0 halTimerRecord[timerId]TL = 0 halTimerRecord[timerId]callBackFunc = cBack else return HAL_TIMER_PARAMS_ERROR return HAL_TIMER_OK

FUNCTIONS ndash API fn HalTimerInit brief Initialize Timer Service param None return None void HalTimerInit (void) disable all timer interrupts IE amp= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit) Setup prescale value amp clock for timer halTimerRecord[HAL_TIMER_0]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_0]prescaleVal = HAL_TIMER_PRESCALE_VAL halTimerRecord[HAL_TIMER_1]clock = HAL_TIMER_12MHZ halTimerRecord[HAL_TIMER_1]prescaleVal = HAL_TIMER_PRESCALE_VAL

114

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 115: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

fn HalTimerStart brief Start the Timer Service param timerId - ID of the timer timerPerTick - number of micro sec per tick (ticks x prescale) clock = usectick return Status - OK or Not OK uint8 HalTimerStart (uint8 timerId uint16 timePerTick) if (halTimerRecord[timerId]configured) halTimerSetOpMode (timerId halTimerRecord[timerId]opMode) halTimerSetCount (timerId timePerTick) HalTimerInterruptEnable(timerId halTimerRecord[timerId]intEnable) if (timerId == HAL_TIMER_0) TCON |= TCON_T0_START_BV if (timerId == HAL_TIMER_1) TCON |= TCON_T1_START_BV else return HAL_TIMER_NOT_CONFIGURED return HAL_TIMER_OK

fn HalTimerStop brief Stop the Timer Service param timerId - ID of the timer return Status - OK or Not OK uint8 HalTimerStop (uint8 timerId) switch(timerId) case HAL_TIMER_0 TCON amp= ~(TCON_T0_START_BV) break case HAL_TIMER_1 TCON amp= ~(TCON_T1_START_BV) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK 115

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 116: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

fn halTimerSetCount brief param timerId - ID of the timer timerPerTick - Number micro sec per ticks return Status - OK or Not OK uint8 halTimerSetCount (uint8 timerId uint16 timePerTick) uint16 count uint8 high_byte low_byte Load count = ((sectick) x clock) prescale count = (uint16) (timePerTick(halTimerRecord[timerId]prescaleVal)halTimerRecord[timerId]clock) count = (uint16) (timePerTick) switch(halTimerRecord[timerId]opModeampOP_MODE_MASK) case HAL_TIMER_MODE_13BITS count = (8192 - count) high_byte = (uint8) (count gtgt 5) low_byte = (uint8) (count amp 0x07) break case HAL_TIMER_MODE_16BITS count = (65536 - count) high_byte = (uint8) (count gtgt 8) low_byte = (uint8) (count amp 0x0F) break case HAL_TIMER_MODE_8BITS_AUTO count = (256 - (uint8) count) high_byte = (uint8) count low_byte = high_byte break

case HAL_TIMER_MODE_8BITS_SPLIT count = (256 - (uint8) count) high_byte = (uint8) (count amp 0x0F) low_byte = high_byte break default break halTimerRecord[timerId]TH = high_byte halTimerRecord[timerId]TL = low_byte switch(timerId) case HAL_TIMER_0 TH0 = halTimerRecord[timerId]TH TL0 = halTimerRecord[timerId]TL break case HAL_TIMER_1 TH1 = halTimerRecord[timerId]TH TL1 = halTimerRecord[timerId]TL break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

116

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 117: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

fn halTimerSetOpMode brief Setup operate modes param timerId - ID of the timer opMode - operation mode of the timer return Status - OK or Not OK uint8 halTimerSetOpMode (uint8 timerId uint8 opMode) switch (timerId) case HAL_TIMER_0 TMOD amp= ~(0x0F) TMOD |= opMode break case HAL_TIMER_1 TMOD amp= ~(0xF0) TMOD |= (opModeltlt4) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

fn HalTimerInterruptEnable brief Setup interrupt enable param timerId - ID of the timer enable - TRUE or FALSE return Status - OK or Not OK uint8 HalTimerInterruptEnable (uint8 timerId bool enable) switch(timerId) case HAL_TIMER_0 if (halTimerRecord[timerId]intEnable) IE |= IE_T0_IntEn_Bit else IE amp= ~(IE_T0_IntEn_Bit) break case HAL_TIMER_1 if (halTimerRecord[timerId]intEnable) IE |= IE_T1_IntEn_Bit else IE amp= ~(IE_T1_IntEn_Bit) break default return HAL_TIMER_INVALID_ID return HAL_TIMER_OK

117

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 118: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

118

fn halTimerSendCallBack brief Send Callback back to the caller param timerId - ID of the timer return None void halTimerSendCallBack (uint8 timerId) if (halTimerRecord[timerId]callBackFunc) (halTimerRecord[timerId]callBackFunc) (timerId) fn halProcessTimer0 brief Processes Timer 0 Events void halProcessTimer0 (void) TCON amp= ~(TCON_T0_IntFlag_Bit) TH0 = halTimerRecord[HAL_TIMER_0]TH TL0 = halTimerRecord[HAL_TIMER_0]TL halTimerSendCallBack(HAL_TIMER_0) fn halProcessTimer1 brief Processes Timer 1 Events void halProcessTimer1 (void) TCON amp= ~(TCON_T1_IntFlag_Bit) TH1 = halTimerRecord[HAL_TIMER_1]TH TL1 = halTimerRecord[HAL_TIMER_1]TL halTimerSendCallBack(HAL_TIMER_1)

INTERRUPT SERVICE ROUTINE fn halTimer0Isr brief Timer 0 ISR HAL_ISR_FUNCTION( halTimer0Isr T0_VECTOR ) halProcessTimer0() fn halTimer1Isr brief Timer 1 ISR HAL_ISR_FUNCTION( halTimer1Isr T1_VECTOR ) halProcessTimer1()

if (HAL_TIMER == TRUE) hellip endif

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 119: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

練習4 測試Timer的應用程式

119

include MyAPP1h uint8 count = 0 uint16 usec_per_tick void Blink_LED(uint8 timerId) void main() uint8 read_keys HalDriverInit() LCD_DispStr(0 0 Timer Demo) HalTimerConfig(HAL_TIMER_0 HAL_TIMER_MODE_16BITS HAL_INT_ENABLE Blink_LED) HalTimerConfig(HAL_TIMER_1 HAL_TIMER_MODE_16BITS HAL_INT_DISABLE NULL) HAL_ENABLE_INTERRUPTS() while(1) read_keys = 0x00 read_keys = HalKeyRead() switch(read_keys) case HAL_KEY_SW_1 usec_per_tick = 1000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK FAST) break

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 120: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

120

case HAL_KEY_SW_2 usec_per_tick = 10000 HalTimerStart(HAL_TIMER_0 usec_per_tick) LCD_ClrLine(0) LCD_DispStr(0 0 LED1 BLINK SLOW) break case HAL_KEY_SW_3 HalTimerStop(HAL_TIMER_0) HalLedSet(HAL_LED_1 HAL_LED_MODE_OFF) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break case HAL_KEY_SW_4 HalLedSet(HAL_LED_ALL HAL_LED_MODE_TOGGLE) LCD_ClrLine(0) LCD_DispStr(0 0 TIMER STOP) break default break

This is the callback function when interrupt occur void Blink_LED(uint8 timerId) if(count == 20) count = 0 HalLedSet(HAL_LED_1 HAL_LED_MODE_TOGGLE) count++

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 121: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

Lab14 建立新的應用程式

121

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 122: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

建立新應用程式 名稱為MyRTC

122

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 123: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

複製一份MyAPP1來修改即可

123

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 124: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

修改ewp與eww檔名與內容

124

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 125: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

125

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 126: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

全新而完整的應用程式

126

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通

Page 127: [嵌入式系統] MCS-51 實驗 - 使用 IAR (3)

總結

127

歷經三個PART我們從最早從簡單的點亮LED實習來學習嵌入式C語言的基本語法與技巧同時觀察MCU的header file內容以了解SFR與中斷向量的命名

我們從main()函式中抽離出一切對硬體的操作並且使用函式將這類型的操作給包裝起來稱之為驅動程式

在一系列包含7段顯示器LCD模組中斷與計時器UARTADDAROM的讀寫RTC與溫度感測器等實習我們循序漸進地學到「硬體驅動程式」與開發板SDK的包裝使得我們的開發專案能更有系統簡潔而且有效率地被重複使用

這些經驗是如此的細微而且重要還有很多韌體開發及應用無法一一說完但相信大家一定能藉著本系列課程所學到基礎而能更容易地繼續往上蓋大樓記住一法通萬法通