SlideShare ist ein Scribd-Unternehmen logo
1 von 127
Downloaden Sie, um offline zu lesen
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小時制(AM/PM)的選擇。
 工作電壓為 2.0V~5.5V,採用三線通訊介面(3-wire
interface)。內部具有31 Bytes的SRAM。
 DS1302具有主電源/備用電源的雙電源引腳(VCC1為後備
電源,VCC2為主電源,由VCC1 或VCC2 兩者中的較大者
供電),同時提供對備用電源進行涓流充電的能力。
 X1和X2外接32.768 kHz的石英振盪器。RST是重置/晶片
選擇腳,對RST輸入Low重置晶片而將RST設為High可啟
動所有資料傳送。
DS1302 RTC的RST/CE接腳功能
4
 RST/CE輸入有兩種功能:
 RST接至控制邏輯,允許位址/命令序列送入移位暫存器
 RST提供終止資料傳送。當RST為高電壓時,所有的數據傳送被初始化,
允許對DS1302進行操作。如果在傳送過程中RST置為低電壓,則會終止
此次資料傳送,I/O引腳變為高阻態。
 啟動運行時,在VCC>2.0V之前,RST必須保持低電位。只有在SCLK為低
電位時,才能將RST置為高電位。I/O為串列資料輸出端(雙向)。SCLK為
時鐘輸入端。
40 kΩ pull-down
DS1302之指令 – Command Byte
5
 Command Byte用於初始化每次的資料傳輸,bit-0必
定為input staring。
3-Wire通訊介面的讀寫
6
Burst mode: command byte bit1~5 = 11111’b = 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燈 – 最簡單的寫法
13
#include<ioAT89C52.h>
typedef unsigned char uint8;
void delayms(uint8);
void main(void)
{
P1_bit.P1_0 = 1;
while(1)
{
P1_bit.P1_0 = 0;
delayms(250);
P1_bit.P1_0 = 1;
delayms(250);
}
}
#include<ioAT89C52.h>
#define LED0 P1_bit.P1_0
typedef unsigned char uint8;
void delayms(uint8);
void main(void)
{
LED0 = 1;
while(1)
{
LED0 = 0;
delayms(250);
LED0 = 1;
delayms(250);
}
}
閃爍LED燈 – 使用機板標頭檔
14
// ioMapping.h
#define LED_REGISTER P0
#define LED_BIT (1 << 0)
#include<ioAT89C52.h>
#include "ioMapping.h"
typedef unsigned char uint8;
void delayms(uint8);
void main(void)
{
LED_REGISTER |= LED_BIT;
while(1)
{
LED_REGISTER &= ~LED_BIT;
delayms(250);
LED_REGISTER |= LED_BIT;
delayms(250);
}
}
閃爍LED燈 – 通用機板標頭檔
15
#include<ioAT89C52.h>
#include "ioMapping.h"
typedef unsigned char uint8;
void delayms(uint8);
void main(void)
{
LED_REGISTER |= LED_BIT;
while(1)
{
LED_REGISTER &= ~LED_BIT;
delayms(250);
LED_REGISTER |= LED_BIT;
delayms(250);
}
}
// ioMapping.h
#if COMPILING_BOARD_V1
#include "ioMapping_v1.h"
#elif COMPILING_BOARD_V2
#include "ioMapping_v2.h"
#else
#error "No I/O map selected for the board"
#endif
// ioMapping_v1.h
#define LED_REGISTER P0
#define LED_BIT (1 << 0)
// ioMapping_v2.h
#define LED_REGISTER P3
#define LED_BIT (1 << 4)
I/O處理程式碼
16
閃爍LED燈 – Facade模式
17
 LED的I/O子系統介面與內容,就是LED的驅動程式
 隱藏子系統的細節是良好設計中十分重要的一環,
呼叫端的程式不會依賴子系統的細節
Main
加上按鈕
18
設定中斷
19
 雖然為腳位設定中斷與設定輸入都是屬於初始化,但
這兩件事情通常會將實作分離,只需要在使用中斷的
程式碼中包含設定中斷的複雜度。
 三個中斷處理函式(有時會用巨集來做)
競賽情況(Race Condition)
 在工作間共享記憶體十分危險,必須十分小心。
20
避免競賽情況 – 使用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
• /Driver: 驅動程式目錄 (有時也會用/hal)
/Boot-Loader: 開機程式
/Hardware: 各種硬體裝置的驅動程式
/Include: 驅動程式的header files
/API: 將所有驅動程式包裝成API
/Boot: Boot程式
/LCD: LCD程式
/SDRAM: SDRAM驅動程式
• /System: 系統程式
/Include: 系統程式的header files
/API: 將所有系統程式包裝成API
/Common: 系統中的通用功能
/RTOS: 嵌入式OS的目錄
/Include: RTOS的header
/Memory: 記憶體管理
/Sync: Task間同步機制
/IPC: Task間通訊機制
/Glib: 圖形函式庫
/Sub-System:各種子系統
/GUI: 圖形用戶介面
/TCPIP: TCPIP通訊堆疊
/FileSystem: 檔案系統
• /AP: 應用程式 (或/APP)
/Include: 應用程式的header files
/Source: 應用程式的原始碼
/Common: 應用程式的通用功能
/AP1: 應用程式1
/AP2: 應用程式2
/Resource: 應用程式的圖形、字串資源
• /Third_Party_Lib: 第三方函式庫
/HandWriting: 手寫辨識函式庫
/Fonts: 字型
/VoiceComp: 聲音壓縮函式庫
• /Include: header, sys_config.h(系統配置檔)
• /Build: 製作映像檔(執行檔)的東西,
如makefile跟link script
• /Tools: 開發中所需的程式,例如compiler
• /Documents: 開發規範、datasheet、user guide、
Spec, API手冊等
練習1: 結構化你的程式碼
24
 在D槽新建一個目錄結構
 D:MySimpSystem
在IAR中New一個Worksapce
25
環境設定
26
New一個應用程式File
27
建立Groups
28
完成以下的Groups
29
先把幾個Header File歸入Group
30
D:MySimpSystemhaltargetJC51B
D:MySimpSystemhalinclude
hal_types.h
/*****************************************************
Filename: hal_types.h
Revised: $Date: 2013-10-18 15:20 $
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
D:MySimpSystemhaltargetJC51B
hal_mcu.h
32
/**************************************************************
Filename: hal_mcu.h
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_defs.h"
#include "hal_types.h"
/* Target Defines */
#define HAL_MCU_AT89C52
/* Compiler Abstraction */
/* ---------------------- IAR Compiler ---------------------- */
#ifdef __IAR_SYSTEMS_ICC__
#include <ioAT89C52.h>
#define HAL_COMPILER_IAR
#define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__
#define _PRAGMA(x) _Pragma(#x)
#define HAL_ISR_FUNC_DECLARATION(f,v) _PRAGMA(vector=v) __near_func __interrupt void f(void)
#define HAL_ISR_FUNC_PROTOTYPE(f,v) _PRAGMA(vector=v) __near_func __interrupt void f(void)
#define HAL_ISR_FUNCTION(f,v) HAL_ISR_FUNC_PROTOTYPE(f,v); HAL_ISR_FUNC_DECLARATION(f,v)
/* ---------------------- Keil Compiler ---------------------- */
#elif defined __KEIL__
#include <reg51.h>
D:MySimpSystemhaltargetJC51B
#define HAL_COMPILER_KEIL
#define HAL_MCU_LITTLE_ENDIAN() 0
#define HAL_ISR_FUNC_DECLARATION(f,v) 
void f(void) interrupt v
#define HAL_ISR_FUNC_PROTOTYPE(f,v) 
void f(void)
#define HAL_ISR_FUNCTION(f,v) 
HAL_ISR_FUNC_PROTOTYPE(f,v); 
HAL_ISR_FUNC_DECLARATION(f,v)
/* ------------ 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_bit.EA = 1; )
#define HAL_DISABLE_INTERRUPTS() st( IE_bit.EA = 0; )
#define HAL_INTERRUPTS_ARE_ENABLED() (IE_bit.EA)
typedef unsigned char halIntState_t;
#define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bit.EA; HAL_DISABLE_INTERRUPTS(); )
#define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bit.EA = 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_bit.EA = _isrIntState; }
#else
#define HAL_ENTER_ISR()
#define HAL_EXIT_ISR()
#endif /* __IAR_SYSTEMS_ICC__ */
/**************************************************************************************************
*/
#endif
hal_board.h & hal_board_cfg.h
34
D:MySimpSystemhalinclude
D:MySimpSystemhaltargetJC51B
#include "hal_board_cfg.h"
/*********************************************
Filename: hal_board_cfg.h
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_mcu.h"
#include "hal_defs.h"
#include "hal_types.h"
#endif
/*********************************************
*/
hal_defs.h
35
/*****************************************************************
Filename: hal_defs.h
Revised: $Date: 2013-10-18 14:48 $
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 << (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) >>((ByteNum) * 8)) & 0x00FF))
#define BUILD_UINT32(Byte0, Byte1, Byte2, Byte3)
((uint32)((uint32)((Byte0) & 0x00FF) 
+ ((uint32)((Byte1) & 0x00FF) << 8) 
+ ((uint32)((Byte2) & 0x00FF) << 16) 
+ ((uint32)((Byte3) & 0x00FF) << 24)))
#define BUILD_UINT16(loByte, hiByte) 
((uint16)(((loByte) & 0x00FF) + (((hiByte) & 0x00FF) << 8)))
#define HI_UINT16(a) (((a) >> 8) & 0xFF)
#define LO_UINT16(a) ((a) & 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
D:MySimpSystemhalinclude
hal_drivers.h
36
/****************************************************
Filename: hal_drivers.h
Revised: $Date: 2013-10-18 14:52 $
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
D:MySimpSystemhalinclude
練習2: 加入LCD的驅動程式
#include<ioAT89C52.h>
#define BTN1 P3_bit.P3_2
#define BTN2 P3_bit.P3_3
#define LCD_RW P1_bit.P1_1
#define LCD_EN P3_bit.P3_4
#define LCD_RS P3_bit.P3_5
#define LCD_BF P0_bit.P0_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;
D:MySimpSystemhalinclude
/* 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
D:MySimpSystemhaltargetJC51B
/*********************************************
Filename: hal_lcd.c
Revised: $Date: 2013-10-19 16:21 $
Revision: $Revision: $
Description:
*********************************************/
/******* INCLUDES *******/
#include "hal_board_cfg.h"
#include "hal_defs.h"
#include "hal_types.h"
#include "hal_lcd.h"
/******* 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 – 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)
…
#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_drivers.h
Revised: $Date: 2013-10-18 14:52 $
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
D:MySimpSystemhalinclude
44
D:MySimpSystemhalcommon
/****************************************************************************
Filename: hal_drivers.c
Revised: $Date: 20103-10-19 17:00 $
Revision: $Revision: $
Description: This file contains the common functions used by the driver
*****************************************************************************/
/******** INCLUDES *************/
#include "hal_types.h"
#include "hal_drivers.h"
#include "hal_lcd.h"
/******** FUNCTIONS – 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(time>0)
{
n = 162;
while(n>0) n--;
time --;
}
}
/*****************************************************
* @fn HalDriverInit
* @brief Initialize HW
* @param None
* @return None
******************************************************/
void HalDriverInit (void)
{
#if (defined HAL_LCD) && (HAL_LCD == TRUE)
LCD_Init(2, 16);
#endif
}
修改hal_board_cfg.h
45
/***************************************************************
Filename: hal_board_cfg.h
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_mcu.h"
#include "hal_defs.h"
#include "hal_types.h"
#include "hal_lcd.h"
/* -------- Driver Configuration -------- */
/* Set to TRUE enable LCD usage, FALSE disable it */
#ifndef HAL_LCD
#define HAL_LCD TRUE
#endif
#endif
/**********************************************************************************
*/
準備加入按鍵驅動程式
46
 先修改一下hal_board_cfg.h的內容
/***************************************************************
Filename: hal_board_cfg.h
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_mcu.h"
#include "hal_defs.h"
#include "hal_types.h"
#include "hal_lcd.h"
#include "hal_key.h"
/* ---- 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_bit.P3_2 // INT0
#define PUSH1_POLARITY ACTIVE_LOW
/* BTN2 */
#define PUSH2_BV BV(3)
#define PUSH2_SBIT P3_bit.P3_3 // INT1
#define PUSH2_POLARITY ACTIVE_LOW
/* BTN3 */
#define PUSH3_BV BV(4)
#define PUSH3_SBIT P3_bit.P3_4 // T0
#define PUSH3_POLARITY ACTIVE_LOW
/* BTN4 */
#define PUSH4_BV BV(5)
#define PUSH4_SBIT P3_bit.P3_5 // T1
#define PUSH4_POLARITY ACTIVE_LOW
47
/* ----- Macros ------*/
// ---- Debounce ---- //
#define HAL_DEBOUNCE(expr) { int i; for (i=0; i<500; 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_key.h
Revised: $Date: 2013-10-19 17:51 $
Revision: $Revision: $
Description: This file contains the interface to the KEY Service.
***********************************************************************/
#ifndef HAL_KEY_H
#define HAL_KEY_H
/****** INCLUDES ******/
#include "hal_board.h"
/****** 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 – 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
D:MySimpSystemhalinclude
49
/*********************************************
Filename: hal_key.c
Revised: $Date: 2013-10-19 22:27 $
Revision: $Revision: $
Description: HAL KEY Service.
**********************************************/
/******* INCLUDES **********/
#include "hal_mcu.h"
#include "hal_defs.h"
#include "hal_types.h"
#include "hal_board.h"
#include "hal_drivers.h"
#include "hal_key.h"
#if (defined HAL_KEY) && (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 enable/disable*/
#define HAL_KEY_CPU_IE IE
D:MySimpSystemhaltargetJC51B
/********* Key 1 ************/
/* SW_1 is at P3.2 */
#define HAL_KEY_SW_1_PORT PUSH1_SBIT
/* edge interrupt */
#define HAL_KEY_SW_1_EDGEBIT BV(0) // TCON => 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_bit.IE0
/********* Key 2 ************/
/* SW_2 is at P3.3 */
#define HAL_KEY_SW_2_PORT PUSH2_SBIT
/* edge interrupt */
#define HAL_KEY_SW_2_EDGEBIT BV(2) // TCON => 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_bit.IE1
/********* Key 3 ************/
/* SW_3 is at P3.4, Key3 has no interrupt */
#define HAL_KEY_SW_3_PORT PUSH3_SBIT
/********* Key 4 ************/
/* SW_4 is at P3.5, Key4 has no interrupt */
#define HAL_KEY_SW_4_PORT PUSH4_SBIT
/******** GLOBAL VARIABLES ********/
static uint8 HalKeyConfigured;
/* interrupt enable/disable flag */
bool Hal_KeyIntEnable;
/******* FUNCTIONS – 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)
{
/* Enable/Disable 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 ************/
/* Rising/Falling edge configuration */
HAL_KEY_CPU_TCON &= ~(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 ************/
/* Rising/Falling edge configuration */
HAL_KEY_CPU_TCON &= ~(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 &= ~(HAL_KEY_SW_1_IEBIT);
HAL_KEY_SW_1_IFG = 0;
HAL_KEY_CPU_IE &= ~(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_mcu.h
hal_types.h
hal_board_cfg.h
hal_defs.h
hal_drivers.h
hal_board.h
hal_lcd.h
hal_key.h
hal_drviers.c
hal_lcd.c
hal_key.c
在進行RTC實驗之前
54
 我們現在有按鍵跟LCD驅動程式,何不寫一個應用
程式,完成如exercise4-03.c的進度條顯示程式。
D:MySimpSystemProjectsMyAPP1Source
#include "hal_types.h"
#include "hal_drivers.h"
#include "hal_board_cfg.h"
#include "MyAPP1.h"
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=0;i<101;i++)
{
num[0] = (i/100)+0x30;
num[1] = ((i/10)%10)+0x30;
num[2] = (i%10)+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 = (i*100/125);
LCD_DispHorBar(1, 0, percent_bar);
delayms(200);
}
}
}
}
顯現電路板設定組態檔的威力
 將driver與硬體I/O相關的設定移到hal_borad_cfg.h
#define LCD_RW P1_bit.P1_1
#define LCD_EN P3_bit.P3_4
#define LCD_RS P3_bit.P3_5
#define LCD_BF P0_bit.P0_7
#define LCD_DATA_PORT P0
/****************************************************
Filename: hal_board_cfg.h
*****************************************************/
#ifndef HAL_BOARD_CFG_H
略
/* BTN1 */
#define PUSH1_BV BV(2)
#define PUSH1_SBIT P3_bit.P3_2 // INT0
#define PUSH1_POLARITY ACTIVE_LOW
/* BTN2 */
#define PUSH2_BV BV(3)
#define PUSH2_SBIT P3_bit.P3_3 // INT1
#define PUSH2_POLARITY ACTIVE_LOW
/* BTN3 */
#define PUSH3_BV BV(4)
#define PUSH3_SBIT P3_bit.P3_4 // T0
#define PUSH3_POLARITY ACTIVE_LOW
/* BTN4 */
#define PUSH4_BV BV(5)
#define PUSH4_SBIT P3_bit.P3_5 // T1
#define PUSH4_POLARITY ACTIVE_LOW
/* -- LCD I/O Configuration --*/
#define LCD_RW P1_bit.P1_1
#define LCD_EN P3_bit.P3_4
#define LCD_RS P3_bit.P3_5
#define LCD_BF P0_bit.P0_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_cfg.h
 寫出RTC的應用程式
練習4: 加入3-wire通訊介面Driver
63
/*************************************************************************
Filename: hal_triwire.h
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_board.h"
/**** CONSTANTS ****/
/* 3-Wire delay */
#define TriWireDELAY 10
/**** FUNCTIONS – 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_triwire.c
64
/**********************************************************************
Filename: hal_triwire.c
Revised: $Date: 2013-10-18 21:07 $
Revision: $Revision: $
Description: This file contains the interface to the 3-wire driver.
**********************************************************************/
/********* INCLUDES ***********/
#include "hal_board_cfg.h"
#include "hal_defs.h"
#include "hal_types.h“
#include "hal_drivers.h"
#include "hal_triwire.h"
/********* 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 < 8; index++) {
TriWire_SCLK = LOW;
if(output_data & 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 >> 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 < 8; index++) {
input_data = input_data >> 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 byte@Reg_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)
…
#endif
Add file與修改hal_board_cfg.h
67
/* ----------------------------------------------
* 3-Wire Port Configuration
* ----------------------------------------------
*/
#define TriWire_SCLK P1_bit.P1_4
#define TriWire_IO P1_bit.P1_2
#define TriWire_RST P1_bit.P1_3
測試驅動程式 (I)
68
 寫一個應用程式,測試3-wire的驅動程式
#include "MyAPP1.h"
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_ds1302.h
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_board.h"
/***** 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 – API ******/
extern void DS1302_Init(void);
extern void DS1302_ReadTime(SYSTEMTIME *Time);
extern void DS1302_WriteTime(SYSTEMTIME *Time);
#endif
73
74
/*********************************************
Filename: hal_ds1302.c
Revised: $Date: 2013-10-18 21:36 $
Revision: $Revision: $
********************************************/
/***** INCLUDES ******/
#include "hal_board_cfg.h"
#include "hal_defs.h"
#include "hal_types.h"
#include "hal_drivers.h"
#include "hal_triwire.h"
#include "hal_ds1302.h"
/***** 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) & REG_MASK_CH;
if(Clock_halt) {
TriWire_Write(DS1302_WP , DS1302_WR_ON); // Allow write
// Write initial date and time: 2013/11/12, TUE, 23:59:55
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->Second = FormatReg2Dec(ReadValue, REG_MASK_SECOND);
ReadValue = TriWire_Read(DS1302_MINUTE+1);
Time->Minute = FormatReg2Dec(ReadValue, REG_MASK_MINUTE);
ReadValue = TriWire_Read(DS1302_HOUR+1);
Time->Hour = FormatReg2Dec(ReadValue, REG_MASK_HOUR);
Time->Hourmode = ReadValue & REG_MASK_HOUR_MODE;
ReadValue = TriWire_Read(DS1302_DATE+1);
Time->Date = FormatReg2Dec(ReadValue, REG_MASK_DATE);
ReadValue = TriWire_Read(DS1302_MONTH+1);
Time->Month = FormatReg2Dec(ReadValue, REG_MASK_MONTH);
ReadValue = TriWire_Read(DS1302_WEEKDAY+1);
Time->Weekday = FormatReg2Dec(ReadValue, REG_MASK_WEEKDAY);
ReadValue = TriWire_Read(DS1302_YEAR+1);
Time->Year = 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->Year) );
TriWire_Write(DS1302_MONTH , FormatDec2Reg(Time->Month) );
TriWire_Write(DS1302_DATE , FormatDec2Reg(Time->Date) );
TriWire_Write(DS1302_WEEKDAY, FormatDec2Reg(Time->Weekday));
TriWire_Write(DS1302_HOUR , FormatDec2Reg(Time->Hour) );
TriWire_Write(DS1302_MINUTE , FormatDec2Reg(Time->Minute) );
TriWire_Write(DS1302_SECOND , FormatDec2Reg(Time->Second) );
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 & reg_mask) >> 4)*10 + (reg_data & 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_data/10)*16 + dec_data%10;
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->DateString[0] = '2';
Time->DateString[1] = '0';
Time->DateString[2] = Time->Year/10 + 0x30; // '0' : ASCII = 0x30
Time->DateString[3] = Time->Year%10 + 0x30;
Time->DateString[4]='-';
Time->DateString[5] = Time->Month/10 + 0x30;
Time->DateString[6] = Time->Month%10 + 0x30;
Time->DateString[7]='-';
Time->DateString[8] = Time->Date/10 + 0x30;
Time->DateString[9] = Time->Date%10 + 0x30;
Time->DateString[10] = '0';
Time->WeekdayString[0] = *(WeekdayTable[(Time->Weekday%10)-1] + 0);
Time->WeekdayString[1] = *(WeekdayTable[(Time->Weekday%10)-1] + 1);
Time->WeekdayString[2] = *(WeekdayTable[(Time->Weekday%10)-1] + 2);
Time->WeekdayString[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->TimeString[0] = Time->Hour/10 + 0x30; // '0' : ASCII = 0x30
Time->TimeString[1] = Time->Hour%10 + 0x30;
Time->TimeString[2] = ':';
Time->TimeString[3] = Time->Minute/10 + 0x30;
Time->TimeString[4] = Time->Minute%10 + 0x30;
Time->TimeString[6] = Time->Second/10 + 0x30;
Time->TimeString[7] = Time->Second%10 + 0x30;
Time->TimeString[8] = '0';
}
#if (HAL_DS1302 == TRUE)
…
#endif
修改hal_board_cfg.h
79
/**************************************************************************************************
Filename: hal_board_cfg.h
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_mcu.h"
#include "hal_defs.h"
#include "hal_types.h"
#include "hal_lcd.h"
#include "hal_key.h"
#include "hal_triwire.h"
#include "hal_ds1302.h"
**** 略 *****
/* ------ 3-Wire Port Configuration ------*/
#define TriWire_SCLK P1_bit.P1_4
#define TriWire_IO P1_bit.P1_2
#define TriWire_RST P1_bit.P1_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_drivers.c的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) && (HAL_LCD == TRUE)
LCD_Init(2, 16);
#endif
#if (defined HAL_KEY) && (HAL_KEY == TRUE)
HalKeyInit();
HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE);
#endif
#if (defined HAL_DS1302) && (HAL_DS1302 == TRUE)
DS1302_Init();
#endif
}
練習5: 寫一支電子時鐘應用程式
81
#include "MyAPP1.h"
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(&currentTime);
while(1)
{
DS1302_ReadTime(&currentTime);
LCD_DispStr(0, 0, currentTime.DateString);
LCD_DispStr(0, 12, currentTime.WeekdayString);
LCD_DispStr(1, 0, currentTime.TimeString);
}
}
Lab12: DS18B20溫度感測器
82
DS18B20溫度感測器
83
 DS18B20是一個數位溫度感測器,它可以提供9~12位元
的攝氏溫度輸出,而且可以設定超溫警告閥值。它使
用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊。
 電壓範圍:3.0~5.5V
 溫度範圍:-55oC~+125oC。-10~+85oC時精度為±0.5oC
 解析度為9~12位元,對應的
可分辨溫度量為 0.5oC、0.25oC、
0.125oC和 0.0625oC。在9位元
解析度時,最多在93.75ms內
能把溫度轉換為數位值;在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 。
Read/Write時序圖
88
使用注意事項
89
 DS1820與MCU使用串列通訊,因此對DS1820進行讀寫時必須嚴格
保證讀寫時序,否則將無法讀取測溫結果。
 實際應用中1-Wire bus上所掛DS1820數量並非任意多個,當數量超
過8個時就需要解決MCU的匯流排驅動問題。
 連接DS1820的匯流排電纜有長度限制,經驗中使用一般電線長度
超過50m時,讀取的測溫資料將發生錯誤。使用雙絞線帶遮罩電
纜時,正常通訊距離可達150m。
 DS1820測溫程式中,向DS1820發出溫度轉換命令後,程式總要等
待DS1820的返回訊號,一旦某個DS1820接觸不好或斷線,當程式
讀該DS1820時,將沒有返回訊號,程式進入閉迴路。這一點在進
行DS1820硬體連接和軟體設計時也要給予一定的重視。 測溫電纜
線建議採用遮罩4芯雙絞線,其中一對線接地線與訊號線,另一組
接VCC和地線,遮罩層在源端單點接地。
/*************************************************
Filename: hal_onewire.c
Revised: $Date: 2013-11-5 21:07 $
**************************************************/
/****** INCLUDES ******/
#include "hal_board_cfg.h"
#include "hal_defs.h"
#include "hal_types.h"
#include "hal_drivers.h"
#include "hal_onewire.h"
/****** 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 < 8; index++) {
OneWire_DQ = LOW;
OneWire_DQ = output_data & 0x01; // 5us
delay_time(OneWireDELAY_Write); // 76us
OneWire_DQ = HIGH;
output_data = output_data >> 1;
}
}
1-Wire通訊介面驅動程式
90
/***********************************************
Filename: hal_onewire.h
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_board.h“
/****** 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 < 8; index++) {
OneWire_DQ = LOW;
input_data = input_data >> 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)
…
#endif
DS18B20溫度感測器驅動程式
/***************************************************
Filename: hal_ds18b20.h
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_board.h“
/******* 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__
{
// 2's complement, +85C = 0101, 0101 = 0x55
uint8 Alarm_TH;
// 2's 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_ds18b20.c
Revised: $Date: 2013-11-05 21:36 $
Revision: $Revision: $
Description: This file contains the interface to the ds18b20 temperature sensor.
***********************************************************************************/
/******* INCLUDES *******/
#include "hal_board_cfg.h"
#include "hal_defs.h"
#include "hal_types.h"
#include "hal_drivers.h"
#include "hal_ds18b20.h"
#include "hal_onewire.h"
/******* 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->Alarm_TH);
OneWire_WriteByte(tconfig->Alarm_TL);
OneWire_WriteByte(tconfig->Resolution);
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: 1.Initialize, 2.ROM CMD, 3.RAM CMD
DS18B20_Init();
OneWire_WriteByte(DS18B20_CMD_SKIP_ROM);
OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP);
DS18B20_Wait_Conv(ttemp->Resolution);
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 & 0xF8;
if(temp_sign) {
ttemp->Temp_Sign = 1; // negative
ttemp->Temp_Integer = ((LO_UINT8(temp_high_byte) << 4) | HI_UINT8(temp_low_byte));
ttemp->Temp_Integer = ~(ttemp->Temp_Integer) + 1;
ttemp->Temp_Decimal = LO_UINT8(~(temp_low_byte & 0x0F));
}else{
ttemp->Temp_Sign = 0; // positive
ttemp->Temp_Integer = ((LO_UINT8(temp_high_byte) << 4) | HI_UINT8(temp_low_byte));
ttemp->Temp_Decimal = LO_UINT8(temp_low_byte & 0x0F);
}
94
95
// String construction
if(temp_sign) ttemp->TempString[0] = '-';
else ttemp->TempString[0] = ' ';
if((ttemp->Temp_Integer)/100) { // hundred's digit
ttemp->TempString[1] = ((ttemp->Temp_Integer)/100) + '0';
}else{
if(temp_sign) {
ttemp->TempString[0] = ' ';
ttemp->TempString[1] = '-';
}else{
ttemp->TempString[1] = ' ';
}
}
if(((ttemp->Temp_Integer)%100)/10) { // ten's digit
ttemp->TempString[2] = (((ttemp->Temp_Integer)%100)/10) + '0';
}else{
if(temp_sign) {
ttemp->TempString[1] = ' ';
ttemp->TempString[2] = '-';
}else{
ttemp->TempString[2] = ' ';
}
}
ttemp->TempString[3] = ((ttemp->Temp_Integer)%10) + '0';
ttemp->TempString[4] = '.';
ttemp->TempString[5] = (ttemp->Temp_Decimal*625/1000) + '0';
ttemp->TempString[6] = 'C';
ttemp->TempString[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_TIME/8);
break;
case DS18B20_RES_10BITS:
delayms(DS18B20_CONV_TIME/4);
break;
case DS18B20_RES_11BITS:
delayms(DS18B20_CONV_TIME/4);
delayms(DS18B20_CONV_TIME/4);
break;
case DS18B20_RES_12BITS:
delayms(DS18B20_CONV_TIME/4);
delayms(DS18B20_CONV_TIME/4);
delayms(DS18B20_CONV_TIME/4);
delayms(DS18B20_CONV_TIME/4);
break;
default:
break;
}
}
#if (HAL_DS18B20 == TRUE)
…
#endif
1-Wire & DS18B20 驅動程式測試
97
實習12
98
 現在,請綜合驅動程式,寫一個應用程式,讓LCD不只
顯示出時間,也可顯示目前溫度。
 步驟1: 加入1-wrie驅動程式
1. 加入hal_onewire.h / hal_onewire.c
2. 修改hal_board_cfg.h
3. 修改hal_drivers.c
 步驟2: 加入DS18B20溫度感測器驅動程式
1. 加入hal_ds18b20.h / hal_ds18b20.c
2. 修改hal_board_cfg.h
3. 修改hal_drivers.c
 步驟3: 撰寫應用程式
含溫度顯示的電子時鐘應用程式
99
#include "MyAPP1.h"
SYSTEMTIME currentTime;
SENSEDTEMP currentTemp;
TEMPCONFIG configTemp = {0x55, 0xF6, DS18B20_RES_11BITS};
void main()
{
HalDriverInit();
DS18B20_Config(&configTemp);
OneWire_BusReset();
currentTemp.Resolution = configTemp.Resolution;
while(1)
{
DS1302_ReadTime(&currentTime);
LCD_DispStr(0, 0, currentTime.DateString);
LCD_DispStr(0, 12, currentTime.WeekdayString);
LCD_DispStr(1, 0, currentTime.TimeString);
DS18B20_ReadTemp(&currentTemp);
LCD_DispStr(1, 9, currentTemp.TempString);
}
}
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_bit.P1_0
#define LED1_POLARITY ACTIVE_LOW
/* LED D5 */
#define LED2_BV BV(5)
#define LED2_SBIT P1_bit.P1_5
#define LED2_POLARITY ACTIVE_LOW
/* LED D6 */
#define LED3_BV BV(6)
#define LED3_SBIT P1_bit.P1_6
#define LED3_POLARITY ACTIVE_LOW
/* LED D7 */
#define LED4_BV BV(7)
#define LED4_SBIT P1_bit.P1_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_led.h
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_board.h"
/***** 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 ON/OFF */
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_led.c
Revised: $Date: 2013-11-06 $
Revision: $Revision: 29281 $
Description: This file contains the interface to the HAL LED Service.
**************************************************************************/
/***** INCLUDES *****/
#include "hal_mcu.h"
#include "hal_defs.h"
#include "hal_types.h"
#include "hal_drivers.h"
#include "hal_led.h"
#include "hal_board.h"
/***** GLOBAL VARIABLES *****/
// LED state at last set/clr update
static uint8 HalLedState;
#if HAL_LED == TRUE
// LED state at last set/clr 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 ON/OFF given LEDs
* @param led - bit mask value of leds to be turned ON/OFF/TOGGLE
* 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=0;i<HAL_LED_DEFAULT_MAX_LEDS;i++) {
if (HalLedState & (1<<i)) HalLedOnOff(leds & (1<<i), HAL_LED_MODE_OFF);
else HalLedOnOff(leds & (1<<i), 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_ON,LED_OFF,
* @return none
*********************************************************/
void HalLedOnOff (uint8 leds, uint8 mode)
{
if (leds & HAL_LED_1) {
if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1();
else HAL_TURN_OFF_LED1();
}
if (leds & HAL_LED_2) {
if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2();
else HAL_TURN_OFF_LED2();
}
106
107
if (leds & HAL_LED_3) {
if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3();
else HAL_TURN_OFF_LED3();
}
if (leds & 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 &= (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() << 1;
HalSleepLedState |= HAL_STATE_LED3() << 2;
HalSleepLedState |= HAL_STATE_LED4() << 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) && (HAL_LED == TRUE)
HalLedInit();
#endif
略
}
練習2: 測試LED的應用程式
109
 測試時先關閉DS1302 RTC與DS18B20測溫功能
#include "MyAPP1.h"
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_timer.h
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_board.h"
/******** 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_timer.c
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_mcu.h"
#include "hal_defs.h"
#include "hal_types.h"
#include "hal_timer.h"
#include "hal_led.h"
/******** CONSTANTS ********/
// IE BV
#define IE_T0_IntEn_Bit BV(1)
#define IE_T1_IntEn_Bit BV(3)
// IF BV@TCON
#define TCON_T0_IntFlag_Bit BV(5)
#define TCON_T1_IntFlag_Bit BV(7)
// Timer Enable BV@TCON
#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 – 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 < 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 – API ********/
/*******************************************************************
* @fn HalTimerInit
* @brief Initialize Timer Service
* @param None
* @return None
*******************************************************************/
void HalTimerInit (void)
{ // disable all timer interrupts
IE &= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit);
/* Setup prescale value & 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 = usec/tick
* @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 &= ~(TCON_T0_START_BV); break;
case HAL_TIMER_1:
TCON &= ~(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 = ((sec/tick) x clock) / prescale */
//count = (uint16) (timePerTick*(halTimerRecord[timerId].prescaleVal)/halTimerRecord[timerId].clock);
count = (uint16) (timePerTick);
switch(halTimerRecord[timerId].opMode&OP_MODE_MASK)
{
case HAL_TIMER_MODE_13BITS:
count = (8192 - count);
high_byte = (uint8) (count >> 5);
low_byte = (uint8) (count & 0x07);
break;
case HAL_TIMER_MODE_16BITS:
count = (65536 - count);
high_byte = (uint8) (count >> 8);
low_byte = (uint8) (count & 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 & 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 &= ~(0x0F);
TMOD |= opMode;
break;
case HAL_TIMER_1:
TMOD &= ~(0xF0);
TMOD |= (opMode<<4);
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 &= ~(IE_T0_IntEn_Bit);
break;
case HAL_TIMER_1:
if (halTimerRecord[timerId].intEnable) IE |= IE_T1_IntEn_Bit;
else IE &= ~(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 &= ~(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 &= ~(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)
…
#endif
練習4: 測試Timer的應用程式
119
#include "MyAPP1.h"
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模組、中斷與計時器、
UART、AD/DA、ROM的讀寫、RTC與溫度感測器等實習,
我們循序漸進地學到「硬體驅動程式」與開發板SDK的
包裝,使得我們的開發專案能更有系統、簡潔而且有
效率地被重複使用。
 這些經驗是如此的細微而且重要,還有很多韌體開發
及應用無法一一說完,但相信大家一定能藉著本系列
課程所學到基礎而能更容易地繼續往上蓋大樓。記住:
一法通,萬法通。

Weitere ähnliche Inhalte

Was ist angesagt?

20分でわかった事にするパワーマネジメント
20分でわかった事にするパワーマネジメント20分でわかった事にするパワーマネジメント
20分でわかった事にするパワーマネジメントmagoroku Yamamoto
 
How shit works: the CPU
How shit works: the CPUHow shit works: the CPU
How shit works: the CPUTomer Gabel
 
射頻電子 - [實驗第二章] I/O電路設計
射頻電子 - [實驗第二章] I/O電路設計射頻電子 - [實驗第二章] I/O電路設計
射頻電子 - [實驗第二章] I/O電路設計Simen Li
 
[ZigBee 嵌入式系統] ZigBee 應用實作 - 使用 TI Z-Stack Firmware
[ZigBee 嵌入式系統] ZigBee 應用實作 - 使用 TI Z-Stack Firmware[ZigBee 嵌入式系統] ZigBee 應用實作 - 使用 TI Z-Stack Firmware
[ZigBee 嵌入式系統] ZigBee 應用實作 - 使用 TI Z-Stack FirmwareSimen Li
 
[ZigBee 嵌入式系統] ZigBee Architecture 與 TI Z-Stack Firmware
[ZigBee 嵌入式系統] ZigBee Architecture 與 TI Z-Stack Firmware[ZigBee 嵌入式系統] ZigBee Architecture 與 TI Z-Stack Firmware
[ZigBee 嵌入式系統] ZigBee Architecture 與 TI Z-Stack FirmwareSimen Li
 
Maxwell と Java CUDAプログラミング
Maxwell と Java CUDAプログラミングMaxwell と Java CUDAプログラミング
Maxwell と Java CUDAプログラミングNVIDIA Japan
 
Fun with Network Interfaces
Fun with Network InterfacesFun with Network Interfaces
Fun with Network InterfacesKernel TLV
 
C++ AMPを使ってみよう
C++ AMPを使ってみようC++ AMPを使ってみよう
C++ AMPを使ってみようOsamu Masutani
 
ROP 輕鬆談
ROP 輕鬆談ROP 輕鬆談
ROP 輕鬆談hackstuff
 
射頻電子實驗手冊 - [實驗7] 射頻放大器模擬
射頻電子實驗手冊 - [實驗7] 射頻放大器模擬射頻電子實驗手冊 - [實驗7] 射頻放大器模擬
射頻電子實驗手冊 - [實驗7] 射頻放大器模擬Simen Li
 
20111015 勉強会 (PCIe / SR-IOV)
20111015 勉強会 (PCIe / SR-IOV)20111015 勉強会 (PCIe / SR-IOV)
20111015 勉強会 (PCIe / SR-IOV)Kentaro Ebisawa
 
Something About Dynamic Linking
Something About Dynamic LinkingSomething About Dynamic Linking
Something About Dynamic LinkingWang Hsiangkai
 
GPUとSSDがPostgreSQLを加速する~クエリ処理スループット10GB/sへの挑戦~ [DB Tech Showcase Tokyo/2017]
GPUとSSDがPostgreSQLを加速する~クエリ処理スループット10GB/sへの挑戦~ [DB Tech Showcase Tokyo/2017]GPUとSSDがPostgreSQLを加速する~クエリ処理スループット10GB/sへの挑戦~ [DB Tech Showcase Tokyo/2017]
GPUとSSDがPostgreSQLを加速する~クエリ処理スループット10GB/sへの挑戦~ [DB Tech Showcase Tokyo/2017]Kohei KaiGai
 
ELFの動的リンク
ELFの動的リンクELFの動的リンク
ELFの動的リンク7shi
 
傳輸線理論
傳輸線理論傳輸線理論
傳輸線理論祁 周
 

Was ist angesagt? (20)

20分でわかった事にするパワーマネジメント
20分でわかった事にするパワーマネジメント20分でわかった事にするパワーマネジメント
20分でわかった事にするパワーマネジメント
 
How shit works: the CPU
How shit works: the CPUHow shit works: the CPU
How shit works: the CPU
 
射頻電子 - [實驗第二章] I/O電路設計
射頻電子 - [實驗第二章] I/O電路設計射頻電子 - [實驗第二章] I/O電路設計
射頻電子 - [實驗第二章] I/O電路設計
 
Arduino簡介
Arduino簡介Arduino簡介
Arduino簡介
 
[ZigBee 嵌入式系統] ZigBee 應用實作 - 使用 TI Z-Stack Firmware
[ZigBee 嵌入式系統] ZigBee 應用實作 - 使用 TI Z-Stack Firmware[ZigBee 嵌入式系統] ZigBee 應用實作 - 使用 TI Z-Stack Firmware
[ZigBee 嵌入式系統] ZigBee 應用實作 - 使用 TI Z-Stack Firmware
 
Boost.SIMD
Boost.SIMDBoost.SIMD
Boost.SIMD
 
[ZigBee 嵌入式系統] ZigBee Architecture 與 TI Z-Stack Firmware
[ZigBee 嵌入式系統] ZigBee Architecture 與 TI Z-Stack Firmware[ZigBee 嵌入式系統] ZigBee Architecture 與 TI Z-Stack Firmware
[ZigBee 嵌入式系統] ZigBee Architecture 與 TI Z-Stack Firmware
 
Maxwell と Java CUDAプログラミング
Maxwell と Java CUDAプログラミングMaxwell と Java CUDAプログラミング
Maxwell と Java CUDAプログラミング
 
Fun with Network Interfaces
Fun with Network InterfacesFun with Network Interfaces
Fun with Network Interfaces
 
C++ AMPを使ってみよう
C++ AMPを使ってみようC++ AMPを使ってみよう
C++ AMPを使ってみよう
 
ROP 輕鬆談
ROP 輕鬆談ROP 輕鬆談
ROP 輕鬆談
 
射頻電子實驗手冊 - [實驗7] 射頻放大器模擬
射頻電子實驗手冊 - [實驗7] 射頻放大器模擬射頻電子實驗手冊 - [實驗7] 射頻放大器模擬
射頻電子實驗手冊 - [實驗7] 射頻放大器模擬
 
20111015 勉強会 (PCIe / SR-IOV)
20111015 勉強会 (PCIe / SR-IOV)20111015 勉強会 (PCIe / SR-IOV)
20111015 勉強会 (PCIe / SR-IOV)
 
LLVM最適化のこつ
LLVM最適化のこつLLVM最適化のこつ
LLVM最適化のこつ
 
Something About Dynamic Linking
Something About Dynamic LinkingSomething About Dynamic Linking
Something About Dynamic Linking
 
Linux Network Stack
Linux Network StackLinux Network Stack
Linux Network Stack
 
Stack pivot
Stack pivotStack pivot
Stack pivot
 
GPUとSSDがPostgreSQLを加速する~クエリ処理スループット10GB/sへの挑戦~ [DB Tech Showcase Tokyo/2017]
GPUとSSDがPostgreSQLを加速する~クエリ処理スループット10GB/sへの挑戦~ [DB Tech Showcase Tokyo/2017]GPUとSSDがPostgreSQLを加速する~クエリ処理スループット10GB/sへの挑戦~ [DB Tech Showcase Tokyo/2017]
GPUとSSDがPostgreSQLを加速する~クエリ処理スループット10GB/sへの挑戦~ [DB Tech Showcase Tokyo/2017]
 
ELFの動的リンク
ELFの動的リンクELFの動的リンク
ELFの動的リンク
 
傳輸線理論
傳輸線理論傳輸線理論
傳輸線理論
 

Andere mochten auch

RF Module Design - [Chapter 8] Phase-Locked Loops
RF Module Design - [Chapter 8] Phase-Locked LoopsRF Module Design - [Chapter 8] Phase-Locked Loops
RF Module Design - [Chapter 8] Phase-Locked LoopsSimen Li
 
RF Module Design - [Chapter 1] From Basics to RF Transceivers
RF Module Design - [Chapter 1] From Basics to RF TransceiversRF Module Design - [Chapter 1] From Basics to RF Transceivers
RF Module Design - [Chapter 1] From Basics to RF TransceiversSimen Li
 
Multiband Transceivers - [Chapter 1]
Multiband Transceivers - [Chapter 1] Multiband Transceivers - [Chapter 1]
Multiband Transceivers - [Chapter 1] Simen Li
 
RF Module Design - [Chapter 2] Noises
RF Module Design - [Chapter 2] NoisesRF Module Design - [Chapter 2] Noises
RF Module Design - [Chapter 2] NoisesSimen Li
 
Multiband Transceivers - [Chapter 5] Software-Defined Radios
Multiband Transceivers - [Chapter 5]  Software-Defined RadiosMultiband Transceivers - [Chapter 5]  Software-Defined Radios
Multiband Transceivers - [Chapter 5] Software-Defined RadiosSimen Li
 
RF Module Design - [Chapter 7] Voltage-Controlled Oscillator
RF Module Design - [Chapter 7] Voltage-Controlled OscillatorRF Module Design - [Chapter 7] Voltage-Controlled Oscillator
RF Module Design - [Chapter 7] Voltage-Controlled OscillatorSimen Li
 
Multiband Transceivers - [Chapter 3] Basic Concept of Comm. Systems
Multiband Transceivers - [Chapter 3]  Basic Concept of Comm. SystemsMultiband Transceivers - [Chapter 3]  Basic Concept of Comm. Systems
Multiband Transceivers - [Chapter 3] Basic Concept of Comm. SystemsSimen Li
 
RF Module Design - [Chapter 5] Low Noise Amplifier
RF Module Design - [Chapter 5]  Low Noise AmplifierRF Module Design - [Chapter 5]  Low Noise Amplifier
RF Module Design - [Chapter 5] Low Noise AmplifierSimen Li
 
Multiband Transceivers - [Chapter 2] Noises and Linearities
Multiband Transceivers - [Chapter 2]  Noises and LinearitiesMultiband Transceivers - [Chapter 2]  Noises and Linearities
Multiband Transceivers - [Chapter 2] Noises and LinearitiesSimen Li
 
RF Module Design - [Chapter 3] Linearity
RF Module Design - [Chapter 3]  LinearityRF Module Design - [Chapter 3]  Linearity
RF Module Design - [Chapter 3] LinearitySimen Li
 
ADF4113 Frequency Synthesizer 驅動程式實作
ADF4113 Frequency Synthesizer 驅動程式實作ADF4113 Frequency Synthesizer 驅動程式實作
ADF4113 Frequency Synthesizer 驅動程式實作Simen Li
 
RF Module Design - [Chapter 4] Transceiver Architecture
RF Module Design - [Chapter 4] Transceiver ArchitectureRF Module Design - [Chapter 4] Transceiver Architecture
RF Module Design - [Chapter 4] Transceiver ArchitectureSimen Li
 
RF Module Design - [Chapter 6] Power Amplifier
RF Module Design - [Chapter 6]  Power AmplifierRF Module Design - [Chapter 6]  Power Amplifier
RF Module Design - [Chapter 6] Power AmplifierSimen Li
 
Multiband Transceivers - [Chapter 7] Multi-mode/Multi-band GSM/GPRS/TDMA/AMP...
Multiband Transceivers - [Chapter 7]  Multi-mode/Multi-band GSM/GPRS/TDMA/AMP...Multiband Transceivers - [Chapter 7]  Multi-mode/Multi-band GSM/GPRS/TDMA/AMP...
Multiband Transceivers - [Chapter 7] Multi-mode/Multi-band GSM/GPRS/TDMA/AMP...Simen Li
 
Multiband Transceivers - [Chapter 7] Spec. Table
Multiband Transceivers - [Chapter 7]  Spec. TableMultiband Transceivers - [Chapter 7]  Spec. Table
Multiband Transceivers - [Chapter 7] Spec. TableSimen Li
 
Multiband Transceivers - [Chapter 6] Multi-mode and Multi-band Transceivers
Multiband Transceivers - [Chapter 6] Multi-mode and Multi-band TransceiversMultiband Transceivers - [Chapter 6] Multi-mode and Multi-band Transceivers
Multiband Transceivers - [Chapter 6] Multi-mode and Multi-band TransceiversSimen Li
 
Multiband Transceivers - [Chapter 4] Design Parameters of Wireless Radios
Multiband Transceivers - [Chapter 4] Design Parameters of Wireless RadiosMultiband Transceivers - [Chapter 4] Design Parameters of Wireless Radios
Multiband Transceivers - [Chapter 4] Design Parameters of Wireless RadiosSimen Li
 
射頻電子 - [實驗第四章] 微波濾波器與射頻多工器設計
射頻電子 - [實驗第四章] 微波濾波器與射頻多工器設計射頻電子 - [實驗第四章] 微波濾波器與射頻多工器設計
射頻電子 - [實驗第四章] 微波濾波器與射頻多工器設計Simen Li
 
射頻電子 - [實驗第三章] 濾波器設計
射頻電子 - [實驗第三章] 濾波器設計射頻電子 - [實驗第三章] 濾波器設計
射頻電子 - [實驗第三章] 濾波器設計Simen Li
 
全端物聯網探索之旅 - 重點整理版
全端物聯網探索之旅 - 重點整理版全端物聯網探索之旅 - 重點整理版
全端物聯網探索之旅 - 重點整理版Simen Li
 

Andere mochten auch (20)

RF Module Design - [Chapter 8] Phase-Locked Loops
RF Module Design - [Chapter 8] Phase-Locked LoopsRF Module Design - [Chapter 8] Phase-Locked Loops
RF Module Design - [Chapter 8] Phase-Locked Loops
 
RF Module Design - [Chapter 1] From Basics to RF Transceivers
RF Module Design - [Chapter 1] From Basics to RF TransceiversRF Module Design - [Chapter 1] From Basics to RF Transceivers
RF Module Design - [Chapter 1] From Basics to RF Transceivers
 
Multiband Transceivers - [Chapter 1]
Multiband Transceivers - [Chapter 1] Multiband Transceivers - [Chapter 1]
Multiband Transceivers - [Chapter 1]
 
RF Module Design - [Chapter 2] Noises
RF Module Design - [Chapter 2] NoisesRF Module Design - [Chapter 2] Noises
RF Module Design - [Chapter 2] Noises
 
Multiband Transceivers - [Chapter 5] Software-Defined Radios
Multiband Transceivers - [Chapter 5]  Software-Defined RadiosMultiband Transceivers - [Chapter 5]  Software-Defined Radios
Multiband Transceivers - [Chapter 5] Software-Defined Radios
 
RF Module Design - [Chapter 7] Voltage-Controlled Oscillator
RF Module Design - [Chapter 7] Voltage-Controlled OscillatorRF Module Design - [Chapter 7] Voltage-Controlled Oscillator
RF Module Design - [Chapter 7] Voltage-Controlled Oscillator
 
Multiband Transceivers - [Chapter 3] Basic Concept of Comm. Systems
Multiband Transceivers - [Chapter 3]  Basic Concept of Comm. SystemsMultiband Transceivers - [Chapter 3]  Basic Concept of Comm. Systems
Multiband Transceivers - [Chapter 3] Basic Concept of Comm. Systems
 
RF Module Design - [Chapter 5] Low Noise Amplifier
RF Module Design - [Chapter 5]  Low Noise AmplifierRF Module Design - [Chapter 5]  Low Noise Amplifier
RF Module Design - [Chapter 5] Low Noise Amplifier
 
Multiband Transceivers - [Chapter 2] Noises and Linearities
Multiband Transceivers - [Chapter 2]  Noises and LinearitiesMultiband Transceivers - [Chapter 2]  Noises and Linearities
Multiband Transceivers - [Chapter 2] Noises and Linearities
 
RF Module Design - [Chapter 3] Linearity
RF Module Design - [Chapter 3]  LinearityRF Module Design - [Chapter 3]  Linearity
RF Module Design - [Chapter 3] Linearity
 
ADF4113 Frequency Synthesizer 驅動程式實作
ADF4113 Frequency Synthesizer 驅動程式實作ADF4113 Frequency Synthesizer 驅動程式實作
ADF4113 Frequency Synthesizer 驅動程式實作
 
RF Module Design - [Chapter 4] Transceiver Architecture
RF Module Design - [Chapter 4] Transceiver ArchitectureRF Module Design - [Chapter 4] Transceiver Architecture
RF Module Design - [Chapter 4] Transceiver Architecture
 
RF Module Design - [Chapter 6] Power Amplifier
RF Module Design - [Chapter 6]  Power AmplifierRF Module Design - [Chapter 6]  Power Amplifier
RF Module Design - [Chapter 6] Power Amplifier
 
Multiband Transceivers - [Chapter 7] Multi-mode/Multi-band GSM/GPRS/TDMA/AMP...
Multiband Transceivers - [Chapter 7]  Multi-mode/Multi-band GSM/GPRS/TDMA/AMP...Multiband Transceivers - [Chapter 7]  Multi-mode/Multi-band GSM/GPRS/TDMA/AMP...
Multiband Transceivers - [Chapter 7] Multi-mode/Multi-band GSM/GPRS/TDMA/AMP...
 
Multiband Transceivers - [Chapter 7] Spec. Table
Multiband Transceivers - [Chapter 7]  Spec. TableMultiband Transceivers - [Chapter 7]  Spec. Table
Multiband Transceivers - [Chapter 7] Spec. Table
 
Multiband Transceivers - [Chapter 6] Multi-mode and Multi-band Transceivers
Multiband Transceivers - [Chapter 6] Multi-mode and Multi-band TransceiversMultiband Transceivers - [Chapter 6] Multi-mode and Multi-band Transceivers
Multiband Transceivers - [Chapter 6] Multi-mode and Multi-band Transceivers
 
Multiband Transceivers - [Chapter 4] Design Parameters of Wireless Radios
Multiband Transceivers - [Chapter 4] Design Parameters of Wireless RadiosMultiband Transceivers - [Chapter 4] Design Parameters of Wireless Radios
Multiband Transceivers - [Chapter 4] Design Parameters of Wireless Radios
 
射頻電子 - [實驗第四章] 微波濾波器與射頻多工器設計
射頻電子 - [實驗第四章] 微波濾波器與射頻多工器設計射頻電子 - [實驗第四章] 微波濾波器與射頻多工器設計
射頻電子 - [實驗第四章] 微波濾波器與射頻多工器設計
 
射頻電子 - [實驗第三章] 濾波器設計
射頻電子 - [實驗第三章] 濾波器設計射頻電子 - [實驗第三章] 濾波器設計
射頻電子 - [實驗第三章] 濾波器設計
 
全端物聯網探索之旅 - 重點整理版
全端物聯網探索之旅 - 重點整理版全端物聯網探索之旅 - 重點整理版
全端物聯網探索之旅 - 重點整理版
 

Ähnlich wie Real-Time Clock chip DS1302 introduction

Design of Real - Time Operating System Using Keil µVision Ide
Design of Real - Time Operating System Using Keil µVision IdeDesign of Real - Time Operating System Using Keil µVision Ide
Design of Real - Time Operating System Using Keil µVision Ideiosrjce
 
Shellcoding in linux
Shellcoding in linuxShellcoding in linux
Shellcoding in linuxAjin Abraham
 
Virtual platform
Virtual platformVirtual platform
Virtual platformsean chen
 
Pragmatic Optimization in Modern Programming - Demystifying the Compiler
Pragmatic Optimization in Modern Programming - Demystifying the CompilerPragmatic Optimization in Modern Programming - Demystifying the Compiler
Pragmatic Optimization in Modern Programming - Demystifying the CompilerMarina Kolpakova
 
DSP_Assign_2 (Autosaved)
DSP_Assign_2 (Autosaved)DSP_Assign_2 (Autosaved)
DSP_Assign_2 (Autosaved)Joseph Chandler
 
Madeo - a CAD Tool for reconfigurable Hardware
Madeo - a CAD Tool for reconfigurable HardwareMadeo - a CAD Tool for reconfigurable Hardware
Madeo - a CAD Tool for reconfigurable HardwareESUG
 
RTI-CODES+ISSS-2012-Submission-1
RTI-CODES+ISSS-2012-Submission-1RTI-CODES+ISSS-2012-Submission-1
RTI-CODES+ISSS-2012-Submission-1Serge Amougou
 
Crash_Report_Mechanism_In_Tizen
Crash_Report_Mechanism_In_TizenCrash_Report_Mechanism_In_Tizen
Crash_Report_Mechanism_In_TizenLex Yu
 
Drizzles Approach To Improving Performance Of The Server
Drizzles  Approach To  Improving  Performance Of The  ServerDrizzles  Approach To  Improving  Performance Of The  Server
Drizzles Approach To Improving Performance Of The ServerPerconaPerformance
 
Trap Handling in Linux
Trap Handling in LinuxTrap Handling in Linux
Trap Handling in LinuxYongraeJo
 
Cadence GenusTutorial------------ .pdf.pdf
Cadence GenusTutorial------------ .pdf.pdfCadence GenusTutorial------------ .pdf.pdf
Cadence GenusTutorial------------ .pdf.pdfSamHoney6
 
Porting a Streaming Pipeline from Scala to Rust
Porting a Streaming Pipeline from Scala to RustPorting a Streaming Pipeline from Scala to Rust
Porting a Streaming Pipeline from Scala to RustEvan Chan
 
Julia - Easier, Better, Faster, Stronger
Julia - Easier, Better, Faster, StrongerJulia - Easier, Better, Faster, Stronger
Julia - Easier, Better, Faster, StrongerKenta Sato
 

Ähnlich wie Real-Time Clock chip DS1302 introduction (20)

Design of Real - Time Operating System Using Keil µVision Ide
Design of Real - Time Operating System Using Keil µVision IdeDesign of Real - Time Operating System Using Keil µVision Ide
Design of Real - Time Operating System Using Keil µVision Ide
 
Shellcoding in linux
Shellcoding in linuxShellcoding in linux
Shellcoding in linux
 
VLSI
VLSIVLSI
VLSI
 
VLSI
VLSIVLSI
VLSI
 
Lab6 rtos
Lab6 rtosLab6 rtos
Lab6 rtos
 
Virtual platform
Virtual platformVirtual platform
Virtual platform
 
Pragmatic Optimization in Modern Programming - Demystifying the Compiler
Pragmatic Optimization in Modern Programming - Demystifying the CompilerPragmatic Optimization in Modern Programming - Demystifying the Compiler
Pragmatic Optimization in Modern Programming - Demystifying the Compiler
 
Readme
ReadmeReadme
Readme
 
DSP_Assign_2 (Autosaved)
DSP_Assign_2 (Autosaved)DSP_Assign_2 (Autosaved)
DSP_Assign_2 (Autosaved)
 
Madeo - a CAD Tool for reconfigurable Hardware
Madeo - a CAD Tool for reconfigurable HardwareMadeo - a CAD Tool for reconfigurable Hardware
Madeo - a CAD Tool for reconfigurable Hardware
 
RTI-CODES+ISSS-2012-Submission-1
RTI-CODES+ISSS-2012-Submission-1RTI-CODES+ISSS-2012-Submission-1
RTI-CODES+ISSS-2012-Submission-1
 
Basics of building a blackfin application
Basics of building a blackfin applicationBasics of building a blackfin application
Basics of building a blackfin application
 
Vlsi lab2
Vlsi lab2Vlsi lab2
Vlsi lab2
 
Crash_Report_Mechanism_In_Tizen
Crash_Report_Mechanism_In_TizenCrash_Report_Mechanism_In_Tizen
Crash_Report_Mechanism_In_Tizen
 
Drizzles Approach To Improving Performance Of The Server
Drizzles  Approach To  Improving  Performance Of The  ServerDrizzles  Approach To  Improving  Performance Of The  Server
Drizzles Approach To Improving Performance Of The Server
 
Trap Handling in Linux
Trap Handling in LinuxTrap Handling in Linux
Trap Handling in Linux
 
Cadence GenusTutorial------------ .pdf.pdf
Cadence GenusTutorial------------ .pdf.pdfCadence GenusTutorial------------ .pdf.pdf
Cadence GenusTutorial------------ .pdf.pdf
 
Porting a Streaming Pipeline from Scala to Rust
Porting a Streaming Pipeline from Scala to RustPorting a Streaming Pipeline from Scala to Rust
Porting a Streaming Pipeline from Scala to Rust
 
Session1
Session1Session1
Session1
 
Julia - Easier, Better, Faster, Stronger
Julia - Easier, Better, Faster, StrongerJulia - Easier, Better, Faster, Stronger
Julia - Easier, Better, Faster, Stronger
 

Mehr von Simen Li

2018 VLSI/CAD Symposium Tutorial (Aug. 7, 20:00-21:00 Room 3F-VII)
2018 VLSI/CAD Symposium Tutorial (Aug. 7, 20:00-21:00 Room 3F-VII)2018 VLSI/CAD Symposium Tutorial (Aug. 7, 20:00-21:00 Room 3F-VII)
2018 VLSI/CAD Symposium Tutorial (Aug. 7, 20:00-21:00 Room 3F-VII)Simen Li
 
Node.js Event Loop & EventEmitter
Node.js Event Loop & EventEmitterNode.js Event Loop & EventEmitter
Node.js Event Loop & EventEmitterSimen Li
 
Voltage Controlled Oscillator Design - Short Course at NKFUST, 2013
Voltage Controlled Oscillator Design - Short Course at NKFUST, 2013Voltage Controlled Oscillator Design - Short Course at NKFUST, 2013
Voltage Controlled Oscillator Design - Short Course at NKFUST, 2013Simen Li
 
Phase-locked Loops - Theory and Design
Phase-locked Loops - Theory and DesignPhase-locked Loops - Theory and Design
Phase-locked Loops - Theory and DesignSimen Li
 
Agilent ADS 模擬手冊 [實習3] 壓控振盪器模擬
Agilent ADS 模擬手冊 [實習3] 壓控振盪器模擬Agilent ADS 模擬手冊 [實習3] 壓控振盪器模擬
Agilent ADS 模擬手冊 [實習3] 壓控振盪器模擬Simen Li
 
Agilent ADS 模擬手冊 [實習2] 放大器設計
Agilent ADS 模擬手冊 [實習2]  放大器設計Agilent ADS 模擬手冊 [實習2]  放大器設計
Agilent ADS 模擬手冊 [實習2] 放大器設計Simen Li
 
Agilent ADS 模擬手冊 [實習1] 基本操作與射頻放大器設計
Agilent ADS 模擬手冊 [實習1] 基本操作與射頻放大器設計Agilent ADS 模擬手冊 [實習1] 基本操作與射頻放大器設計
Agilent ADS 模擬手冊 [實習1] 基本操作與射頻放大器設計Simen Li
 
射頻電子實驗手冊 - [實驗8] 低雜訊放大器模擬
射頻電子實驗手冊 - [實驗8] 低雜訊放大器模擬射頻電子實驗手冊 - [實驗8] 低雜訊放大器模擬
射頻電子實驗手冊 - [實驗8] 低雜訊放大器模擬Simen Li
 
射頻電子實驗手冊 [實驗6] 阻抗匹配模擬
射頻電子實驗手冊 [實驗6] 阻抗匹配模擬射頻電子實驗手冊 [實驗6] 阻抗匹配模擬
射頻電子實驗手冊 [實驗6] 阻抗匹配模擬Simen Li
 
射頻電子實驗手冊 [實驗1 ~ 5] ADS入門, 傳輸線模擬, 直流模擬, 暫態模擬, 交流模擬
射頻電子實驗手冊 [實驗1 ~ 5] ADS入門, 傳輸線模擬, 直流模擬, 暫態模擬, 交流模擬射頻電子實驗手冊 [實驗1 ~ 5] ADS入門, 傳輸線模擬, 直流模擬, 暫態模擬, 交流模擬
射頻電子實驗手冊 [實驗1 ~ 5] ADS入門, 傳輸線模擬, 直流模擬, 暫態模擬, 交流模擬Simen Li
 

Mehr von Simen Li (10)

2018 VLSI/CAD Symposium Tutorial (Aug. 7, 20:00-21:00 Room 3F-VII)
2018 VLSI/CAD Symposium Tutorial (Aug. 7, 20:00-21:00 Room 3F-VII)2018 VLSI/CAD Symposium Tutorial (Aug. 7, 20:00-21:00 Room 3F-VII)
2018 VLSI/CAD Symposium Tutorial (Aug. 7, 20:00-21:00 Room 3F-VII)
 
Node.js Event Loop & EventEmitter
Node.js Event Loop & EventEmitterNode.js Event Loop & EventEmitter
Node.js Event Loop & EventEmitter
 
Voltage Controlled Oscillator Design - Short Course at NKFUST, 2013
Voltage Controlled Oscillator Design - Short Course at NKFUST, 2013Voltage Controlled Oscillator Design - Short Course at NKFUST, 2013
Voltage Controlled Oscillator Design - Short Course at NKFUST, 2013
 
Phase-locked Loops - Theory and Design
Phase-locked Loops - Theory and DesignPhase-locked Loops - Theory and Design
Phase-locked Loops - Theory and Design
 
Agilent ADS 模擬手冊 [實習3] 壓控振盪器模擬
Agilent ADS 模擬手冊 [實習3] 壓控振盪器模擬Agilent ADS 模擬手冊 [實習3] 壓控振盪器模擬
Agilent ADS 模擬手冊 [實習3] 壓控振盪器模擬
 
Agilent ADS 模擬手冊 [實習2] 放大器設計
Agilent ADS 模擬手冊 [實習2]  放大器設計Agilent ADS 模擬手冊 [實習2]  放大器設計
Agilent ADS 模擬手冊 [實習2] 放大器設計
 
Agilent ADS 模擬手冊 [實習1] 基本操作與射頻放大器設計
Agilent ADS 模擬手冊 [實習1] 基本操作與射頻放大器設計Agilent ADS 模擬手冊 [實習1] 基本操作與射頻放大器設計
Agilent ADS 模擬手冊 [實習1] 基本操作與射頻放大器設計
 
射頻電子實驗手冊 - [實驗8] 低雜訊放大器模擬
射頻電子實驗手冊 - [實驗8] 低雜訊放大器模擬射頻電子實驗手冊 - [實驗8] 低雜訊放大器模擬
射頻電子實驗手冊 - [實驗8] 低雜訊放大器模擬
 
射頻電子實驗手冊 [實驗6] 阻抗匹配模擬
射頻電子實驗手冊 [實驗6] 阻抗匹配模擬射頻電子實驗手冊 [實驗6] 阻抗匹配模擬
射頻電子實驗手冊 [實驗6] 阻抗匹配模擬
 
射頻電子實驗手冊 [實驗1 ~ 5] ADS入門, 傳輸線模擬, 直流模擬, 暫態模擬, 交流模擬
射頻電子實驗手冊 [實驗1 ~ 5] ADS入門, 傳輸線模擬, 直流模擬, 暫態模擬, 交流模擬射頻電子實驗手冊 [實驗1 ~ 5] ADS入門, 傳輸線模擬, 直流模擬, 暫態模擬, 交流模擬
射頻電子實驗手冊 [實驗1 ~ 5] ADS入門, 傳輸線模擬, 直流模擬, 暫態模擬, 交流模擬
 

Kürzlich hochgeladen

Immutable Image-Based Operating Systems - EW2024.pdf
Immutable Image-Based Operating Systems - EW2024.pdfImmutable Image-Based Operating Systems - EW2024.pdf
Immutable Image-Based Operating Systems - EW2024.pdfDrew Moseley
 
Forming section troubleshooting checklist for improving wire life (1).ppt
Forming section troubleshooting checklist for improving wire life (1).pptForming section troubleshooting checklist for improving wire life (1).ppt
Forming section troubleshooting checklist for improving wire life (1).pptNoman khan
 
Turn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptxTurn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptxStephen Sitton
 
Input Output Management in Operating System
Input Output Management in Operating SystemInput Output Management in Operating System
Input Output Management in Operating SystemRashmi Bhat
 
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTFUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTSneha Padhiar
 
Analysis and Evaluation of Dal Lake Biomass for Conversion to Fuel/Green fert...
Analysis and Evaluation of Dal Lake Biomass for Conversion to Fuel/Green fert...Analysis and Evaluation of Dal Lake Biomass for Conversion to Fuel/Green fert...
Analysis and Evaluation of Dal Lake Biomass for Conversion to Fuel/Green fert...arifengg7
 
Prach: A Feature-Rich Platform Empowering the Autism Community
Prach: A Feature-Rich Platform Empowering the Autism CommunityPrach: A Feature-Rich Platform Empowering the Autism Community
Prach: A Feature-Rich Platform Empowering the Autism Communityprachaibot
 
US Department of Education FAFSA Week of Action
US Department of Education FAFSA Week of ActionUS Department of Education FAFSA Week of Action
US Department of Education FAFSA Week of ActionMebane Rash
 
The Satellite applications in telecommunication
The Satellite applications in telecommunicationThe Satellite applications in telecommunication
The Satellite applications in telecommunicationnovrain7111
 
Mine Environment II Lab_MI10448MI__________.pptx
Mine Environment II Lab_MI10448MI__________.pptxMine Environment II Lab_MI10448MI__________.pptx
Mine Environment II Lab_MI10448MI__________.pptxRomil Mishra
 
SOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATIONSOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATIONSneha Padhiar
 
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMS
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMSHigh Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMS
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMSsandhya757531
 
Python Programming for basic beginners.pptx
Python Programming for basic beginners.pptxPython Programming for basic beginners.pptx
Python Programming for basic beginners.pptxmohitesoham12
 
"Exploring the Essential Functions and Design Considerations of Spillways in ...
"Exploring the Essential Functions and Design Considerations of Spillways in ..."Exploring the Essential Functions and Design Considerations of Spillways in ...
"Exploring the Essential Functions and Design Considerations of Spillways in ...Erbil Polytechnic University
 
Detection&Tracking - Thermal imaging object detection and tracking
Detection&Tracking - Thermal imaging object detection and trackingDetection&Tracking - Thermal imaging object detection and tracking
Detection&Tracking - Thermal imaging object detection and trackinghadarpinhas1
 
KCD Costa Rica 2024 - Nephio para parvulitos
KCD Costa Rica 2024 - Nephio para parvulitosKCD Costa Rica 2024 - Nephio para parvulitos
KCD Costa Rica 2024 - Nephio para parvulitosVictor Morales
 
Novel 3D-Printed Soft Linear and Bending Actuators
Novel 3D-Printed Soft Linear and Bending ActuatorsNovel 3D-Printed Soft Linear and Bending Actuators
Novel 3D-Printed Soft Linear and Bending ActuatorsResearcher Researcher
 
Substation Automation SCADA and Gateway Solutions by BRH
Substation Automation SCADA and Gateway Solutions by BRHSubstation Automation SCADA and Gateway Solutions by BRH
Substation Automation SCADA and Gateway Solutions by BRHbirinder2
 
TEST CASE GENERATION GENERATION BLOCK BOX APPROACH
TEST CASE GENERATION GENERATION BLOCK BOX APPROACHTEST CASE GENERATION GENERATION BLOCK BOX APPROACH
TEST CASE GENERATION GENERATION BLOCK BOX APPROACHSneha Padhiar
 

Kürzlich hochgeladen (20)

Immutable Image-Based Operating Systems - EW2024.pdf
Immutable Image-Based Operating Systems - EW2024.pdfImmutable Image-Based Operating Systems - EW2024.pdf
Immutable Image-Based Operating Systems - EW2024.pdf
 
Forming section troubleshooting checklist for improving wire life (1).ppt
Forming section troubleshooting checklist for improving wire life (1).pptForming section troubleshooting checklist for improving wire life (1).ppt
Forming section troubleshooting checklist for improving wire life (1).ppt
 
Turn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptxTurn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptx
 
Input Output Management in Operating System
Input Output Management in Operating SystemInput Output Management in Operating System
Input Output Management in Operating System
 
Versatile Engineering Construction Firms
Versatile Engineering Construction FirmsVersatile Engineering Construction Firms
Versatile Engineering Construction Firms
 
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTFUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
 
Analysis and Evaluation of Dal Lake Biomass for Conversion to Fuel/Green fert...
Analysis and Evaluation of Dal Lake Biomass for Conversion to Fuel/Green fert...Analysis and Evaluation of Dal Lake Biomass for Conversion to Fuel/Green fert...
Analysis and Evaluation of Dal Lake Biomass for Conversion to Fuel/Green fert...
 
Prach: A Feature-Rich Platform Empowering the Autism Community
Prach: A Feature-Rich Platform Empowering the Autism CommunityPrach: A Feature-Rich Platform Empowering the Autism Community
Prach: A Feature-Rich Platform Empowering the Autism Community
 
US Department of Education FAFSA Week of Action
US Department of Education FAFSA Week of ActionUS Department of Education FAFSA Week of Action
US Department of Education FAFSA Week of Action
 
The Satellite applications in telecommunication
The Satellite applications in telecommunicationThe Satellite applications in telecommunication
The Satellite applications in telecommunication
 
Mine Environment II Lab_MI10448MI__________.pptx
Mine Environment II Lab_MI10448MI__________.pptxMine Environment II Lab_MI10448MI__________.pptx
Mine Environment II Lab_MI10448MI__________.pptx
 
SOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATIONSOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATION
 
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMS
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMSHigh Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMS
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMS
 
Python Programming for basic beginners.pptx
Python Programming for basic beginners.pptxPython Programming for basic beginners.pptx
Python Programming for basic beginners.pptx
 
"Exploring the Essential Functions and Design Considerations of Spillways in ...
"Exploring the Essential Functions and Design Considerations of Spillways in ..."Exploring the Essential Functions and Design Considerations of Spillways in ...
"Exploring the Essential Functions and Design Considerations of Spillways in ...
 
Detection&Tracking - Thermal imaging object detection and tracking
Detection&Tracking - Thermal imaging object detection and trackingDetection&Tracking - Thermal imaging object detection and tracking
Detection&Tracking - Thermal imaging object detection and tracking
 
KCD Costa Rica 2024 - Nephio para parvulitos
KCD Costa Rica 2024 - Nephio para parvulitosKCD Costa Rica 2024 - Nephio para parvulitos
KCD Costa Rica 2024 - Nephio para parvulitos
 
Novel 3D-Printed Soft Linear and Bending Actuators
Novel 3D-Printed Soft Linear and Bending ActuatorsNovel 3D-Printed Soft Linear and Bending Actuators
Novel 3D-Printed Soft Linear and Bending Actuators
 
Substation Automation SCADA and Gateway Solutions by BRH
Substation Automation SCADA and Gateway Solutions by BRHSubstation Automation SCADA and Gateway Solutions by BRH
Substation Automation SCADA and Gateway Solutions by BRH
 
TEST CASE GENERATION GENERATION BLOCK BOX APPROACH
TEST CASE GENERATION GENERATION BLOCK BOX APPROACHTEST CASE GENERATION GENERATION BLOCK BOX APPROACH
TEST CASE GENERATION GENERATION BLOCK BOX APPROACH
 

Real-Time Clock chip DS1302 introduction

  • 1. Chien-Jung Li Nov. 2013 MCS-51 基礎實習 使用IAR Embedded Workbench (III)
  • 3. DS1302 RTC介紹 3  DS1302是美國DALLAS公司生產的即時時鐘電路(Real- time clock, RTC),它可對年、月、日、周日、時、分、 秒進行計時並具有閏年補償功能,而且也有24小時制 與12小時制(AM/PM)的選擇。  工作電壓為 2.0V~5.5V,採用三線通訊介面(3-wire interface)。內部具有31 Bytes的SRAM。  DS1302具有主電源/備用電源的雙電源引腳(VCC1為後備 電源,VCC2為主電源,由VCC1 或VCC2 兩者中的較大者 供電),同時提供對備用電源進行涓流充電的能力。  X1和X2外接32.768 kHz的石英振盪器。RST是重置/晶片 選擇腳,對RST輸入Low重置晶片而將RST設為High可啟 動所有資料傳送。
  • 4. DS1302 RTC的RST/CE接腳功能 4  RST/CE輸入有兩種功能:  RST接至控制邏輯,允許位址/命令序列送入移位暫存器  RST提供終止資料傳送。當RST為高電壓時,所有的數據傳送被初始化, 允許對DS1302進行操作。如果在傳送過程中RST置為低電壓,則會終止 此次資料傳送,I/O引腳變為高阻態。  啟動運行時,在VCC>2.0V之前,RST必須保持低電位。只有在SCLK為低 電位時,才能將RST置為高電位。I/O為串列資料輸出端(雙向)。SCLK為 時鐘輸入端。 40 kΩ pull-down
  • 5. DS1302之指令 – Command Byte 5  Command Byte用於初始化每次的資料傳輸,bit-0必 定為input staring。
  • 6. 3-Wire通訊介面的讀寫 6 Burst mode: command byte bit1~5 = 11111’b = 31(decimal) Reads or writes in burst mode start with bit 0 of address 0.
  • 10. 實習11 10  目標:製作一個電子時鐘,將日期與時間顯示在LCD上。 這是我們第一次要同時控制兩個較複雜的裝置,它們 的驅動程式如果寫在一個.c檔,程式檔會變很龐大。現 在我們要開始學習如何管理程式碼,這是進入商用產 品開發的第一站。  DS1302 RTC使用3-wire介面與MCU通訊  LCD使用LCD1602A的訊號介面與MCU通訊  練習1: 結構化你的程式碼  練習2: 加入LCD的驅動程式  練習3: 練習撰寫API手冊(以LCD驅動程式為例)  練習4: 加入3-wire通訊介面與DS1302的驅動程式  練習5: 完成電子時鐘
  • 13. 閃爍LED燈 – 最簡單的寫法 13 #include<ioAT89C52.h> typedef unsigned char uint8; void delayms(uint8); void main(void) { P1_bit.P1_0 = 1; while(1) { P1_bit.P1_0 = 0; delayms(250); P1_bit.P1_0 = 1; delayms(250); } } #include<ioAT89C52.h> #define LED0 P1_bit.P1_0 typedef unsigned char uint8; void delayms(uint8); void main(void) { LED0 = 1; while(1) { LED0 = 0; delayms(250); LED0 = 1; delayms(250); } }
  • 14. 閃爍LED燈 – 使用機板標頭檔 14 // ioMapping.h #define LED_REGISTER P0 #define LED_BIT (1 << 0) #include<ioAT89C52.h> #include "ioMapping.h" typedef unsigned char uint8; void delayms(uint8); void main(void) { LED_REGISTER |= LED_BIT; while(1) { LED_REGISTER &= ~LED_BIT; delayms(250); LED_REGISTER |= LED_BIT; delayms(250); } }
  • 15. 閃爍LED燈 – 通用機板標頭檔 15 #include<ioAT89C52.h> #include "ioMapping.h" typedef unsigned char uint8; void delayms(uint8); void main(void) { LED_REGISTER |= LED_BIT; while(1) { LED_REGISTER &= ~LED_BIT; delayms(250); LED_REGISTER |= LED_BIT; delayms(250); } } // ioMapping.h #if COMPILING_BOARD_V1 #include "ioMapping_v1.h" #elif COMPILING_BOARD_V2 #include "ioMapping_v2.h" #else #error "No I/O map selected for the board" #endif // ioMapping_v1.h #define LED_REGISTER P0 #define LED_BIT (1 << 0) // ioMapping_v2.h #define LED_REGISTER P3 #define LED_BIT (1 << 4)
  • 17. 閃爍LED燈 – Facade模式 17  LED的I/O子系統介面與內容,就是LED的驅動程式  隱藏子系統的細節是良好設計中十分重要的一環, 呼叫端的程式不會依賴子系統的細節 Main
  • 21. 避免競賽情況 – 使用mutex 21  任何工作間共享的記憶體不論是讀取或寫入,都要在 程式中建立臨界區域(critical section),表示正在存取共 享資源(記憶體或設備),必須保護共享資源,同一時間 只能讓一個工作修改,稱為互斥(mutual exclusion),簡 寫為mutex。  對於包含OS的系統,當兩個非中斷工作同時執行時, 能夠透過mutex表示兩個工作共享相同的資源,只需要 簡單地透過變數表示資源(或全域變數)可以供其他工作 使用就行了。  當其中之一是中斷時,資源所有權的改變必須是單元 動作(atomic),單元動作是指無法被系統其他部分中斷 的動作。
  • 22. 結構化你的程式碼: Source Tree 22  Source Tree: 擺放原始碼檔案的目錄結構,基本原則是一個目錄可以對應到系 統架構中的一個方塊。  還記得我們在學C語言時,可以藉由撰寫Makefile來幫 助我們同時編譯多個原始碼嗎?  在開發系統時,你必須告訴寫Makefile的工程師那些要 編譯的檔案放在哪裡,source tree結構規範就是在告訴 工程師這件事。  寫Makefile這件事情有點麻煩,幸好我們有IDE開發環境 可以使用,我們只要將各種原始碼檔案分門別類放好, 再告訴IDE這些東西的Path在哪裡,剩下的就交給它吧!
  • 23. 常見目錄名稱的意思 23 • /Driver: 驅動程式目錄 (有時也會用/hal) /Boot-Loader: 開機程式 /Hardware: 各種硬體裝置的驅動程式 /Include: 驅動程式的header files /API: 將所有驅動程式包裝成API /Boot: Boot程式 /LCD: LCD程式 /SDRAM: SDRAM驅動程式 • /System: 系統程式 /Include: 系統程式的header files /API: 將所有系統程式包裝成API /Common: 系統中的通用功能 /RTOS: 嵌入式OS的目錄 /Include: RTOS的header /Memory: 記憶體管理 /Sync: Task間同步機制 /IPC: Task間通訊機制 /Glib: 圖形函式庫 /Sub-System:各種子系統 /GUI: 圖形用戶介面 /TCPIP: TCPIP通訊堆疊 /FileSystem: 檔案系統 • /AP: 應用程式 (或/APP) /Include: 應用程式的header files /Source: 應用程式的原始碼 /Common: 應用程式的通用功能 /AP1: 應用程式1 /AP2: 應用程式2 /Resource: 應用程式的圖形、字串資源 • /Third_Party_Lib: 第三方函式庫 /HandWriting: 手寫辨識函式庫 /Fonts: 字型 /VoiceComp: 聲音壓縮函式庫 • /Include: header, sys_config.h(系統配置檔) • /Build: 製作映像檔(執行檔)的東西, 如makefile跟link script • /Tools: 開發中所需的程式,例如compiler • /Documents: 開發規範、datasheet、user guide、 Spec, API手冊等
  • 31. hal_types.h /***************************************************** Filename: hal_types.h Revised: $Date: 2013-10-18 15:20 $ 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 D:MySimpSystemhaltargetJC51B
  • 32. hal_mcu.h 32 /************************************************************** Filename: hal_mcu.h 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_defs.h" #include "hal_types.h" /* Target Defines */ #define HAL_MCU_AT89C52 /* Compiler Abstraction */ /* ---------------------- IAR Compiler ---------------------- */ #ifdef __IAR_SYSTEMS_ICC__ #include <ioAT89C52.h> #define HAL_COMPILER_IAR #define HAL_MCU_LITTLE_ENDIAN() __LITTLE_ENDIAN__ #define _PRAGMA(x) _Pragma(#x) #define HAL_ISR_FUNC_DECLARATION(f,v) _PRAGMA(vector=v) __near_func __interrupt void f(void) #define HAL_ISR_FUNC_PROTOTYPE(f,v) _PRAGMA(vector=v) __near_func __interrupt void f(void) #define HAL_ISR_FUNCTION(f,v) HAL_ISR_FUNC_PROTOTYPE(f,v); HAL_ISR_FUNC_DECLARATION(f,v) /* ---------------------- Keil Compiler ---------------------- */ #elif defined __KEIL__ #include <reg51.h> D:MySimpSystemhaltargetJC51B #define HAL_COMPILER_KEIL #define HAL_MCU_LITTLE_ENDIAN() 0 #define HAL_ISR_FUNC_DECLARATION(f,v) void f(void) interrupt v #define HAL_ISR_FUNC_PROTOTYPE(f,v) void f(void) #define HAL_ISR_FUNCTION(f,v) HAL_ISR_FUNC_PROTOTYPE(f,v); HAL_ISR_FUNC_DECLARATION(f,v) /* ------------ Unrecognized Compiler ---------- */ #else #error "ERROR: Unknown compiler." #endif #pragma vector = extern0 __interrupt void Int_Extern0(void)
  • 33. 33 /* Interrupt Macros */ #define HAL_ENABLE_INTERRUPTS() st( IE_bit.EA = 1; ) #define HAL_DISABLE_INTERRUPTS() st( IE_bit.EA = 0; ) #define HAL_INTERRUPTS_ARE_ENABLED() (IE_bit.EA) typedef unsigned char halIntState_t; #define HAL_ENTER_CRITICAL_SECTION(x) st( x = IE_bit.EA; HAL_DISABLE_INTERRUPTS(); ) #define HAL_EXIT_CRITICAL_SECTION(x) st( IE_bit.EA = 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_bit.EA = _isrIntState; } #else #define HAL_ENTER_ISR() #define HAL_EXIT_ISR() #endif /* __IAR_SYSTEMS_ICC__ */ /************************************************************************************************** */ #endif
  • 34. hal_board.h & hal_board_cfg.h 34 D:MySimpSystemhalinclude D:MySimpSystemhaltargetJC51B #include "hal_board_cfg.h" /********************************************* Filename: hal_board_cfg.h 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_mcu.h" #include "hal_defs.h" #include "hal_types.h" #endif /********************************************* */
  • 35. hal_defs.h 35 /***************************************************************** Filename: hal_defs.h Revised: $Date: 2013-10-18 14:48 $ 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 << (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) >>((ByteNum) * 8)) & 0x00FF)) #define BUILD_UINT32(Byte0, Byte1, Byte2, Byte3) ((uint32)((uint32)((Byte0) & 0x00FF) + ((uint32)((Byte1) & 0x00FF) << 8) + ((uint32)((Byte2) & 0x00FF) << 16) + ((uint32)((Byte3) & 0x00FF) << 24))) #define BUILD_UINT16(loByte, hiByte) ((uint16)(((loByte) & 0x00FF) + (((hiByte) & 0x00FF) << 8))) #define HI_UINT16(a) (((a) >> 8) & 0xFF) #define LO_UINT16(a) ((a) & 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 D:MySimpSystemhalinclude
  • 36. hal_drivers.h 36 /**************************************************** Filename: hal_drivers.h Revised: $Date: 2013-10-18 14:52 $ 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 D:MySimpSystemhalinclude
  • 37. 練習2: 加入LCD的驅動程式 #include<ioAT89C52.h> #define BTN1 P3_bit.P3_2 #define BTN2 P3_bit.P3_3 #define LCD_RW P1_bit.P1_1 #define LCD_EN P3_bit.P3_4 #define LCD_RS P3_bit.P3_5 #define LCD_BF P0_bit.P0_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; D:MySimpSystemhalinclude /* 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. 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. 39 D:MySimpSystemhaltargetJC51B /********************************************* Filename: hal_lcd.c Revised: $Date: 2013-10-19 16:21 $ Revision: $Revision: $ Description: *********************************************/ /******* INCLUDES *******/ #include "hal_board_cfg.h" #include "hal_defs.h" #include "hal_types.h" #include "hal_lcd.h" /******* 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 – 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) … #endif
  • 40. 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. 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. 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
  • 43. 將delayms()放到common driver 43 /************************************************************************* Filename: hal_drivers.h Revised: $Date: 2013-10-18 14:52 $ 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 D:MySimpSystemhalinclude
  • 44. 44 D:MySimpSystemhalcommon /**************************************************************************** Filename: hal_drivers.c Revised: $Date: 20103-10-19 17:00 $ Revision: $Revision: $ Description: This file contains the common functions used by the driver *****************************************************************************/ /******** INCLUDES *************/ #include "hal_types.h" #include "hal_drivers.h" #include "hal_lcd.h" /******** FUNCTIONS – 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(time>0) { n = 162; while(n>0) n--; time --; } } /***************************************************** * @fn HalDriverInit * @brief Initialize HW * @param None * @return None ******************************************************/ void HalDriverInit (void) { #if (defined HAL_LCD) && (HAL_LCD == TRUE) LCD_Init(2, 16); #endif }
  • 45. 修改hal_board_cfg.h 45 /*************************************************************** Filename: hal_board_cfg.h 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_mcu.h" #include "hal_defs.h" #include "hal_types.h" #include "hal_lcd.h" /* -------- Driver Configuration -------- */ /* Set to TRUE enable LCD usage, FALSE disable it */ #ifndef HAL_LCD #define HAL_LCD TRUE #endif #endif /********************************************************************************** */
  • 46. 準備加入按鍵驅動程式 46  先修改一下hal_board_cfg.h的內容 /*************************************************************** Filename: hal_board_cfg.h 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_mcu.h" #include "hal_defs.h" #include "hal_types.h" #include "hal_lcd.h" #include "hal_key.h" /* ---- 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_bit.P3_2 // INT0 #define PUSH1_POLARITY ACTIVE_LOW /* BTN2 */ #define PUSH2_BV BV(3) #define PUSH2_SBIT P3_bit.P3_3 // INT1 #define PUSH2_POLARITY ACTIVE_LOW /* BTN3 */ #define PUSH3_BV BV(4) #define PUSH3_SBIT P3_bit.P3_4 // T0 #define PUSH3_POLARITY ACTIVE_LOW /* BTN4 */ #define PUSH4_BV BV(5) #define PUSH4_SBIT P3_bit.P3_5 // T1 #define PUSH4_POLARITY ACTIVE_LOW
  • 47. 47 /* ----- Macros ------*/ // ---- Debounce ---- // #define HAL_DEBOUNCE(expr) { int i; for (i=0; i<500; 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. 加入按鍵的驅動程式 48 /********************************************************************** Filename: hal_key.h Revised: $Date: 2013-10-19 17:51 $ Revision: $Revision: $ Description: This file contains the interface to the KEY Service. ***********************************************************************/ #ifndef HAL_KEY_H #define HAL_KEY_H /****** INCLUDES ******/ #include "hal_board.h" /****** 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 – 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 D:MySimpSystemhalinclude
  • 49. 49 /********************************************* Filename: hal_key.c Revised: $Date: 2013-10-19 22:27 $ Revision: $Revision: $ Description: HAL KEY Service. **********************************************/ /******* INCLUDES **********/ #include "hal_mcu.h" #include "hal_defs.h" #include "hal_types.h" #include "hal_board.h" #include "hal_drivers.h" #include "hal_key.h" #if (defined HAL_KEY) && (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 enable/disable*/ #define HAL_KEY_CPU_IE IE D:MySimpSystemhaltargetJC51B /********* Key 1 ************/ /* SW_1 is at P3.2 */ #define HAL_KEY_SW_1_PORT PUSH1_SBIT /* edge interrupt */ #define HAL_KEY_SW_1_EDGEBIT BV(0) // TCON => 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_bit.IE0 /********* Key 2 ************/ /* SW_2 is at P3.3 */ #define HAL_KEY_SW_2_PORT PUSH2_SBIT /* edge interrupt */ #define HAL_KEY_SW_2_EDGEBIT BV(2) // TCON => 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_bit.IE1 /********* Key 3 ************/ /* SW_3 is at P3.4, Key3 has no interrupt */ #define HAL_KEY_SW_3_PORT PUSH3_SBIT /********* Key 4 ************/ /* SW_4 is at P3.5, Key4 has no interrupt */ #define HAL_KEY_SW_4_PORT PUSH4_SBIT
  • 50. /******** GLOBAL VARIABLES ********/ static uint8 HalKeyConfigured; /* interrupt enable/disable flag */ bool Hal_KeyIntEnable; /******* FUNCTIONS – 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) { /* Enable/Disable 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 ************/ /* Rising/Falling edge configuration */ HAL_KEY_CPU_TCON &= ~(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 ************/ /* Rising/Falling edge configuration */ HAL_KEY_CPU_TCON &= ~(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
  • 51. } else { /* Interrupts NOT enabled */ HAL_KEY_CPU_IE &= ~(HAL_KEY_SW_1_IEBIT); HAL_KEY_SW_1_IFG = 0; HAL_KEY_CPU_IE &= ~(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. 52 #else void HalKeyInit(void) { } void HalKeyConfig(bool interruptEnable) { } uint8 HalKeyRead(void) { return 0; } #endif /* HAL_KEY */ /****************************************************************** ******************************************************************/
  • 54. 在進行RTC實驗之前 54  我們現在有按鍵跟LCD驅動程式,何不寫一個應用 程式,完成如exercise4-03.c的進度條顯示程式。 D:MySimpSystemProjectsMyAPP1Source #include "hal_types.h" #include "hal_drivers.h" #include "hal_board_cfg.h" #include "MyAPP1.h" 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=0;i<101;i++) { num[0] = (i/100)+0x30; num[1] = ((i/10)%10)+0x30; num[2] = (i%10)+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 = (i*100/125); LCD_DispHorBar(1, 0, percent_bar); delayms(200); } } } }
  • 55. 顯現電路板設定組態檔的威力  將driver與硬體I/O相關的設定移到hal_borad_cfg.h #define LCD_RW P1_bit.P1_1 #define LCD_EN P3_bit.P3_4 #define LCD_RS P3_bit.P3_5 #define LCD_BF P0_bit.P0_7 #define LCD_DATA_PORT P0 /**************************************************** Filename: hal_board_cfg.h *****************************************************/ #ifndef HAL_BOARD_CFG_H 略 /* BTN1 */ #define PUSH1_BV BV(2) #define PUSH1_SBIT P3_bit.P3_2 // INT0 #define PUSH1_POLARITY ACTIVE_LOW /* BTN2 */ #define PUSH2_BV BV(3) #define PUSH2_SBIT P3_bit.P3_3 // INT1 #define PUSH2_POLARITY ACTIVE_LOW /* BTN3 */ #define PUSH3_BV BV(4) #define PUSH3_SBIT P3_bit.P3_4 // T0 #define PUSH3_POLARITY ACTIVE_LOW /* BTN4 */ #define PUSH4_BV BV(5) #define PUSH4_SBIT P3_bit.P3_5 // T1 #define PUSH4_POLARITY ACTIVE_LOW /* -- LCD I/O Configuration --*/ #define LCD_RW P1_bit.P1_1 #define LCD_EN P3_bit.P3_4 #define LCD_RS P3_bit.P3_5 #define LCD_BF P0_bit.P0_7 #define LCD_DATA_PORT P0 55
  • 57. 57
  • 58. 58
  • 59. 59
  • 60. 60
  • 61. 61
  • 62. 為RTC準備什麼 62  3-wire通訊介面的驅動程式  DS1302的驅動程式  寫完後將他們一一加入project的group  修改hal_board_cfg.h  寫出RTC的應用程式
  • 63. 練習4: 加入3-wire通訊介面Driver 63 /************************************************************************* Filename: hal_triwire.h 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_board.h" /**** CONSTANTS ****/ /* 3-Wire delay */ #define TriWireDELAY 10 /**** FUNCTIONS – 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
  • 64. 加入3-wire的driver: hal_triwire.c 64 /********************************************************************** Filename: hal_triwire.c Revised: $Date: 2013-10-18 21:07 $ Revision: $Revision: $ Description: This file contains the interface to the 3-wire driver. **********************************************************************/ /********* INCLUDES ***********/ #include "hal_board_cfg.h" #include "hal_defs.h" #include "hal_types.h“ #include "hal_drivers.h" #include "hal_triwire.h" /********* 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);
  • 65. /********************************************************* * @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 < 8; index++) { TriWire_SCLK = LOW; if(output_data & 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 >> 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 < 8; index++) { input_data = input_data >> 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. 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 byte@Reg_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) … #endif
  • 67. Add file與修改hal_board_cfg.h 67 /* ---------------------------------------------- * 3-Wire Port Configuration * ---------------------------------------------- */ #define TriWire_SCLK P1_bit.P1_4 #define TriWire_IO P1_bit.P1_2 #define TriWire_RST P1_bit.P1_3
  • 68. 測試驅動程式 (I) 68  寫一個應用程式,測試3-wire的驅動程式 #include "MyAPP1.h" 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
  • 73. 加入DS1302 RTC驅動程式 /************************************************************* Filename: hal_ds1302.h 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_board.h" /***** 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 – API ******/ extern void DS1302_Init(void); extern void DS1302_ReadTime(SYSTEMTIME *Time); extern void DS1302_WriteTime(SYSTEMTIME *Time); #endif 73
  • 74. 74 /********************************************* Filename: hal_ds1302.c Revised: $Date: 2013-10-18 21:36 $ Revision: $Revision: $ ********************************************/ /***** INCLUDES ******/ #include "hal_board_cfg.h" #include "hal_defs.h" #include "hal_types.h" #include "hal_drivers.h" #include "hal_triwire.h" #include "hal_ds1302.h" /***** 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) & REG_MASK_CH; if(Clock_halt) { TriWire_Write(DS1302_WP , DS1302_WR_ON); // Allow write // Write initial date and time: 2013/11/12, TUE, 23:59:55 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 } }
  • 75. /************************************************************************************************* * @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->Second = FormatReg2Dec(ReadValue, REG_MASK_SECOND); ReadValue = TriWire_Read(DS1302_MINUTE+1); Time->Minute = FormatReg2Dec(ReadValue, REG_MASK_MINUTE); ReadValue = TriWire_Read(DS1302_HOUR+1); Time->Hour = FormatReg2Dec(ReadValue, REG_MASK_HOUR); Time->Hourmode = ReadValue & REG_MASK_HOUR_MODE; ReadValue = TriWire_Read(DS1302_DATE+1); Time->Date = FormatReg2Dec(ReadValue, REG_MASK_DATE); ReadValue = TriWire_Read(DS1302_MONTH+1); Time->Month = FormatReg2Dec(ReadValue, REG_MASK_MONTH); ReadValue = TriWire_Read(DS1302_WEEKDAY+1); Time->Weekday = FormatReg2Dec(ReadValue, REG_MASK_WEEKDAY); ReadValue = TriWire_Read(DS1302_YEAR+1); Time->Year = FormatReg2Dec(ReadValue, REG_MASK_YEAR); DateToStr(Time); TimeToStr(Time); } 75
  • 76. 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->Year) ); TriWire_Write(DS1302_MONTH , FormatDec2Reg(Time->Month) ); TriWire_Write(DS1302_DATE , FormatDec2Reg(Time->Date) ); TriWire_Write(DS1302_WEEKDAY, FormatDec2Reg(Time->Weekday)); TriWire_Write(DS1302_HOUR , FormatDec2Reg(Time->Hour) ); TriWire_Write(DS1302_MINUTE , FormatDec2Reg(Time->Minute) ); TriWire_Write(DS1302_SECOND , FormatDec2Reg(Time->Second) ); 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 & reg_mask) >> 4)*10 + (reg_data & 0x0F); return(DecValue); }
  • 77. /******************************************************************** * @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_data/10)*16 + dec_data%10; 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->DateString[0] = '2'; Time->DateString[1] = '0'; Time->DateString[2] = Time->Year/10 + 0x30; // '0' : ASCII = 0x30 Time->DateString[3] = Time->Year%10 + 0x30; Time->DateString[4]='-'; Time->DateString[5] = Time->Month/10 + 0x30; Time->DateString[6] = Time->Month%10 + 0x30; Time->DateString[7]='-'; Time->DateString[8] = Time->Date/10 + 0x30; Time->DateString[9] = Time->Date%10 + 0x30; Time->DateString[10] = '0'; Time->WeekdayString[0] = *(WeekdayTable[(Time->Weekday%10)-1] + 0); Time->WeekdayString[1] = *(WeekdayTable[(Time->Weekday%10)-1] + 1); Time->WeekdayString[2] = *(WeekdayTable[(Time->Weekday%10)-1] + 2); Time->WeekdayString[3] = '0'; } 77
  • 78. 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->TimeString[0] = Time->Hour/10 + 0x30; // '0' : ASCII = 0x30 Time->TimeString[1] = Time->Hour%10 + 0x30; Time->TimeString[2] = ':'; Time->TimeString[3] = Time->Minute/10 + 0x30; Time->TimeString[4] = Time->Minute%10 + 0x30; Time->TimeString[6] = Time->Second/10 + 0x30; Time->TimeString[7] = Time->Second%10 + 0x30; Time->TimeString[8] = '0'; } #if (HAL_DS1302 == TRUE) … #endif
  • 79. 修改hal_board_cfg.h 79 /************************************************************************************************** Filename: hal_board_cfg.h 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_mcu.h" #include "hal_defs.h" #include "hal_types.h" #include "hal_lcd.h" #include "hal_key.h" #include "hal_triwire.h" #include "hal_ds1302.h" **** 略 ***** /* ------ 3-Wire Port Configuration ------*/ #define TriWire_SCLK P1_bit.P1_4 #define TriWire_IO P1_bit.P1_2 #define TriWire_RST P1_bit.P1_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
  • 80. 修改hal_drivers.c的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) && (HAL_LCD == TRUE) LCD_Init(2, 16); #endif #if (defined HAL_KEY) && (HAL_KEY == TRUE) HalKeyInit(); HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE); #endif #if (defined HAL_DS1302) && (HAL_DS1302 == TRUE) DS1302_Init(); #endif }
  • 81. 練習5: 寫一支電子時鐘應用程式 81 #include "MyAPP1.h" 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(&currentTime); while(1) { DS1302_ReadTime(&currentTime); LCD_DispStr(0, 0, currentTime.DateString); LCD_DispStr(0, 12, currentTime.WeekdayString); LCD_DispStr(1, 0, currentTime.TimeString); } }
  • 83. DS18B20溫度感測器 83  DS18B20是一個數位溫度感測器,它可以提供9~12位元 的攝氏溫度輸出,而且可以設定超溫警告閥值。它使 用一條數據傳輸線(1-Wire)介面與MCU進行雙向通訊。  電壓範圍:3.0~5.5V  溫度範圍:-55oC~+125oC。-10~+85oC時精度為±0.5oC  解析度為9~12位元,對應的 可分辨溫度量為 0.5oC、0.25oC、 0.125oC和 0.0625oC。在9位元 解析度時,最多在93.75ms內 能把溫度轉換為數位值;在12 位元解析度時,最多在750ms 內把溫度值轉換為數位值。
  • 87. 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 。
  • 89. 使用注意事項 89  DS1820與MCU使用串列通訊,因此對DS1820進行讀寫時必須嚴格 保證讀寫時序,否則將無法讀取測溫結果。  實際應用中1-Wire bus上所掛DS1820數量並非任意多個,當數量超 過8個時就需要解決MCU的匯流排驅動問題。  連接DS1820的匯流排電纜有長度限制,經驗中使用一般電線長度 超過50m時,讀取的測溫資料將發生錯誤。使用雙絞線帶遮罩電 纜時,正常通訊距離可達150m。  DS1820測溫程式中,向DS1820發出溫度轉換命令後,程式總要等 待DS1820的返回訊號,一旦某個DS1820接觸不好或斷線,當程式 讀該DS1820時,將沒有返回訊號,程式進入閉迴路。這一點在進 行DS1820硬體連接和軟體設計時也要給予一定的重視。 測溫電纜 線建議採用遮罩4芯雙絞線,其中一對線接地線與訊號線,另一組 接VCC和地線,遮罩層在源端單點接地。
  • 90. /************************************************* Filename: hal_onewire.c Revised: $Date: 2013-11-5 21:07 $ **************************************************/ /****** INCLUDES ******/ #include "hal_board_cfg.h" #include "hal_defs.h" #include "hal_types.h" #include "hal_drivers.h" #include "hal_onewire.h" /****** 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 < 8; index++) { OneWire_DQ = LOW; OneWire_DQ = output_data & 0x01; // 5us delay_time(OneWireDELAY_Write); // 76us OneWire_DQ = HIGH; output_data = output_data >> 1; } } 1-Wire通訊介面驅動程式 90 /*********************************************** Filename: hal_onewire.h 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_board.h“ /****** 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. 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 < 8; index++) { OneWire_DQ = LOW; input_data = input_data >> 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) … #endif
  • 92. DS18B20溫度感測器驅動程式 /*************************************************** Filename: hal_ds18b20.h 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_board.h“ /******* 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__ { // 2's complement, +85C = 0101, 0101 = 0x55 uint8 Alarm_TH; // 2's 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. 93 /*********************************************************************************** Filename: hal_ds18b20.c Revised: $Date: 2013-11-05 21:36 $ Revision: $Revision: $ Description: This file contains the interface to the ds18b20 temperature sensor. ***********************************************************************************/ /******* INCLUDES *******/ #include "hal_board_cfg.h" #include "hal_defs.h" #include "hal_types.h" #include "hal_drivers.h" #include "hal_ds18b20.h" #include "hal_onewire.h" /******* 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->Alarm_TH); OneWire_WriteByte(tconfig->Alarm_TL); OneWire_WriteByte(tconfig->Resolution); OneWire_ReadByte(); OneWire_ReadByte(); }
  • 94. /***************************************************************************************** * @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: 1.Initialize, 2.ROM CMD, 3.RAM CMD DS18B20_Init(); OneWire_WriteByte(DS18B20_CMD_SKIP_ROM); OneWire_WriteByte(DS18B20_CMD_CONVERT_TEMP); DS18B20_Wait_Conv(ttemp->Resolution); 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 & 0xF8; if(temp_sign) { ttemp->Temp_Sign = 1; // negative ttemp->Temp_Integer = ((LO_UINT8(temp_high_byte) << 4) | HI_UINT8(temp_low_byte)); ttemp->Temp_Integer = ~(ttemp->Temp_Integer) + 1; ttemp->Temp_Decimal = LO_UINT8(~(temp_low_byte & 0x0F)); }else{ ttemp->Temp_Sign = 0; // positive ttemp->Temp_Integer = ((LO_UINT8(temp_high_byte) << 4) | HI_UINT8(temp_low_byte)); ttemp->Temp_Decimal = LO_UINT8(temp_low_byte & 0x0F); } 94
  • 95. 95 // String construction if(temp_sign) ttemp->TempString[0] = '-'; else ttemp->TempString[0] = ' '; if((ttemp->Temp_Integer)/100) { // hundred's digit ttemp->TempString[1] = ((ttemp->Temp_Integer)/100) + '0'; }else{ if(temp_sign) { ttemp->TempString[0] = ' '; ttemp->TempString[1] = '-'; }else{ ttemp->TempString[1] = ' '; } } if(((ttemp->Temp_Integer)%100)/10) { // ten's digit ttemp->TempString[2] = (((ttemp->Temp_Integer)%100)/10) + '0'; }else{ if(temp_sign) { ttemp->TempString[1] = ' '; ttemp->TempString[2] = '-'; }else{ ttemp->TempString[2] = ' '; } } ttemp->TempString[3] = ((ttemp->Temp_Integer)%10) + '0'; ttemp->TempString[4] = '.'; ttemp->TempString[5] = (ttemp->Temp_Decimal*625/1000) + '0'; ttemp->TempString[6] = 'C'; ttemp->TempString[7] = '0'; }
  • 96. 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_TIME/8); break; case DS18B20_RES_10BITS: delayms(DS18B20_CONV_TIME/4); break; case DS18B20_RES_11BITS: delayms(DS18B20_CONV_TIME/4); delayms(DS18B20_CONV_TIME/4); break; case DS18B20_RES_12BITS: delayms(DS18B20_CONV_TIME/4); delayms(DS18B20_CONV_TIME/4); delayms(DS18B20_CONV_TIME/4); delayms(DS18B20_CONV_TIME/4); break; default: break; } } #if (HAL_DS18B20 == TRUE) … #endif
  • 97. 1-Wire & DS18B20 驅動程式測試 97
  • 98. 實習12 98  現在,請綜合驅動程式,寫一個應用程式,讓LCD不只 顯示出時間,也可顯示目前溫度。  步驟1: 加入1-wrie驅動程式 1. 加入hal_onewire.h / hal_onewire.c 2. 修改hal_board_cfg.h 3. 修改hal_drivers.c  步驟2: 加入DS18B20溫度感測器驅動程式 1. 加入hal_ds18b20.h / hal_ds18b20.c 2. 修改hal_board_cfg.h 3. 修改hal_drivers.c  步驟3: 撰寫應用程式
  • 99. 含溫度顯示的電子時鐘應用程式 99 #include "MyAPP1.h" SYSTEMTIME currentTime; SENSEDTEMP currentTemp; TEMPCONFIG configTemp = {0x55, 0xF6, DS18B20_RES_11BITS}; void main() { HalDriverInit(); DS18B20_Config(&configTemp); OneWire_BusReset(); currentTemp.Resolution = configTemp.Resolution; while(1) { DS1302_ReadTime(&currentTime); LCD_DispStr(0, 0, currentTime.DateString); LCD_DispStr(0, 12, currentTime.WeekdayString); LCD_DispStr(1, 0, currentTime.TimeString); DS18B20_ReadTemp(&currentTemp); LCD_DispStr(1, 9, currentTemp.TempString); } }
  • 101. 實習13: 加入驅動程式並測試 101  練習1: 加入LED驅動程式並完成設定  練習2: 撰寫測試LED功能的應用程式  練習3: 加入Timer驅動程式並完成設定  練習4: 撰寫測試Timer功能的應用程式
  • 102. 練習1: 加入LED驅動程式 (I) 102 /* ------------------------------------------------------------------------------------------------ * LED Configuration * ------------------------------------------------------------------------------------------------ */ #define HAL_NUM_LEDS 4 /* LED D0 */ #define LED1_BV BV(0) #define LED1_SBIT P1_bit.P1_0 #define LED1_POLARITY ACTIVE_LOW /* LED D5 */ #define LED2_BV BV(5) #define LED2_SBIT P1_bit.P1_5 #define LED2_POLARITY ACTIVE_LOW /* LED D6 */ #define LED3_BV BV(6) #define LED3_SBIT P1_bit.P1_6 #define LED3_POLARITY ACTIVE_LOW /* LED D7 */ #define LED4_BV BV(7) #define LED4_SBIT P1_bit.P1_7 #define LED4_POLARITY ACTIVE_LOW
  • 103. 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. 104 /************************************************************************ Filename: hal_led.h 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_board.h" /***** 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 ON/OFF */ 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. 105 /************************************************************************* Filename: hal_led.c Revised: $Date: 2013-11-06 $ Revision: $Revision: 29281 $ Description: This file contains the interface to the HAL LED Service. **************************************************************************/ /***** INCLUDES *****/ #include "hal_mcu.h" #include "hal_defs.h" #include "hal_types.h" #include "hal_drivers.h" #include "hal_led.h" #include "hal_board.h" /***** GLOBAL VARIABLES *****/ // LED state at last set/clr update static uint8 HalLedState; #if HAL_LED == TRUE // LED state at last set/clr 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 */ }
  • 106. /********************************************************************* * @fn HalLedSet * @brief Tun ON/OFF given LEDs * @param led - bit mask value of leds to be turned ON/OFF/TOGGLE * 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=0;i<HAL_LED_DEFAULT_MAX_LEDS;i++) { if (HalLedState & (1<<i)) HalLedOnOff(leds & (1<<i), HAL_LED_MODE_OFF); else HalLedOnOff(leds & (1<<i), 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_ON,LED_OFF, * @return none *********************************************************/ void HalLedOnOff (uint8 leds, uint8 mode) { if (leds & HAL_LED_1) { if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED1(); else HAL_TURN_OFF_LED1(); } if (leds & HAL_LED_2) { if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED2(); else HAL_TURN_OFF_LED2(); } 106
  • 107. 107 if (leds & HAL_LED_3) { if (mode == HAL_LED_MODE_ON) HAL_TURN_ON_LED3(); else HAL_TURN_OFF_LED3(); } if (leds & 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 &= (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. 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() << 1; HalSleepLedState |= HAL_STATE_LED3() << 2; HalSleepLedState |= HAL_STATE_LED4() << 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) && (HAL_LED == TRUE) HalLedInit(); #endif 略 }
  • 109. 練習2: 測試LED的應用程式 109  測試時先關閉DS1302 RTC與DS18B20測溫功能 #include "MyAPP1.h" 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. 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; } } }
  • 111. 練習3: 加入Timer驅動程式並設定 111 /*********************************************************************** Filename: hal_timer.h 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_board.h" /******** 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. 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. 113 /*********************************************************************** Filename: hal_timer.c 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_mcu.h" #include "hal_defs.h" #include "hal_types.h" #include "hal_timer.h" #include "hal_led.h" /******** CONSTANTS ********/ // IE BV #define IE_T0_IntEn_Bit BV(1) #define IE_T1_IntEn_Bit BV(3) // IF BV@TCON #define TCON_T0_IntFlag_Bit BV(5) #define TCON_T1_IntFlag_Bit BV(7) // Timer Enable BV@TCON #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 – 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);
  • 114. /*************************************************************************************************** * @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 < 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 – API ********/ /******************************************************************* * @fn HalTimerInit * @brief Initialize Timer Service * @param None * @return None *******************************************************************/ void HalTimerInit (void) { // disable all timer interrupts IE &= ~(IE_T0_IntEn_Bit|IE_T1_IntEn_Bit); /* Setup prescale value & 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
  • 115. /************************************************************************************************* * @fn HalTimerStart * @brief Start the Timer Service * @param timerId - ID of the timer * timerPerTick - number of micro sec per tick, (ticks x prescale) / clock = usec/tick * @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 &= ~(TCON_T0_START_BV); break; case HAL_TIMER_1: TCON &= ~(TCON_T1_START_BV); break; default: return HAL_TIMER_INVALID_ID; } return HAL_TIMER_OK; } 115
  • 116. /*************************************************************************************************** * @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 = ((sec/tick) x clock) / prescale */ //count = (uint16) (timePerTick*(halTimerRecord[timerId].prescaleVal)/halTimerRecord[timerId].clock); count = (uint16) (timePerTick); switch(halTimerRecord[timerId].opMode&OP_MODE_MASK) { case HAL_TIMER_MODE_13BITS: count = (8192 - count); high_byte = (uint8) (count >> 5); low_byte = (uint8) (count & 0x07); break; case HAL_TIMER_MODE_16BITS: count = (65536 - count); high_byte = (uint8) (count >> 8); low_byte = (uint8) (count & 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 & 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
  • 117. /******************************************************* * @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 &= ~(0x0F); TMOD |= opMode; break; case HAL_TIMER_1: TMOD &= ~(0xF0); TMOD |= (opMode<<4); 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 &= ~(IE_T0_IntEn_Bit); break; case HAL_TIMER_1: if (halTimerRecord[timerId].intEnable) IE |= IE_T1_IntEn_Bit; else IE &= ~(IE_T1_IntEn_Bit); break; default: return HAL_TIMER_INVALID_ID; } return HAL_TIMER_OK; } 117
  • 118. 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 &= ~(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 &= ~(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) … #endif
  • 119. 練習4: 測試Timer的應用程式 119 #include "MyAPP1.h" 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. 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++; }
  • 125. 125
  • 127. 總結 127  歷經三個PART,我們從最早從簡單的點亮LED實習來學 習嵌入式C語言的基本語法與技巧,同時觀察MCU的 header file內容以了解SFR與中斷向量的命名。  我們從main()函式中抽離出一切對硬體的操作,並且使 用函式將這類型的操作給包裝起來,稱之為驅動程式。  在一系列包含7段顯示器、LCD模組、中斷與計時器、 UART、AD/DA、ROM的讀寫、RTC與溫度感測器等實習, 我們循序漸進地學到「硬體驅動程式」與開發板SDK的 包裝,使得我們的開發專案能更有系統、簡潔而且有 效率地被重複使用。  這些經驗是如此的細微而且重要,還有很多韌體開發 及應用無法一一說完,但相信大家一定能藉著本系列 課程所學到基礎而能更容易地繼續往上蓋大樓。記住: 一法通,萬法通。