Enhanced Holtek C Compiler user's guide

Using Enhanced Holtek C
Revision: 1.30
Date: March 15, 2011
Using Enhanced Holtek C
Table of Contents
Chapter 1 Introduction.................................................................................... 6
Chapter 2 Holtek C Compiler User Environment Configuration ................. 7
2.1 Entering the HT-IDE3000, Establishing a new Project, Selecting the Enhanced Holtek C Compiler .......7
2.2 Selecting the Enhanced Holtek C Compiler after program establishment .................................................7
Chapter 3 A Quick Start to Microcontroller C Language Program ............. 9
3.1 Defining the Main Function..............................................................................................................................9
3.2 Defining Sub-functions ....................................................................................................................................9
3.3 Defining Global Variables ..............................................................................................................................10
3.4 Defining the Interrupt Service Routine : ISR ................................................................................................10
3.5 Others ..............................................................................................................................................................11
Chapter 4 The C Program Language ........................................................... 12
4.1 C Language Structure ....................................................................................................................................12
4.2 Start a Program with C Language .................................................................................................................12
4.2.1 Define main ............................................................................................................................................12
4.2.2 Include a Header File .............................................................................................................................13
4.2.3 Define symbols and variables ................................................................................................................13
4.2.4 Setup the initial status of the MCU.........................................................................................................14
4.2.5 Define the sub-functions ........................................................................................................................14
4.2.6 Design the Interrupt Service Routine .....................................................................................................15
4.3 Variable and Data Type...................................................................................................................................16
4.3.1 Variable Name .......................................................................................................................................16
4.3.2 Data Type...............................................................................................................................................16
4.3.3 Variable Effective Scope ........................................................................................................................16
4.3.4 Data Type...............................................................................................................................................17
4.3.5 Bit Data Type .........................................................................................................................................17
4.3.6 Storage Class and Qualifier ...................................................................................................................18
4.3.7 Absolute Variable ...................................................................................................................................19
4.3.8 Constant.................................................................................................................................................19
4.3.9 Pointer and Array ...................................................................................................................................20
4.3.10 struct and union ...................................................................................................................................21
4.4 Operators ........................................................................................................................................................22
4.5 Program flow control .....................................................................................................................................25
4.5.1 if-else statement.....................................................................................................................................25
4.5.2 Switch statements ..................................................................................................................................25
4.5.3 for statement ..........................................................................................................................................26
4.5.4 while statement ......................................................................................................................................27
4.5.5 do-while statement .................................................................................................................................27
4.5.6 goto statement .......................................................................................................................................27
4.5.7 break and continue statement................................................................................................................27
4.6 Functions ........................................................................................................................................................28
4.6.1 Arguments ..............................................................................................................................................28
4.6.2 Return Values ........................................................................................................................................28
4.7 Interrupt Service Routines .............................................................................................................................29
4.8 Inline Assembly Codes in C...........................................................................................................................30
4.9 Preprocessor ..................................................................................................................................................32
4.9.1 Define Characters (#define) ...................................................................................................................32
4.9.2 #include..................................................................................................................................................32
4.9.3 Inline Assembly ......................................................................................................................................32
Rev. 1.30
2
March 15, 2011
Using Enhanced Holtek C
4.9.4 Conditional Compiling (#if/#endif) ..........................................................................................................33
4.9.5 Compiler Special Options pragma .........................................................................................................34
4.10 Holtek C built-in Functions ..........................................................................................................................36
Chapter 5 Basic C Language Programs...................................................... 37
5.1 C Syntax Concepts .........................................................................................................................................37
5.2 Loop Application ............................................................................................................................................38
5.2.1 Example 1: 8 Flashing LEDs..................................................................................................................38
5.2.2 Delay Timing ..........................................................................................................................................38
5.3 Notes for writing an MCU Application Program ..........................................................................................40
5.4 Microcontroller Application Program Example ..........................................................................................41
5.5 Points to Note for Microcontroller Application Program Design ...............................................................42
Chapter 6 Example Program – Basic Level ................................................ 44
6.1 LED Running Light Display ...........................................................................................................................44
6.1.1 Objective ................................................................................................................................................44
6.1.2 Peripheral Components .........................................................................................................................44
6.1.3 Circuit Diagram ......................................................................................................................................44
6.1.4 MCU Configuration Options ..................................................................................................................44
6.1.5 Program Flow.........................................................................................................................................45
6.1.6 Original Program ....................................................................................................................................45
6.1.7 Program Description ..............................................................................................................................45
6.2 LED Blinking Light..........................................................................................................................................46
6.2.1 Objective ................................................................................................................................................46
6.2.2 Peripheral Components .........................................................................................................................46
6.2.3 Circuit Diagram ......................................................................................................................................46
6.2.4 MCU Configuration Options ...................................................................................................................46
6.2.5 Program Flow.........................................................................................................................................47
6.2.6 Original Program ....................................................................................................................................47
6.2.7 Program Description ..............................................................................................................................47
6.3 Single 7-segment Display ..............................................................................................................................48
6.3.1 Objective ................................................................................................................................................48
6.3.2 Peripheral Components .........................................................................................................................48
6.3.3 Circuit Diagram ......................................................................................................................................48
6.3.4 Microcontroller Configuration Options....................................................................................................48
6.3.5 Program Flow.........................................................................................................................................49
6.3.6 Original Program ....................................................................................................................................49
6.3.7 Program Description ..............................................................................................................................49
6.4 5*5 Dot Matrix LED Display ............................................................................................................................49
6.4.1 Objective ................................................................................................................................................49
6.4.2 Peripheral Components .........................................................................................................................49
6.4.3 Circuit Diagram ......................................................................................................................................50
6.4.4 Microcontroller Configuration Options....................................................................................................50
6.4.5 Program Flow.........................................................................................................................................50
6.4.6 Original Program ....................................................................................................................................51
6.4.7 Program Description ..............................................................................................................................51
6.5 HT1621 LCD Control using the HT48 Series of MCUs ................................................................................52
6.5.1 Objective ................................................................................................................................................52
6.5.2 Peripheral Components .........................................................................................................................52
6.5.3 Circuit .....................................................................................................................................................55
6.5.4 Configuration Option ..............................................................................................................................55
6.5.5 Program Flow.........................................................................................................................................55
6.5.6 Original Program ....................................................................................................................................56
6.5.7 Program Description ..............................................................................................................................59
6.6 Using the HT48 to control the LCD panel .....................................................................................................61
Rev. 1.30
3
March 15, 2011
Using Enhanced Holtek C
6.6.1 Objective ................................................................................................................................................61
6.6.2 Peripheral Components .........................................................................................................................61
6.6.3 Circuit Diagram ......................................................................................................................................62
6.6.4 Configuration Option ..............................................................................................................................62
6.6.5 Program Flow.........................................................................................................................................62
6.6.6 Original Program ....................................................................................................................................63
6.6.7 Program Description ..............................................................................................................................64
6.7 HT46R63 MCU with LCD Driver Application Program .................................................................................66
6.7.1 Objective ................................................................................................................................................66
6.7.2 Peripheral Components .........................................................................................................................66
6.7.3 Circuit Diagram ......................................................................................................................................67
6.7.4 MCU Configuration Option .....................................................................................................................67
6.7.5 Program Flow.........................................................................................................................................67
6.7.6 Original Program ....................................................................................................................................68
6.7.7 Program Description ..............................................................................................................................69
6.8 Display General Functions – HD44780 LCM ................................................................................................69
6.8.1 initialLCD( ) ............................................................................................................................................69
6.8.2 PutChar( ) ..............................................................................................................................................70
6.8.3 MoveAt( ) ...............................................................................................................................................70
6.8.4 main( ) ....................................................................................................................................................70
6.9 Key Scan Program ..........................................................................................................................................71
6.9.1 Objective ................................................................................................................................................71
6.9.2 Peripheral Components .........................................................................................................................71
6.9.3 Circuit Diagram ......................................................................................................................................71
6.9.4 MCU Configuration Options ...................................................................................................................72
6.9.5 Program Flow.........................................................................................................................................72
6.9.6 Original Program ....................................................................................................................................73
6.9.7 Program Description ..............................................................................................................................73
Chapter 7 Application Example – Interrupt Program ................................. 75
7.1 LED Control using the Timer .........................................................................................................................75
7.1.1 Objective ................................................................................................................................................75
7.1.2 Peripheral Components .........................................................................................................................76
7.1.3 Circuit Diagram ......................................................................................................................................77
7.1.4 MCU Configuration Option .....................................................................................................................77
7.1.5 Program Flow.........................................................................................................................................77
7.1.6 Original Program ....................................................................................................................................78
7.1.7 Program Description ..............................................................................................................................78
7.2 Analog to Digital Converter Application .......................................................................................................79
7.2.1 Objective ................................................................................................................................................79
7.2.2 Peripheral Components .........................................................................................................................79
7.2.3 Circuit Diagram ......................................................................................................................................81
7.2.4 MCU Configuration Options ..................................................................................................................82
7.2.5 Program Flow.........................................................................................................................................82
7.2.6 Original Program ....................................................................................................................................82
7.2.7 Program Description ..............................................................................................................................84
Chapter 8 NiMH Battery Charger (HA0084T) Application using the HT46R52A85
8.1 Objective .........................................................................................................................................................85
8.2 Register and Peripheral Components ..........................................................................................................86
8.3 Circuit Diagram ...............................................................................................................................................88
8.4 MCU Configuration Options ..........................................................................................................................88
8.5 Program Flow ..................................................................................................................................................89
8.6 Original Program and Program Description ................................................................................................93
Rev. 1.30
4
March 15, 2011
Using Enhanced Holtek C
Chapter 9 Program Example – The HT46R74D-1 Tyre Pressure Gauge 109
9.1 Objective .......................................................................................................................................................109
9.2 Functions ......................................................................................................................................................109
9.3 Circuit Diagram .............................................................................................................................................110
9.4 MCU Configuration Options ........................................................................................................................114
9.5 Program Flowchart .......................................................................................................................................115
9.6 Original Program and Program Description ..............................................................................................120
Chapter 10 Mixed Language –Assembly and C ....................................... 136
10.1 Naming of Variables, Functions and Parameters ....................................................................................136
10.2 Parameter Passing .....................................................................................................................................136
10.3 Return Value Setting ..................................................................................................................................137
10.4 Calling Assembly Functions from the C Program ...................................................................................137
10.5 Calling C Function from Assembly Program ...........................................................................................138
Rev. 1.30
5
March 15, 2011
Using Enhanced Holtek C
Chapter 1
Introduction
Applications for Holtek Semiconductor's range of 8-bit microcontrollers, can be developed
using both assembly language and the Holtek Enhanced C language. For this latter case
Holtek has provided a C compiler for user convenience.
As the program and data memory space of some 8-bit microcontrollers can be somewhat
limited in capacity, assembly language is often chosen for application development due its
lower demands on memory resources. However, as microcontroller development trends see
the release of devices with higher memory capacities, continuing to use assembly language
brings with it the complications of longer application program development time and more
complex future program maintenance and upgrade..
Using the C language, can reduce these difficulties due to its higher readability and portability
features. Also in addition to reduced program implementation times, it is also easier for
users to switch to other microcontrollers and more easier to reduce or increase functions.
These features make C an extremely efficient program choice for MCU application program
development.
This book describes how to use the Holtek Enhanced C language to write application
programs for Holtek microcontrollers , and covers items such as program structure, general
usage, special usage as well as including a range of application examples. The book also
shows any special considerations that need to be taken into account during application
program development . Readers can use, modify and apply the supplied application programs
for their own application development verifying the results using the Holtek HT-ICE and HTIDE3000 development tools
Chapter 2 gives a brief introduction on the configuration steps of the Holtek C compiler,
showing how to setup the HT-IDE3000 for Holtek C compiler use. Chapter 3 shows a quick
method to get users writing C programs as quickly as possible. For users who are already
familiar with ANSI C language, it is possible to start writing a C program very quickly after
reading this chapter. Chapter 4 introduces the C language in more detail and those who are
not familiar with C should read this chapter carefully to get going with using the C language.
Chapter 5 introduces more about basic concepts, special notes and recommended methods
for writing programs using C. Finally Chapters 6 to 9 provide C language program application
examples using actual Holtek microcontrollers.
Rev. 1.30
6
March 15, 2011
Using Enhanced Holtek C
Chapter 2 Holtek C Compiler User Environment
Configuration
2.1 Entering the HT-IDE3000, Establishing a new Project, Selecting the
Enhanced Holtek C Compiler
After entering the HT-IDE3000 development environment, adhere to the following steps to
establish a new project:
→ Select Project from the menu
→ Select New from within the Project menu
→ The window shown below should now appear. In the Language Tool area select Enhanced
Holtek C Compiler/Assembler.
2.2 Selecting the Enhanced Holtek C Compiler after program
establishment
After the project is open, select Project Setting from within the Option menu, and in the
Language Tool area select the Enhanced Holtek C Compiler/Assembler.
Rev. 1.30
7
March 15, 2011
Using Enhanced Holtek C
The Enhanced C compiler contains the ehcc32srsc.exe, ehcc32mrsc.exe and ehcc32mrmc.
exe files.
Rev. 1.30
8
March 15, 2011
Using Enhanced Holtek C
Chapter 3 A Quick Start to Microcontroller C Language
Program
The following chapter introduces how to quickly write a microcontroller application program
in C language. Those who are familiar with ANSI C standard language or have some
programming experience may start immediately writing a C microcontroller application
program. The following chapters are provided as the fundamentals of a basic C program, in
which some elements are essential such as 3.1, while other elements may only be required
according to specific application needs.
3.1 Defining the Main Function
#include “ht46r63.h"
void main(void)
{
int Flag ;
……
TurnOn_LCD() ;
Flag = LCD_display(cstr) ;
TurnOff_LCD() ;
……
}
The file ht46r63.h defines the constants relevant to the microcontroller, such as the register
addresses. This enhances greatly the readability of the program
3.2 Defining Sub-functions
To include sub-functions or not depends on the size and functions of the program. Basically
the method is just to form a series of smaller modules for the application program instead of
putting the whole program into the main function. For rapid implementation and understanding
of the application program, the main function only needs to contain call definition functions.
For example, a function to enable or disable the LCD can be defined individually as a single
sub-function, such as in the example below, which can then be called by any other function. If
designed as a general type, it can also be included into the program database via the Library
Manager for other projects to use.
void TurnOn_LCD(void)
{
}
int LCD_display(char *cstr)
{
}
void TurnOff_LCD(void)
{
}
The parameters and return values of the sub-function can be of basic types such as int, float,
char, void, or structure types as struct, union, enum, array, pointer types etc.
To avoid the function calling itself, the maximum number of function call levels should be
checked against the number of MCU stack levels.
Rev. 1.30
9
March 15, 2011
Using Enhanced Holtek C
3.3 Defining Global Variables
Some variables will be required for data storage during program execution. Owing to the
restrictions of microcontroller memory size and the C compiler, it is recommended to define
these general variables as global variables which will be more effective both for program
compiling and execution. For example, defining the constant type of pointer variable cstr as
the alphabetic string “Hello!" can be done as follows:
char * const cstr = “Hello!";
To initialize the global variables in Holtek C, all should be defined as const or constant int
type.
Ex. const char aa = 3
constant int bb = 3
3.4 Defining the Interrupt Service Routine : ISR
If the MCU internal functions contain interrupt functions, the interrupt service routine, ISR, of
the internal function should be defined in the following way:
#pragma vector ISR_tmr0 @ 0x0c
void ISR_tmr0(void)
{
tick++ ;
}
The interrupt service routine must obey the following rules:
→ The returned data type must be void
→ No parameters included - must be void
→ Must use the previous process instruction #pragma vector to setup the interrupt vector
by adding @ after the function name (ISR_tmr0 in this example) and using the previously
defined interrupt vector constant
For example:
#define VECTOR_TMR0 0x0c
#pragma vector ISR_tmr0 @ VECTOR_TMR0
void ISR_tmr0(void)
{
}
→ There are two methods for calling a general function within an interrupt
1、Direct calling: the called function must be declared to be nolocal to remove the risk of
using the same RAM area. For example:
#pragma vector ISR_tmr0 @ 0x0c
#pragma nolocal fun
fun()
{
}
void ISR_tmr0(void)
{
fun() ;
}
2、Embedded assembly language: for example:
#pragma vector ISR_tmr0 @ 0x0c
fun()
{
}
void ISR_tmr0(void)
{
Rev. 1.30
10
March 15, 2011
Using Enhanced Holtek C
#asm
call _fun;
#endasm
}
Note: In general, calling a general function from within an interrupt is not
recommended.
3.5 Others
The main function, sub-functions and interrupt service routines mentioned above need not
be defined in the same original program file. To be more efficient, it is better to provide the
definitions separately in different files with a meaningful file name making it easier to locate
the functions that are required in the future.
Rev. 1.30
11
March 15, 2011
Using Enhanced Holtek C
Chapter 4
The C Program Language
Essentially Holtek C is a simulated C language from ANSI (American National Standards
Institute.) In order to accomodate the structure of Holtek's 8-bit microcontrollers, some specific
syntax for storing and controlling the MCU data are provided. In addition, this chapter also
introduces a way to design and write an MCU application program using C language for 8-bit
microcontrollers.
4.1 C Language Structure
A C language program is composed of statements which must be followed with a semicolon
“;" at the end of each statement as an ending symbol. The statements are classified into
four kinds:
→ Declaration: Declare the variable and data type, and the data structure
Ex. char flag, tick_cnt ; // declare variable flag and tick_cnt as char type
→ Definition: Define the variable value and address
Ex. int total = 10 ; // define variable total with a setting value of 10
→ Expression: Execute mathematics and logic calculation, control the program flow
Ex. count = (input>10) ? 10 : input ;
→ Function Call: Execute a function
Ex. putchar(ch) ; // write a character to the output port
Each statement can have an added note for description. The C compiler will not compile the
notes. The following two types of notes are acceptable:
→ Digits and characters within symbol /* and /*, including the line feed character`\n'
If /* and /* are not in the same line, then all the content in between them will be regarded
as notes.
Ex. /* this is a comment 1 */
→ Content from the symbol // to the end of the line will be regarded as notes.
Ex. // This is the another way of writing notes.
In the C language, the program block is defined by the function format, so all the statements to
be executed need to be defined (included) into some function, such as a description formula.
4.2 Start a Program with C Language
Follow the steps below to write a simple application program using C language.
4.2.1 Define main
Ex.
void main(void)
{
}
In the C language, main is the start of a program execution, similar to a start in assembly
language
ORG 00
jmp start
start:
void is the data type. main and void are both reserved words that must be included and must
be written in lower case.
Rev. 1.30
12
March 15, 2011
Using Enhanced Holtek C
4.2.2 Include a Header File
Ex.
#include “ht46r63.h" // include a header file ht46r63.h
void main(void)
{
}
The header file ht46r63.h provides many definitions of variable and symbols relevant to the
MCU for program writing. The advantage is that the program will be easier to understand
during writing or for future maintenance by improving program readability. Ex.
unsigned char _pa @0x12 ;
Define _pa as a unsigned char type of variable with an address at 0x12 of the RAM (port A),
so the statement will be as shown below in the program:
_pa = 0 ;
which has the same function as CLR PA ; (PA=[12H]) in the assembly language.
4.2.3 Define symbols and variables
Using symbols makes the program easier to read and modify. For example, define symbol
pa0 as shown below:
#define _pa0 _12_0
means _pa0 is bit 0 of the RAM address 12H, namely bit 0 of Port A:
_pa0 = 1 ;
means to set bit 0 of Port A to 1, which is of the same function as SET [12H].0 in assembly
language.
The previous processing instruction #define is to define a symbol with a specific value,
alphabetic string, or macro instruction.
The C compiler preprocessor will replace these defined symbols before compiling.
The previous processing instruction #undef is to delete the definitions that have been given
the symbols, making them invalid. For a more detailed description refer to Chapter 4.9.
Variables or symbols in other MCU registers are defined in the header files of the
corresponding MCU for programming reference. Some required variables or symbols not
defined in the header file can be made for the convenience of program development and
maintenance. For example:
#include“ht48R50A-1.h"
#define scl_pa3 // SCL (clock line) connected to bit 3 of Port A in the MCU
#define scl_c_13_3 // bit 3 of Port A in the register (bit type variable)
#define scl_pa1 // SDA (data line) connected to bit 1 of Port A in the MCU
#define scl_c_13_1 // bit 1 of A port in the register
void main(void)
{
}
Define the four symbols, scl, scl_c, sda, sda_c as different output/input ports.
Define the variables to take up RAM/ROM space. If the address is designated, this variable
will occupy the address, otherwise no address will be assigned to the variable until the Linker
is activated. The function is the same as the assembly language below.
_pa DB ?
The function of symbol definition is the same as EQU in the assembly language. Ex:
#define scl_pa3 and scl EQU _pa3 have the same effect
Rev. 1.30
13
March 15, 2011
Using Enhanced Holtek C
4.2.4 Setup the initial status of the MCU
Setup the initial value of each device in the MCU according to the program function, such as
the initial status of peripheral devices and registers etc.
scl_c = 0 ; // set SCL (=PAC) status as output
sda_c = 0 ; // set SDA (=PA) status as output
4.2.5 Define the sub-functions
Individual functions can be implemented using sub-functions which are very useful for
program error detection, ease of maintenance and reuse purposes. The function parameters,
return values and so forth should be noted during definition. Generally the main() will be put
at the end of the program with each sub-function defined at the front or in the other program
files. The following example shows a part of it whose detailed description can be referred to in
Chapter 4.6.
#include “ht48r50a-1.h" // include header file
#define scl_pa3 // SCL (clock line) connect to the 3rd bit of A port in the MCU
#define scl_c13_3 // the 3rd bit of Port A (address 0x13) in the register (bit type
variable)
#define sda_pa1 // SDA (data line) connect the 1st bit of Port A in the MCU
#define sda_c_13_1 // the 1st bit of the Port A (address 0x13) in the register
// function: StartCondition() sub-function
// function: start a command
// input: NA
// output: NA
void StartCondition(void)
{
sda=1 ; //SDA output high
scl=1 ; //SCL pull high
sda=0 ; // SDA output low
scl=0 ; // complete start command
}
// function: StopCondition()
// function: end the previous command
// input: NA
// output: NA
void StopCondition(void)
{
}
// function: main()
// function: main function
// input: NA
// output: NA
void main (void)
{
unsigned char Rdata, type ;
// initial setting of the register
scl_c = sda_c = 0 ; // set the 1st and 3rd bits of Port A as output types (SCL, SDA
as output)
StartCondition() ; // call sub-function
……
}
Rev. 1.30
14
March 15, 2011
Using Enhanced Holtek C
4.2.6 Design the Interrupt Service Routine
For microcontrollers with hardware interrupts, it is necessary to design an interrupt service
routine to deal with the interrupt events. Define the interrupt service function of the peripheral
device (Interrupt Service Routine, ISR) as shown below:
#pragma vector ISR_tmr0 @ 0x0c
void ISR_tmr0(void)
{
tick++ ;
}
The interrupt service routine must obey the following rules:
→ The return data type must be void
→ No parameters included
→ The interrupt vector must be set in the function (here in the example is added a @ and
interrupt vector (here 0x0c) after ISR_tmr0) or using the previously defined constants. For
example:
#define VECTOR_TMR0 0x0c
#pragma vector ISR_tmr0 @ VECTOR_TMR0
void ISR_tmr0(void)
{
}
Rev. 1.30
15
March 15, 2011
Using Enhanced Holtek C
4.3 Variable and Data Type
During programming, some data such as flags, execution times, delay time etc. may need to
be stored for which the variable definitions must be setup in advance. Due to the necessity of
using ROM or RAM, before using the variables, the data type must be defined for the compiler
to correctly compile the program and configure the memory space. Additionally the data type,
storage class and qualifiers can be added.
4.3.1 Variable Name
Variable Naming Rules
→ The first character must be an English letter or underscored symbol which can be followed
by letters or digits
→ The previous 32 characters of the variable name is effective
→ Symbols like +, -, *, /…etc. cannot not be included in the variable
→ Case-sensitive, ex. count and Count belong to different variable names
Example: number, total_tick , _tick are legal variable names while 2num, $dot, line\n are
illegal.
4.3.2 Data Type
Type
bit
char
signed char
unsigned char
short
unsigned short
int
unsigned int
long
unsigned long
void
float
double
Size (bits)
1
8
8
8
16
16
16
16
32
32
0
32
32
Arithmetic Type
unsigned integer
signed integer
signed integer
unsigned integer
signed integer
unsigned integer
signed integer
unsigned integer
signed integer
unsigned integer
—
real
real
Scope
0, 1
-128 ~ +127
-128 ~ +127
0 ~ 255
-32768 ~ +32767
0 ~ 65535
-32768 ~ +32767
0 ~ 65535
-2147483648 ~ +2147483647
0 ~ 4294967295
—
-3.4028e+38~3.4028e+38*
-3.4028e+38~3.4028e+38*
* float, double uses the IEEE754 32bit format.
4.3.3 Variable Effective Scope
Determines the effective scope of the variable according to its definition, such as:
→ Local Variable
Those being defined in the program block (ex. the function) are all local variables which
are only effective when the program block is executed and invalid after completion. The
program block indicates the statements within “{“ and "}".
The static variables defined in the function are all global variables. Refer to the 4.3.2
description.
→ Global Variable
Those being defined outside the program block are global variables which are all effective
during program execution and can be accessed or modified by any function.
Ex:
#include “ht48r50a-1.h"
unsigned char flag ; // global variable
void main(void)
{
char type ; // local variable, effective only when the function is executed
static status = 0 ;// static variable, set to 0 only at first execution
……
}
Rev. 1.30
16
March 15, 2011
Using Enhanced Holtek C
4.3.4 Data Type
When making variable declarations, the data type must be designated so as to inform the
compiler of the required memory size. The data type can be Integer type and Floating Point
type, in which the integer type can be subdivided into signed and unsigned.
■ Integer
→ char
This occupies one byte of memory space with a range of -128 to 127 if “signed" added
or 0 to 255 if “unsigned". If no signed or unsigned is marked, it will be regarded as
signed which can be used to define characters such as `A', `d', `$', `3'…etc.
→ short
This occupies 2 bytes of memory space with a range of -32768 to 32767 if signed or 0 to
65535 if unsigned. If neither signed nor unsigned, it will be regarded as signed.
Holtek C uses little-endian format, saving the least significant byte of the variable at the
low address of the memory. Ex. variable count = 0x1234 is saved at 40H address of the
memory while the low byte value 0x34 will be saved at 40H and the high byte 0x12 at 41H.
→ int
same as short type
→ long
This occupies 4 bytes of memory space with a scope of -2147483648 to 2147483647 if
signed or 0 to 4294967295 if unsigned. If neither signed nor unsigned, it will be regarded
as signed in the little-endian format. The 32-bit variable is first saved with the least
significant byte of the least significant word to the low address of the memory and then
the high byte of the least significant word to the least significant byte of the high word and
finally the high byte of the high word.
■ Floating Point
Holtek C supports IEEE 754 32 bit format, including float and double data types. The floating
point value is stored in memory in the format as shown in the table below:
IEEE 754 32 bit
sign
x
biased exponent
xxxx xxxx
mantissa
xxx xxxx xxxx xxxx xxxx xxxx
The floating point value type is:
number = (-1)sign x 2(exponent – 127) x 1.mantissa
For example, a floating point value of 2.77000e+37 will be saved as 7DA6B69B in the memory
using 32 bits in total.
32bit
Memory value
sign
7DA6B69Bh
0
Biased exponent
1111 1011b
(=251)
1.mantissa
Decimal value
1.0100110101101101001101b
2.77000e+37
(=1.302447676659)
4.3.5 Bit Data Type
This data type is similar to the integer type except that there are only two values of 0 and 1,
so only the LSB (least significant bit) of the integer will be selected by the following specific
usages:
→ bit type can be neither used as a pointer data type nor defined as a const
→ bit type can be setup as the return type of a function, which is placed in the relative location
of an accumulator.
→ the initial value of the bit type variable will not be setup during program execution, so the
program should set the initial value by itself.
→ a local bit variable will occupy a byte (with only one bit effective) while a global will occupy
a bit.
Rev. 1.30
17
March 15, 2011
Using Enhanced Holtek C
→ the following shows the legal usage:
static bit init_flag ; // definition inside the function will be regarded as local variables
bit toggle_flag ;
→ ex.
int data = 0x54 ;
bit flag ;
flag = data ;
then flag = 0 (take the data LSB)
If the microcontroller contains more than one RAM bank, such as in the HT46R63, the bit type
variable definition should point to RAM bank 0 using the preprocessor instruction #pragma
rambank0 as below:
#pragma rambank0
bit flag ;
#pragma norambank
4.3.6 Storage Class and Qualifier
Storage Class
auto, register, static, extern
Qualifier
const, constant ,volatile, persistent
Specifier
typedef
The variable data type should be assigned first at its declaration or definition while the storage
class and qualifier are optional according to the actual application requirement.
■ Storage class
The storage class is related to the local variable and global variable.
→ Storage class auto
auto is used by the local variable that has no storage class assigned. Writing auto or not
has the same effectiveness. The local variable is placed in RAM bank 0.
→ Storage class register
register is similar to auto which is also used by the local variable. When variable accesses
are frequent, the local variable can be set to register and the C compiler will use the
register instead of the non-data memory space to store this variable so as to enhance the
access speed and reduce compilation. This function is currently not applied.
→ Storage class static
The static variable will remain effective until the whole program ends. Its initial value
will only be set once at the beginning of program execution. Though effective before the
program comes to an end, the static variable defined inside the function is still a local
variable which must be read/written within the function that defines it.
→ Storage extern
extern is used to inform the C compiler that this variable is defined in another program file
that needs to be connected using the Linker so as to know the variable location.
For the present microcontroller applications, it is recommended to use extern rather than the
other three which have no special advantages and can be functionally replaced by defining a
global variable.
■ Qualifier
→ Qualifier const
The C compiler will place the const variable into the program memory. When defining a
const, a value which cannot be changed during the program execution must be setup.
The const variable cannot be configured as extern at present.
→ Qualifier Constant
This qualifier, exclusively provided by the Holtek C compiler, will place the constant
Rev. 1.30
18
March 15, 2011
Using Enhanced Holtek C
variable in the last page of the program memory and should be configured when defining
the const variable. The value cannot be changed during program execution. Three notes
for using this qualifier are as follows:
● Used for int or unsigned int data types only
● The setting value adjusts to the program memory width of the microcontroller. For
example, when used in the HT48R50A-1, which has a Program Memory width of 15
bits, the high bit will be invalid, so 0x9A will be changed to 0x1A by the C compiler and
the highest bit, which is bit 15, will be cleared to zero.
● All variables or arrays defined with this qualifier cannot exceed a total of 255 words
● To set the int or unsigned int variable to a constant value, it is recommended to use
constant instead of const so as to increase the program efficiency.
■ Specifier
→ Specifier typedef
typedef is used to define a new name declaration in light of the data type instead of the
new variable of the data type. Ex. declare UCHAR (new name) to be an unsigned char
data type by using:
typedef unsigned char UCHAR ; // UCHAR is the new name of the unsigned char
UCHAR count ; // the data type of the variable count is unsigned char
// equal to unsigned char count;
Using typedef to declare the new name of the data type makes the program easier to be
understood with better readability. Ex.
typedef unsigned int WORD ; // WORD represents and unsigned 16-bit integer
typedef unsigned long DWORD ; // DWORD represents a 32-bit double word
4.3.7 Absolute Variable
This variable can point to global or static variables at a fixed memory address. Ex.
unsigned char PortA @ 0x12 ;
By adding @ and the address after the variable name, the C compiler will change absolute
variables in the program to this address during compilation yet does not reserve any position
in the memory for it. Therefore the variable will not be found in the map file generated from the
linker and will be interpreted by the C compiler as an EQU assembly language instruction. Ex.
_PortA EQU 12h
This is basically a definition given to the register of the microcontroller program reading
convenience.
4.3.8 Constant
The integral constant can be listed in a radix format.
Radix
Constant format
Example
Binary system
0bnumber or 0Bnumber
0b10111110
Octal number system
0number
0276
Decimal system
number
190
Hexadecimal system
0xnumber or 0Xnumber
0xBE
If the last character of the constant is an I or L then this indicates that either a signed long or
unsigned long type is used. A suffix of u or U after S indicates the constant is an unsigned
type.
The floating point constant type is double, or else float if suffixed with an f or F.
The character constant must be included in single quotation marks, ex. `a'
The string constant must be included in double quotation marks, ex. “Hello!" The definition
of the string constant will influence the memory address where it is stored. For example:
char *cp = “one" ; // C compiler will display an error
Rev. 1.30
19
March 15, 2011
Using Enhanced Holtek C
char *const sptr = “Hello" ;// “Hello" is stored in the program memory
The constant type variable or array must be configured with a value or the C compiler will
display an error message as shown in the above example.
4.3.9 Pointer and Array
The pointer itself is a variable that stores the address of other variables such as an indirect
address in assembly language. The pointer must point to a defined (stored in memory)
variable when being used, or an error may occur during execution. The pointer declaration
format is:
Data type * pointer name [, * pointer name,….];
The data type means the variable data type indicated by the pointer, such as char, of which
the name is similar to that of a variable and can be declared to indicate different pointers of
the same data type in the same line. For example,
char *tptr, *array_ptr ;
int *line_ptr ;
The above merely declares the pointer variable. The pointer must point to defined variables to
become effective. String arrays are not supported yet. For example,
char *rainbow[] = { "red", "orange", "yellow" };// not supported
■ Pointer operator & and *
The operator & preceding a variable, such as &line, means to obtain the memory address of
the variable.
For example,
int line ; // define variable
int *line_ptr ; // declare pointer
line = 12 ;
line_ptr = &line ;
If the variable line is placed at the address 64 of the RAM, the pointer line_ptr is equal to 64.
The operator * preceding a variable means to obtain the variable content indicated by the
pointer as shown in the above example.
int total ; // define variable
total = *line_ptr ; // obtain the line content pointed to by line_ptr,
the variable total is equal to 12
Regarding the function pointer, currently the enhanced Holtek C only supports the global const
function pointer, in which no parameters can be included. Holtek C does not support function
pointers. For example:
fun()
{
return 1;
}
int (*const p)() =fun; // global and initialization required
void main()
{
int a;
a=(*p)();
}
The pointer size depends on the microcontroller memory size. If there is only one RAM bank,
the pointer itself will take one byte while multiple RAM banks will take two bytes. If the variable
contains const or constant qualifiers, the pointer will point to the program memory in which
the variable content cannot be modified. If no const or constant is included in the variable, the
pointer will point to the variable in the data memory RAM. Holtek C cannot obtain the constant
address of const. For example:
Rev. 1.30
20
March 15, 2011
Using Enhanced Holtek C
const int ldc = 0;
void main(){
int *a;
a = &ldc; // cannot pass
}
■ Array
An array is composed of elements of the same data type. Ex.
char array_name[32] ;
is composed of 32 char type elements whose name is array_name using an index to
distinguish each element. As an example, array_name[3] means the fourth element. The array
index is a positive integer starting from zero up to the total number of elements minus one.
For example, the last element is array_name[31] in the above example. This data type is very
useful for table production.
An array can also be used as a pointer only in a different format. The following example
explains the usage between pointers and arrays.
char *nptr, *fptr ; // declare pointers
char ch, tbl ; // define variables
char table[5] = { `a' , `b' , `c' , `d' , `e' } ; // define arrays
nptr = table ; // pointer nptr points to the first element table[0] of the array table
ch = *nptr ; // save character `a' to variable ch
tbl = table[0] ; // save character`a'to variable tbl, so both ch and tbl variables are the same.
fptr = &table[4] ; // pointer fptr points to the 5th element, table[4],of the array table
ch = *fptr ; // save the character `e' (the 5th element) to variable ch
tbl = *(nptr+4) ; // nptr points to the first element of the array table plus 4, therefore bl =`e'
Note: The maximum value of the array size depends on the RAM/ROM size of the MCU,
therefore the length of const arrays will not exceed one rombank(2000h) and the length of
constant arrays will not exceed one rompage(256h). A general array will not exceed 256
bytes. Arrays of three dimensions or more are not presently supported.
4.3.10 struct and union
A structure is a collection of one or more variables, possibly of different data types and
managed under the same structure name. A structure declaration is equal to a new defined
data type. When a variable is declared as a structure type, the content can be read/written
using the structure name.
The variable data type cannot be in a bit form but can be declared with a bit-field method, for
example:
struct str_name {
unsigned flag : 1 ; // this variable is placed at the least significant bit
unsigned no_used : 7 ;
unsigned stack : 5 ; // this variable is placed at the highest bits
} usage ;
Every bit field will be placed into an 8-bit unit with no crossover into two 8-bit units and cannot
defined in a format of more than 9-bit bit field unions with the same structure. The only
difference lies in the configuration of the memory space. A union provides a way to manipulate
different kinds of data in a single storage area. Each variable must declare its data type while
the union size is the largest data type size. The start address of every variable is the same,
that is the union address.
union union_name {
char num_byte ; // occupy one byte
int num_int ; // occupy 2 byte
long num_long ; // occupy 4 byte
Rev. 1.30
21
March 15, 2011
Using Enhanced Holtek C
} number ;
The union number is 4 bytes.
Qualifiers can also be used in the structure and union types, such as const, with the same
result as the general data type.
■ Structure Operator -> and .
If the variable data type indicated by the pointer is a structure or union, either the operator
of a right arrow “->" or a dot “." with the variable name can be used to manipulate the
variables.
Example:
struct tag {
char flag ;
int number ;
unsigned ac : 1 ;
unsigned z : 1 ;
};
struct tag status ; // define the variable status as a structure tag data type
struct tag *sptr ; // declare the pointer sptr as a structure tag data type
bit vac, pac ; // define the variable vac, pac as a bit data type
status.flag = 1 ; // write 1 to the structure variable flag
status.ac = 1 ; // write 1 to the structure variable ac
vac = status.ac ; // vac = 1
sptr = &status ; // pointer sptr points to the structure status
pac = sptr->ac ; // pac = 1
4.4 Operators
Operators are arithmetic symbols for the data stored in the variables. An expression is a group
of operators, data, variables, function and expression in which the operators include:
→ Arithmetic operators
+, -, *, /, % are addition, subtraction, multiplication, division and remainder operators.
→ Comparison operators
Compare two operands and report the latter result to be true (not zero) or false (zero)
> greater than
>= greater than or equal to
< smaller than
<= smaller than or equal to
== equal to
!= unequal to
→ Logical operators
Take the true or false condition of the operators for logical operation and report if the result
is true (not zero) or false (zero)
&& logic AND
| | logic OR
! logic NOT
→ Bitwise logical operators
Bit logic operation
& bit AND
| bit OR
Rev. 1.30
22
March 15, 2011
Using Enhanced Holtek C
^ bit XOR
~ bit complement
>> bit move to right
<< bit move to left
→ Assignment operators
<var> += <expr>; add expr value to the variable, save the result to the variable
<var> -=<expr>; subtract expr value to the variable, save the result to the variable
<var> *=<expr>; multiply expr value to the variable, save the result to the variable
<var> /=<expr>; divide expr value to the variable, save the quotient to the variable
<var> %=<expr>; divide expr value to the variable, save the remainder to the variable
<var> &=<expr>; take the variable and the expr value as the bit AND, save the result to the variable
<var> |=<expr>; take the variable and the expr value or bit OR, save the result to the variable
<var> ^=<expr>; take the variable and the expr value or bit XOR, save the result to the variable
<var> >>=<expr>; move the variable to the right for expr bits, save the result to the variable
<var> <<=<expr>; move the variable to the left for expr bits, save the result to the variable
→ Increment and decrement operators
++<var> add 1 to the variable and then calculate
<var>++ calculate and then add 1 to the variable
--<var> subtract 1 from the variable and then calculate
<var>-- calculate and then subtract 1 from the variable
→ Conditional operators
<expr> ? <statement1> : <statement2> ;
If the <expr> operation result is true, execute <statement1>, or else execute <statement2>
→ The priority and associativity of operators
When multiple operators are included in one operation, the operation priority of the
operators should be noted to avoid the result being different to what is expected. The table
below lists the operator priority and associativity. Operators in the front column own a
higher priority while the priority of those in the same column depend on their associativity.
Rev. 1.30
Operators
Description
Associativity
[]
()
->
sizeof
Array element
Quotation for Function or operation
Indirect access of structure or equation members
Byte size of data
From left to right
++
-~
!
+
&
*
Add 1
Subtract 1
Take one's complement
Deny
Unary minus sign
Unary plus sign
Take the variable address
Access the content of the pointer address
From right to left
*
/
%
Multiplication
Division
Remainder
From left to right
+
-
Addition
Subtraction
From left to right
<<
>>
<
<=
>
>=
Move left
Move right
Smaller than
Smaller than or equal to
Greater than
Greater than or equal to
From left to right
23
March 15, 2011
Using Enhanced Holtek C
Operators
Description
Associativity
==
!=
&
^
|
&&
||
?:
Equal
Unequal
Bit AND
Bit XOR
Bit OR
Logic AND
Logic OR
Conditional operation
From left to right
=
*=
/=
%=
+=
-=
<<=
>>=
&=
|=
^=
Configuration
Multiply, then save to the variable
Divide, then save the quotient to the variable
Take the remainder, save to the variable
Add, then save to the variable
Subtract, then save to the variable
Move left, then save to the variable
Move right, then save to the variable
Bit AND, then save to the variable
Bit OR, then save to the variable
Bit XOR, then save to the variable
From left to right
Separate variables or expressions
From left to right
,
■ Type conversions before operation
When an operator has operands of different types, they must be converted to a common
data type which will be automatically executed by the C compiler. To prevent data loss
during conversions, it will be converted to a larger type in general. In some situations, even
the operand type is the same, a type conversion will still be executed before the operation.
The C compiler will convert automatically according to the operation status. If a conversion
is required to be implemented using a definite method, it is acceptable to execute a forced
conversion type. (type cast).
Example:
char count, a = 0 , b = 50 ;
if( a – b < 10 )
count++ ;
The result from subtraction and comparison by the C compiler show -50, so count++ will be
executed. If the operand changes to:
if( (unsigned int)(a – b) < 10 )
count++ ;
then being converted to an unsigned int with an operation result of 206, count++ will not
be executed and the shift operators will operate differently according to the operand type.
The right shift operator in the signed char/int/short/long type operation is to copy the most
significant bit, MSB, of the original to that of one bit to the right of the MSB. For example:
signed int 0x0124 after shifting to right for one bit becomes 0x0092 (MSB=0)
signed int 0x8024 after shifting to right for one bit becomes 0xC012 (MSB=1)
The right shift operand on the unsigned char/int/short/long type will fill the MSB with 0.
The left shift operand to the unsigned/signed type operation will clear the least significant bit
to zero.
Rev. 1.30
24
March 15, 2011
Using Enhanced Holtek C
4.5 Program flow control
After familiarisation with the program architecture, variables and the data types, expressions
and operators, the most efficient best program flow can be designed. In the following
statements, bold characters represent reserved words which must be used when executing
these statements. Using these reserved words as variable names are not permitted. What is
grouped in brackets in the syntax is optional, depending upon the actual requirement.
4.5.1 if-else statement
Syntax:
if ( cond-expression )
statement1 ;
[ else
statement2 ;
]
Description:
This control statement is used to determine conditions. Different conditions may require
different manipulations and flow control can be executed with this statement. If the result
of the conditional cond-expression is true (not zero,) the statement1 will be executed;
otherwise if the else part is included, statement2 in the else part will be executed. The
brackets indicate that the requirement of this part entirely depends upon the program.
statement1 and statement2 may contain more than one statement. If the statements
increase, then braces will be needed to group them.
For example:
if( seconds > 59 )
{
minutes++ ;
seconds = 0 ;
}
else
seconds++ ;
4.5.2 Switch statements
Syntax:
switch( expression )
{
case constant1 : statement1 ;
break ;
case constant2 : statement2 ;
break ;
……
[ default : statementX ;
break ; ]
}
Description: if-else controls the corresponding flow of an expression and has only two results.
If the result of an expression exceeds two values, the switch-case statement will help increase
the readability of the program and help to better understand its function. If the result of the
expression is equal to constant1 then statement1 will then be executed. If the result of the
expression is equals to constant2 then statement2 will be executed. If no results are equal to
any of the expression then statementX will be executed as a default.
The default part is optional. Each case or default may contain several statements, ex:
case constant2 :
Rev. 1.30
25
March 15, 2011
Using Enhanced Holtek C
statement20 ;
statement21 ;
……
break ;
expression can be either a variable or an expression that can calculate a value.
A break must be added to end the case within each switch statement. If no break is
added then the program will continue to the next executing all statements until a break is
encountered. In the example below, if a break is not included, then in case `1', when
input_key=1, color=RED will be executed but the next statement color=GREEN will also be
executed as there is no break. The result may not be what is expected by the programmer.
Example:
switch( input_key )
{
scase 1 : color = RED ;
break ;
case 2 : color = GREEN ;
break ;
……
default : color = WHITE ;
break ;
}
4.5.3 for statement
Syntax:
for (initial-expression ; cond-expression ; update-expression)
statement1 ;
Description:
The for statement is to repeatedly execute the same operation (statement) as a loop
function.
The initial-expression will be firstly executed usually with some variable setup, which will
be executed once. If this expression is not present, then the cond-expression comparison
will be executed directly.
The cond-expression is a conditional expression, and is the same as cond-expression in
the if-else. When a condition is satisfied, statement1 will be executed or else it will leave
this loop and jump to the statement after statement1. After the condition is satisfied and
statement1 executed, the program will continue to the update-expression, then return to
cond-expression for comparison and repeat the same execution until the condition is no
longer satisfied and the jump out of the loop to the next statement. If update-expression
does not exist, the comparison to cond-expression will be directly executed.
Statement1 can be more than one statement which must be included in braces.
Example:
Clear each element in the variable array to zero,
int idx ;
char cbuf[20] ;
for( idx = 0 ; idx < 20 ; idx++ )
cbuf[idx] = 0 ;
Rev. 1.30
26
March 15, 2011
Using Enhanced Holtek C
4.5.4 while statement
Syntax:
while ( cond-expression )
statement1 ;
Description: This statement has a similar conditional loop function to the for statement except
for the initial-expression and update-expression. Once cond-expression is true, statement1
will be executed until the condition is no longer true and jump out of the loop. statement1 can
be more than one statement which must be included in braces.
Example:
int idx ;
idx = 0 ;
while( idx < 20 )
{
cbuf[idx] = 0 ;
idx++ ;
}
4.5.5 do-while statement
Syntax:
do {
statement1 ;
} while ( cond-expression ) ;
Description: The do-while will execute statement1 first and then compare it with the condexpression. If the condition is satisfied, statement1 will be executed again until the condition is
no longer true to jump out of the loop. This statement is similar to the while statement except
that statement1 will be executed at least once. statement1 can be more than one statement.
Example:
idx = 0 ;
do {
cbuf[idx] = 0 ;
idx++ ;
} while( idx < 20 ) ;
4.5.6 goto statement
Syntax:
goto label ;
Description: goto is a compulsory flow control statement which can directly jump out of a loop
switching the program to a statement label or from a switch-case to label. The standard name
label and statement goto, are not allowed to force the program to jump to other functions, so
therefore must be included in the same function.
Example: refer to the 4.5.7 example
4.5.7 break and continue statement
Syntax:
break ;
continue ;
Description: break is to jump out from a loop or switch case, one layer at a time. continue is to
jump over the statements after a continue to execute the next loop.
Example:
idx = 0 ;
Rev. 1.30
27
March 15, 2011
Using Enhanced Holtek C
while( idx < 20 )
{
if( cbuf[idx] == 0 ) // cbuf[] no character
break ; // jump out while loop
idx++ ;
}
for( idx =0 ; idx < 20 ; idx++ )
{
if( cbuf[idx] != 0 ) continue ; // cbuf[] still have character, return idx++, continue
goto count_l ; // no character, count total characters
}
…… // other statements
count_l : // label
// idx = total characters
4.6 Functions
A function is a collection of statements. All statements to be executed must be defined in a
function (main() is the main function.) Before using a function, it must be declared and defined
or the compiler will generate an error message. In addition to the statement content, the most
important part of functions are their arguments and return values. The format is:
return-type function_name(var-type arg1, var-type arg2, …)
{
statements ;
}
return-type is the type of the function return value. Data types in section 4.2 can be used
here. function_name is the name of a function, composed of characters, digits (0~9) and
underscores using case-sensitive for respective meanings. var_type is the argument type with
arg1, arg2 as the names using case-sensitive for their respective meanings.
4.6.1 Arguments
Based on the data type, the arguments are saved using the following method for calling into a
function.
→ All arguments are saved using internal variables. The name of the variable is based on the
function plus a digit starting from zero. For example, if the function is named by multiple,
the first argument will be saved to variable multiple0 and the second argument will be
saved to multiple1 etc. If the argument type is int or unsigned int, two storage bytes will be
used. For example, if the second argument is int type, the variable multiple1 will store the
low byte of the argument while the variable miltiple1+1 will save the high byte.
4.6.2 Return Values
With regard to assembly language:
→ If the return value is one byte, it will be placed into an accumulator to call back the
statements in a function.
→ If the return value is two bytes (int, short), the low byte will be placed into the accumulator
and the high byte in the variable RH.
→ If the return value is four bytes (long, float), the low byte of the low word will be placed into
the accumulator, the high byte of the low word in the variable RH, the low byte of the high
word in the variable RM and the high byte of high word in the variable RU.
To increase program modularity and readability, the best method is to implement
each function using individual routines. The main function will be responsible for the
management and calling of individual functions which can be placed into different program
files from the main function.
Rev. 1.30
28
March 15, 2011
Using Enhanced Holtek C
4.7 Interrupt Service Routines
The C language can write the Interrupt Service Routines (ISRs) for interrupts in the
microcontroller hardware. The following rules should be noted:
→ The return value type of the function must be void
→ No parameters should be included in the function
→ Use #pragma vector to setup the interrupt vector in the interrupt service routine
Use @ to indicate the interrupt vector
→ Calling the interrupt service routine from other locations is not recommended.
→ Regarding microcontrollers without nested interrupts, the interrupt function cannot be
enabled in the interrupt service routine.
Ex:
#pragma vector ISR_Timer @ 0x08
void ISR_Timer(void)
{
}
// define: return value type, no arguments, set the interrupt vector to 0x08
The C compiler will check for the required registers used by the interrupt service routine
and save the register values after entering the interrupt service routine and then restore the
previously saved register values following the execution of the interrupt service routine. Finally
it will proceed with execution back from the interrupt and at the same time enable the interrupt
function to generate an interrupt. If the interrupt function is required by any other program
sections, the corresponding registers can be setup by the user.
When the interrupt service routine is processing this interrupt and another urgent interrupt is
generated and needs to be handled, the microcontroller must stop the current interrupt service
routine and handle the newly generated interrupt. This is in fact the nested interrupt feature.
When compiling the interrupt service routine, the Holtek C compiler will save some frequently
used register values to the RAM space. After the interrupt service routine has completed it
will return to the previous interrupt breakpoint and restore the saved contents back to the
registers. To support an interrupt nested event, the Holtek C compiler will save a group of
RAM space for each interrupt vector. For example the interrupt service routine in the interrupt
vector 1 (INT 1) will save the register contents to V1xx while that in the interrupt vector 2 (INT 2)
will be saved to V2xx, and so on.
The register contents saved by the interrupt service routine includes accumulator (ACC),
status (S), bank pointer (BP), indirect address pointer (MP0, IAR0) and intermediate variables
used in actual operations (prefixed by T, ex. T2, T3….) These registers or intermediate
variables will be saved to their associated variables, V1A, V1S, V1BP, V1MP0, V1MP1, V1T2,
V1T3…(interrupt vector 1), V2A, V2S, V2BP, V2MP0, V2MP1, V2T2, V2T3…(interrupt vector
2) and so on. Microcontrollers without a BP and MP1 need not be saved. Although different
interrupt events can be nested, the same interrupt event cannot be nested which means the
previous one should be processed first before acknowledging the next interrupt event. It is
acceptable to disable the same interrupt in the interrupt service routine.
If different interrupts in a microcontroller cannot be nested, the Holtek C compiler can use only
a group of memory space to store the register contents yet must be defined in advance in
the program of the interrupt service routine (using #pragma novectornest) where the interrupt
function will be disabled (disable interrupt, _emi=0).
Rev. 1.30
29
March 15, 2011
Using Enhanced Holtek C
4.8 Inline Assembly Codes in C
For more simple and effective compiled programs, it is possible to embed assembly code into
the C-program.
Syntax:
#asm
[label:] opcode [operands]
...
#endasm
#asm
Description:
#asm and #endasm are the preprocessor virtual instructions of the inline assembly
code. The C compiler will directly write the assembly codes after #asm (or between
#asm and #endasm) to the output file as if it was using the assembly code for
program creation.
Comment:
The embedded inline assembly code can only be located within a function.
The embedded inline assembly code can only include instructions and cannot
include the definition of variables and sections etc.
Any embedded variables must use the associated assembly names. The connection
between the variable and the assembly name is as follows:
Global Variable: var→ _ var (exceed one byte: _var,_ var[1],_ var[2],_ var[3])
Ex. char a;long b;
Associated ASM name: a→_a, b→_b,_b[1],_b[2],_b[3]
Local Variable: CR1, CR2, CR3…(exceed one byte: CR1, CR1[1], CR1[2],
CR1[3] ) among which the digits are arranged in the order of compilation.
Therefore if the defined order is changed, the compiling name will also be
changed at the same time while the local variable will not have a corresponding
compiling name until it is used. For example, if the r in the above example was
not given a value of zero, an error will be reported as CR4 cannot be found.
Ex. void fun()
{
char a;long b;
a = 0;b=0;
//Associated ASM name: a→CR1, b→CR2,CR2[1],CR2[2],CR2[3]
}
Function name: name(a,b)→_name(function argument name:
name0,name1,name2…)
Ex: void fun(char a,char b)
{}
Associated ASM name: fun→_fun, a→fun0, b→fun1
The variable static should not appear in the embedded assembly as its assembled
name is random.
If there is no way to reference a variable to its corresponding assembly name, refer
to #pragma debug variable 8 2 CR1 d1 in the output asm file.
Here d1 is a variable, CR1 is the assembler name corresponding to d1. The compile
operation must have completed before the asm file can be generated.
Example:
char a;
int b;
void fun(char p1,int p2)
{
a = p1;
#asm // b = p2;
Rev. 1.30
30
March 15, 2011
Using Enhanced Holtek C
MOV A,fun1
MOV _b,A
MOV A,fun1[1]
mov _b[1],A
#endasm
}
void main()
{
int d1;
char d2;
unsigned char q, r;
r = 0;
q = d1 / d2; // get quotient
#asm // r = q;
MOV A, CR3 ; CR3→q
MOV CR4,A ; CR4→r
#endasm
#asm // fun(d2,d1)
MOV A,CR2
MOV fun0,A ; p1 = d2
MOV A,CR1
MOV fun1,A
MOV A,CR1[1]
MOV fun1[1],A ; p2 = d1
CALL _fun
#endasm
}
Rev. 1.30
31
March 15, 2011
Using Enhanced Holtek C
4.9 Preprocessor
A preprocessor is a character string prefixed with #. All preprocessors in the program will be
initially managed by the preprocessor. These commands provide functions such as define,
macro, include file, conditional compiler and pragma.
4.9.1 Define Characters (#define)
→ #define
Syntax:
#define sym_name replaced_text
Description: Define sym_name as replaced_text which can be a value, expression or
alphabetic string. The preprocessor will change all sym_name statements in the
program to replaced-text.
Example:
#define TOTAL_COUNT 40
#define PA0_12_0
→ #undef
Syntax:
#undef sym_name
Description: cancel the previously defined characters or preprocessed macros
Example:
#undef PA0 // cancel the pre-defined PA0
4.9.2 #include
→ #include
Syntax:
#include “file_name"or
#include <file_name>
Description: Combine the designated file into the present program loation.
When file_name is placed within in quotes, the compiler will first search for the file in
the working directory. If the file is not found, it will continue to search in the current
directory or else generate an error message.
When file_name is placed within < >, the compiler searches only in the directory
setup by the environment parameter.
4.9.3 Inline Assembly
→ #asm #endasm
Syntax:
#asm
assembly instruction, ex. MOV A, 1
#endasm
Description: Locate assembly code commands between #asm and #endasm
Example: #asm
AND A, 0Fh
SUB A, 09h
#endasm
Rev. 1.30
32
March 15, 2011
Using Enhanced Holtek C
4.9.4 Conditional Compiling (#if/#endif)
→ #if #else #endif
Syntax:
#if expression
statements1 ;
[#else
statements2 ; ]
#endif
Description: Controls conditional compilation. When an expression is true, the program
in statements1 will be compiled, otherwise statements1 will be ignored. If there is
an #else, then statements2 will be compiled. #else is optional according to actual
needs.
Example:
#if MODE > 0
#define DISP_MODE MODE
#else
#define DISP_MODE 7
#endif
→ #ifdef
Syntax:
#ifdef symbol
statements1 ;
[ #else
statements2 ; ]
#endif
Description: If symbol is defined in advance (using #define), then statements1 will be
compiled, otherwise statements2 will be compiled. #else is optional.
→ #ifndef
Syntax:
#ifndef symbol
statements1 ;
[ #else
statements2 ; ]
#endif
Description: Opposite of #ifdef, if symbol has not been defined previously, then statemens1
will be compiled or else statements2 will be compiled. #else is optional.
→ #elif
Syntax:
#if expression1
statements1 ;
#elif expression2
statements2 ;
#endif
Description: If expression is true, statements1 will be compiled, or if expression2 is true,
statements2 will be compiled. #elif is the abbreviation for #else #if.
Preprocessor
Rev. 1.30
Function
#asm
Indicate to following this line is “in-line assembly"
#define
Define symbol or preprocess macro
#elif
Abbreviation for #else #if
33
Example
#asm
add a, 1
#endasm
#define COUNT 20
#define OK
#define add(a,b) ((a)+(b))
Refer to #ifdef
March 15, 2011
Using Enhanced Holtek C
Preprocessor
#else
#endasm
#endif
#error
Function
Define “condition not true" original expression
Indicate the end of “in-line assembly"
End up “conditional type original expression"
Error message occurs
#if
Define “condition true" original expression
If the condition is true, place the subsequent original
expression into the program
#ifdef
If the preprocessed symbols are defined, add the
subsequent original expressions
#ifndef
If the preprocessed symbols are not defined, add the
subsequent original expressions
#include
#pragma
#undef
Add the contents in the header file
Special compiler options
Cancel previously defined symbol or preprocess macro
Example
Refer to #if
Refer to #asm
Refer to #if
#error Size too big
#if tick < 10
tick++ ;
#else
tick = 0 ;
#endif
#ifdef COUNT
delay() ;
#else
nothing() ;
#endif
#ifndef COUNT
nothing() ;
#endif
#include “ht46R23.h"
Refer to relevant section
#undef COUNT
4.9.5 Compiler Special Options pragma
Format
#pragma keyword [ options ]
Some keywords may have options. Keywords for pragma are as follows.
keyword
bp_free
bp_nofree
function
nobp
nolocal
nomp0
nomp1
rambank0
norambank
options
—
—
V
—
V
—
—
—
rombank0
norombank
—
rombank
vector
V
V
novectornest
—
Function Description
No changes to the BP register in the function ②
Cancel the bp_free function ②
Set the ROM address at the function location
Do not save the BP register contents in the interrupt service routine ②
Set function parameter and internal variable as general type, not LOCAL ②
Do not save the MP0 register contents in the interrupt service routine ②
Do not save the MP1 register contents in the interrupt service routine ②
Set the variable to the location address of the RAM bank 0 ③
Cancel the rambank function
Set the variable to the location address of ROM bank 0 ①
Cancel the rombank function ①
Locate a function to a ROM bank ①
Define interrupt service routine
Only a group of register storage assigned to the interrupt service routine; no
interrupt nesting allowed
① Only effective in microcontrollers with multiple ROM banks
② Only effective on microcontrollers with multiple RAM banks and only one ROM bank
③ Only effective on microcontrollers with multiple RAM banks
Keyword functions are listed as follows:
→ #pragma bp_free
#pragma bp_nofree
Regarding the statements included within these two preprocessors, the compiler will delete
all command codes that change the BP register, namely the MOV BP, A commands, so as
to reduce the command codes generated by the compiler. Ensure that the memory where
variables are located are all within the same RAM bank, starting from the statement after
#pragma bp_free and before #pragma bp_nofree. These two preprocessors can be added
to include any statement in the function.
→ #pragma function function_name @rom_address
Locate the designated function function_name at rom_address in ROM.
Rev. 1.30
34
March 15, 2011
Using Enhanced Holtek C
Rom_address can be hexadecimal, ex. 0x100 means to locate the designated function in
the 256 ROM addresses. If the function is to be located at address 256 in ROM bank 1,
then set rom_address to 0x2100.
→ #pragma nobp
This is only effective in interrupt service routines, indicating that the compiler should not
save the BP register contents in the interrupt service routine.
The command will be effective in all interrupt service routines in one single program.
→ #pragma nolocal function_name
For general functions. Regarding designated functions, function_name will set the local
variables and internal registers used by the function while compiling as general type
variables instead of common type whose RAM space is shared by other variables. When
the interrupt service routine calls other functions, the local or internal variable data used by
these functions may be at risk of being corrupted if they share the same RAM space with
other functions. This preprocessor is able to eliminate this risk.
→ #pragma nomp0
#pragma nomp1
Only effective within interrupt service routines, indicating to the compiler not to save the
MP0 or MP1 register contents in the interrupt service routine. One effective for all interrupt
service routines in a single program file.
The compiler will determine whether to save the BP, MP0, MP1 register content or not in
accordance with the microcontroller structure.
→ #pragma rambank0
#pragma norambank
Define the variables to be saved in RAM bank 0. All variables defined between these two
preprocessors will all be stored in RAM bank 0. Used when the microcontroller has more
than one RAM bank. If the microcontroller has only one RAM bank then this preprocessor
is not required. When the variable is a bit type, the variable must be defined in RAM bank 0.
→ #pragma rombank0
#pragma norombank
Locate functions in ROM bank 0. All functions defined within these two preprocessors will
be placed in ROM bank 0.
→ #pragma rombank banknum function_name1 [, function_name2 [, ..]]
This preprocessor will locate the designated function in the ROM bank. banknum is the
ROM bank number which is set according to the microcontroller ROM structure. The.
function_name1, function_name2 are the function names. More than one function can be
designated at the same time.
→ #pragma vector isr_name @vector_address
Declare the name of the interrupt service routine and interrupt vector value. A previous
declaration is required for each interrupt service routine. isr_name is the function name.
vector_address is the interrupt vector value.
→ #pragma novectornest
This means only a group of register memory is reserved in the interrupt service routine.
When nested interrupts are not allowed by the microcontroller it must complete the
previous processing before handling the next one. This preprocessor can help save RAM
space and avoid an overflow from RAM bank 0.
Refer to segment 4.7 for the interrupt service routine description.
Rev. 1.30
35
March 15, 2011
Using Enhanced Holtek C
4.10 Holtek C built-in Functions
■ Direct assembly compilation built-in functions
C Function assembly instruction
void _clrwdt( ) CLR WDT
void _clrwdt1( ) CLR WDT1
void _clrwdt2( ) CLR WDT2
void _halt( ) HALT
void _nop( ) NOP
■ Other built-in Functions
void_rr (char *p) sets the pointer p to 1 byte and rotates right one bit
ex. ch = 0xA5 ;_rr(&ch) ; then ch = 0xD2
void_rr (int *pl) sets the pointer pl to 2 bytes and rotates right one bit
ex. ch = 0xA5A5 ;_rr(&cnt) ; then cnt = 0xD2D2
void_rl (char *p) sets the pointer p to 1 byte and rotates left one bit
ex. ch = 0xA5 ;i_rl(&ch) ; then ch = 0x4B
void_lrl (int *pl) sets the pointer pl to 2 bytes and rotates left one bit
ex. cnt = 0xA5A5 ;_lrl(&cnt) ; then cnt = 0x4B4B
void_swap(char *p) sets the pointer p to 1 byte and exchanges the four low bits with
the four high bits
ex. ch = 0xA5 ;_swap (&ch) ; then ch = 0x5A
void_delay(unsigned long tick) delay for tick instruction cycles
tick <=263690, if tick =0 it means infinite loop
(Refer to segment 5.2.2 description)
Rev. 1.30
36
March 15, 2011
Using Enhanced Holtek C
Chapter 5
Basic C Language Programs
The main point of this chapter is to introduce C-language writing methods using examples. It
will start with simple syntax using the microcontroller characteristics and easy to understand
frequently used programs. After familiarization with these methods the section moves on to
more complex syntax.
5.1 C Syntax Concepts
→ The equal mark “=" (assignment) in the C statement contains writing, pointing, output
functions.
Ex.
PortAC = 0x01 ;
If PortAC is the control register (0x13) of I/O Port A, then the above statement indicates to
set bit 0 in Port A to 1 and the other bits to 0. Bits sets to 0 indicate outputs while bits set to
1 indicate inputs. This statement is equal to the following in assembly language:
MOV A, 01
MOV PAC, A ;; PAC = [13H]
→ Use two successive equal marks “==" when using conditional statement and “!=" for
the contrary.
if( count == 10 )
{
}
This means if the variable count is equal to 10, then execute the statement within the
brackets, or else jump out of the brackets if it is written as
if( count = 10 )
therefore “10” will be first written to the variable count, and then checked if count is true (not
zero).
It must be true in this example and the statement within the brackets will be executed ,
therefore it may be an error.
→ Number value syntax and and assembly language difference
Hexadecimal values start with 0x followed by 0 to 9 and A to F and are non case-sensitive.
Ex. 0x13, 0xad2, 0x2B
→ The variable or register at the right side of the equal mark “=" contains a read function,
Ex. status = PortA ;
Read the input value form Port A and save to variable status which functions as the
following in assembly language
MOV A, PortA ;; PortA = [12H]
MOV status, A
Rev. 1.30
37
March 15, 2011
Using Enhanced Holtek C
5.2 Loop Application
When a program needs to repeat the same or similar actions, using a loop can be of help. For
example, clear the contents in the data memory to zero, or setup or clear every bit in the I/O
port. Keywords for this syntax include for, while, do-while etc. as the description below shows.
5.2.1 Example 1: 8 Flashing LEDs
Functional Description : Use the HT48R06A-1 to control 8 flashing LEDs.
Circuit Description : Connect eight pins on Port A in the HT48R06A-1 to the resistor and
LED and control the LED from port A.
Program Description : The program will setup the eight pins of Port A in turn to illuminate the
corresponding LEDs.
#include “ht48r06A-1.h" // insert the header file ht48r06a-1.h, defined variables are
necessary
// _pa is the data port address of Port A, _pac is the control register of Port A.
void main(void) // define main function
{
char status, cnt ; // define local variable as the LED control code
_pac = 0 ; // write zero to the control register of Port A, set Port A to be output
type
for( cnt = 0 ; cnt < 8 ; cnt++ ) // loop, turn on the LED for 8 times in all
{
status = (1 << cnt) ; // The first LED to is PA0, and PA1 is the second…
_pa = status ; // output to Port A, illuminate a single LED and turn off the
others
}
}
Try: Change the for loop in the program above to a while loop.
5.2.2 Delay Timing
When handling the peripheral devices of the microcontroller, strict timing requests will be
made, therefore using C to design a good timing control program will be a great asset in C
applications. The following methods can be used to do this:.
→ Use an in-line assembly method to embed an assembler timing routine into the C program.
If using a call function then it is necessary to understand how use the mixed language
assembler and C-language together. If using macros then this will increase the program
size which is not good for flexible Program Memory space. This implementation method is
suitable for applications whose delay timing is shorter than five instruction cycles.
→ Using C to do the timing control program, it is necessary to calculate the actual operation
time of the assembled instructions after compilation. Some timings are however inaccurate
and will require some adjustments.
This chapter will use C to write a timing control program, analyse it and provide a correct
function for the user to easily control the required timing. This function uses instruction
codes compiled using the Holtek C Compiler. If using other C compilers, a similar analysis
will be necessary however the results may be different.
5.2.2.1 Timing Control Method (1) – using for-loop
→ Define a timing control program delay
void delay (unsigned int cycle)
{
unsigned int count ;
for( count = cycle ; count > 0 ; count-- )
;
}
Rev. 1.30
38
March 15, 2011
Using Enhanced Holtek C
Input variable cycle to decide the instruction cycle delay, which can be acquired from the
microcontroller frequency 1 stands for 26 cycles, 2 for 34 cycles…the assembly program after
compiling will be as follows.
The calling parameters for delay(count) will be stored in the variable delay0 (low byte) and
delay0+1 (high byte)
for( count=cycle ; count > 0 ; count-- )
0000 0700 R MOV A,delay0
0001 0080 R MOV count,A
0002 0700 R MOV A,delay0[1]
0003 0080 R MOV count[1],A
0004 2800 R JMP L5
0005 L2:
0005 0700 R MOV A,count
0006 0A01 SUB A,01h
0007 0080 R MOV count,A
0008 380A SNZ [0AH].0
0009 1580 R DEC count[1]
000A L5:
000A 1080 R SZ count
000B 2800 R JMP L2
000C 1080 R SZ count[1]
000D 2800 R JMP L2
000E L1:
000E 0003 RET
// CALL, JMP, RET needs two instruction cycles
// SZ skips the next instruction, two instruction cycles will be required.
count =1 means to wait for 22 instruction cycles, count =2 means to wait for 30 instruction
cycles.
5.2.2.2 Timing Control Method (2) – using while-loop
→ Define the timing control program delayw
void delayw (unsigned int count)
{
while ( count != 0 )
count-- ;
}
Changed to use the while loop, the compiled instruction codes are as shown below:
0000 2800 R JMP L8
0001 L7:
0001 0700 R MOV A,count
0002 0A01 SUB A,01h
0003 0080 R MOV count,A
0004 380A SNZ [0AH].0
0005 1580 R DEC count[1]
0006 L8:
0006 1080 R SZ count
0007 2800 R JMP L7
0008 1080 R SZ count[1]
0009 2800 R JMP L7
000A L6:
000A 0003 RET
// CALL, JMP, RET need two instruction cycles
// SZ, SNZ skips the next instruction, two instruction cycles will be required.
count =1 means to wait for 22 instruction cycles, count =2 means to wait for 30 instruction
cycles.
Rev. 1.30
39
March 15, 2011
Using Enhanced Holtek C
5.2.2.3 Timing Control Method (3)- using built-in function: _delay()
void _delay(unsigned long clocks)
The parameter clocks is an instruction cycle count delay. For example, if the frequency of the
MCU is 4MHz resulting in an execution time of 1us for every instruction cycle, then a valid
count within a range of 1 ~ 263690 is allowed. If the valid count is zero, an endless delay
is requested and can be used to wait for a hardware interrupt to occur. This function can
accurately figure out the exact time and be executed correctly. For exact timing applications,
this function can be called. If the required time exceeds the 263690 count limit, this function
can be called repeatedly.
5.3 Notes for writing an MCU Application Program
a) Modularise the application program by extracting each function in the function format and
respectively defining in different files with each function and file named by their functions
for easier memorisation. By decreasing the compilation time, less error can be expected in
a compiled program with reduced maintenance and modification will also be easier.
b) Variables should be defined with realistic meanings so as to avoid errors and make them
easier to be used during programming and to reduce maintenance time.
c) Do not execute the read/write operations to the following registers as the assembly
language instructions compiled by C will use these registers. If the registers are used by
the application program at the same time, possible erroneous behavior may affect program
execution.
C Variable Name
(Defined in the header file .h)
Register
RAM Address
IAR0
0x00
_iar0
MP0
0x01
_mp0
IAR1
0x02
_iar1
MP1
0x03
_mp1
BP
0x04
_bp
ACC
0x05
_acc
PCL
0x06
_pcl
STATUS
0x0a
_status
Additionally, symbols defined in the header file (.h), such as _c, _ac, _z, _ov, _pdf and _to
should be avoided. Ex. if(_c) a = ah + bh + 1 would not be allowed.
d) When using the Holtek C compiler, if the program needs to use the following built-in
functions, the data type of the parameter should be noted and a functional declaration will
be required. Ex.
extern void _delay(unsigned long) ;
_rr(char *) , _rrc(char *), _lrr(int *), _lrrc(int *), _rl(char *), _rlc(char *), _lrl(int *),
_lrlc(int *), _swap(char *), _delay(unsigned long)
The return type of the above built-in functions are all void.
If it is necessary to make a left/right shift on the parameter, the following operators can be
used.
count = time >> 3 ; count = entry << 4 ;
There is no rotate operator in C language. It can be implemented by using the signed type
and operator shifting to the left/right.
e) Initialise the memory to zero
The designer should give every variable an initial value or it will be random.
f) 16-bit data is composed of two registers, ex. adrl and adrh of the A/D Converter, which can
be saved by a unsigned int type of variable after being read.
Rev. 1.30
40
March 15, 2011
Using Enhanced Holtek C
unsigned int voltage ;
voltage = (unsigned int)_adrh ;
voltage = (voltage << 4) + (unsigned int)(_adrl >> 4) ; // 12 bit ADC
g) Avoid using goto statement as these will label definitions which restrict program
modularisation. An excess of labels will reduce program readability.
h) Avoid using #include to add a .c file into the other .c files. The preprocessor #include
is used to insert the header file, .h, allowing the C compiler to read defined constants,
declared variables and functions etc in the header file as a statement reference for the
original program and then to generate the correct instruction codes. If a .c program file
is added to another .c program file, which equates to an increase in program file size to
that of the two files added together, this will, not only increase the compiling time but also
reduce readability and result in less easier maintenance
5.4 Microcontroller Application Program Example
The microcontroller application program is required to execute certain operations. The
following examples are written in C. Designers can directly add to the program to other
subroutines waiting to be called and implement the required operation.
a) Initialise the memory space by clearing it to zero.
Generally this step will be taken before entering the main program by adding it to the main
function main() or construct another subroutine and call it form the main function.
Clear the data memory bank 1 to zero.
unsigned char *mptr ;
for( mptr = (unsigned char *)0x140 ; mptr < (unsigned char *)0x153 ; mptr++ )
*mptr = 0 ; // clear the 0x40 to 0x53 addresses in the RAM bank1 to zero
b) Delay
Sometimes the application program may need to wait (or delay) for a period of time
before proceeding with other operations, so the waiting time should be calculated
accurately. Taking a microcontroller with a 4MHz oscillator as an example which will have
an instruction cycle time of 1us. If only a few usec of waiting time is required, then it is
acceptable to directly call the built-in function _nop(), or the delay() function. The nop()
funciton only takes one instruction cycle. If a 2us waiting time is required simply call _nop()
twice.
If more waiting time is required, directly call the integrated function _delay().
The parameter clocks in the _delay( clocks) function is the unsigned long data type. Clocks
= 0 means an endless delay which can be used to wait for an interrupt to occur which is
similar to an endless loop; clocks can have a range of 1 to 263690. If this time is exceeded,
continuous calling is allowed.
c) Table Data Reading
Table data is often seen in an application program for operation references which can be
read by the array or pointer in the C language.
unsigned char WordTable[16] = { 0x41, 0xE7, 0x52, 0x62, 0xE4, 0x68, 0x48, 0xE3,
0x40, 0x60, 0xC0, 0x4C, 0x59, 0x46, 0x58, 0xD8 } ;
// define array, display‘0’, ‘1’, ‘2’, …., ‘9’,’A’, ‘b’, ‘C’, ‘d’, ‘E’, ‘F’
int k ;
LedPortCtrl = 0 ; // setup the PA Port as output
LedPort = 0xff ; // all off
for( k = 0 ; k < 16 ; k++ ) // display a total of 16 character bits
{
LedPort = WordTable[k] ; // turn on the number k word, reading from the table
_delay(50000) ; // delay 50ms
Rev. 1.30
41
March 15, 2011
Using Enhanced Holtek C
}
Another method is to use a pointer. The last data 0x00 of the table indicates the end of the
table.
unsigned char WordTable[17] = { 0x41, 0xE7, 0x52, 0x62, 0xE4, 0x68, 0x48, 0xE3,
0x40, 0x60, 0xC0, 0x4C, 0x59, 0x46, 0x58, 0xD8, 0x00 } ;
unsigned char *tptr ;
tptr = WordTable ;
while( *tptr != 0 )
{
LedPort = *tptr++ ;
_delay(50000) ;
}
d) Reading two bytes of data
Use the A/D Converter interrupt to read the converted digital data. Take the 9 bits of the
HT46R62 as an example:
unsigned int AdcValue ; // define a global variable to save the converted value
void ADC_ISR( ) // define the A/D Converter interrupt service routine and read/save
the converted value
{
AdcValue = ((unsigned int)_adrh <<1) + ((unsigned int)_adrl >>7) ;
// read the data D8~D1 of the high bits and shift left one bit
// read the low byte, shift right 7 bits and combine as one int data type,
// and save the variable
}
If the current timer count needs to be read from the clock, take the HT48R70A-1 as an
example in which Timer 0 is 16-bit.
unsigned int TimerCount ; // save the read timer count
_t0on = 0 ; // disable Timer 0
TimerCount = (unsigned int)_tmr0h <<8) + (unsigned int)_tmr0l ;
// read the high bit and shift right 8 bits, read the low bit timer count and add the
variable of int for saving
_t0on = 1 ; // enable Timer 0 and continue counting
e) As for variables or registers outside of RAM bank 0, read/write operations can be executed
by designating variable addresses, ex. write the value to the address 0x40 in RAM bank 1.
unsigned char Bank0140 @ 0x140 ; // define Bank0140 and assign an address
unsigned char out ;
Bank0140 = 0x20 ; // write 0x20 to the address 0x40 in the RAM bank 1
out = Bank0140 ; // save the 0x40 content in the RAM bank 1 to the variable out
5.5 Points to Note for Microcontroller Application Program Design
a) Code Optimization for Multi-ROM-bank MCUs
Developing programs for multiple ROM bank microcontrollers will need to include the
instruction (MOV BP,A) for switching the BP register to operate in different ROM banks,
this will increase the program memory code size. To reduce the program code size, the
following two steps can be applied to the program.
■ Locate all called functions in the same ROM bank, ex.
#pragma rombank 1 func1, func2, func3
// locate the func1, func2, and func3 to the ROM bank 1. Refer to section 4.9.5.
void func1(void)
{
}
void func2(void)
{
Rev. 1.30
42
March 15, 2011
Using Enhanced Holtek C
......
func1( ) ; // call func1 and assign to the same ROM bank with func2
......
switch( )
{
case xx :
}
}
void func3(void)
{
func2( ) ; // assign to store in the same ROM bank with func3
if( )
{
}
else
......
func1( ) ;
......
}
■ Locate all global variables used by the function to ROM bank 0 using #pragma
rambank0
#pragma rambank0
char count ; // assign variable count to RAM bank0
#pragma norambank
Rev. 1.30
43
March 15, 2011
Using Enhanced Holtek C
Chapter 6
Example Program – Basic Level
This chapter uses the C language in a basic way to introduce ways develop microcontroller
application programs using the simplest program structure and statements. Each example
provides frequently used syntax and statements to design control applications and keyboard
processing programs for a display, including a 7-segment LED display, LCD display, 4x4
matrix switch input from which some functions can be switched to other applications simply by
a few I/O modifications and re-compilation.
6.1 LED Running Light Display
6.1.1 Objective
To learn how to use a for/while loop to implement a delay and continuously output data to port
A to illuminate eight LEDs in turn. The interval time is 500ms.
6.1.2 Peripheral Components
Connect the I/O Port A in the HT48R06A-1 to the cathode of the eight LEDs via current limiting
resistors allowing the MCU to illuminate the LEDs by outputting a low level to the connected
PA port.
6.1.3 Circuit Diagram
4MHzPA0~PA7 connected to an LED cathode. The MCU oscillator frequency is 4MHz.
6.1.4 MCU Configuration Options
Select the ICE internal oscillator to have a frequency of 4000KHz
WDT : disable
WDT Instruction : one clear instruction
PA wake up : none
Pull high : all
WDT OSC : on chip RC
OSC : crystal
Sys volt : 5.000V
Sys freq : 4000kHz, Internal
Rev. 1.30
44
March 15, 2011
Using Enhanced Holtek C
6.1.5 Program Flow
Start
Set Port A as outputs with
high level to extinguish LEDs
Turn on PA LEDs in sequence
End
6.1.6 Original Program
1
#include “ht48r06a-1.h”
2
#define LedPort _pa // pa port
3
#define LedPortCtrl _pac // pa control port
4
void main(void) // main function
5
{
6
int k ;
7
LedPortCtrl = 0 ; // set pa port as output
8
LedPort = 0xff ; // turn off all LEDs
9
for( k = 0 ; k < 8 ; k++ )
10 {
11
LedPort = ~ (1 << k) ; // illuminate the number k LED
12
_delay(250000) ; // delay 500ms
13 _delay(250000) ;
14}
15 16 LedPort = 0xff ; // turn off all LED
}
6.1.7 Program Description
1
Insert the header file. It is better to add this statement at the beginning of each
program file telling the C compiler to include these file declarations and definitions.
2~3
Define the variable LedPort as the data register and LedPortCtrl as the control
register for Port A.
7
Write 0 to the Port A control register to setup port A as outputs. This statement has
the same function as the assembly instruction: CLR PAC
8
Write 0xff to the port A data register to output 11111111b which ensures all LEDs are off.
9
The for loop is to illuminate each LED in turn starting with PA0 to PA7.
11
Shift 1 to left for k bits. The letter k stands for the Port A pin number, where k = 0,
1, 2,…7. Then execute a 1's complement to change the 1 to 0, and the other seven
0's to 1 and then write to the number k pin of the Port A data register to setup a low
level output to turn on the related LED. The other pins will be high and the LEDS will
remain off.
12~13 Generate a 500ms delay to keep the LED on and proceed to illuminate the next LED.
The on/off interval of the LEDs will be larger than 500ms as the for loop needs to
execute the previous operation before illuminating the LED.
15
Rev. 1.30
Turn off all LEDs.
If a second round of LED sequential illumination is required, modify line 15 to "goto
again" and add "again": (with a colon) before line 9 or while(1) in line 14 to make an
endless loop.
45
March 15, 2011
Using Enhanced Holtek C
6.2 LED Blinking Light
6.2.1 Objective
To learn how to use the loop execution delay and continuously output data to Port A to
illuminate eight LEDs in turn. The illumination order is read from the array with the following
sequency: LED0, LED0+LED1, LED0+LED1+LED2 until all eight LEDs are on. The on/
off interval is 500ms. This shows how to use the an array variable in C instead of using an
assembly program to read data using the table read instructions (TABRDC, TABRDL) which
increases program readability.
6.2.2 Peripheral Components
Connect the I/O Port A vial current limiting resistors to the cathode of eight LEDs so as to turn
on the LED by outputting a low level to the connected PA port.
6.2.3 Circuit Diagram
PA0~PA7 is connected to the LED cathode. The MCU oscillator frequency is 4MHz.
6.2.4 MCU Configuration Options
Select the ICE internal oscillator with a frequency of 4000KHz.
WDT : disable
WDT Instruction : one clear instruction
PA wake up : none
Pull high : all
WDT OSC : on chip RC
OSC : crystal
Sys volt : 5.000V
Sys freq : 4000kHz, Internal
Rev. 1.30
46
March 15, 2011
Using Enhanced Holtek C
6.2.5 Program Flow
Start
Set Port A as outputs with
high level to extinguish LEDs
Read array data and turn on LEDs
End
6.2.6 Original Program
1
#include “ht48r06a-1.h"
2
#define LedPort _pa // pa port
3
#define LedPortCtrl _pac // pa control port
4
char LedTable[8] = { 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00 } ;
5
// array variable, setup display data, turn on LED0, LED0+LED1, LED0+LED1+LED2,
….
6
void main(void) // main function
7
{
8
int k ;
9
LedPortCtrl = 0 ; // set the pa port as output
10
LedPort = 0xff ; // turn off all LED
11
for( k = 0 ; k < 8 ; k++ )
12
{
13
LedPort = LedTable[k] ; // output LED control code to turn LEDx
14
_delay(250000) ; // interval of 250ms
15
_delay(250000) ; // interval of 250ms
16 }
17
LedPort = 0xff ; // turn off all LED
18 }
6.2.7 Program Description
All program content is the same as section 6.1 except for line 13. Line 13 is to acquire the
displayed data from the array LedTable, and then output it to the LED port. Lines 14 and 15
are for the internal function _delay() calling. Parameter 250000 means the delay clock value is
250000. In this example, 1 clock = 1us with each call requiring a 250ms delay.
Rev. 1.30
47
March 15, 2011
Using Enhanced Holtek C
6.3 Single 7-segment Display
6.3.1 Objective
To display sixteen characters from 0~9 and A~F using a common anode seven-segment
display with an interval of 50ms. This example is similar to the earlier example except for the
array content. The display code characters must be setup according to seven-segment display
structure.
6.3.2 Peripheral Components
Connect the I/O port pa0 ~ pa7 of the microcontroller to the seven-segment display. The
names of the display code are listed in the following tables. Output low to some segment to
turn it on.
a
f
g
b
p
d
Character
Code
Character
Code
Segment
c
e
Port
a
b
c
d
e
f
g
p
PA2
PA3
PA4
PA7
PA5
PA1
PA0
PA6
0
1
2
3
4
5
6
7
8
9
41h
E7h
52h
62h
E4h
68h
48h
E3h
40h
60h
A
b
C
d
E
F
—
—
—
—
C0h
4Ch
59h
46h
58h
D8h
—
—
—
—
6.3.3 Circuit Diagram
6.3.4 Microcontroller Configuration Options
Select the ICE internal oscillator to have a frequency of 4000KHz
WDT : disable
WDT Instruction : one clear instruction
PA wake up : none
Pull high : all
WDT OSC : on chip RC
OSC : crystal
Sys volt : 5.000V
Sys freq : 4000kHz, Internal
Rev. 1.30
48
March 15, 2011
Using Enhanced Holtek C
6.3.5 Program Flow
Same as the 6.2.5 program flow
6.3.6 Original Program
1
#include“ht48r06a-1.h"
2
#define LedPort_pa // pa port
3
#define LedPortCtrl_pac // pa control port
4
unsigned char WordTable[16] = { 0x41, 0xE7, 0x52, 0x62, 0xE4, 0x68, 0x48, 0xE3,
5
0x40, 0x60, 0xC0, 0x4C, 0x59, 0x46, 0x58, 0xD8 } ;
6
// define array, display `0' , `1' , `2' , …, `9' , `A' , `b' , `C' , `d'
, `E' , `F'
7
void main(void) // main function
8
{
9
int k ;
10
LedPortCtrl = 0 ; // set pa port as output
11
LedPort = 0xff ; // extinguish all
12
for( k = 0 ; k < 16 ; k++ ) // display 16 characters totally
13
{
14
LedPort = WordTable[k] ; // turn on the number k character
15
_delay(50000) ; // delay 50ms
16
}
17
LedPort = 0xff ; // extinguish all
18
}
6.3.7 Program Description
14 Read the display data from the WordTable array and then output it to the LED port.
6.4 5*5 Dot Matrix LED Display
6.4.1 Objective
To control a 5x5 dot matrix LED to display “HOLTEK” with an interval of 50ms, and each
character displayed for 24ms on five rows. This example uses a pointer and an array to read
the display elements. The example provided here can be used to read 2-dimensional data.
6.4.2 Peripheral Components
Connect PA0~PA4 to the dot matrix array, row0~row4, and PB0~PB4 to column0~4 using the
25 LEDs arranged as a 5x5 array, as the figure shows, and then connect it to Port A and Port
B of the microcontroller.
●○○○●○●●●○●○○○○●●●●●●●●●●●○○○●
●○○○●●○○○●●○○○○○○●○○●○○○○●○○●○
●●●●●●○○○●●○○○○○○●○○●●●●○●●●○○
●○○○●●○○○●●○○○○○○●○○●○○○○●○○●○
●○○○●○●●●○●●●●●○○●○○●●●●●●○○○●
Rev. 1.30
49
March 15, 2011
Using Enhanced Holtek C
6.4.3 Circuit Diagram
6.4.4 Microcontroller Configuration Options
Select the ICE internal oscillator to have a frequency of 4000KHz
WDT : disable
WDT Instruction : one clear instruction
PA wake up : none
Pull high : all
WDT OSC : on chip RC
OSC : crystal
Sys volt : 5.000V
Sys freq : 4000kHz, Internal
6.4.5 Program Flow
Start
Set Port A, B as output types
Extinguish the 5x5 dot matrix LEDs
Extract a pointer from the table
to read the the character code
Start from the first row, total of 5 in all
Turn on one row and 5 columns of the row
NO
YES
Already 5 rows?
Rev. 1.30
50
End
March 15, 2011
Using Enhanced Holtek C
6.4.6 Original Program
1
#include “ht48r06a-1.h"
2
#define LedRowPort _pa // row, pa port
3
#define LedRowPortCtrl _pac // pa control port
4
#define LedColPort _pb // column, pb port
5
#define LedColPortCtrl _pbc // pb control port
6
char charH[5] = { 0x1f, 0x4, 0x4, 0x4, 0x1f } ; // high level means illuminating
7
char charO[5] = { 0x0e, 0x11, 0x11, 0x11, 0x0e } ;
8
char charL[5] = { 0x1f, 0x10, 0x10, 0x10, 0x10 } ;
9
char charT[5] = { 0x01, 0x01, 0x1f, 0x01, 0x01 } ;
10
char charE[5] = { 0x1f, 0x15, 0x15, 0x15, 0x11 } ;
11
char charK[5] = { 0x1f, 0x4, 0x4, 0x0a, 0x11 } ;
12
char *LedTable[6] = { charH, charO, charL, charT, charE, charK } ; // pointer array
13
14
void main(void) // main function
15
{
16
int k ;
17
char *tptr ;
18
LedRowPortCtrl = 0 ; // set pa port as output
19
LedColPortCtrl = 0 ; // set pb as output
20
LedColPort = LedRowPort = 0 ; // turn off LED
21
for( k = 0 ; k < 6 ; k++ ) // display all 6 characters in all
22
{
23
tptr = LedTable[k] ; // read the pointer of the number k character
24
for( j = 0 ; j < 5 ; j++ )
25
{
26
LedColPort=(1 << j );//turn on column j of number k character
27
LedPort=tptr[j];//output row character and turn on the related character
28
_delay(5000) ; // every row has an interval of 5ms
29
}
30
_delay(50000) ; // every character has an interval of 50ms
31
}
32
LedColPort = 0 ; // turn off all LEDs
33
}
6.4.7 Program Description
6 ~ 11 Define the six character “HOLTEK” pattern
Rev. 1.30
12
The array LedTable defines the pointer of the above six arrays
21
From the first character, six characters in all
23
Extract the character pointer from the array LedTable
24
Each character has a 5x5 dot matrix, displayed by row
26
Output the displayed row data
27
Output the five column data of this row
28
The interval for each row is 5ms
30
The interval for each character is 50ms
51
March 15, 2011
Using Enhanced Holtek C
6.5 HT1621 LCD Control using the HT48 Series of MCUs
6.5.1 Objective
The example here uses the HT48 series of MCUs to control the HT1621 LCD controller by
sending instructions to the HT1621 to control the LCD panel characters using HT48 I/O ports
connected to the HT1621. This example uses the HT48R10A-1 MCU to control the HT1621
and introduces a method of turning on and clearing all the LCD pixels
6.5.2 Peripheral Components
The HT1621 is a 128-bit LCD controller whose internal RAM directly corresponds to LCD
displayed data. It can used to control LCD panels or for software controlled multi-functional
application display systems. The interface between the MCU and the HT1621 requires four to
five lines and the internal power saving mode greatly reduces its power consumption.
■ Data Memory
The HT1621 LCD driver includes a display data memory of 32x4 bits, arranged as follows.
C O M 3
C O M 2
C O M 1
C O M 0
S E G 0
0
S E G 1
1
S E G 2
2
S E G 3
3
S E G 3 1
3 1
D
3
D
2
D 1
D 0
A d d r e s s 6 b its
(A 5 , A 4 , ..., A 0 )
A d d r
D a ta
D a ta 4 b its
(D 3 , D 2 , D 1 , D 0 )
There are 32 segments and 4 columns in all. When the LCD is enabled, data is written into
this memory to respectively control the associated pixels to be either on or off. D0 controls
whether the cross points of common 0 and segment 0 ~ segment 31 are illuminated or
not while D1 controls those of common 1 and segment 0 ~ segment 31, D2 controls those
of common 2 and segment 0 ~ segment 31, and D3 controls the those of common 3 and
segment 0 ~ segment 31.
■ Instruction Format
The HT1621 LCD controller supports two modes, the command mode and the data mode.
The common mode is used to enable/disable the LCD display and setup the structure of the
LCD display. Binary codes starting with 100 is the ID code for the command mode. The data
mode is to read/write data from/to the LCD memory, the ID code in this case is 110 or 101.
The following table describes the commands used in this example. For details refer to HT1621
datasheet.
Rev. 1.30
52
March 15, 2011
Using Enhanced Holtek C
■ Command Mode
Command
ID
Command Code
Function
Power Reset
SYS DIS
100
0000-0000-x
Disable system oscillator and LCD bias
generator
V
—
SYS EN
100
0000-0001-x
Enable system oscillator
LCD OFF
100
0000-0010-x
Disable LCD bias generator
V
LCD ON
100
0000-0011-x
Enable LCD bias generator
—
0010-abxc-x
Set LCD bias and common options
c=0, bias=1/2
c=1, bias=1/3
ab=00, 2 common
ab=01, 3 common
ab=10, 4 common
—
BIAS& COM
100
■ Data Mode
Command
ID
Command Code
Function
READ
110
A5A4A3A2A1A0D0D1D2D3
Read data from RAM
WRITE
101
A5A4A3A2A1A0D0D1D2D3
Write data to RAM
READ-MODIFYWRITE
101
A5A4A3A2A1A0D0D1D2D3
Read/write data to RAM
x : don't care bit
A5 ~ A0 : RAM address
D3 ~ D0 : RAM data
Before using the LCD, two commands, SYS EN and LCD ON, should be sent to the HT1621
to enable the LCD. Using serial communication, all commands must be sent bit by bit in the
following order: first send the ID (3 bits) and then the command code (9 or 10 bits) and finally
pull the /CS level high at the end.
Repeat this sequence, and send the next command. If the subsequent command is the same
command and a successive address, it is acceptable not to pull the /CS level high but directly
continue with reading/writing data until all the data is processed.
■ Command Timing
● READ Mode (Command ID Code : 110)
● READ Mode (Success Address Reading)
C S
W R
R D
D A T A
Rev. 1.30
1
1
0
A 5 A 4 A 3 A 2 A 1 A 0 D 0 D 1 D 2 D 3 D 0 D 1 D 2 D 3 D 0 D 1 D 2 D 3 D 0 D 1 D 2 D 3 D 0
M e m o ry A d d re s s (M A ) D a ta (M A )
D a ta (M A + 1 ) D a ta (M A + 2 ) D a ta (M A + 3 )
53
March 15, 2011
Using Enhanced Holtek C
● WRITE Mode (Command ID Code: 1 0 1)
● WRITE Mode (Success Address Writing)
C S
W R
1
D A T A
1
0
A 5 A 4 A 3 A 2 A 1 A 0 D 0 D 1 D 2 D 3 D 0 D 1 D 2 D 3 D 0 D 1 D 2 D 3 D 0 D 1 D 2 D 3 D 0
M e m o ry A d d re s s (M A ) D a ta (M A )
D a ta (M A + 1 ) D a ta (M A + 2 ) D a ta (M A + 3 )
● READ-MODIFY-WRITE Mode (Command ID Code: 101)
● READ-MODIFY-WRITE Mode (Success Address Accessing)
C S
W R
R D
1
D A T A
1
0
A 5 A 4 A 3 A 2 A 1 A 0 D 0 D 1 D 2 D 3 D 0 D 1 D 2 D 3 D 0 D 1 D 2 D 3 D 0 D 1 D 2 D 3 D 0 D 1 D 2 D 3 D 0
M e m o ry A d d re s s (M A ) D a ta (M A )
D a ta (M A )
D a ta (M A + 1 ) D a ta (M A + 1 ) D a ta (M A + 2 )
● Command Mode (Command Mode ID: 100)
C S
W R
D A T A
Rev. 1.30
1
0
0
C 8 C 7 C 6 C 5 C 4 C 3 C 2 C 1 C 0
C 8 C 7 C 6 C 5 C 4 C 3 C 2 C 1 C 0
C o m m a n d 1
C o m m a n d ...
C o m m a n d i
54
C o m m a n d
o r
D a ta M o d e
March 15, 2011
Using Enhanced Holtek C
● Command Mode (Data and Command Code)
6.5.3 Circuit
Connect the HT48R10A-1 I/O ports to the HT1621 pins as shown below:
HT48R10A-1 I/O port
HT1621 pin
PB1
DATA
PB2
/WR
PB3
/CS
PB4
/RD
6.5.4 Configuration Option
HT48R10A-1 configuration option settings:
WDT clock source : disable
OSC : Ext. Crystal
Pull-high PA : Pull-high
Pull-high PB : Pull-high
Input type PA : Schmitt Trigger
BZ/BZ : Disable
fSYS = 4M
6.5.5 Program Flow
Start
Set LCD in Normal status
Set LCD with SYS EN enabled
Set LCD with 4 commons, 1/3 bias
Set LCD On (enabled)
Initialise the LCD
Clear LCD RAM data (turn off LCD)
LCD)
Write to all LCD RAM space
Turn on LCD
Read the segment 4 data from LCD
RAM. Check if it is the same (0x0f)
as the above written content
End
Rev. 1.30
55
March 15, 2011
Using Enhanced Holtek C
6.5.6 Original Program
1
#include “ht48r10a-1.h"
2
#define CMD_NORMAL 0xE3 // normal command
3
#define CMD_SYSEN 0x01 // system enable
4
#define CMD_SYSDIS 0x00 // system disable
5
#define CMD_LCDOFF 0x02 // LCD off
6
#define CMD_LCDON 0x03 // LCD on
7
#define csb_pb3 // the CSB pin of the HT1621 = bit 3 of port B
8
#define wrb_pb2 // the WRB pin of the HT1621 = bit 2 of port B
9
#define rdb_pb4 // the RDB pin of the HT1621 = bit 4 of port B
10
#define ldata_pb1 / the DATA pin of the HT1621 = bit 1 of port B
11
#define ldata_ctrl_15_1 // bit 1 of port B controls the DATA I/O
12
13
void DelayTime(unsigned int count) // 10 * count + 11, if count > 256
14
{
15
while( count != 0 ) count-- ;
16
}
17
void nop(void) // calling this function will take five instruction cycles
18
{
19
20
asm(“NOP") ;
}
21
void SendCommand(unsigned char cmd) // send command to the HT1621
22
{
23
unsigned int CmdCode ;
24
int idx ;
25
// compose command ID 100b and command code into 12 bits
26
CmdCode = ((unsigned int)100b << 9) | ((unsigned int)cmd <<1) ;
27
ldata_ctrl = 0 ; // set port B bit 1 (DATA) as output type
28
csb = 0 ; // CSB pull low
29
for ( idx = 11 ; idx >= 0 ; idx-- )
30
{
if( (CmdCode & (1 << idx)) !=0 ) // check if every bit is 1 or 0, from bit11~bit0
31
32
ldata = 1 ; // write 1
33
else
34
ldata = 0 ; // write 0
35
36
wrb = 0 ; // WRB -> low -> high
37
_delay(5) ; // delay 5 ms (5 instruction clock)
38
wrb = 1 ;
39
_delay(5) ;
40
}
41
csb = 1 ; // CSB pull high, end and send command
42
}
43
// change bit0~bit3 in the odata to bit3~bit0. Ex. change 1110 to 0111
44
char SwapBit(char odata)
45
{
46
Rev. 1.30
char ndata ;
56
March 15, 2011
Using Enhanced Holtek C
47
int k ;
48
ndata = 0 ;
49
for( k = 0 ; k < 4 ; k++ )
50
ndata |= ((odata >> k) & 0x1) << (3- k) ;
51
return (ndata) ;
52
}
53
// write the lowest 4 bits in the dataN to LCD RAM address (bit0~bit5 effective)
54
//bit 0, 1, 2, 3 of dataN is the com0, com1, com2,com3 data
55
void WriteLCD(char addr, char dataN)
56
{
57
unsigned int DataCode ; // 16 bits
58
char NewData ;
59
int idx ;
DataCode = ((unsigned int)101b << 6) | (addr & 0x3f) ;
60
// combine addr 6 low bits into DataCode
61
NewData = SwapBit(dataN) ; // change bit0~bit3 in dataN to bit3~bit0
62
DataCode = (DataCode<<4) | NewData ; combine four low bits into dataN
63
ldata_ctrl = 0 ; // set port B bit 1 (DATA) as output type
64
csb = 0 ; // CSB pull low
65
for (idx = 12 ; idx >=0 ; idx--) // send 13 bits
66
{
67
if( (DataCode * (1 << idx)) !=0 ) // check if every bit is 1 or 0 from bit12~bit0
68
ldata = 1 ; // write 1
69
else
70
ldata = 0 ; // write 0
71
72
wrb = 0 ; // WRB -> low -> high
73
73
74
wrb = 1 ;
75
_delay(5) ;
76
}
77
_delay(5) ; // delay 5 ms (5 instruction clocks)
csb = 1 ; // CSB pull high, end and send command
78
}
79
// read a nibble (4 bits) from the LCD RAM addr (bit0~bit5 effective) and send back
80
// the returned values bit 0, 1, 2, 3 is com0, com1, com2, com3
81
char ReadLCD(char addr)
82
{
83
unsigned int DataCode ; // 16 bits
84
char retcode ;
85
int idx ;
86
87
DataCode = ((unsigned int)110b << 6) | (addr & 0x3f) ;
// combine addr 6 low bits into DataCode
Rev. 1.30
88
ldata_ctrl = 0 ; // set port B bit 1 (DATA) as output type
89
csb = 0 ; // CSB pull low
90
for (idx = 8 ; idx >=0 ; idx--) // send 9 bits
57
March 15, 2011
Using Enhanced Holtek C
91
{
if( (DataCode & (1 << idx)) !=0 ) // check if every bit is 1 or 0 from bit8~bit0
92
93
ldata = 1 ; // write 1
94
else
95
ldata = 0 ; // write 0
96
97
wrb = 0 ; // WRB -> low -> high
98
_delay(5) ; // 5 us delay (5 instruction clock)
99
wrb = 1 ;
100
_delay(5) ;
101
}
102
// read 4 bits
103
ldata_ctrl = 1 ; // set port B bit 1 (DATA) as input type
104
retcode = 0 ;
105
105
106
{
for( idx = 0 ; idx < 4 ; idx++ ) // idx=0 read D0, iex=1 read D1…
107
rdb = 0 ; // RDB pull low
108
_delay(5) ;
109
rdb = 1 ; // RDB pull high
110
if( ldata == 1 ) retcode |= (1 << idx) ; // read one bit if it is 1
111
}
112
csb = 1 ; // CSB pull high, end and send command
113
return retcode ;
114
}
115
// clear the content in LCD RAM to 0
116
void CleanLCD(void)
117 {
118
char seg ;
119
for( seg = 0 ; seg < 32 ; seg++ )
120
WriteLCD(seg, 0) ;
121
}
122
// turn on all LCD
123
void DisplayLCD(void)
124
{
125
char seg ;
126
for( seg = 0 ; seg < 32 ; seg++ )
127
128
WriteLCD(seg, 0xf) ; // turn on com0, com1, com2, com3
}
129
Rev. 1.30
130
void main(void)
131
{
132
char DataR ;
133
_pb = 0 ; // port B data is 0
134
csb = 1 ; // CSB pull high – disable LCD
135
_pbc = 0 ; // set port B as output
136
while(1) // endless loop, jump out only when an error occurs
137
{
58
March 15, 2011
Using Enhanced Holtek C
138
SendCommand(CMD_NORMAL) ; // send NORMAL command
139
SendCommand(CMD_SYSEN) ; // send SYS EN command
140
SendCommand(0x29) ; // set LCD to 4 commons and 1/3 bias
141
SendCommand(CMD_LCDON) ; turn LCD on
142
CleanLCD( ) ; // clear LCD RAM to 0, all pixels are off
143
DisplayLCD( ) ; // turn on all pixels, wirte 0xf to LCD RAM
144
145
DataR = ReadLCD(4) ; // read the segment 4 data
146
if ( DataR !=0x0f) // read and written data are different, error
147
break ; // jump out of loop
148
SendCommand(CMD_LCDOFF) ; // send LCD OFF command
149
150
}
}
6.5.7 Program Description
2~6
Define the command constants for the HT1621, namely the 8 bits after the initial100
command code.
7~11
Define the HT48R10A-1 I/O lines which connect to the HT1621 pins.
17~20
Function nop() uses five instruction cycles which can be used for a delay according
to the system frequency.
21~42
Function SendCommand is to send commands to the HT1621. Parameter cmd is
the command code.
26
100b This is the command ID. Three bits are shifted left for 9 bits to bits 11~9 plus
the input parameter cmd is shifted left for one bit to bits 8~1, a total of eight bits.
Finally bit 0 can have any value. This line ensures it has a zero value.
27
Setup the DATA pin as an output type.
28
Pull the CSB pin to a low level.
29~40
Output the 12 bits command to the HT1621 starting with bit 11.
31~34
If the bit value is 1, output 1; 0 then output 0.
36~39
Pull the WRB control bit to a low level and then high again. Write the above data to
the HT1621. An internal function_delay(5) is available for delaying 5 ms. However
note that the actual time is determined by the MCU oscillator frequency.
41
CSB Pull the pin high to end the command transmission.
44~52
Function SwapBit is to exchange the parameter input bits 0~3 to bits 3~0. For
example the bits 1110 will be changed to 0111. The point here is that the data is
transformed into the format required by the HT1621.This is in a transmission order
starting from D0, D2, D2 and D3.
49
Four bits for shifting
50
Move bit 0 to bit 3, bit 1 to bit 2, bit 2 to bit 1, bit 3 to bit 0.
55~78
Write the lowest four bits of the input parameter dataN to the HT1261 RAM addr.
Only bit0~bit5 in the addr is effective. Bit0~3 in the DataN is com0, com1, com2,
com3 data.
Rev. 1.30
60
The variable DataCode is to output the command. First shift the command ID, 101b,
to the left for 6 bits plus the lower 6 bits of addr
61
Convert the input parameter dataN bit0~bit3 to bit3~bit0 according to the command
format.
62
Shift the DataCode in column 60 to the left for 4 bits plus the data of column 61, to
prepare the output data for the HT1621 RAM.
63
Setup bit 1 (DATA pin) of Port B as an output.
59
March 15, 2011
Using Enhanced Holtek C
64
Pull CSB to a low level.
65~78
Write the 13 bits from bit 12~bit 0 to the HT1621 RAM
67~70
If the bit value is 1, then output a 1; if 0 then output 0.
72~75
Pull WRB pin to a low level, delay, and then pull high to write this bit
77
Pull CSB to a high level to end the command transmission.
81~114 Function ReadLCD is to read a byte from addr in the HT1621 RAM.
Only the lowest six bits (bit0~bit5) in addr are effective. Only four of the read back
bits of the returned value is effective.
87
Generate the output value DataCode by shifting the command ID 110 for six bits
plus the lowest six bits in addr.
88
Setup bit 1 (DATA pin) of Port B as an output.
89
Pull CSB to a low level.
90
Transmit the nine bits, including the ID 110 and the 6 bit address
92~95
Check whether each bit is 1 or 0 and then transmit.
97~100 Pull the WRB pin to a low level and then pull high to complete the transmission.
103
Set bit 1 (DATA) of Port B as an input.
105
Read four bits. idx=0 read D0, idx=1 read D1…
107~109 Pull RDB low, delay and then pull high.
110
Save the read bit to the variable etcode |=(1 << idx) ; // read one bit, if it is 1.
112
Pull CSB to a high level to end the command transmission.
113
Return retcode
116~121 Function CleanLCD will clear the LCD RAM contents to zero. The LCD is off.
119
Starting from the first segment (seg=0), clear to zero until the 32nd segment
120
Write 0 to one segment, and clear to 0.
123~128 Function DisplayLCD will write 1 to the LCD RAM and turn on all commons and
segments
126
Starts from the first segment until the 32nd segment.
127
Write 1 to all commons of the LCD RAM segments.
130~150 Main function. Controls HT1621 LCD functions such as enable, turn off/on and to
check if the read/write operations to the HT1621 RAM is correct.
133
Port B data is 0.
134
Pull CSB to a high level. Disable the HT1621.
135
St port B as output type.
136
Endless loop which repeats operation from column 138 to 148 and jumps out only
when an error occurs.
138
Send NORMAL command to the HT1621
139
Send SYS EN command to the HT1621. Enable the system.
140
Setup the LCD to 4 commons and 1/3 bias.
141
Enable the LCD
142
Clear the LCD RAM to zero. All pixels are off.
143
Turn on all pixels. Write 0x0f to the LCD RAM.
145
Read Segment 4 data.
146~147 If the read and write data are different, error, jump out of the endless loop.
148
Rev. 1.30
Send LCD OFF command.
60
March 15, 2011
Using Enhanced Holtek C
6.6 Using the HT48 to control the LCD panel
6.6.1 Objective
The objective here is to use the HT48 series device to control the DV16100NRB LCD display
driver. This LCM module uses the internal Hitachi HD44780 for drive and control. The example
here utilises the C language to have the microcontroller generate the correct signals to meet
the timing requirements of the LCM and to display characters. Some functions in this example
can be used as common functions which can be called formulas for applications that use
the LCM to display. For detailed instruction and timing data, please refer to the LCM related
information.
6.6.2 Peripheral Components
To use the HT48R10A-1 to control the an LCM character display, the I/O ports PB0~PB7
should be connected to D0~D7 on the HD44780 for data transmission. Port C is used to
control the LCM with PC0 connected to pin E for the LCM for enable (E=1) and disable (E=0.)
Port PC1, connected to R/W, controls the LCM reading (R/W=1) and writing (R/W=0.) Port
PC2, connected to RS, controls the LCM register select to be either an instruction register
(RS=0) or data register (RS=1.) If the application circuit uses other I/O ports to connect to the
HD44780, only the #define statements need to be modified.
HT48R10A-1 Pin
HD44780 Pin
PC0
E
Description
Enable control, E=1 (enable), =0 (disable)
PC1
R/W
Read (=1), Write (=0)
PC2
RS
LCM register select: 0 = instruction register, 1 = data register
PB0~PB7
D0 ~ D7
Data line
→ Before executing a read/write to the HD44780, it is necessary to first check if the LCD is
busy. This can be done by using the busy flag (BF) and address (AC) command to read
the instruction register (IR) contents (RS=0, R/W=1).
→ The flow for a single byte LCD read is as follows.
Set RS = 1 to read from the data register or RS =0 to read from the instruction register.
Set R/W = 1
Set E = 1 to enable the LCD
Read data from D0~D7 and save.
Set E = 0 to disable the LCD
→ The flow for a single byte LCD write dr11 data to the LCD is as follows.
Set RS = 1 to read from the data register or RS =0 to read from the instruction register.
Set R/W = 0
Set E = 1 to enable the LCD
Locate data to D0~D7
Set E = 0 to disable the LCD
Rev. 1.30
61
March 15, 2011
Using Enhanced Holtek C
6.6.3 Circuit Diagram
Using the MCU to control the LCM character display via I/O pins PB0~PB7
6.6.4 Configuration Option
WDT clock source : disable
OSC : Ext. Crystal
Pull-high PA : Non-Pull-high
Pull-high PB : Non-Pull-high
Pull-high PC : Non-Pull-high
Input type PA : Schmitt Trigger
BZ/BZ : Disable
fSYS = 4M
6.6.5 Program Flow
Start
1.Setup PC0/PC1/PC2 as outputs
2.Setup LCD for 8-bit control
3.LCD ON/OFF setup: display all data
4.Setup entry mode: automatic AC increment
5.Clear display - address counter is 0
LCD initialization
Setup the address counter to the first column
From 'A' to 'p' - write into LCD DD RAM
Setup the address counter to the second column
From 'a' to 'p' - write into LCD DD RAM
End
Rev. 1.30
62
March 15, 2011
Using Enhanced Holtek C
6.6.6 Original Program
1
#include “ht48r10a-1.h"
2
#define LcdData _pb // LCD D0~D7 = PB0~PB7
3
#define LcdDataCtrl_pbc // PB port control register , data is output or input
4
#define LcdE_pc0 // E control pin = PC0
5
#define LcdRW_pc1 // R/W control pin = PC1
6
#define LcdRS_pc2 // RS control pin = PC2
7
#define LcdPortCtrl_pcc // PC port control register
8
#define CMD_READ 1 // R/W constant, read
9
#define CMD_WRITE 0 // RW constant, write
10
#define REG_IR 0 // RS constant, instruction register IR
11
#define REG_DR 0 // RS constant, data register DR
12
#define ENABLE 1 // E constant, enable LCD
13
#define DISABLE 0 // E constant, disable LCD
14
// check if LCD is still busy.
15
// endless loop if the LCD malfunctions?
16
void CheckLCDBusy(void)
17
{
18
LcdDataCtrl = 0xff ; // set DATA as input type
19
LcdRS = REG_IR ; // select the instruction register (IR)
20
LcdRW = CMD_READ ; // Read operation
21
LcdE = ENABLE ; // LCD enable
22
while( (LcdData & 0x80) != 0 ) ; // BF=1 means busy, keep checking
23
24
// LCD not busy
25
26
LcdE = DISABLE ;
}
27
// write data to the LCD instruction register (IR) or data register (DR)
28
// input parameter regflag = 1 to the data register (DR), or =0 to the instruction register (IR)
29
// wdata = data written
30
void WriteToLCD(char regflag, char wdata)
31
{
32
CheckLCDBusy() ; // check and wait until the LCD is not busy
33
LcdRS = regflag ; // select register IR/DR
34
LcdRW = CMD_WRITE ; // write operation
35
LcdDataCtrl = 0 ; // set DATA as output type
36
LcdData = wdata ; // place data to DATA
37
LcdE = ENABLE ; // enable the LCD
38
Rev. 1.30
LcdE = DISABLE ; // no delay required, high → low writing completed.
39
}
40
// main function
41
void main(void)
42
{
43
LcdPortCtrl = 0 ; // 3 LCD control pins setup as output types
44
WriteToLCD(REG_IR, 0x38) ; // setup function, 8-bit control, double line display,
5x7 dot matrix
45
WriteToLCD(REG_IR, 0x0f) ; // ON/OFF control, display all data and cursors,
cursor blinking
63
March 15, 2011
Using Enhanced Holtek C
46
WriteToLCD(REG_IR, 0x06) ; // entry mode, after the external read and write
operation, the address counter AC
47
// automatically adds 1, cursor shifts to the right
48
WriteToLCD(REG_IR, 0x01) ; // clear the display, set the address counter to 0, I/D=1
49
WriteToLCD(REG_IR, 0x80) ; set DD RAM address, set the address counter to 0
50
// position cursor at the first column - first position
51
// start to write characters to LCD DD RAM for LCD displaying
52
for( k = 0, char1 = `A' ; k < 16 ; k++ ) // 16 characters total for one column
starting with ` A '
53
{
54
WriteToLCD(REG_DR, char1);//display character in char1 starting with`A'
55
char1++ ; // next letter
56
}
57
WriteToLCD(REG_IR, 0xC0) ; // DD RAM address setup, set the address counter to 0x40
58
// position cursor at the second column - first position
59
for( k = 0,char1=`a'; k<16 ;k++ )//16 characters in all for one column starting with`a'
60
{
WriteToLCD(REG_DR, char1) ;//display characters in char1 starting with`a'
61
62
char1++ ; //next letter
63
}
64
65
WriteToLCD(REG_IR, 0x08) ; // ON/OFF control, no LCD display
}
6.6.7 Program Description
2~3
Define Port B as data I/O port, connected to the HD44780 pins
4~7
Define Port C as control signal lines, connected to the HD44780 control pins
8~13
Define control instructions constants for program readability
16~27 Function CheckLCDBusy checks if the LCM is busy and wait until it is idle and then
return
18
Set DATA(D0~D7) as inputs
19
Select the instruction register (IR)
20
Select Read operation
21
Enable the LCM
22
Loop: Read data form the LCM and check if the BF bit is 1 (busy.) If yes, keep
reading and checking until the LCM is no longer busy. A more rigorous method would
be to setup a time limit or a limit on the number of times checked. If the LCM remains
busy after this error condition occurs, then an error code should be generated.
25
Disable the LCM
30~39 Function WriteToLCD will write data wdata to the instruction register (IR, regflag=0) or
the data register (DR, regflag=1)
32
check and wait until the LCD is not busy
33
Select the register to be IR or DR
34
Write operation
35
Set DATA port as output
36
Place data into DATA (D0~D7)
37
Enable the LCD, pull pin E high
38
Enable the LCD, pull pin E low. No delay required, high low writing completed
41~65 Main function
43
Rev. 1.30
Setup the three LCD control pins as outputs
64
March 15, 2011
Using Enhanced Holtek C
44
Rev. 1.30
Setup LCD functions → 8-bit control, double line display, 5x7 dot matrix
45
Setup LCD ON/OFF control → Display all data and cursor with cursor blinking
46
Set the LCD entry mode → after an external data read/write, the address count AC
will be automatically incremented by 1, and the cursor shifts to the right.
48
Clear the display, set the address counter to 0, I/D=1
49
DD RAM address setup → set the address counter to 0 and position the cursor at the
first column at the first position
52
Start to write characters to the LCD DD RAM for the LCD display, total of 16
characters for one column starting with `A'
54
Write characters to the LCD RAM for display
55
Next character
57
Set DD RAM address to 0x40, which positions the cursor at the second column at the
first position
59
Display the 16 characters starting with `a' at the second column
61
Write the characters to be displayed to the LCD RAM
62
Next character
64
LCD ON/OFF control, no LCD display
65
March 15, 2011
Using Enhanced Holtek C
6.7 HT46R63 MCU with LCD Driver Application Program
This chapter uses the HT46R63 to show how to control an LCD driver using C language
to display figures on an LCD panel. The LCD simulator in the HT-IDE3000 can be used to
simulate the LCD panel without needing actual hardware implementation. Refer to the LCD
Simulator chapter in the HT-IDE3000 user's guide for information.
6.7.1 Objective
The objective here is to control an LCD panel using the HT46R63 with a C program so as
display digits on an LCD panel. The displayed digits are the timing values of an 8-bit clock
with seconds as the unit.
6.7.2 Peripheral Components
The data controlling whether each LCD pixel, COMx/SEGy, is to be displayed or not is stored
in the LCD memory of the HT46R63. This memory is the data memory located in Bank 1 of
the MCU, with an addresses range of 40H to 53H. The relationship between the SEGMENTs,
COMMONs and addresses is shown in the figure below.
Display Memory
When a 1 is written to the address bit, the related pixel SEGx/COMy will be displayed.
During the application program development and debug process, it is more practical to use
the LCD simulator provided in the HT-IDE3000 rather than use actual LCD hardware. Before
program development, first configure the LCD panel structure. The example here uses
lcddemo.lcd as the panel structure file, which is directly opened by the HT-LCDS software, to
give a picture as shown below.
Rev. 1.30
66
March 15, 2011
Using Enhanced Holtek C
SEG0
SEG1
SEG2
SEG3
SEG4
SEG5
SEG6
SEG7
SEG8
40H
41H
42H
43H
44H
45H
46H
47H
48H
COM0
1e
1f
—
2e
2f
—
3e
3f
—
COM1
1d
1c
—
2d
2c
—
3d
3c
—
COM2
1b
1a
1g
2b
2a
2g
3b
3a
3g
The upper part of the figure is the LCD panel figure. The 0 to 9 digits are displayed using the
control data written to the LCD RAM by the program. The digits are composed of up to seven
segments, each of which is controlled by the associated SEG/COM pixels. Figures on the
panel are acquired from the bmp format file which must be assigned while setting the LCD
structure.
The table below the figure shows the relationship definitions between SEG/COM and each
seven digit display segment. For example, the address 40H, 41H, 42H controls the first seven
segment figure display and has three commons. in this example so every byte can have only
three bits effective at the most.
In the example, a number of delays will be will be accumulated and then the numerals
displayed on the panel. The ones digit is displayed on the third segment (3a~3g), the tens
digit on the second segment (2a~2g) and the hundreds digit on the first segment (1a~1g.)
6.7.3 Circuit Diagram
HT46R63 MCU
6.7.4 MCU Configuration Option
The HT46R63 configuration options are setup as follows. Options not mentioned can be setup
as either enable or disable.
LCD duty: 3 COM
LCD segment: 20 segments
SEG7-SEG10: LCD output
SEG11-SEG14: Logical output
SEG15-SEG18: Logical output
6.7.5 Program Flow
Start
Clear LCD RAM (extinguish LCD)
Loop, from 0 to 999
Display the digits in tens,
hundreds, and ones on the LCD
End
Rev. 1.30
67
March 15, 2011
Using Enhanced Holtek C
6.7.6 Original Program
1
#include“ht46r63.h"
2
// define the LCD RAM data of the digit`0'~`9', seven bits controls each
segment display
3
// each segment pattern - gacf bdc
4
char digit[10] = { 0b01111101, 0b00011000, 0b01110011, 0b01111010,
//`0',`1',`2',`3'
5
0b00011110, 0b01101110, 0b01101111, 0b00111000, // `4',`5',`6',`7'
6
0b01111111, 0b01111110 } ; // `8', `9'
7
char LcdRam[20] @ 0x140 ; // LCD RAM
8
void DelayTime(unsigned int count) // 10 * count + 11, if count > 256
9
{
10
while( count != 0 ) count-- ;
11
}
12
// addr (IN) = LCD RAM address = 0x140+x
13
//data1 = data written to the LCD RAM, write addr to bit0~2 and addr+1 to bit3~5
14
// write bit2 of addr+2 to bit 6
15
void DisplayLcd(unsigned char addr, unsigned char data1)
16
{
17
LcdRam[addr - 0x140] = data1 & 0x7 ; // obtain bit 0 ~ 2
18
LcdRam[addr - 0x140+1] = (data1 >> 3) & 0x7 ; // obtain bit 3~5
LcdRam[addr–0x140+2]=((data>>6) & 0x7)<<2;//obtain bit 6, shift 2 bits to the left
19
20
}
21
// main function
22
void main(void)
23
{
24
int k, count ;
25
26
for( k=0 ; k<20; k++) LcdRam[k] =0;// clear the LCD memory to 0, no LCD display
27
for( count=0 ; count < 1000 ; count++ ) // display digits from 0 to 999
28
{
29
k = (count /100) % 10 ; // obtain the hundreds digit
30
DisplayLcd(0x146, digit[k]) ;
31
k = (count / 10) % 10 ; // obtain the tens digit
32
DisplayLcd(0x143, digit[k]) ; // display digit
33
k = count % 10 ; // obtain the ones digit
34
DisplayLcd(0x140, digit[k]) ;
35
_delay(250000) ; // delay one second
36
_delay(250000) ;
37
_delay(250000);
38
_delay(250000) ;
39
40
Rev. 1.30
}
}
68
March 15, 2011
Using Enhanced Holtek C
6.7.7 Program Description
4~6
Define the 0 to 9 digits, the LCD RAM control codes and the,display digits
7
Define the address of the array LcdRam[20] to be at 0x40 in RAM bank 1 which is the
start address of the LCD RAM. The control code to be displayed must be written to
the related address. The LcdRam[0] address is 0x140, LcdRam[1] is 0x141, …, and
LcdRam[19] is 0x153.
15~20 Function DisplayLcd writes each part of the control code data1 to the LCD RAM
address addr, addr+1, addr+2. Here bits 0~2 of data1 is written to addr bits 0~2, bits
3~5 of data1 is written to addr+1 and bits 0~2, bit 6 of datal is written to addr+2 bit 2.
Once the control codes are written to the LCD RAM, the related pixels will
immediately respond to the written data.
22~38 Main function
26
Clear the LCD memory to 0, extinguish LCD display
27~37 Loop, display digits on the LCD panel starting from 0 to 999
29
Obtain the hundreds digit
30
Obtain the hundreds digit control code the from array digit[]. Transmit the LCD RAM
address 0x146 and control codes to the function DisplayLcd to display the hundreds
digit.
31
Obtain the tens digit
32
Obtain the tens digit control code from array digit[]. Transmit the LCD RAM address
0x143 and control codes to the function DisplayLcd to display the tens digit.
33
Obtain the ones digit
34
Obtain the ones digit control code from array digit[]. Transmit the LCD RAM address
0x140 and control codes to the function DisplayLcd to display the ones digit.
35~38 _delay delay for 1 second
6.8 Display General Functions – HD44780 LCM
This chapter sums up the functions in the example 6.6 using an easier format and interface for
use by other application programs that use an LCD.
6.8.1 initialLCD( )
Define the constants for which are used to initialize the LCD features. Features not defined as
follows are with a fixed value which need not modify (default=0).
#define LCD_MODE_RIGHT 0x2 // entry mode: I/D=1 cursor shifts to the right
#define LCD_MODE_MOVE 0x1 // entry mode: S=1 the display shifts accordingly
#define LCD_FUNC_5X10 0x04 // F=1 5x10 dot matrix
#define LCD_FUNC_2LINE 0x08 // N=1 dual line display
#define LCD_FUNC_8 0x10 // DL=1 8-bit control (DB7~DB0)
#define LCD_DISP_B 0x01 // ON/OFF control : B=1 cursor flashing
#define LCD_DISP_C 0x02 // C=1 display cursor
#define LCD_DISP_D 0x04 // D=1 display all data
// function input parameters and definitions
// funcset : functionset instruction, bits 4,3,2 = DL, N, F
// DL=1 is 4 bit (DB7~DB4) control mode
// =0 is 8 bit (DB7~DB0) control mode
// N=0 single line display
// =1 dual line display
// F=0 5x7 dot matrix character
// =1 5x10 dot matrix character
// dispon : Display ON/OFF instruction, bits 2, 1, 0 = D, C, B
// D=0 no data displayed
// =1 display all data
Rev. 1.30
69
March 15, 2011
Using Enhanced Holtek C
// C=0 cursor not displayed
// =1 display cursor
// B=0 cursor not flashing
// =1 cursor flashing
// entrymode: enter mode instruction bit 1, 0 = I/D, S
// I/D=0 when data is written to or read from the DD RAM, the address counter (AC) will
// decrease by 1 so the cursor will shift to the left
// =1 when data is written to or read from the DD RAM, the address counter (AC) will
// increment by 1 so the cursor will shift to the right
// S =1 when data is written to the DD RAM, all display will shift to the left (if I/D=0)
or to the right
// (if I/D=1) while reading data from the DD RAM the display will not move
// =0 display does not move
void InitialLCD(char funcset, char dispon, char entrymode)
{
char bcode ;
LcdPortCtrl = 0 ; // three LCD control pins setup as outputs
bcode = (funcset & 0x1C) | 0x20 ; // take the funcset bits of 2, 3, 4 (functionset
instruction)
WriteTo LCD(REG_IR, bcode) ; // function setup, 4/8 bits, single/dual line
display, 5x7/5x10 dot matrix
bcode = (dispon & 0x7) | 0x08 ;
// ON/OFF control, the dispon bits or 0, 1, 2, is the ON/OFF 0, 1, 2
WriteToLCD(REG_IR, bcode) ; // ON/OFF control, display all data and cursors,
cursor flashing
bcode = (entrymode & 0x03) | 0x04 ; // entry mode, entrymode bit 1, 0
WriteToLCD(REG_IR, bcode) ; // entry mode, after the external data read/write,
the address counter (AC) will change
WriteToLCD(REG_IR, 0x01) ; // clear display, set the address counter to 0, I/D=1
WriteToLCD(REG_IR, 0x80) ; // DD RAM address setting, set the AC to 0
// set the cursor to the first line at the first position
}
6.8.2 PutChar( )
Write the first letter to the LCD DD RAM for display.
void PutChar(char bdata)
{
WriteToLCD(REG_DR, bdata) ; // write to LCD DD RAM
}
6.8.3 MoveAt( )
Move the cursor to the indicated location on the LCD, namely change the address counter (AC)
to a new address where x and y indicate the xth position on the yth column (x=0~19, y=0~3) .
There are a maximum of 20 characters for each column and a maximum of four columns..
void MoveAt(char x, char y)
{
char bdata ;
bdata = x + ((y & 2)==0 ? 0 : 20) + ((y&1)==0 ? 0 : 0x40) + 0x80 ;
WriteToLCD(REG_IR, bdata) ;
}
6.8.4 main( )
void main(void)
{
char funcset, disp, entrymode ;
Rev. 1.30
70
March 15, 2011
Using Enhanced Holtek C
}
funcset = LCD_FUNC_2LINE | LCD_FUNC_8 ; // dual line display, 8-bit transmission
entrymode = LCD_MODE_RIGHT ;
disp = LCD_DISP_B | LCD_DISP_C | LCD_DISP_D ;
InitialLCD(funcset, disp, entrymode) ; // initialize LCD
6.9 Key Scan Program
6.9.1 Objective
This example introduces how to control a 4x4 keyboard array using I/O lines. Each key is
given a specific hexadecimal value. When a key is pushed, the LCD will display the given
value of the key in binary format. If multiple keys are pushed at the same time, only the first
scanned key value will be displayed. In the C language, the switch/case statement format will
replace multiple if/else if format so as to increase program readability.
6.9.2 Peripheral Components
Sixteen switches are connected to port A, PA0~PA7, and four LEDs are connected to port B,
PB0~PB3.
Set PA0~PA3 as outputs and PA4~PA7 as inputs. When a pushed key is scanned by the
program, the key value will be displayed using the LEDs connected to Port PB.
Scanning is executed from the first column and the first row. Begin by finding the row where
the pushed key is located, then find the column. Then transmit the scan code using PA0~PA3
with a 0 for the target row and a 1 for other rows. For example, first search on the first row by
sending out a 0111 pattern on PA0~PA3 and read back from PA4~PA. If the value is not 1111,
then one of the keys on this row has been pressed. If a 0 appears on PA5, then this means
that one of the keys on this column has been pressed. Therefore in this case the pressed key
is located on the first row and the second column.
6.9.3 Circuit Diagram
Rev. 1.30
71
March 15, 2011
Using Enhanced Holtek C
6.9.4 MCU Configuration Options
The configuration option settings of the HT48R10A-1 are as follows;
WDT clock source : disable
OSC : Ext. Crystal
Pull-high PA : Pull-high
Pull-high PB : Pull-high
Input type PA : Schmitt Trigger
BZ/BZ : Disable
fSYS = 4M
6.9.5 Program Flow
Start
Set PB, PA0~PA3 as outputs
Set PA4~PA7 as inputs
Loop: output scan code for each row
from the first to the fourth row
Past the forth row
Yes
No
Read scan code from port A
No
Key pressed on one row
Yes
Output to port B, turn on
the LEDs related to the key
Rev. 1.30
72
March 15, 2011
Using Enhanced Holtek C
6.9.6 Original Program
1
#include “ht48r10a-1.h"
2
char scan_code[4] = { 0xfe, 0xfd, 0xfb, 0xf7 } ;
3
void main(void)
4
{
5
char key_code, pos ;
6
int row ;
7
_pbc = 0 ; // set port B as outputs for LED driving
8
_pac = 0x0f ; // set PA0~PA3 as outputs, PA4~PA7 as inputs
9
_pa = _pb = 0 ; // clear PA, PB
10
scan_l:
11
for( row = 0 ; row < 4 ; row++ ) // scan from the first row
12
{
_pa = scan_code[row] ; // output the scan code of this row
13
14
key_code = _pa ; // read scan code from PA
15
if( (key_code ^ scan_code[row]) !=0)//a key has been pressed on this row
16
{
17
switch (key_code & 0xf0)//obtain the highest 4 bits (PA7~PA4)
18
{
19
case 0xe0 : pos = row * 4 ; // PA4=0
20
break ;
21
case 0xd0 : pos = row * 4 + 1 ; // PA5=0
22
break ;
case 0xb0 : pos = row * 4 + 2 ; // PA6=0
23
24
break ;
25
case 0x70 : pos = row * 4 + 3 ; // PA7=0
26
break ;
27
default : // error
goto scan_l;//using other error display is acceptable
28
29
}
30
pos ^= 0x0f ; //set the lowest four bits low to turn on the LEDs
31
_pb = pos ; // turn on the LED
32
break ; // jump out of the loop
33
}
34
}
35
// no key is pressed or LED display has ended
36
37
goto scan_l ; // scan from the beginning
}
6.9.7 Program Description
Rev. 1.30
2
Define four scan code array scan_code[4] for key scanning
7
Set port B as outputs to drive the LEDs
8
Set PA0~PA3 as outputs, PA4~PA7 as inputs
9
Clear PA, PB
10
Start point for repeat execution
11
Loop, scan from the first row, in total four rows
13
Output the scan code of this row to port A
14
Read scan code from port A
73
March 15, 2011
Using Enhanced Holtek C
15
Check if any key is pressed on this row
17
Key is pressed - check column location // obtain highest 4 bits (PA7~PA4)
19
First column pressed - location is counted to be column x 4
20
Jump out of switch
21
Second column pressed - location is counted to be column x 4 + 1
22
Jump out of switch
23
Third column pressed - location is counted to be column x 4 + 2
24
Jump out of switch
25
Fourth column pressed - location is counted to be column x 4 + 3
26
Jump out of switch
27~28 For other situations, these steps should not be executed under normal conditions. To
avoid abnormal conditions from happening, this can be a precaution to set with an
incorrect value (-1).
Rev. 1.30
30
Set the lowest four bits low to turn on the LEDs
31
Output to Port B, turn on the LED
32
Jump out of the loop, go to the 36th column
36
No key is pressed or has LED display completed once. // scan from the beginning
74
March 15, 2011
Using Enhanced Holtek C
Chapter 7 Application Example – Interrupt Program
This chapter introduces how to manage microcontroller interrupt events using C. The interrupt
service routine in chapter 4.7, describes how to write an interrupt service routine and also
includes some special notes. The following rules should be obeyed when defining an interrupt
service routine.
→ The return value type of the function must be a void interrupt
→ No arguments are allowed in the function
→ Set the interrupt vector in the interrupt service routine using @ to designate an interrupt
vector
→ It is recommended not to call interrupt service r5outines from other program locations
→ Do not enable the interrupt to be generated again in the interrupt service routine. Same
interrupts should be prevented from being generated.
void interrupt ISR_Timer(void) @ 0x08
{
}
// Define: return value type, no arguments, set the interrupt vector to 0x08
The C compiler will save the register contents after entering the interrupt service routine
according to the interrupt requirements. After the interrupt service routine has been executed,
the stored contents will be recovered back to their original registers and finally the program
will jump back to the point where the interrupted occurred. The interrupt function will also be
re-enabled to allow the generation of further interrupts. It is also not necessary to store the
contents of some registers in an interrupt service routine, such as BP, MP0, and MP1 etc. to
reduce program code size. For a description and usage about #prgama refer to section 4.9.
Do not enable the same interrupt function in the interrupt service routine to prevent a double
entry to the same interrupt vector from occurring. However other interrupts can be enabled as
long as they do not call the same functions which would create data corruption.
7.1 LED Control using the Timer
7.1.1 Objective
This example uses the timer to control the on/off time of an LED. The same on and off time is
controlled using an interrupt service routine written by C.
Rev. 1.30
75
March 15, 2011
Using Enhanced Holtek C
7.1.2 Peripheral Components
A single LED is connected to Port A in the HT48R10A-1. Control of this pin requires using
the MCU registers INTC, TMRC, and TMR. Each definition is listed in the accompanying
table. The TMRC (Timer Control Register) controls the timer functions as well as its start/stop
operation.
Bit No.
Label
Function
0~2
PSC0~
PSC2
To define the prescaler stages, PSC2, PSC1, PSC0=
000: fINT=fSYS/2 or fRTC/2
001: fINT=fSYS/4 or fRTC/4
010: fINT=fSYS/8 or fRTC/8
011: fINT=fSYS/16 or fRTC/16
100: fINT=fSYS/32 or fRTC/32
101: fINT=fSYS/64 or fRTC/64
110: fINT=fSYS/128 or fRTC/128
111: fINT=fSYS/256 or fRTC/256
3
TE
To define the TMR active edge of timer/event counter
(0=active on low to high; 1=active on high to low)
4
TON
5
—
6
7
TM0
TM1
To enable/disable timer 0 counting
(0=disabled; 1=enabled)
Unused bit, read as "0"
To define the operating mode
01=Event count mode (external clock)
10=Timer mode (internal clock)
11=Pulse width measurement mode
00=Unused
TMRC(0EH) register
Bit No.
Label
0
EMI
Controls the master (global) interrupt (1= enabled; 0= disabled)
Function
1
EEI
Controls the external interrupt (1= enabled; 0= disabled)
2
ETI
Controls the timer/event counter interrupt (1= enabled; 0= disabled)
3
—
Unused bit, read as "0"
4
EIF
External interrupt request flag (1= active; 0= inactive)
5
TF
Internal timer/event counter request flag (1= active; 0= inactive)
6
—
Unused bit, read as "0"
7
—
Unused bit, read as "0"
INTC (0BH) register
TMR is the register which stores the initial value of the timer. The value will also be stored
in the preload register when writing to TMR. When the timer is stopped, the value will be
written to the timer/counter. Whenever the timer is enabled, the timer counter value will be
incremented until a value of FFH is reached, at which point the timer will overflow. At this time,
the following situation will occur.
→ Generate an interrupt signal
→ Reload the value in the preload register to the timer/counter and keep counting up.
If a timer overflow is required at specific counts, then a value of 256 – count should be
written to the TMR register. Further range increase can be achieved by using prescaler bits
PSC0~PC2 in the TMRC register.
If a timer interrupt is required, it is necessary to enable the timer interrupt function in the INTC
register by setting the ETI bit to 1. When a timer overflow occurs, a timer interrupt will be
generated which will cause the program to jump to the interrupt vector 08H.
The interrupt function will control the LED through PA0 pin on Port A.
Rev. 1.30
76
March 15, 2011
Using Enhanced Holtek C
7.1.3 Circuit Diagram
Connect the PA0 of port A to the negative pole of the LED.
7.1.4 MCU Configuration Option
HT48R10A-1 configuration option settings:
WDT clock source : disable
OSC : Ext. Crystal
Pull-high PA : Pull-high
Input type PA : Schmitt Trigger
BZ/BZ : Disable
fSYS = 4M
7.1.5 Program Flow
Timer Interrupt Function
Start
ms variable plus 1
Set PA0 as outputs
Set EMI, ETI of INTC
Set TMRC as fSYS/256
Select timer mode
Smaller or equal to 62
ms variable
Larger than 62
Set TON, enable timer
Set the ms variable to 0
The interrupt function handles
the LED on/off
Enter endless loop; allow
the timer to control the LED on/off
Rev. 1.30
77
return
March 15, 2011
Using Enhanced Holtek C
7.1.6 Original Program
1
#include “ht48r10a-1.h"
2
#define _ton _0e_04 // register TMRC bit4, TON
3
char sec_count ; // record second
4
void interrupt ISR_TIMER(void) @ 0x8 // define the interrupt service routine ISR to be
located at address 0x08
5
{
6
sec_count++ ; // every 16ms plus 1
7
if(sec_count > 62 ) // exceed 16x62 = 992 ms, one second
8
{
9
sec_count = 0 ; // restart
10
_pa0 ^= 0x01 ; // toggle LED, every second, on/off in sequence
11
}
12
}
13
void main(void)
14
{
15
_pac = 0x01; // set PA0 as output
16
_pa = 0xff ; // turn off LED
17
_intc = 0x05 ; // set EMI, ETI which enables the interrupt function
18
_tmrc = 0x87 ; // set the timer register, fint=fSYS/256, timer mode
19
_tmr = (256 – 250) ; // every 250 clock cycles generates a timer interrupt
20
sec_count = 0 ; // set the initial value
21
_ton = 1 ; // enable the timer and start counting
22
while(1) ; // endless loop
23
}
7.1.7 Program Description
2
Define variable_ton as bit4 of the timer controller TMRC. TON controls the timer start/
stop operation.
3
Define variable sec_count to record seconds.
4~12
Define the timer interrupt service routine ISR_TIMER(void) to be located at address
0x08
6
Add 1 every 16 ms
7
Check if time 62 times ( over 16x62 = 992 ms - one second)
9
Reset sec_count to 0, restart counting
10
toggle LED on and off in sequence every second
12~23 Main program main(void)
Rev. 1.30
15
Set PA0 as output connect PA0 to LED
16
Set PA0 to 1 to turn off LED
17
Set EMI and ETI in the interrupt control register (INTC) to enable the interrupt
18
Setup the timer control register (TMRC), fint=fSYS/256. timer mode, fSYS= 4MHz, 1
clock=64us, timer frequency = 4M/256, clock = 1/timer frequency = 64us
19
Set the timer to generate a timer interrupt every 250 clock cycles, 250x64us = 16ms
20
Setup initial value
21
Set_ton=1 to enable the timer count
22
Endless loop while(1)
78
March 15, 2011
Using Enhanced Holtek C
7.2 Analog to Digital Converter Application
7.2.1 Objective
The example here uses the analog to digital converter in the HT46R63 MCU to convert
external analog signals to digital values and display the value on an LCD panel. The ADC
interrupt service routine (ISR) and LCD display programs are written in C.
7.2.2 Peripheral Components
The LCD Simulator panel file LcdDemo.lcd and segment patterns provided in the Holtek HTIDE3000 can be used to simulate an LCD for convenience. Refer to the section 6.7.
The A/D Converter circuit in the HT46R63 includes the following registers which should be
setup before use.
→ ADR Register (22H)
Bit7
Bit6
Bit5
Bit4
Bit3
Bit2
Bit1
Bit0
D7
D6
D5
D4
D3
D2
D1
D0
The converted A/D Converter value will be stored in the ADR register, with a value from 0 ~
255.
→ ACSR Register (23H) determines the A/D conversion speed
Bit No.
Rev. 1.30
Label
Functions
0
1
ADCS0
ADCS1
ADCS1, ADCS0: select the A/D converter clock source
0,0 : fSYS/2
0,1 : fSYS/8
1,0 : fSYS/32
1,1 : unsdefined
2
CMPL
Comparator control (this bit is 0 druing reset)
0 : disable
1 : enable
3-6
—
7
TEST
Not used. Read as“0"
For testing only
79
March 15, 2011
Using Enhanced Holtek C
→ ADCR Register (22H) selects the A/D conversion channel which is located on Port B. .
Bit No.
Label
Functions
ACS0
ACS1
ACS2
ACS2, ACS1, ACS0 - selects the A/D input channel
0,0,0 : AN0
0,0,1 : AN1
0,1,0 : AN2
0,1,1 : AN3
1,0,0 : AN4
1,0,1 : AN5
1,1,0 : AN6
1,1,1 : AN7
PCR0
PCR1
PCR2
PCR2, PCR1, PCR0 : Set the PB7~PB0 functions
0,0,0 : PB7,PB6,PB5,PB4,PB3,PB2,PB1,PB0
0,0,1 : PB7,PB6,PB5,PB4,PB3,PB2,PB1,AN0
0,1,0 : PB7,PB6,PB5,PB4,PB3,PB2,AN1,AN0
0,1,1 : PB7,PB6,PB5,PB4,PB3,AN2,AN1,AN0
1,0,0 : PB7,PB6,PB5,PB4,AN3,AN2,AN1,AN0
1,0,1 : PB7,PB6,PB5,AN4,AN3,AN2,AN1,AN0
1,1,0 : PB7,PB6,AN5,AN4,AN3,AN2,AN1,AN0
1,1,1 : AN7,AN6,AN5,AN4,AN3,AN2,AN1,AN0
6
EOCB
A/D conversion point (=0 means conversion completed)
Whenever bits 3~5 setup are changed, a START signal
should be transmitted to initialize the A/D converter, or the
flag EOCB will be in an uncertain condition.
7
START
Enable the A/D converter (0->1->0 => enable, 0->1 =>
reset A/D converter and set EOCB as 1.
0
1
2
3
4
5
Before starting an A/D conversion, first select the conversion channel on Port B, select the
clock speed and then set the START bit which is bit7, in the ADCR register to 0 -> 1 -> 0, to
initiate an A/D conversion cycle. After the conversion is finished, the EOCB bit which is bit6 in
the ADCR register will be cleared to 0. The interrupt function in the A/D converter should be
enabled to generate an interrupt.
If the conversion channel or Port B configuration is changed, the A/D converter should be
initialised using the following steps:
Set the START bit in the ADCR register to 1 and then clear it to 0 within 10 instruction cycles
before changing Port B. In order to using the interrupt function in the HT46R62 A/D converter,
the interrupt vector and interrupt control configuration are also necessary.
→ INTC0 Register
Bit No.
Label
Function
0
EMI
Control the master (global) interrupt (1=enabled; 0=disabled)
1
EEI0
Control the external interrupt 0 (1=enabled; 0=disabled)
2
EEI1
Control the external interrupt 1 (1=enabled; 0=disabled)
3
ETI
Control the Timer/Event Counter interrupt (1=enabled; 0=disabled)
4
EIF0
External interrupt 0 request flag (1=active; 0=inactive)
5
EIF1
External interrupt 1 request flag (1=active; 0=inactive)
6
TF
Internal Timer/Event Counter request flag (1=active; 0=inactive)
7
—
For test mode used only.
Must be written as "0"; otherwise may result in unpredictable operation.
INTC0 (0BH) Register
The EMI bit, bit0, should be set to 1 to enable the master interrupt enable.
Rev. 1.30
80
March 15, 2011
Using Enhanced Holtek C
→→ INTC1 Register
Bit No.
Label
Function
0
ETBI
Controls the time base interrupt (1=enabled; 0=disabled)
1
EADI
Control the A/D converter interrupt (1=enabled; 0=disabled)
2
ERTI
3
—
Control the real time clock interrupt (1=enabled; 0=disabled)
Unused bit, read as "0"
4
TBF
Time base time-out interrupt 0 request flag (1=active; 0=inactive)
5
ADF
End of A/D conversion interrupt request flag (1=active; 0=inactive)
6
RTF
RTC time-out interrupt request flag (1=active; 0=inactive)
7
—
Unused bit, read as "0"
INTC1 (1EH) Register
The bit1 should be set to 1 to enable the A/D converter interrupt function.
7.2.3 Circuit Diagram
  
 
    
    
 
 ­

HT46R63/HT46C63
Rev. 1.30
81
March 15, 2011
Using Enhanced Holtek C
7.2.4 MCU Configuration Options
HT46R63 configuration option setup:
WDT clock source : disable
OSC : Ext. Crystal
fSYS= 4M
LCD duty: 3 COM
LCD segment: 20 segments
SEG7-SEG10: LCD output
SEG11-SEG14: Logical output
SEG15-SEG18: Logical output
Comparator : disable
7.2.5 Program Flow
Start
Clear LCD RAM to 0, no display
Enable ADC interrupt and
master interrupt function
Setup the ADC clock, conversion channel,
conversion channel to enable the A/D converter
A/D conversion completed?
Not completed
Completed
Display the converted
value on the LCD panel
7.2.6 Original Program
1
#include “ht46r63.h”
2
// Definitions in the header file are variable_emi = _intc0.0, _eadi = 1e1(INTC1 bit1),
3
// A/D converter registers are _adr (0x21), _adcr (0x22), acsr (0x23)
4
#define adc_start_22_7 // bit 7 (SATRT) of ADCR register
5
#define fSYS8 0x01 // ADC clock source and fSYS/8
6
#define CH_AN0 0 // ADC conversion channel
7
#define ADC_2CH 2 // ADC master channel number: 2, AN0 (PB0), AN1 (PB1)
8
char intflag = 0 ; // ADC interrupt flag
9
unsigned char adcvalue = 0 ; // ADC value after conversion
10
void interrupt ADC_ISR(void)@0x14 // ADC interrupt service routine - interrupt vector
is 0x14
11
{
12
Rev. 1.30
intflag = 1 ; // set the ADC interrupt flag
82
March 15, 2011
Using Enhanced Holtek C
13
adcvalue = _adr ; // read the converted value
14
}
15
// Enable the ADC conversion
16
// adc_clk = clock source of ADC, fSYS/2, fSYS/8, fSYS/32 (bit0~1 of ACSR)
17
// channel = channel number of AN, 0 ~ 7 (bit 0~2 of ADCR)
18
// port_cfg = port B setting (bit 3~5 of ADCR)
19
void StartADCTrans(char adc_clk, unsigned char channel, unsigned char port_cfg)
20
{
21
_acsr = adc_clk ; // set the clock source and frequency
22
adcr = (port_cfg << 3) | channel ; // set the channel and Port B configuration
23
adc_start = 1 ; adc_start = 0;//change the ADC channel and Port B configuration
24
adc_start = 0 ; adc_start = 1 ; adc_start = 0 ; // enable the A/D Converter
25
}
26
// the following function (except for the main) are the same as Chapter 6.7
27
// Define the LCD data for digits `0' ~ `9' with 7 bits controlling each segment
display
28
// patterns for each segment gacf bdc
29
char digit[10] = { 0b01111101, 0b00011000, 0b01110011, 0b01111010,
//`0',`1',`2',`3'
30
0b00011110, 0b01101110, 0b01101111, 0b00111000, // `4',`5',`6',`7'
31
0b01111111, 0b01111110 } ; // `8', `9'
32
char LcdRam[20] @ 0x140 ; // LCD RAM
33
void DelayTime(unsigned int count) // 10 * count + 11, if count > 256
34
{
35
while( count != 0 ) count-- ;
36
}
37
// addr (IN) = LCD RAM address = 0x140+x
38
// datal = write to the LCD RAM data with bits 0~2 to addr and bits 3~5 to addr+1
39
// write bit 6 to bit 2 in addr+2
40
void DisplayLcd(unsigned char addr, unsigned char data1)
41
{
42
LcdRam[addr – 0x140] = data1 & 0x7 ; // take bit0~2
43
LcdRam[addr – 0x140+1] = (data1 >> 3) & 0x7 ; // take bit3~5
LcdRam[addr – 0x140+2] = ((data >> 6) & 0x7) << 2; take bit 6 and
44
move 2 bits to the left
45
}
46
// main program
47
void main(void)
48
{
49
int k ;
50
51for( k=0 ; k < 20 ; k++) LcdRam[k] = 0 ; // clear the LCD memory to 0, no LCD display
Rev. 1.30
52
_emi = 0 ; // stop all interrupt generation
53
_emi = 1 ; // ADC interrupt function enabled
54
_emi = 1 ; // all interrupt functions enabled
55
Intflag = 0 ; // ADC interrupt flag
56
StartADCTrans(fSYS8, CH_AN0, ADC_2CH) ; // start ADC conversion
57
while(1) // endless loop, wait for an ADC interrupt
83
March 15, 2011
Using Enhanced Holtek C
58 {
59
if( intflag == 1 ) break ; // ADC interrupt generated, jump out of the loop
60}
61
// display the converted digits on the LCD panel
62
k = adcvalue /100 ; // obtain the hundreds digit
63
DisplayLcd(0x146, digit[k]) ; // display the hundreds digit
64
k = (adcvalue /10)% 10 ; // obtain the tens digit
65
DisplayLcd(0x143, digit[k]) ; // display the tens digit
66
k = adcvalue % 10 ; // obtain the ones digit
67
DisplayLcd(0x140, digit[k]) ;
68
_delay(250000) ; // delay 1 second
69
_delay(250000) ;
70
_delay(250000) ;
71
_delay(250000) ;
72for( k=0 ; k < 20 ; k++ ) LcdRam[k] = 0 ; // clear the LCD memory to 0, no LCD display
73
}
7.2.7 Program Description
4
Define the START bit, bit 7 in the ADCR register
5~7
Define the ADC clock source, conversion channel and total channels used in this
example
8
Define the ADC interrupt flag =1 indicating an ADC conversion complete
9
Define the variable and save the values converted by the ADC
10~14 Define the ADC interrupt service routine ADC_ISR(void) - the interrupt vector is 0x14
12
Set the ADC interrupt flag
13
Read the converted value from the register and save the variable
19~25 Define function StartADCTrans() to execute the ADC conversion
21
Setup the ADC conversion clock and frequency
22
Select the ADC conversion channel and total channels
23
Change Port B configuration
24
Enable the ADC conversion function
26~45 Same as Chapter 6.7, - the LCD display function
47~73 Main function, setup and enable an ADC conversion and display the converted value
on the LCD panel
51
Clear the LCD memory to 0, no LCD display
52
Stop all interrupt generation
53
ADC interrupt function enabled
54
All interrupt functions enabled
55
Clear the ADC interrupt flag to 0
56
Enable an ADC conversion
57~60 Endless loop, wait for an ADC interrupt and then jump out of the loop
59
Generate an ADC interrupt, jump out of the loop
62~67 Display the converted value on the LCD panel
62~63 Obtain the hundreds digit and display
64~65 Obtain the tens digit and display
66~67 Obtain the ones digit and display
68~69 Delay display time for 1 second
72
Rev. 1.30
Disable the LCD display
84
March 15, 2011
Using Enhanced Holtek C
Chapter 8 NiMH Battery Charger (HA0084T) Application
using the HT46R52A
8.1 Objective
With the miniaturization trend of electric appliances, portable products have become more
and more popular, such as mobile phones, digital cameras, PDA, MP3 players etc. The need
for rechargeable batteries has accompanied this trend. Among all kinds of the rechargeable
battery, the NiMH battery is especially used to replace the traditional battery having the
advantages of high capacity, low price and environmental protection concerns. Holtek provides
a NiMH battery charger demo board for the designer to design a NiMH battery charger.
■ Charger Features
→ Uses fixed current to supply power charging with 70mA for slow charging and 575mA for
quick charging
→ Provides a battery discharge option to reduce memory effects of the battery – uses a 50mA
discharge current
→ Uses -∆V detection to check if the battery is fully charged
→ Automatically stops charging after a charging time of up to 6 hours
→ Two LED display to show the charging status
→ Single battery charging at a time
■ Charger Description
The charger uses a fixed current to charge an NiMH battery. It will immediately start charging
when a battery is inserted with an option to discharge the NiMH battery before charging. It
will enter the charging mode immediately after the discharge. Prior to the charging process,
the charger will determine whether the voltage is greater than 1.25V so as to enter the quick
charging mode, or else it will enter the slow charging mode to protect the battery then and
step into the quick charging mode after the slow charge has finished.
■ Charging Method
Implements a NiMH battery charger using the HT46R52A and fixed current source. The
HT46R52A provides a PWM output to and an ADC input for current control. The HT46R85A
offers a four 4-channel ADC to read external signals for battery voltage detection. When a -∆V
in the battery is detected, the battery is fully charged. The 12-bit ADC can provide a resolution
up to 1.2mV.
■ Charging Flow Description
→ When the power is off, the LED on the demo board is off.
→ When the power is on, the green LED remains on and the others will be on for on second
and then off, during which time the demo board is waiting for the insertion of a NiMH
battery.
→ After a NiMH battery is inserted, the battery starts to be charged with two LEDs indicating
the charging status.
→ When the NiMH battery is fully charged, it will stop charging with two LEDs indicating the
fully charged status.
→ When a NiMH battery is fully charged and then removed, two LEDs will indicate that it is
waiting for further battery charging
→ Yellow and red LEDs both off: waiting for battery to be inserted
→ Yellow LED on and red LED off: quick charging in progress
→ Yellow and red LEDs both on: the battery is fully charged or has been charged for six
hours.
→ Yellow LED on with red flashing: slow charging in progress
Rev. 1.30
85
March 15, 2011
Using Enhanced Holtek C
→ Red LED on with yellow flashing: discharging in progress
The table below lists some reference values used during the charging process
Parameters
Default Values
Functions
Charging_time
240: about 6 hours
Charging time setup, 1.5 min. per unit, stop charging when
time is up
V48
V155
1270: about 1.55V
Stop charging when battery voltage over 1.55V is detected,
1.22mV per unit
V25
V125
1024: about 1.25V
Quick charging when battery voltage over 1.25V is detected,
or enter slow charging mode, 1.22mV per unit
V22
V115
942: about 1.15V
Start charging when voltage over 1.15V during discharging,
1.22mV per unit
V03
V01
82: about 0.1V
Battery voltage must be larger than 0.1V to indicate that a
battery has been inserted, 1.22mV per unit.
Vpk_time
64: about 64
seconds
Battery has exhibited a -rV situation. After a Vpk_time the
battery will be considered to be fully charged. 1 sec. per unit
V20mv
180H: about 29mV
Control the slow charging current to be larger than 58mA,
every 10H indicates 2.44mA
V30mv
200H: about 39mV
Control the slow charging current to be smaller than 78mA,
every 10H indicates 2.44mA
V250mv
E80H: about 283mV
Control the quick charging current to be larger than 566mA,
every 10H indicates 2.44mA
V260mv
F00H: about 293mV
Control the quick charging current to be smaller than 586mA,
every 10H indicates 2.44mA
8.2 Register and Peripheral Components
The example here can be used for the PWM (Pulse Width Measurement) to control the
current during battery charging.
When configuring the MCU structure, bit0 (PD.0) of Port D should be set to be in the PWM
mode. PD0 should be setup as an output (using the PDC control register) in the program.
Write a 1 to PD0 before activating the PWM output and then write the required value to the
PWM register. The table below shows the I/O function of PD0.
I/O Mode
I/P (Normal)
O/P (Normal)
I/P (PWM)
O/P (PWM)
PD0
Logical Input
Logical Output
Logical Input
PWM
Parameter
AC (0~3)
i < AC
Modulation cycle i
(i=0~3)
i ≥ AC
DC (Duty Cycle)
DC+1
64
DC
64
PWM Modulation Frequency
PWM Cycle Frequency
PWM Cycle Duty
fSYS/64 for (6+2) bits mode
fSYS/256
[PWM]/256
The table above describes the duty cycle for each modulation cycle in the PWM (6+2) mode.
The ACSR register configures the A/D converter clock frequency.
Rev. 1.30
86
March 15, 2011
Using Enhanced Holtek C
Bit No.
Label
Function
Selects the A/D converter clock source
00=system clock/2
01=system clock/8
10=system clock/32
11=undefined
ADCS0
ADCS1
0
1
2~6
—
Unused bit, read as "0"
7
TEST
For test mode used only
ACSR (23H) Register
The ADCR register controls the A/D converter enable/disable and the channel select of the PB
input port.
Bit No.
Label
0
1
2
ACS0
ACS1
ACS2
Function
Defines the analog channel select
3
4
5
PCR0
PCR1
PCR2
Defines the port B configuration select. If PCR0, PCR1
and PCR2 are all zero, the ADC circuit is powered off
to reduce power consumption.
6
EOCB
Indicates end of A/D conversion.
(0=end of A/D conversion)
Each time bits 3~5 change state the A/D should be
initialised by issuing a START signal, otherwise the
EOCB flag may have an undefined condition. See
"Important note for A/D initialisation".
7
START
Starts the A/D conversion.
A → 1 → 0=Start
0 → 1=Reset A/D converter and set EOCB to "1"
ADCR (22H) Register
ACS2
ACS1
ACS0
Analog Channel
0
0
0
AN0
0
0
1
AN1
0
1
0
AN2
0
1
1
AN3
1
0
0
AN4
1
0
1
*
1
1
0
*
1
1
1
*
Analog Input Channel Selection
PCR2
PCR1
PCR0
4
3
2
1
0
0
0
0
PB4
PB3
PB2
PB1
PB0
0
0
1
PB4
PB3
PB2
PB1
AN0
0
1
0
PB4
PB3
PB2
AN1
AN0
0
1
1
PB4
PB3
AN2
AN1
AN0
1
0
0
PB4
AN3
AN2
AN1
AN0
1
0
1
AN4
AN3
AN2
AN1
AN0
1
1
0
1
1
1
Undefined, cannot be used
Port B configuration
Rev. 1.30
87
March 15, 2011
Using Enhanced Holtek C
Register
Bit7
Bit6
Bit5
Bit4
BIt3
Bit2
Bit1
Bit0
ADRL (20H)
D3
D2
D1
D0
0
0
0
0
ADRH (21H)
D11
D10
D9
D8
D7
D6
D5
D4
Note: D0~D11 is A/D conversion result data bit LSB~MSB.
The execution result of the AC converter will be saved in the ADRL and ADRH registers.
8.3 Circuit Diagram
8.4 MCU Configuration Options
HT46R52configuration option setup:
WDT
Disable
CLRWDT
Two clear instructions
WDT clock source
WDTOSC
Pull-high PD0
Non-Pull-high
LVR
Disable
OSC
RC
PD0/PWM
Enable PWM
PA3/PFD
Disable PFD
----------------------------------------------------------------------------------76543210
Wake-up PA0- 0 0 0 0 0 0 0 0
1:Wake-up, 0:Non-Wake-up
Pull-high PA0- 1 1 1 1 1 1 1 1
1:Pull-high, 0:Non-Pull-high
Pull-high PB0- - - - 1 1 1 1 1
1:Pull-high, 0:Non-Pull-high
-----------------------------------------------------------------------------------
Rev. 1.30
88
March 15, 2011
Using Enhanced Holtek C
8.5 Program Flow
■ Main Program
START
Initial process
N
Detect if the battery
is inserted?
N
Discharge function is
selected in the charging
mode?
N
Battery voltage larger
than 1.25V?
Y
Discharge the battery,
detect if the voltage is
smaller than 1.0V?
Y
Y
N
Slow charging
N
Y
Quick charging
Check if a –∆V battery
voltage condition occurs?
N
Detect if the charging time
is larger than 6 hours?
Y
Detect if the battery
has been removed?
Y
Battery removed indication
N
Rev. 1.30
89
March 15, 2011
Using Enhanced Holtek C
■ Program Initialisation
Initial process START
Set I/O port PWM = 0
Red and yellow LED off
Setup ADCR and ACSR
Clear RAM
STOP Charging
Enable Timer Interrupt
Set Timer 4ms interrupt once
Red, yellow LED display
for 1 sec. and turn off
RET
Rev. 1.30
90
March 15, 2011
Using Enhanced Holtek C
■ Quick Charging Process Program
Quick charging START
Measure if the current
charging current is larger
than 565mA?
N
Increase PWM value
Y
Decrease PWM value
N
Measure if the current
charging current is smaller
than 585mA?
Y
Charging time
longer than 6 hours?
Y
N
Battery voltage
larger than 1.55V?
Y
Charging completed
N
Quick Charging EXIT
Rev. 1.30
91
March 15, 2011
Using Enhanced Holtek C
■ Slow Charging Process Program
Slow charging START
Measure if the current
charging current is larger
than 60mA?
N
Increase PWM value
Y
Decrease PWM value
N
Measure if the current
charging current is smaller
than 80mA?
Y
Charging time
longer than 6 hours?
Y
N
Battery voltage
larger than 1.55V?
Y
Charging completed
N
Quick Charging EXIT
Rev. 1.30
92
March 15, 2011
Using Enhanced Holtek C
8.6 Original Program and Program Description
■ File main.c
1
2
void main()
3
{
4
5
cinitial(); // initial all RAM & IO, turn LED (green) on
6
ch0_old = 0 ; // a new run
7
8
while(1) // infinite loop
9
{
10
while(1) // check battery status : exist/not exist
11
{
12
bat_main_sub(); // get battery's status, the battery is placed or not
13
// set the battery's LED flag
14
if( bat0_on_flag && !ch0_old ) // battery is placed, and it's a
new
run
15
break ;
16
17
ch0_old = 0 ; // flag : this is new run
18
}
19
20
// bat0_on_flag=1 battery is placed
21
// 1. check discharge switch, PB3
22
if( !_pb3 )
23
Ch0_Discharging(); // start to discharge
24
25
// ch0_battery_charging_sub_lp:
26
// 2. do battery charging
27
28
Ch0_DoCharging() ;
29
30
}
}
■ Program Description
2
Main program
5
Call function cinitial() to clear the RAM, setup I/O status, turn on green LED
6
Set flag ch0_old=0: new cycle execution
8~29
Outside endless loop, program execution never ends in this loop
10~18 Inside loop, detect if the battery is placed in the charger, if yes, jump out of the loop
or keep detecting if no
12
Call function bat_main_sub() to detect the battery status
14~15 If a battery is inserted, which is not the previous one, jump out of the loop for correct
handling procedure
Rev. 1.30
17
If not, set flag and wait for the next battery and continue detecting
22
Execution over which means the battery has been inserted to the waiting charger
Check if PB3 of Port B is a low voltage (needs to be discharged first)
93
March 15, 2011
Using Enhanced Holtek C
23
Yes, call function Ch0_Discharging() to execute the discharge function
28
Call function Ch0_DoCharging() to execute the charging function
//------------------------------------// Ch0_DoCharging()
// 1. battery charging with slow speed
// 2. battery charging with fast speed
//------------------------------------1 void Ch0_DoCharging()
2{
3
while(1)
4
{
5
bat0_flag_initial(); // initialize flags, set PWM
6
madc_on_sub(); // check battery's status
7
8
if( !ch0_old ) show_bat0_led(); //show led which flag for battery
9
10
_delay(250000) ; // delay 0.25s
11
_delay(250000) ;
12
_delay(250000) ;
13
_delay(250000) ; // total delay 1s
14
15
if( !bat0_on_flag ) // when have no battery in,jump
16
{
17
led0_on_flag = 0 ;
18
led1_on_flag = 0 ; // clear led show
19
ch0_old = 0 ; // the battery charging finished flag clear
20
21
return ; // jump back
}
22
23
if( bat0_voltage_over_flag ) // when battery charging finish,jump
24
{
led0_on_flag = 1 ; // charging finished,led0&led1 on
25
26
led1_on_flag = 1 ; // RED, Yellow are lit
27
ch0_old=1; // old battery
28
return ; // check battery status again
29
}
30
31
if( bat0_1c_charging_flag ) // fast charging
32
{
33
Ch0_FastCharging() ;
34
return ;
35
}
36
37
// slow charging mode
38
bat0_flag_initial(); // initial charging.
39
bat0_charging_initial(); // load initial battery's average value
40
Rev. 1.30
94
March 15, 2011
Using Enhanced Holtek C
41
// bat0_01c_charging_ap:
42
while(1)
43
{
44
bat0_50ma_charging(); // charging battery by 50ma current
45
stop_charging(); // stop charging
46
_delay(250000) ; // delay 0.25s
47
_delay(250000) ; // total delay 0.5s
48
49
madc_on_sub(); // check battery status
50
led0_on_flag = 1 ;
51
led1_on_flag ^= 1 ; // toggle flag (Red LED flash)
52
53
ad_4_data(); // load battery's average
54
get_Vbat0_inc80mv();
55
get_bat0_Vpeak();
56
57
if(!bat0_on_flag) // if no batttery in
58
{
59
led0_on_flag=0; // battery remove,led0&led1 off
60
led1_on_flag=0;
61
ch0_old=0; // flag for battery remove already
62
return ; // check battery status again
63
}
64
65
if( time_1min >= charging_time ) // battery charging's time over
66
{
67
led0_on_flag=1; //charging finished,led0&led1 on
68
led1_on_flag=1;
69
ch0_old=1; // flag for battery : no change of battery
70
return ; // check battery status again
71
}
72
73
if( bat0_1c_charging_flag )
74
break ;
75
}
76
77
led0_on_flag=1;
78
79
led1_on_flag=0;
}
80 }
Rev. 1.30
95
March 15, 2011
Using Enhanced Holtek C
■ Program Description
1
This loop is an endless loop to execute the charging operation and control the LED
on or off flags according to post charge status. Finally it returns to the main program.
3
Endless loop
5
Call function bat0_flag_initial() to setup the initial value of the parameter and PWM
6
Call function madc_on_sub() to read the battery voltage from the A/D converter and
setup the related flag
8
If the battery has just been inserted, the red LED is used to display the current status
10~13 Delay 1 second with LED flashing
The following steps are determined according to the battery voltage.
15~21 If the battery voltage is less than 0.1V which indicates that no battery is inserted, then
set the red and yellow LED flags to be off and return
23~29 If the battery voltage exceeds 1.55V which means the battery is charged, set the LED
flag and return
31~35 If the battery voltage is between 1.25 and 1.55V which means that charging is
in progress, call function Ch0_FastCharging() for quick charging and return after
completion
38~79 Use slow charging if the battery voltage is between 0.1V~1.25V
38
bat0_flag_initial() set the LED flag, PWM value
39
bat0_charging_initial() set the initial value for charging
42~75 Loop, execute slow charging
44
bat0_50ma_charging() control the battery charging current for 6 hours using the
PWM
45~47 Stop charging and wait for 0.5 second
49
madc_on_sub() checks the voltage status of the charged battery
50~51 Set the LED display flag (red blinking, yellow on)
53
ad_4_data() calculates the average voltage value
54~55 Adjust the voltage value and peak value
57~63 Check again the battery status, if the battery has been removed set the flag and
return
65
If the charging time has exceeded 6 hours, set the completed LED flag and return
73
If the required voltage has not yet been reached, it will return to the loop on line 3 for
recharging
//--------------------------// bat0_1c_charging_ap_lp:
// fast charging mode
//---------------------------1 void Ch0_FastCharging()
2{
3
bat0_flag_initial(); // initial charging.
4
bat0_charging_initial(); // load initial battery's average value
5
6
while(1)
7
{
8
bat0_500ma_charging(); // charging battery by 500ma current
9 stop_charging(); // stop charging
10
madc_on_sub(); // check battery status
11
Rev. 1.30
96
March 15, 2011
Using Enhanced Holtek C
12 if( bat0_voltage_over_flag ) // charging has been finished
13{
14
led0_on_flag=1; // charging finished, Yellow and Red LED on
15
led1_on_flag=1;
16
ch0_old=1; // flag for battery
17
18
return ; // check battery status again
}
19
20
// set LED status
21
led0_on_flag=1; // Yellow LED is lit
22
led1_on_flag=0; // Red LED extinguish
23
24
ad_4_data(); // load battery's average
25
get_Vbat0_inc80mv();
26
get_bat0_Vpeak();
27
28
if(!bat0_on_flag) // battery is removed
29
{
30
led0_on_flag=0; // battery remove,led0&led1 off
31
led1_on_flag=0;
32
ch0_old=0; // flag for battery remove already
33
return ; // check battery status again
34
}
35
36
if(time_1min >= charging_time || // battery charging's time over
37
38
bat0_Vpeak_charging_ok ) // battery charging ok
{
39 led0_on_flag=1; //charging finished,led0&led1 on
40 led1_on_flag=1;
41 ch0_old=1; // flag for battery
42
return ; //check battery status again
43}
44
} //charging go on
45 }
■ Program Description
Quick charging
3~4
Set the initial charging value // initial charging
6~44
Endless loop
8
Uses constant current charging - adjust the charge current according to the battery
voltage, maximum of 6 hours
9~10
After completion, check the charged battery voltage
12~18 If the battery if fully charged, set the completed LED flag and return
21~22 Set the LED flags to be yellow LED on, red LED off (indicating quick charging status)
24~26 Calculate and save the average voltage value, peak voltage value
28~34 Check if the battery has been removed, set the LED flag to off status and return
36~42 If the charging time has reached 6 hours or the voltage has reached its peak value,
set the completed LED flag and return
44
Rev. 1.30
If none of the above status has occurred , return to line 6 for quick charging
97
March 15, 2011
Using Enhanced Holtek C
//-------------------------------// timer_isr
//-------------------------------1 void interrupt timer_isr(void) @ 0x08
2{
3
unsigned char tmp ;
4
5
tmp = _pa ^ 0x40 ; // read from PA and XOR PA6
6
_pa = tmp ; // output PA6
7
8
// turn on/off LED
9
if( (tmp & 0x40) != 0 ) // current PA6=1
10{
11
_pa5 = 1 ;
12
if( led2_on_flag ) _pa5 = 0 ;
13
14
_pa4 = 1 ; // Red LED extinguish
15
if( led1_on_flag )
16
17
_pa4 = 0 ; // Red LED lit
}
18 else // PA6=0
19
{
20
_pa5 = 0 ;
21
if( led3_on_flag ) _pa5 =1 ;
22
23
_pa4 = 0 ; // Yellow LED extinguish
24
if( led0_on_flag )
25
26 _pa4 = 1 ; // Yellow LED is lit
}
27
28
// calculate the time
29
time_4ms++; // count
30
if(time_4ms==250) // 1 second
31{
32
time_4ms=0; // clear ms
33 time_1s++; // 1s count add
34 Vpeak_cx++; // Vpeak_cx add
35
if(time_1s==90) // 90 seconds
36{
37
time_1s=0; // time for 90s
38 time_1min++;
39
charging_cx++; // total charging time, increase 1 for every 1.5 minutes
40}
41 }
42 }
Rev. 1.30
98
March 15, 2011
Using Enhanced Holtek C
■ Program Description
Timer interrupt service routine timer_isr
Main function is to control the on/off time of the red and yellow LEDs. The other function is to
measure the charging time.
5
Read the current LED control code (PA6) and invert
6
Set the control status after the inversion
9~17
To manage the red LED (PA6 set to a high level)
Turn off the red LED first. If the LED flag is to turn on, then turn on the red LED
18~26 To manage the yellow LED (PA6 cleared to a low level)
Turn off the yellow LED first. If the LED flag is to turn on one then turn on the yellow
LED
28
The following steps will measure the charging time
29
Interrupt generated every 4ms - the number of occurrences is accumulated
30~41 When 1 sec. is reached, continue and measure the number of 1 sec occurrences
measure the voltage peak value
35~40 When 90 seconds is reached, continue and measure the number of 90 sec,
occurrences and thus the total charging times
original program sub.c
#define RAM_START 0x28
#define RAM_END 0x7F
//------------------------------------// cinitial()
// turn LED (green) on for 1 second
//------------------------------------1 void cinitial()
2{
3
char *addr ;
4
5
_pa=0x03;
6
_pac=0x80; // PA7:I/P, others are O/P
7
_pbc=0xff; // PB are In
8
_pb=0x00;
9
_pdc=0x00; // PD are Out
10
_pd=0x00;
11
12
_acsr = 0x02; // AD clock source = system clock / 32
13
_adcr = ch3+a0; // set AD channel number and PB
14
_pwm = 0x00; // pwm output 0
15
16
for( addr=(char *)RAM_START ; addr <= (char *)RAM_END ; addr++ )
17
*addr = 0 ; // clear RAM
18
Rev. 1.30
19
stop_charging(); // stop PWM
20
_intc = 0x05; // enable Timer/Counter 0
21 _tmr = (256-250); // set tmr’s value for 4ms tmr (250*16us = 4ms)
22
23 _tmrc = timer_mode+timer_on+T1_64; // set TMR0 : timer mode, timer on and
// fSYS/64, fSYS=4MHz
24 led0_on_flag=1; // set LED flag
99
March 15, 2011
Using Enhanced Holtek C
25
led1_on_flag=1;
26
led2_on_flag=0;
27
led3_on_flag=0;
28
29
_delay(250000) ; // delay 0.25s
30 _delay(250000) ; // total delay 0.5s for LED on
31
32 led0_on_flag=0;
33
led1_on_flag=0;
34
led2_on_flag=0;
35
led3_on_flag=0; // clear all led flag, turn all LEDs off
36 _delay(250000) ; // delay 0.25s
37
_delay(250000) ; // delay 0.25s
38 }
■ Program Description
This function is used to initialise the register and memory space and setup the required
structure.
5~10
12
13
Set Port A: PA7 setup as an input and all other pins as outputs, Port B setup as inputs
Port D setup as outputs and stop the PWM function
Select (fSYS/32) as the A/D converter clock source
Select channel0 of the A/D converter and PB0, PB1, PB2 of Port B as the signal input
channels
14
PWM output is zero
16~17 Clear the data memory, addresses 28H ~ 7FH cleared to zero
19
Stop charging
20
Enable the timer interrupt function
21
Set the timer interrupt interval to be 4ms (250 times) (250x16us = 4ms)
22
Set the timer to be in the timer mode with a clock frequency of fSYS /16 and start
timer counting
24~27 Set the LED status as red and yellow both illuminated
29~30 LED status persists for 0.5 second
32~35 Change the LED status to be red and yellow both extinguished
36~37 LED status persist for 0.5 second
//---------------------------// bat_main_sub()
// get battery status
//---------------------------1 void bat_main_sub()
2{
3
stop_charging(); // stop PWM
4
madc_on_sub(); // get battery's voltage and check status
5
6
if( !ch0_old ) show_bat0_led(); // show led
7
8
_delay(250000) ; // delay 0.25s
9
_delay(250000) ;
10
_delay(250000) ;
11
_delay(250000) ; // total delay 1s
12 }
Rev. 1.30
100
March 15, 2011
Using Enhanced Holtek C
■ Program Description
This function detects if there is a battery in the charger waiting to be charged.
3
Stop the PWM output
4
Read from the A/D converter if a battery has been inserted and set the corresponding
flag
6
If no battery is being charged or the battery has been removed, show the current
status using the LEDs
8~11
LED status remains for 1 second
//-------------------------------// bat0_flag_initial()
//------------------------------1 void bat0_flag_initial()
2{
3
Vpeak_cx=0;
4
bat0_Vpeak_charging_ok=0;
5
time_1min=0;
6
_pwm = 0x10 ;
7
time_4ms = 0 ;
8
time_1s = 0 ;
9}
■ Program Description
This function configures the battery charging flags and the timer frequency
3
Set the fixed time of the continuous voltage peak time value to be zero. When the
charging voltage remains the same within a certain length of time, the flag will be set
as fully charged.
4
Set the peak value to be zero. When this flag=1, the battery is fully charged.
5~8
Reset the initial value of the timer and the PWM to zero
//--------------------------------// bat0_charging_initial()
//--------------------------------1 void bat0_charging_initial()
2{
3
int i ;
4
5
6
for( i = 0 ; i < 8 ; i++ )
ad_4_data();
7
8
Vbat0_peak = Vbat0_old = Vbat0 ;
9}
■ Program Description
This function configures the voltage value and voltage peak value of the uncharged battery for
the purpose of comparison.
5~6
Calculate the average of the previous eight voltage values as a reference
8
Store the reference value
//--------------------------------------// madc_on_sub()
// get current battery voltage and status
1 void madc_on_sub()
Rev. 1.30
101
March 15, 2011
Using Enhanced Holtek C
2{
3
Vbat0_old = Vbat0 ; // save old battery value
4
GetBatteryVoltage(); // get battery voltage from ADC channel 0
5
check_battery0_status(); //check battery’s status, set/reset flags
6}
■ Program Description
The function reads the battery voltage value and configures the corresponding flag.
3
Save the previous voltage value
4
Read the battery voltage value
5
Set the corresponding flag according to the voltage value
//---------------------------------------// GetBatteryVoltage() adc_on()
// read battery's voltage from channel 0
//---------------------------------------1 void GetBatteryVoltage()
2{
3
stop_charging(); // stop pwm output
4
_delay(10000) ; // delay 10ms (4MHz)
5
// start to convert by using ADC
6
_adcr = ch3+a0; // enable ADC CH0
7
_emi=0 ; // disable all interrupts
8
_start=0;
9
_start=1;
10
_start=0; // start ADC
11
while(_eoc); // wait for ADC conversion completion
12
_emi=1; // enable interrupt
13
14 // read the conversion result 12 bits, adrl = (D3,D2,D1,D0,0,0,0,0),
15 // adrh=(D11,D10,D9,D8,D7,D6,D5,D4)
16
17
bat0 = (unsigned int)_adrh ;
19 bat0_voltage = bat0 ;
20 }
■ Program Description
This function reads and stores the battery voltage value.
3
Temporarily suspend the PWM output
4
Wait for 10ms
6
Enable channel 0 of the A/D converter
7
Disable all interrupt generation
8~10
Enable the A/D converter, and initiate a conversion cycle
11
Wait for the completion of the A/D converter
12
Enable the interrupt
17~19 Read the conversion value, combine as a 16-bit voltage value and store
//-----------------------------// a0_discharging()
//--------------------------void a0_discharging() // this function is to execute the battery discharging function
Rev. 1.30
102
March 15, 2011
Using Enhanced Holtek C
{
_pd0 = 0 ; // stop the PWM function
_pa = (_pa & 0x0f3) | 0x07 ; // PA2=1 : set PA2 to 1, enable a discharge operation
}
void a0_charging() // this function enables the battery charging function
{
_pa=(_pa&0x0f1)|0x01; // stop discharging, enable charging circuit
_pd0=1; // enable the PWM output
}
//-------------------// stop_charging()
//-------------------void stop_charging() // this function stops the charging
{
_pd0 = 0 ; // stop the PWM output
_pa = (_pa & 0x0f3)|0x03; // stop charging
}
//----------------------------------------------// check_battery0_status()
// check the status of battery 0, set/reset flags
// I/P: bat0_voltage
//-----------------------------------------------1 void check_battery0_status()
2{
3
if( bat0_voltage < V01 ) // battery < 0.1V
4
bat0_on_flag = bat0_1c_charging_flag = bat0_voltage_over_flag = 0 ;
5
else if( bat0_voltage < V125 ) // 0.1V <= battery < 1.25V
6
{
7
bat0_on_flag = 1 ;
8
bat0_1c_charging_flag=0;
9 bat0_voltage_over_flag=0;
10}
11
else if( bat0_voltage < V155 ) // 1.25 <= battery <1.55
12{
13 bat0_on_flag = 1 ;
14
bat0_1c_charging_flag=1;
15 bat0_voltage_over_flag=0;
16 }
17 else
18 {
19 bat0_on_flag=1;
20 bat0_1c_charging_flag=0;
21 bat0_voltage_over_flag=1; // battery >= 1.55
22 }
23 }
■ Program Description
This function sets the related flags according to the acquired battery voltage values for later
use.
3~4
5~10
Rev. 1.30
If the battery voltage is less than 0.1V, set the flag to 0 (battery not inserted)
If the battery voltage is between 0.1V~1.25V, the battery is inserted but not yet
103
March 15, 2011
Using Enhanced Holtek C
charged
11~16 If the battery voltage is between 1.25V~1.55V, the battery is inserted and is being
charged
17
If the battery voltage is larger than 1.55V, the battery is fully charged
//-----------------------------------// show_bat0_led()
// set the battery 0 LED flag
//-----------------------------------void show_bat0_led() // set the red LED according to the current battery voltage
{
led0_on_flag = 0 ; // yellow LED off
led1_on_flag = bat0_on_flag ; // red LED, check if a battery is inserted into the
charger
}
//-------------------------------------------------------// ad_4_data() : compute the average voltage of battery
//-------------------------------------------------------void ad_4_data()
{
int i ;
for( i = 0 ; i < 7 ; i++ ) // move battery value forward
Vbattery[i] = Vbattery[i+1] ;
Vbattery[i] = bat0_voltage ; // store current voltage
Vbat0_old = Vbat0 ; // save old Vbat0
for( i = 0 , Vbat0 = 4 ; i < 8 ; i++ )
Vbat0 += Vbattery[i] ;
Vbat0 >>= 3 ; // div 8 for average value save to Vbat0
}
■ Program Description
This function is to calculate the battery voltage average value as read earlier.
//-------------------------------------// get_Vbat0_inc80mv()
//-------------------------------------void get_Vbat0_inc80mv()
{
if( Vbat0 >= (Vbat0_old + V80mv) ) // if the voltage exceeds the previous 80mV
Vbat0 = Vbat0_old + V80mv ; // change the current voltage value
}
//----------------------------------// get_bat0_Vpeak()
//-------------------------------void get_bat0_Vpeak()
{
if( Vbat0 < Vbat0_peak ) // if the voltage is less than the voltage peak value
{
if( Vpeak_cx >= Vpk_time ) // voltage peak value has persisted for 64 seconds
{ // voltage charged within 64 seconds is less than this peak value
bat0_Vpeak_charging_ok = 1 ; // charging is ok when time>64
Vpeak_cx = 0 ;
}
}
Rev. 1.30
104
March 15, 2011
Using Enhanced Holtek C
else
{
Vbat0_peak = Vbat0 ; // update voltage peak value
Vpeak_cx = 0 ; // peak value timer reset
bat0_Vpeak_charging_ok = 0 ; // peak flag reset
}
}
//--------------------------------------------// SetDischargingLEDflag -- bat0_discharging()
//--------------------------------------------void SetDischargingLEDflag() // set the discharge LED flag
{
led1_on_flag = 1 ; // red LED on
led0_on_flag ^= 1; // yellow LED flashing
}
//--------------------------------// bat0_500ma_charging()
//--------------------------------1 void bat0_500ma_charging()
2{
3
unsigned int temp;
4
5
charging_cx = 0;
6
a0_charging();
7
_adcr = a2+ch3; // ADC channel 2
8
9
while(1)
10 {
11_emi=0;
12 _start=0;
13 _start=1;
14 _start=0; // start AD conversion
15 while(_eoc);
16 _emi=1;
17
18 temp = (unsigned int)_adrh ;
19 temp = (temp << 8)+(unsigned int)_adrl ; // read AD converted value
20 if((temp >= V260mv) && (_pwm != 0)) _pwm-- ;
21 if((temp < V250mv) && (_pwm != 0)) _pwm++ ; // if battery
22
// current<566ma,add pwm
23 24
if( charging_cx >= 240 ) return ; // if charging time >= 6 hours, return
}
25 }
■ Program Description
This function executes the quick charge operation during which the current will be adjusted
according to the measured voltage.
Rev. 1.30
5
Reset the charging time
6
Enable the charging mechanism
105
March 15, 2011
Using Enhanced Holtek C
7
Set channel2 of the AD converter to be the input channel for the battery voltage
9~20
Loop, read the voltage during the charging process and use it to adjust the current
11
Disable any interrupt generation
12~14 Enable the AD converter
15
Wait for completion of an AD conversion
16
Enable the interrupt
18~19 Read the voltage value
20
If the battery voltage exceeds 293mv and the PWM is not zero, then subtract 1 from
the PWM value
21
If the battery voltage is less than 281mv and the PWM is not zero, then add 1 to the
PWM value
23
If the charging time has reached 6 hours, stop and return
24
Keep charging
//---------------------------------// bat0_50ma_charging()
//---------------------------------1 void bat0_50ma_charging()
2{
3
unsigned int temp;
4
5
charging_cx=0;
6
a0_charging(); //set led status's flag
7
_adcr = a2+ch3; //set AD channel 2
8
9
while(1)
10 {
11_emi=0;
12 _start=0;
13 _start=1;
14 _start=0; // start ADC conversion
15 while(_eoc);
16
17
_emi=1;
18
temp = (unsigned int)_adrh ;
19
temp = (temp << 8) + (unsigned int)_adrl ; // read AD conversion value
20
if( temp < V20mv )
21
{
22
if(_pwm) _pwm++; // battery's current<58 mA,pwm add
23
else _pwm = 0x10; // minimum
24
}
25
else if( temp >= V30mv )
26
{
27
28
if( _pwm ) _pwm--; // battery's current>=78 mA,pwm dec
else _pwm=0x10;
29}
30
31
if( charging_cx >= 240 ) return ; // charging's time out 6 hours
32}
33 }
Rev. 1.30
106
March 15, 2011
Using Enhanced Holtek C
■ Program Description
Function to manage the slow charge operation.
5
Set the charging time to be 0
6
Enable PWM and the charging circuit
7
Set Channel 2 of the AD converter
9~32
Loop in battery charge process execution
11
Disable all interrupt generation
12~14 Enable the A/D converter
15
Wait for the completion of the A/D converter
16
Enable the interrupt
18~19 Read the data after A/D conversion
20~24 If the battery voltage is smaller than 29mv, add 1 to PWM
25~29 If the battery voltage is larger than or equal to 39mv, subtract 1 from PWM
31
If the charge time has reached 6 hours, stop and return
32
If there is still time remaining, keep charging
//-------------------------------------// Ch0_Discharging()
//-------------------------------------1 void Ch0_Discharging()
2{
3
madc_on_sub(); // get battery's voltage and status
4
led0_on_flag = 0; // set LED flags
5
led1_on_flag = 1; // turn RED LED on, Yellow flash
6
bat0_charging_initial(); // initial
7
while(1)
8
{
9
a0_discharging(); // to discharge (PA2=1)
10
11
_delay(250000) ; // delay 0.25s
12
_delay(250000) ;
13
_delay(250000) ;
14
_delay(250000) ; // total delay 1s
15
16
madc_on_sub(); // get battery's voltage
17
SetDischargingLEDflag(); // set LED0 flag
18
19
ad_4_data(); // get battery's average voltage
20
if( Vbat0 >= (Vbat0_old + V80mv) )
21
Vbat0 = Vbat0_old + V80mv ;
22
23
get_bat0_Vpeak(); // check peak value
24
bat0_discharging_ok_flag = (Vbat0 < V155) ? 1 : 0 ; // if battery <
25
// 1.15,discharging end
26
27
// if no battery in or battery charging is over or battery discharging is ok, then
return
if( !bat0_on_flag || bat0_voltage_over_flag || bat0_discharging_ok_flag )
28
29
31
return ; // battery discharging ok,jump
}
32 }
Rev. 1.30
107
March 15, 2011
Using Enhanced Holtek C
■ Program Description
Function to discharge the battery in the charger – the LED will be on and the yellow LED will
flash.
3
Read the voltage of the battery in the charger and setup related flags
4~5
Set the red LED to be on and yellow LED off
6
Calculate the reference voltage value for the discharge process
7~31
Loop in the discharge process
9
Enable the discharge switch
11~14 Wait for 1 second
16
Enable the A/D converter, read the battery voltage and setup the related flags
17
Set the LED flags with the red LED on and the yellow LED off in sequence
19
Calculate the average voltage value after discharging
20~21 If this voltage is lower than the reference voltage by 80mv, update the voltage to be
the reference voltage plus 80mv
Rev. 1.30
23
Compare with the voltage peak value or update
24
Check, if the voltage is smaller than 1.55V, set the discharge completed flag
27
If the battery has been removed or discharging completed, then return
31
Continue with the discharging process
108
March 15, 2011
Using Enhanced Holtek C
Chapter 9 Program Example – The HT46R74D-1 Tyre
Pressure Gauge
9.1 Objective
This device uses the HT46R74D-1 as the main MCU device used together with a sensor to
implement a car tyre pressure gauge detector. The final high three bits of the effective value
will be displayed on the LCD with four selectable display units (Psi, Bar, Kpa, Kgf/cm2.) To
increase accuracy, it is recommended to construct a Sensor Output Voltage and Discharge
Time (V-T) table with a higher number of measured values, for related calibration.
9.2 Functions
■ Switches
One switch for unit select: SELECT
One I/O control: controls an I/O pin used for operation indicator
■ Function Description
9.2.1
When the MCU is not powered on or in the halt mode, connect the power or press
"SELECT" to wake up the MCU. The system will turn on the operating indicator as
well as measuring the no-load air pressure value to save this as a calibration value (the
calibration value is saved during the discharge time, Tc, under a fixed charge time of,
Ti).
9.2.2
If there is no switch activation, use the average of ten charge time values minus the
calibration value to be the measured Tc value (the discharge time Tc will be refreshed
once per second). After a table read execution, proceed with the calculation according
to the selected units and acquire the high three bits from the result as the effective
value to be displayed on the LCD. If a switch activation is detected, enter the related
switch handling routine.
9.2.3
If the displayed value is larger than 999, then a "---" will be shown to indicate that the
measured value has exceeded the display range.
9.2.4
When the MCU is in the operating status, each time the "SELECT" switch is pushed,
the display units will be changed. The display units will alternate in the following
order: Psi=>Bar=>Kpa=>Kgf/cm2. At the same time the displayed values will show
the corresponding new unit changes (for the units transform relationship refer to the
appendix.)
9.2.5
When the MCU is in the operating status, if no switch is detected within 60 seconds,
the LCD display will be switched off and the LCD driver I/O port cleared to zero and
then the MCU will enter to enter the power-down mode.
9.2.6
Some parameter definition are modified according to the Sensor Output Voltage –
Discharge Time (V-T) table as described below:
#DEFINE PER 100
#DEFINE PSI_FULL 10000
#DEFINE BAR_FULL 689
#DEFINE KPA_FULL 0D54H
#DEFINE KPA_FULL_H16 01H
#DEFINE KGFCM2_FULL 703
#DEFINE TABLE_NUM 13
#DEFINE TABLE_PER 12
Note:
Rev. 1.30
PER: Enlarge the sensor full scale value 100 times
PSI_FULL: Sensor full scale value is 100(PSI) x100=10000
BAR_FULL: Sensor full scale value is 6.89(PSI) x100=689
KPA_FULL: Sensor full scale value is 689.48(PSI) x100=68948 low 16 bits
109
March 15, 2011
Using Enhanced Holtek C
KAP_FULL_H16: Sensor full scale value is 689.48(PSI) x100=68948 high 16 bits
KGFCM2_FULL: Sensor full scale value is 7.03(PSI) x100=703
TABLE_NUM: V-T table value number
TABLE_PER: The V-T table in this device subdivides the sensor output into twelve
sections, which is to build a set of values with 5mV intervals.
9.3 Circuit Diagram
(Figure 1)
Rev. 1.30
110
March 15, 2011
Using Enhanced Holtek C
■ Circuit Description
The HT46R74D-1 is a dual slope A/D type micro controller which includes an internal amplifier,
voltage follower, integrator and comparator. During the charge cycle, the internal MUX will be
switched to the amplifier output and charge the charge/discharge capacitor. In the discharge
cycle, the MUX will be switched to VDSO to discharge to discharge the capacitor. When the
voltage drops to 1/6VDSO, the comparator will output a low level. This point is defined as the
discharged state.
The internal 3.3V reference voltage in the HT46R74D-1 can be used as a voltage source
for the sensor while the VOBGP pin can provide the sensor with a 1.5V reference voltage.
The output voltage of the sensor should be processed through an amplifier. The amplifier
connection method is illustrated in figure 2:
(Figure 2)
Here, VDOPAO=VOBGP+(VA-VB)*(R2/R1)=1.5V+10*(VA-VB)(where R1=R3, R2=R4,
R2=10R1).
The sensor specification used by this application will output a voltage of 60mV for a full
scale 100PSI value under an operating voltage of 3.3V. The V-T table uses (sensor output
voltage/5mV+10) to be the offset address which includes 13 data sets. When measuring
the tyre air pressure, the same charge time is listed in the table. Every measured discharge
time can be looked up to confirm the approximate offset address and value. After the
calculation, the sensor output voltage value should be taken to two decimals so as to improve
the accuracy, and then the high three effective bits of the calculation result after the unit
conversion will be displayed on the LCD.
■ Special Points to Note
9.3.1 LCD Display Interface (figure 3):
Set the arrangement from left to right as: Digit1, Dot1, Digit2, Dot2, Digit3 and the four unit
names. The corresponding layout is shown in the table:
Rev. 1.30
111
March 15, 2011
Using Enhanced Holtek C
(Figure 3)
Pin
Seg0
Seg1
Seg2
Seg3
Seg4
Seg5
Seg6
Seg7
Seg8
Com0
1f
1a
Bar
2f
2a
Kpa
3f
3a
Kgf/cm²
Com1
1e
1g
1b
2e
2g
2b
3e
3g
3b
Com2
1d
1c
Dot1
2d
2c
Dot2
3d
3c
Psi
9.3.2
Note that the amplifier must be setup according to the selected sensor specification.
The sensor output signal after amplification by the amplifier should not exceed
4/6VDSO.
9.3.3
Select a proper charge/discharge resistor Vr, capacitor Vc and charge time Ti to make
the Vc voltage remain between 1/6VDSO and 5/6VDSO.
9.3.4
To increase accuracy, it is recommended that a table is constructed with more
measured data.
9.3.5
Factors such as charge time changes, different regular voltage output etc will affect
the discharge time. The Sensor Output Voltage – Discharge Time (V-T) table should
be noted for calibration.
There are two interrupt control and status registers, INTC0, INTC1, provided to generate
interrupt events after an A/D conversion. The other related registers and definitions are listed
below, such as the CHPRC (Charge pump/Regulator Control) register which is used to control
the on/off of the charge pump and voltage regulator.
Bit No.
Label
Function
0
EMI
Control the master (global) interrupt (1=enabled; 0=disabled)
1
EEI0
Control the external interrupt 0 (1=enabled; 0=disabled)
2
EEI1
Control the external interrupt 1 (1=enabled; 0=disabled)
3
ET0I
Control the Timer/Event Counter 0 interrupt (1=enabled; 0=disabled)
4
EIF0
External interrupt 0 request flag (1=active; 0=inactive)
5
EIF1
External interrupt 1 request flag (1=active; 0=inactive)
6
T0F
Internal Timer/Event Counter 0 request flag (1=active; 0=inactive)
7
—
For test mode used only.
Must be written as "0"; otherwise may result in unpredictable operation.
INTC0 (0BH) Register
Bit No.
Label
0
ET1I
Control the Timer/Event Counter 1 interrupt (1=enabled; 0=disabled)
1
EADI
Control the ADC interrupt (1=enabled; 0:disabled)
2
ERTI
Control the real time clock interrupt (1=enabled; 0:disabled)
3, 7
Function
Unused bit, read as "0"
4
T1F
Internal Timer/Event Counter 1 request flag (1=active; 0=inactive)
5
ADF
ADC request flag (1=active; 0=inactive)
6
RTF
Real time clock request flag (1=active; 0=inactive)
INTC1 (1EH) Register
Rev. 1.30
112
March 15, 2011
Using Enhanced Holtek C
Bit No.
Label
0
REGCEN
1
CHPEN
2
3~7
Function
Enable/disable Regulator/Charge-Pump module. (1=enable; 0=disable)
Charge Pump Enable/disable setting. (1=enable; 0=disable)
Note: this bit will be ignored if the REGCEN bit is disabled
BGPQST
Bandgap quick start-up function
0: R short, quick start up
1: R connected, normal RC filter mode
Each time REGCEN changes from 0 to 1, that is when the regulator turns on,
this bit should be set to 0 and then set to 1 to ensure a quick start up. The
minimum time to keep the bit low should be about 2ms.
CHPCKD0~ Charge pump clock divider. These 5 bits form a clock divider with a division
CHPCKD4 ratio range of 1 to 32. Charge Pump clock = (fSYS/16) / (CHPCKD+1)
CHPRC (1FH) Register
REGCEN CHPEN
VOREG
Pin
OPA
ADC
Description
Complete module is
HiDisable disabled, OPA/ADC will have
Impedance
no Power
0
X
OFF
VDD
OFF
1
0
OFF
VDD
ON
3.3V
Active
Used when V DD is greater
than 3.6V
1
1
ON
2xVDD
ON
3.3V
Active
Use whefor VDD is less than
3.6V (VDD=2.2V~3.6V)
Bit No.
0
1~2
3
4~5
6
7
Rev. 1.30
Charge VOCHP
Regulator
Pump
Pin
Label
Function
Dual slope block (including input OP) power on/off switch.
ADPWREN 0: disable Power
1: Power source comes from the regulator.
Defines the ADC discharge/charge.
00: reserved
ADDISCH0~
01: charging - Integrator input connect to buffer output
ADDISCH1
10: discharging - Integrator input connect to VDSO)
11: reserved
ADCMPO
Dual Slope ADC - last stage comparator output.
Read only bit, write data instructions will be ignored.
During the discharging state, when the integrator output is less than the
reference voltage, the ADCMPO will change from high to low.
ADC integrator interrupt mode definition. These two bits define the ADCMPO
data interrupt trigger mode:
ADINTM0~ 00: no interrupt
ADINTM1 01: rising edge
10: falling edge
11: both edge
ADC OP chopper clock source on/off switch.
ADCCKEN 0: disable
1: enable (clock value is defined by ADCD register)
ADRR0
ADC resistor selection
0: (VINT, VCMP)= (4/6 VOREG, 1/6 VOREG)
1: (VINT, VCMP)= (4.4/6 VOREG, 1/6 VOREG)
113
March 15, 2011
Using Enhanced Holtek C
Bit No.
Label
0
1
2
ADCD0
ADCD1
ADCD2
3~7
—
Function
Defines the chopper clock. ADCCKEN should be enabled. The suggested clock
value should be around 10kHz.The chopper clock definitions are:
0: clock= (fSYS/32)/1
1: clock= (fSYS/32)/2
2: clock= (fSYS/32)/4
3: clock= (fSYS/32)/8
4: clock= (fSYS/32)/16
5: clock= (fSYS/32)/32
6: clock= (fSYS/32)/64
7: clock= (fSYS/32)/128
Reserved
ADCD (1AH) Register
The registers, ADCR and ADCD, are used to control the on/off function of the dual slope A/D
converter, charge/discharge setting, ADC resistor selection and the chopper frequency setting.
9.4 MCU Configuration Options
//-----------------------------------------------------------// Configuration Options:
//----------------------------------------------------------//Osc: RC
//fSYS: 4MHz
//Wake_Up PA.0-7: PA.0 Wake_Up
// PA.1-PA.7 Non Wake_Up
//Pull-high PA: PULL-HIGH
//Pull-high PB: PULL-HIGH
//Pull-high PC: PULL-HIGH
//Pull-high PD: PULL-HIGH
//PA Buzzer Function: BZ/BZB Disable
//Clock Source: T1
//Wdt: Disable
//WDT Clock Source: T1
//CLR WDT: One clear instruction
//WDT time-out period: 2^12/fs-2^13/fs
//LVR: Disable
//LVD: Disable
//Int Function: Disable
//LCD Driver Clock: IRCOSC/3
//LCD ON/OFF At HALT: LCD OFF At HALT
//LCD Duty: 1/3 duty(3 com)
//LCD Bias: 1/2 bias
//-----------------------------------------------------------
Rev. 1.30
114
March 15, 2011
Using Enhanced Holtek C
9.5 Program Flowchart
START
CALL INI_RAM
CALL INI_IO
SET F_ ON
Setup related registers
CALL SBR_ADC, test the discharge time
under fixed charge time conditions
Charge/discharge x 10 times, save the
average value to [R_TMR1H, R_TIR1L]
CALL SBR_TABLE, look up table for discharge
time related offset address and table data
CALL SBR_CALT, acquire the
binary pressure value and save
CALL SBR_DIS, LCD display
Y
N
Y
Rev. 1.30
F_HALT=0?
N
CALL SBR_KEY_SCAN
CLR LED_IO, LED turned off
CALL SBR_KEY_JUMP
HALT
Time up ?
CLR F_HALT, set the status of
each woken up register and I/O port
115
March 15, 2011
Using Enhanced Holtek C
SBR_CALT
Y
F_ZERO_OUTPUT=1?
Pressure value is 0.00
N
RET
Y
N
F_FULL_OUTPUT=1?
R_ADDR1-R_ADJUST_H
->R_ADDR1
{[R_TABLE1_H,R_TABLE1_L] - [R_TMR1_H,R_TMR1_L}*100
CLR R_TEMP0
CLR R_TEMP1
CLR R_TEMP2
{[R_TABLE1_H,R_TABLE1_L] - [R_TMR1_H,R_TMR1_L}*100/
(R_TABLE1-R_TABLE2)
N
TO0R_ADJUST_L
-> DATA0
N
N
R_ADDR1=
R_ADJUST_H>1?
Save the result as the calibration value
Y
Y
CLR F_ON
Y
C=1?
R_ADDR1=1
Y
Pressure value is 0.00
RET
F_ON=1?
R_ADDR1=
R_ADJUST_H>0?
N
Calculate the product of the decminal times
100 and the full scale value of each display unit
Pressure value is 0.00
Above result/100, obtain the product of the
decminal and the full scale value of each display unit
RET
Save the results from high to low into
[R_TEMP2, R_TEMP1, R_TEMP0]
Calculate the product of the integer and
the full scale value of each display unit
Save the result the decminal and integer
to [R_TEMP2, R_TEMP1, R_TEMP0]
B
Rev. 1.30
116
March 15, 2011
Using Enhanced Holtek C
B
[R_TEMP2, R_TEMP1, R_TEMP0]
/100/TABLE_PER
Y
Obtained value>999?
N
999> Obtained value>100?
Y
Setup the decimal flag and registers
N
LCD display “---”
100> Obtained value>10?
Y
Set the decimal flag
[R_TEMP2, R_TEMP1,
R_TEMP0]/10->
[DATA2, DATA1, DATA0]
N
10> Obtained value>1?
Y
Setup the decimal flag and registers
N
Obtained value<1?
Y
Set the decimal flag
N
[DATA2, DATA1, DATA0]
/TABLE_PER
DATA0<-TO0, DATA1<-TO1
RET
CALL DA999, convert the hexadecimal
value to a decimal number
R_LCD3 <- TO0
R_LCD2 <- TO1
R_LCD1 <- TO2
RET
Rev. 1.30
117
March 15, 2011
Using Enhanced Holtek C
SBR_KEY_SCAN
Initialise the debounce count units
Initialise the timer0 register, enable the timer
4ms time up?
N
Y
Disable timer0, clear the timer0 flag
Switch pressed?
F_KEY->F_KEY_TEM,
Restore the debounce value
N
N
Y
Set flag F_KEY to 1
Clear flag F_KEY to 0
F_KEY=F_KEY_TEM?
Y
Debounce count units minus 1
Debounce count unit = 0?
Y
N
F_KEY->F_KEY_PREV
F_KEY=F_KEY_PREV?
Y
SET F_REPEAT
CLR F_REPEAT
RET
Rev. 1.30
118
March 15, 2011
Using Enhanced Holtek C
SBR_KEY_JUMP
Y
N
F_KEY=0?
60S timing plus 1
CLR R_60S_L
CLR R_60S_H
60 time up?
N
F_REPEAT=0?
Y
Set flag F_HALT to 1
Units change, set flag, but the
other unit flags must not be changed
RET
RET
Rev. 1.30
119
March 15, 2011
Using Enhanced Holtek C
9.6 Original Program and Program Description
main.c
1
#include <ht46r74d-1.h>
2
#include “pubdef.h"
3
4
void InitialMCU(); // initial MCU
5
unsigned int SBR_ADC();
6
void SBR_CALT_LOOP();
7
void SBR_TABLE();
8
unsigned long SBR_Calculate();//calculate the pressure value with different unit
9
void SBR_Display(unsigned int); //display
10
void SBR_KEY_SCAN(); //detect key
11
void SBR_KEY_JUMP(); //deal with key
12
13
unsigned char CurState ; // current state
14
unsigned int Tmr1Count ; // TMR1 count
15
unsigned int DischargeTime ; // discharge time
16
17
#pragma rambank0
18
bit bHalt ; // halt flag
19
extern bit bKeyPrev ;
20
#pragma norambank
21
22
void main(void)
23
{
24
unsigned char Seconds ;
25
unsigned int TotalTime, num ;
26
unsigned long pressure ;
27
char i ;
28
29
InitialMCU() ;
30
CurState |= POWER_ON ; //set power on or wake up state
31
32
while(1)
33
{
34
Seconds = 0 ;
35
TotalTime = 0L ;
36
DischargeTime = 0 ;
37
38
// calculate the average value of discharge time - average of 10 times
39
for( i = 0 ; i < 10 ; i++ )
40
{
41
// get the discharge time Tc during the charge time Ti be fixed
42
TotalTime += SBR_ADC() ;
43
}
44
45
Rev. 1.30
DischargeTime = (TotalTime / 10) ; // get the average time
120
March 15, 2011
Using Enhanced Holtek C
46
while(1)
47
{
48
SBR_TABLE(); // to get the offset address of table with dichotomy
49
pressure = SBR_Calculate(); // calculate the pressure value with
50
// different unit
51
num = (unsigned int)pressure ;
52
SBR_Display(num); // display
53
54
if( bHalt ) //if at the mode of halt,jump to the halt mode
55
{
56
LED_IO = 0 ; // PA1
57
_halt(); //halt
58
bHalt=0; //wake up
59
bKeyPrev = 1; //set the previous key flag
60
_chprc = 0x63; //set 3.3V regular output
61
_adcr=0x41; //set the related registor
62
_adcd=0x07;
63
_tmr1c=0x88;
64
CurState = (PSI_STATE|POWER_ON) ; // set to 'psi' unit & power
65
// on/wake up
66
LED_IO=1;
67
break ;
68
}
69
70
SBR_KEY_SCAN(); //detect key
71
SBR_KEY_JUMP(); //deal with key
72
if(++Seconds == 50 ) //1S timing,jump to test the discharge time
73break ;
74 }
75}
76}
■ Program Description
main.c
1
Insert the header file ht46r74d-1.h to define the microcontroller register addresses
2
Insert the header file public.h to define the constants and declare the global variables
4~11
Declare the data types of all functions and parameters
13~15 Define the global variables
17~20 The bit type variable must be defined in RAM bank0, so a preprocessor #pragma
rambank0 and #pragma norambank must be added prior to/after the definition or
declaration.
22
Main program starts
24~27 Declare local variables
29
Call InitialMCU function, clear the RAM space and setup I/O ports
30
Set the current status to be POWER ON
33~75 Main loop. The program will not jump out after entering the loop.
34~36 Set initial variable values, reset Seconds, TotalTime and DischargeTime
39~43 Loop x 10, acquire the total discharge time Tc under fixed charge time conditions and
sum
Rev. 1.30
121
March 15, 2011
Using Enhanced Holtek C
45
Divide the ten times total discharge time by 10 to acquire an average time
46~47 Internal loop
48
Find the associated time and voltage from the VT table according to the average
discharge time as calculated above
49
Call function SBR_Calculate() to calculate the tyre pressure value corresponding to
the discharge time and subdivide the tyre pressure value into three decimal digits
according to the selected units.
52
Call function SBR_Display(num) and display the number on the LCD
54
If no switch is detected within 60 seconds, the system will enter the power-down
mode with the bHalt flag set to 1
55
System enters the power-down mode
56
Turn off the operating indicator (LED)
57
System enters the power-down mode until a switch is pressed to be wake-up and
return to the step following this location .
58~59 System returns here after being woken up and clears the pause flag to 0 and set the
switch flag to 1
60~63 Reset the system structure to a 3.3V voltage output, setup dual slope A/D converter
and clock initial values
64
Set the current status to have tyre pressure unit: PSI, system: POWER ON
66
Turn on the operating indicator LED
67
Jump back to the main loop, re-read the switch or discharge time
70
If the system is not in the power-down mode, continue to check if there are any switch
inputs, call function SBR_KEY_SCAN
71
Call function SBR_KEY_JUMP and check and process the switch input and setup
related flags
72
If one second has elapsed, return to the main loop to re-check the charge time
and status, or stay in the internal loop displaying the previous pressure value and
detecting the switch input.
subroutine.c original program
1 #include <ht46r74d-1.h>
2 #include “pubdef.h”
3 unsigned long PresUnit ;
4 unsigned char DischargeIdx ;
5 unsigned char AdjustValue ;
6 unsigned char AdjustIdx ;
7 unsigned char LcdBuf[0x10] @ 0x140 ;
8
9 #pragma rambank0
10 bit bLED_Dot1 ;
11 bit bLED_Dot2 ;
12 bit bKeyPrev ;
13 bit bKeyFlag ;
14 bit bRepeat ;
15 #pragma norambank
16
17 extern unsigned char CurState ; // current state
18 extern unsigned int Tmr1Count ; // TMR1 count
19 extern unsigned int DischargeTime ; // discharge time
20
Rev. 1.30
122
March 15, 2011
Using Enhanced Holtek C
21 const unsigned char LEDDigitalPattern[11] =
22 {
23 0x5f,0x48,0x3e,0x7c,0x69, /*0~4*/
24 0x75,0x77,0x58,0x7f,0x7d, /*5~9*/
25 0x20 /*’-’*/
26 } ;
27
28 const unsigned int VT_Table[TABLE_NUM] = {
29 /* ************* V-T table *************** */
30 31
32 0x197E, 0x180b, 0x16ce, 0x1590, 0x1453, /*0,5,10,15,20;;0~4mv*/
0x1315, 0x11d8, 0x109a, 0x0f5d, 0x0E1f, /*25,30,35,40,45;;5~9mv*/
0x0ce2, 0x0ba4, 0x0a66 /*50,55,60;;10~14mv*/
33 };
34 void InitialMCU()
35 {
36 char i ;
37 char *mptr ;
38
39 ClearMemory() ; // Clear RAM bank
40
41
42
_intc0 = 0;
43
_intc1 = 0 ; // interrupt disable
44
_chprc = 0x63; // set 3.3V regular output, clock divider=12
45
_adcr = 0x41; // set the related registor
46
_adcd = 0x07;
47
_tmr1c = 0x88; // set TMR1 : Timer mode, prescale stages: f(int1)=f(t1)
48
49
_pac=0xff; // set PA to input mode
50
_pbc=0xff; // set PB to input mode
51 LED_IO_C=0; // set PA.1 to output mode
52
LED_IO=1; // turn LED off
53
54
CurState = PSI_STATE ; // initial state : PSI unit
55}
Rev. 1.30
123
March 15, 2011
Using Enhanced Holtek C
■ Program Description InitialMCU
This function is to initialise the system.
3~6
Define the global variable PresUnit (pressure unit), Dischargeldx (the index number
where the discharge time is located), AdjustValue (adjustment value), Adjustldx (index
number of the adjustment value)
7
Define the LCD memory buffer from address 0x140 to 0x14F
9~15
Use the preprocessor to define the global variables bit type, which should be defined
in bank0 of the RAM. Lines 9 and 15 should be deleted if using the HI-TECH C
compiler.
17~19 Declare the used external variables: CurState, Tmr1Count, DischargeTime
21~26 Define the LED character constant table LEDDigitalPattern, where the representative
figures are ‘0’ ~ ‘9’ and ‘-‘
28~33 Define the VT table constant, Tc, this time is proportional to the air pressure
34~44 Function InitialMCU is to clear bank0 and bank1 of RAM to 0
Setup the initial values of the other registers; disable the interrupts, setup the 3.3V
regular output and set the clock divider to 12.
45
Set the ADCR register (0x18) to the discharge status with the power source provided
by the regulator
46
Set the ADCD register (0x1A), set the chopper frequency to ((fSYS/32)/128)
47
Set Timer 1 to the timer mode and the prescale stage as f(int1)=f(t1)
49~50 Set both the I/O port A and B to inputs
51
Set the operating indicator (controlled by the 1st bit of port A) to an output
52
Turn off the operating indicator
54
Set the current air pressure units to be PSI
Original Program SBR_ADC()
//----------------------------------------------//--- SBR_ADC --// get the discharge time Tc during the charge time Ti be fixed
// O/P: time
//----------------------------------------------1 unsigned int SBR_ADC()
2{
3
unsigned int TcTime ;
4
5
_t1on=0; // turn TMR1 off
6
_tmr0c=0x8f; // 32us(fSYS=4MHz), TMR0 -> timer mode, fSYS
7
_tmr0=0;
8
_adcr=0x4b; // at charge mode, ADC OP chopper clock source
9
_t0on=1; // TMR0 on
10
11
12
while(!_t0f) ; //charge and let Vc work over 4/6 VDSO, TMR0
//interrupt (delay)
13
_t0f=0;
14
_t0on=0;
15
_adcr=0x4d; // set : discharge mode
16
while(_adcmpo) ; // ADCMPO high->low if integrator output is less
17 // than the reference voltage
18
Rev. 1.30
_tmr0=0x83;
124
March 15, 2011
Using Enhanced Holtek C
19
_adcr=_adcr^0x06; // set : charge mode
20
_t0on=1; // trun TMR0 on
21
_t1on=0;
22 _tmr1l=0; // clear TMR1
23 _tmr1h=0;
24
while(!_t0f) ; // delay for charge
25
26 _adcr=_adcr^0x06; // set: discharge mode
27 _t1on=1; // TMR1 on, TMR0 off
28_t0on=0;
29_t0f=0;
30 while(_adcmpo) ; //discharge
31 _t1on=0; // TMR1 off
32
33 // return discharge time
34 TcTime = (unsigned int)(_tmr1h) ; // read TMR1 high byte
35 TcTime = (TcTime<<8) | _tmr1l ; // read TMR1 low byte and append to int
36 // variable
37 return( TcTime ) ; // get discharge time
38 }
■ Program Description
This function is to obtain the discharge time under a fixed charge time from the dual slope A/D
converter so as to obtain the air pressure value.
5
Disable timer1
6
Set Timer 0 to the timer mode, fSYS as the clock oscillator source with a division rate of
128 (when the system frequency is 4MHz, the clock has a period of 32us)
7
Clear the Timer 0 count register to 0
8
Enable the A/D, the A/D OP chopper and initiate the charging cycle
9
Enable Timer 0, time is 256x32us=8ms
11
Wait for Timer 0 to generate an overflow interrupt and detect using a polling method
(wait for fully charged condition)
13
Clear the interrupt flag
14
Disable Timer 0
15
Set the A/D OP chopper to the discharge cycle
16
Check if the comparator output has changed, which is the point where the value
is lower than the reference voltage. Stay in the loop until the comparator output
switches. At this point jump out of the loop. .
18
Set the counter register of Timer 0 (0x83)
19
Enable the A/D OP chopper and enter the charging cycle
20
Enable the Timer 0 timer function
21~23 Disable Timer 1, clear Timer 1 counter register to 0
Rev. 1.30
24
Wait for Timer 0 to generate an overflow interrupt (0xff-0x83+1) x32=4ms)
26
Enable the A/D OP chopper and enter the discharge cycle
27
Enable Timer 1
28
Disable Timer 0
29
Clear the Timer 0 interrupt flag
30
Check if the comparator output has switched which is the point where the voltage
is lower than the reference voltage. Stay in the loop until the comparator output
125
March 15, 2011
Using Enhanced Holtek C
switches and then jump out.
31
Disable Timer 1
34~35 Read the Timer 1 counter register contents (=discharge time)
37
Save the discharge time
Original Program SBR_TABLE
//---------------------------------------------------------//--- SBR_TABLE --// get the opposite offset address of table with dichotomy
// if DischargeTime >= VT_TABLE[i], then i-1 is the canditate
// the order in VT_TABLE[] is decreasing order
//----------------------------------------------------------1 void SBR_TABLE()
2{
3
char i ;
4
5
AdjustValue = 0 ; // adjust value
6
AdjustIdx = 0 ; // adjust index
7
8
for( i = 0 ; i < TABLE_NUM ; i++ )
9
{
10
if( DischargeTime >= VT_Table[i] ) // find the proper discharge time
11
{
12
DischargeIdx = !i ? i : i-1 ;
13
CurState &= ~KEY_TEMP ; // reset key temp flag
14
CurState &= ~FULL_OUTPUT ; // clear FULL output state
15
if( !i )
16
CurState |= ZERO_OUTPUT ; // set zero output
17
18
if( (CurState & POWER_ON) != 0 ) // power on state
19
CurState &= ~POWER_ON ; // clear bit
20
21
22
return;
}
23 }
24
25
// i = TABLE_NUM
26
DischargeIdx = TABLE_NUM -1 ;
27
CurState &= ~( KEY_TEMP | ZERO_OUTPUT) ; // reset key temp flag & zero output
28
CurState |= FULL_OUTPUT ; // set FULL output
29
if( (CurState & POWER_ON) != 0 )
30
{
31
CurState &= ~POWER_ON ;
32
AdjustIdx = DischargeIdx ;
33
}
34 }
Rev. 1.30
126
March 15, 2011
Using Enhanced Holtek C
■ Program Description
This function is used to find the discharge time using the VT table to find a value equal to or
close to the actual discharge time. There are 13 reference time values in the VT table, each
one corresponding to a different air pressure value. Save the time found to the reference time
variable and use this time as the table index reference pointer.
5~6
Clear the calibration value and pointer to 0
8~23
Loop, search for a value equal to or close to the actual practical discharge time in the
VT table. The table contains 13 premeasured pressure values corresponding to the
discharge time value, for which they can be checked in order from high to low is to
compare the first value of the table to the last one. If any eligible value is found, then
stop the comparison and return to the original calling location.
10~22 If the discharge time is larger than or equal to the table value, then it means the
stored reference pointer has been found. The record reference pointer (Dischargeldx)
is the index of the value location. Delete the switch flag. The discharge time will
not be smaller than the last value, so the air pressure will not exceed the highest
table value. Clear the flag FULL_OUTPUT(exceeds the highest air pressure). If the
discharge time is larger than or equal to the first table value, it means the air pressure
is lower than the 13 effective values in the table, so setting the flag ZERO_OUTPUT
means the air pressure is smaller than the lowest reference value.
18~19 If the current operating status is POWER ON, clear the POWER ON flag
21
Return to the original calling location
25
If progam execution arrives at this point, it means the discharge time is lower than the
table value (the air pressure is too high)
26
Setup the reference pointer (DischargeIdx) to be at the last table index location
27
Clear the KEY_TEMP and ZERO_OUTPUT flags
28
Setup the FULL_OUTPUT flag
29~33 If the current operating status is POWER ON, clear the POWER ON flag, setup the
calibration pointer
34
Return to the original calling location
■ Original Program SBR_CALCULATE
//----------------------------------------------//--- SBR_Calculate --// calculate pressure with different unit and pressure number
// O/P: pressure number
//----------------------------------------------1 unsigned long SBR_Calculate()
2{
3
unsigned long rtmp, rtmp1, Tslice ;
4
unsigned char rate ;
5
6
if( (CurState & ZERO_OUTPUT) == ZERO_OUTPUT ) // it's Zero output
7
{ //for zero output of sensor
8 bLED_Dot1 = 1 ; //to display 0.00
9
bLED_Dot2 = 0 ;
10
return(0L) ;
11 }
12
Rev. 1.30
13 if( (CurState & FULL_OUTPUT) == FULL_OUTPUT )
14 {
127
March 15, 2011
Using Enhanced Holtek C
15 DischargeIdx -= AdjustIdx ; //for full output of sensor
16
rtmp = 0 ;
17}
18
else
19
{
20
Tslice = (unsigned long)((VT_Table[DischargeIdx] – DischargeTime) *
21
100) ;
22
rate = (unsigned char)(Tslice / (VT_Table[DischargeIdx] -
23
VT_Table[DischargeIdx+1])) ;
24
25
if( CurState & POWER_ON )
26
{
27
CurState &= ~POWER_ON ; // clear flag
28
AdjustValue = rate ;
29
AdjustIdx = DischargeIdx ;
30
}
31
32
if( rate < AdjustValue )
33
{
34
if( DischargeIdx >= AdjustIdx )
35
{
36
bLED_Dot1 = 1 ; //to display 0.00
37
bLED_Dot2 = 0 ;
38
return(0L) ;
39
}
40
DischargeIdx--;
41
}
42
else rate -= AdjustValue ;
43
44
if( DischargeIdx < AdjustIdx ) // DischargeIdx<R_ADJUST_H
45
{
46
bLED_Dot1 = 1 ; //to display 0.00
47
bLED_Dot2 = 0 ;
48
return(0L) ;
49
}
50
51
DischargeIdx -= AdjustIdx ; // DischargeIdx > R_ADJUST_H
52
SBR_CALT_LOOP(); // O/P: PresUnit
53
rtmp = (PresUnit * rate) / 100 ;
54 }
55
56
SBR_CALT_LOOP();
57
rtmp += PresUnit * DischargeIdx ;
58
rtmp1 = rtmp / (PER * TABLE_PER) ; // 12 * 100 R_TO0, R_TO1 = rtmp1
59
Rev. 1.30
60
if( rtmp1 > 100 ) // rtmp1 > 100
61
{
128
March 15, 2011
Using Enhanced Holtek C
62
bLED_Dot1 = bLED_Dot2 = 0 ;
63
return(rtmp1) ;
64
}
65
if( rtmp1 > 10 ) // 100>= rtmp > 10
66
{
67
bLED_Dot1 = 0 ; //>10 & <100
68
bLED_Dot2 = 1 ;
69
70
return( rtmp / (10 * TABLE_PER) ) ;
}
71
72
bLED_Dot1=1;
73
bLED_Dot2=0;
74
return( rtmp / TABLE_PER ) ;
75 }
■ Program Description SBR_CALCULATE
This function is to calculate the air pressure value based on the above reference time, pointers
and actual discharge time along with the selected pressure unit. The calculation method
uses the thirteen time values in the VT table, which means that there are twelve equivalent
intervals from 0.00 pressure to the highest pressure value. Each pressure unit has its own
full scale value, so the nth interval pressure value is (n=0, 1,..12) n*(full scale value/12) while
the actual discharge time is not necessarily equal a reference time (and will be larger than a
reference time). Therefore this small part must be added. First calculate the percentage that
it occupies in the interval and then multiply it by the average pressure value of the interval.
As the calculated time uses char, long etc integer types variables (floating types could also
be considered) multiplication should be carried out first to amplify the value by 100 times. The
following formula is used:
rate = [(reference time – actual discharge time) *100] / [reference time – next reference time]
pressure1 = [rate * (full scale value/12)] /100 (rate and full scale values both multiplied by 100)
[reference time – next reference time] indicates the range of the actual discharge time, namely
reference time > actual discharge time >= next reference time
The full scale value in the program has been multiplied by 100 so as to add with pressure1,
therefore the final total value should be divided by 100.
The final total air pressure value = (n * (full scale value/12) + pressure1) / 100
The order of calculation in the program can be different however the principles are the same.
7~11
If the flag ZERO-OUTPUT is set, it means the discharge time exceeds the highest
value in the VT table (the air pressure is lower than the effective value.) In this case
the pressure value cannot be displayed. Set the display to be 0.00.
Return a value of 0.
13~17 If the flag FULL_OUTPUT is set, it means the discharge time is lower than the
smallest value in the VT table (the air pressure is higher than the effective value in
the table). With reference pointer minus calibration value pointer, set the air pressure
offset value to 0, and jump to line 57 to calculate the total air pressure value.
18~54 Neither ZERO nor FULL, which means the discharge time is located within the table
values. Execute the following line
20~23 Calculate the air pressure offset value rate. rate = ((reference time – actual discharge
time) * 100) / reference time difference = VT_Table [reference pointer] – VT_Table
[reference pointer +1]
Rev. 1.30
129
March 15, 2011
Using Enhanced Holtek C
25~30 If the current operating status is POWER_ON, clear the POWER_ON flag, set the
calibration value = air pressure offset rate. Set the calibration pointer.
32~41 If the air pressure offset rate is smaller than the calibration value, check the reference
pointer. If the reference pointer is smaller or equal to the calibration pointer, set the
air pressure display value to 0.00 with the first decimal point displayed. Return to the
calling place and decrease the reference pointer by one.
42
If the air pressure offset rate is larger than the calibration value, subtract the
calibration value from the air pressure offset value.
44~49 Check the reference pointer. If smaller than the calibration pointer, the display value
will be 0.00.
Set to display the decimal point, return to the calling location.
51
Subtract the calibration pointer from the reference pointer
52
Obtain the full scale value of the current air pressure unit
53
Calculate air pressure offset value = (air pressure offset value * full scale value) /100
(not yet divided by 12)
56
SBR_CALT_LOOP() obtains the full scale value of the air pressure unit
57~58 Air pressure total value = [air pressure offset value + (full scale value * reference
pointer)] / (12*100)
Dividing by 12 is to equal the full scale value divided into twelve average value
intervals. The 100 is to amplify during the calculation.
60
Determine whether to display the decimal point or not based on the air pressure total
value
60~64 If the air pressure value is larger or equal to 100 (three digits), then no need to
display any decimal points. Return this air pressure value.
65~70 If the air pressure value has a value between 99~10 (two digits), it is necessary to
display the second decimal point.
Re-calculate the air pressure total value by dividing by 10 (take three digits) only, and
return to the original calling location
Air pressure total value = [air pressure offset value + (full scale * reference pointer)] /
(12*10)
72~74 If the air pressure total value is between 9 and 1, display the first decimal point
Dot1=1
The air pressure total value does not need to be divided by 100 and now
air pressure total value = (air pressure offset value + (full scale value * reference
pointer)) / 12
Return to the original calling location
■ Original Program SBR_CALT_LOOP
//----------------------------------------------//--- SBR_CALT_LOOP --//SBR for SBR_CALT get the pressure of current unit
//----------------------------------------------1 void SBR_CALT_LOOP(void)
2{
3
switch( CurState & 0x0f ) // check bit0~4
4
{
5
6
7
8
Rev. 1.30
case PSI_STATE : // if unit is Psi
PresUnit = PSI_FULL ; // unsigned long
break ;
case BAR_STATE : //if Bar
130
March 15, 2011
Using Enhanced Holtek C
9
PresUnit = BAR_FULL ;
10
break ;
11
case KPA_STATE : //if Kpa
12
PresUnit = KPA_FULL_H16 ;
13
PresUnit = KPA_FULL | (PresUnit << 16) ;
14
break ;
case KGFCM2_STATE : //if Kgf/cm2
15
16
PresUnit = KGFCM2_FULL ;
17
break ;
18 }
19 }
■ Program Description SBR_CALT_LOOP
This function provides the full scale value in the current air pressure units
3
Analyse the current air pressure unit
5~7
Unit = PSI, give the variable PresUnit to the PSI full scale value
8~10
Unit = Bar, give the variable PresUnit to the Bar full scale value
11~14 Unit = Kpa, give the variable PresUnit to the Kpa full scale value
15~17 Unit = Kgf/cm2, give the variable PresUnit to the Kgf/cm2 full scale value
Original Program SBR_KEY_SCAN
//----------------------------------------------//--- SBR_KEY_SCAN --//--- detect key --//----------------------------------------------1 void SBR_KEY_SCAN()
2{
3
unsigned char Debounce_count ;
4
5
Debounce_count = R_20MS ; // detect key for 20mS
6
CurState &= ~KEY_TEMP ; // clear KEY_TEMP flag
7
_tmr0c = 0x0A0; // set TMR0 to Timer mode, internal clock (Intl.
8
Rev. 1.30
// RC), disable
9
while(1)
10
{ // wait TMR0 time out
11 _tmr0 = 208 ; // 4mS
12 _t0on = 1 ; // turn TMR0 on
13 while( !_t0f ) ; // wait internal timer/event counter 0
14 // interrupt flag
15 _t0f = 0 ; // clear internal timer/event counter 0 request flag (0b.5)
16
_t0on = 0 ; // turn TMR0 off
17
// check input key
18
bKeyFlag = KEY_IO ? 0 : 1 ; // check if key press or not(key no), PA.0
19
// set flag
20
if( (bKeyFlag && (CurState & KEY_TEMP)==0) ||
21
(!bKeyFlag && (CurState & KEY_TEMP)!=0) )
22
{
23
CurState ^= KEY_TEMP ; // toggle flag KEY_TEMP
24
Debounce_count = R_20MS; // renew
131
March 15, 2011
Using Enhanced Holtek C
25
continue ;
26
}
27
28
if( --Debounce_count == 0 )
29
break ;
30
}
31
32
Debounce_count = R_20MS;
33
if( bKeyFlag ) // input key
34
{
35
if( bKeyPrev ) // has pressed previously
36
bRepeat = 1; // set repeat flag
37
else
38
{
39
bRepeat =0;
40
bKeyPrev = 1;
41
}
42
}
43
else // no input key
44
{
45
if( bKeyPrev )
46
bRepeat = bKeyPrev = 0 ;
47
else
bRepeat = 1;
48
49
}
50
51
52 CurState &= ~(ZERO_OUTPUT | FULL_OUTPUT | KEY_TEMP) ; // clear flags
}
■ Program Description SBR_KEY_SCAN
Check if there is a switch input.
5
Set the detection time to be 20ms (Timer 0 generates an interrupt at every 4 ms,
Debounce_count=5, total of 5 times, 20ms). Detect a certain switch input within the
time (eliminate the key bounce mistake)
6
Clear the KEY_TEMP flag in the current operating status
7
Set the Timer 0 as timer mode; use the internal clock oscillator (12 KHz), prescaler 1:1
to pause timing
9~30
The loop, wait for a switch input
11
Set the interrupt interval of the Timer 0 to be 4ms (TMR0 = 208)(256-208)*(1/12 KHz)
=4ms
12
Enable Timer 0
13
The loop, wait for Timer 0 to generate an overflow interrupt
15
Clear the interrupt request flag of Timer 0
16
Disable Timer 0
18
Check if there is any switch input (port A bit 0) and setup flag bKeyFlag
20~26 If a switch input is detected this time but none is detected before this, or a situation
countering to this occurs, it means there is no effective switch input, change the
current operating status to be the switch status, reset the detection time back to the
start of the loop, continue to check the switch status
Rev. 1.30
132
March 15, 2011
Using Enhanced Holtek C
28~29 If the detection time has been down to zero, jump out of the loop
30
Or continue to detect the switch input
32
Set the detection to be 5 times
33~34 If the switch input is considered effective, analyze the switch status
35~36 If the switch has been input before, set the bRepeat flag (repeat)
37~41 Or clear the bRepeat flag, set the bKeyPrev flag (switch input occurred)
43~49 If there is no switch input, analyze the status as below
45~46 Or set the flag bRepeat
51
Clear the flags in the current operating status, ZERO_OUTPUT, FULL_OUTPUT and
KEY_TMEP
52
Return to the original calling location
■ Original Program SBR_KEY_JUMP
//----------------------------------------------//--- SBR_KEY_JUMP --//--- deal with key --//----------------------------------------------1 unsigned int ElapseTime ;
2
3 void SBR_KEY_JUMP()
4{
5 unsigned char tmp ;
6
7 if( !bKeyFlag ) // no input key
8 {
9 ElapseTime++ ;
10 if( ElapseTime >= 0x0bb8 ) // 60 seconds
11 bHalt = 1 ; // set halt flag
12return ;
13}
14
// has input key
15
ElapseTime = 0 ;
16
if( !bRepeat ) // if no repeat key, advance to next unit
17{
18
tmp = CurState & 0x0f; // current unit
19
tmp = (tmp == KGFCM2_STATE) ? PSI_STATE : (tmp << 1) ;
20
// change to next unit state
21
CurState &= 0xf0 ; // clear bit0 ~ 3
22
CurState |= tmp ; // set to next unit
23}
24 }
■ Program Description
1
Define ElapseTime as the time elapsed
7~13
When there is no switch input, accumulate the time and check if it has elapsed for 60
seconds
10~11 If it has elapsed for 60 seconds (0x0bb8=3000, 3000x20ms=60s) without any switch
input, set the flag bHalt = 1
Rev. 1.30
13
Return to the original calling place
14
If there is a switch input, clear the variable ElapseTime, analyze the switch
133
March 15, 2011
Using Enhanced Holtek C
16~23 If the switch input is not repeated, execute the following execution
Change the air pressure unit to be the next counting unit with Psi => Bar => Kpa =>
Kgf/cm2 by turns. Set the new unit to be in the variable of the current operating status.
24
If the switch input is repeated, no further action
■ Original Program SBR_DISPLAY
//----------------------------------------------------------------//--- SBR_Display --//--- display the presure value( 3 decimal digit and unit scaler) --// I/P: value = number to be displayed (decimal)
// write digit pattaern to LCD RAM buffer, 140H ~ 148H
//----------------------------------------------------------------1 const char divi[3] = { 100, 10, 1 } ;
2
3 void SBR_Display(unsigned int value)
4{
5 char i, num, pattern, flag ;
6 // display digit
7 for( i = flag = 0 ; i < 3 ; i++ ) // one digit uses 3 LCD RAM bytes
8 {
9 num = value / divi[i] ; // separate the input value
10 value = value % divi[i] ;
11 if( (num > 9) || (flag==1) )
12 {
13 flag = 1 ;
14 num = 10 ;
15 }
16
pattern = LEDDigitalPattern[num] ; // map the pattern of digit number
17
LcdBuf[3*i] = pattern & 0x7 ; // low nibble for d/e/f segment
18
LcdBuf[3*i+1] = (pattern >> 4) & 0x07 ; // high nibble for c/g/a segment
19
20
num = ((pattern & 0x08)!=0) ? 0x02 : 0 ; // b segment
21
switch( i )
22
{
23
case 0 : // first digit (left)
24
if( (CurState & BAR_STATE) != 0 ) num |= 0x01 ;
25
if( bLED_Dot1 ) num |= 0x04 ;
26
break ;
27
Rev. 1.30
case 1 : // second digit
28
if( (CurState & KPA_STATE) != 0 ) num |= 0x01 ;
29
if( bLED_Dot2 ) num |= 0x04 ;
30
break ;
31
case 2 : // third digit (right)
32
if( (CurState & KGFCM2_STATE) != 0 ) num |= 0x01;
33
if( (CurState & PSI_STATE) != 0 ) num |= 0x04 ;
34
break ;
35
}
36
LcdBuf[3*i+2] = num ; // write (display) the 3rd byte
134
March 15, 2011
Using Enhanced Holtek C
37
}
38 }
■ Program Description
1
Define the division which is 100, 10 and 1
3
This function will divide the input value into a decimal digit to be displayed on the
LCD
7~37
Loop, display three digits and the decimal point
9
Calculate in turn the digits in hundreds, tens, and ones (starting from the hundreds)
10
Keep the remaining value
11~15 If the digits exceeds 9 or the input value is larger than 999, the display will show ‘---’
flag = 1, record the value over 999; num = displayed value
16
Obtain the corresponding digit pattern from the table LEDDigitalPattern
17~18 Write the pattern to the LCD memory address, display the digit, write the three bytes
of the LCD memory to each of the digit pattern which refers to the LCD front pattern.
Bits 0, 1 and 2 of the first byte stored segment f, e, d; Bits 0, 1 and 2 of the second
byte store segment a, g, c; Bit 1 of the third byte stores segment b and the other
bytes store the first and second decimal points and the air pressure unit name .
20
Obtain the segment b value from the pattern
21~35 According to their values determine if dot1, dot2 and the units are to be displayed .
If it is in hundreds (i=0), analyse whether to display the first decimal point and the
BAR unit. If it is in tens (i=1), analyse whether to display the second decimal point
and the KPA unit. If it is in ones (i=2), analyse whether to display the KGF/CM or PSI
unit.
36
Write to the third data byte of the LCD memory
■ Appendix
N/m2 (Pa)
kgf/m2
N/m2 (Pa) 1
2
kgf/m
kgf/cm
98.0665*10
bar
1*105
bar
atm
0.101972 10.1972*10-6 1*10-5
9.80665
2
kgf/cm2
1
3
1*10
1*10
4
10197.2
5
-4
mmH2O
0.986923*10-5 0.101972
9.80665*10
-5
9.67841*10
-5
1*10
lb/in2,psi
mmHg
7.50062*10-3 145.038*10-6
-8
3
0.0735559
0.00142233
1
0.980665
0.967841
10*10
735.559
14.2233
1.01972
1
0.986923
10.1972*103 750.061
14.5038
atm
1.01325*10
10332.3
1.03323
1.01325
mmH2O
0.101972
1*10-8
1*10-4
9.80665*10-5 9.67841*10-5 1
mmHg
133.322
13.5951
0.00135951 0.00133322
0.00131579
13.5951
1
0.0193368
0.0703072
0.0680462
703.072
51.7151
1
lb/in2,psi 6.89476*103 703.072
0.0689476
1
3
10.3323*10 760
14.6959
73.5559*10-3 1.42233*10-3
Note: Atmospheric pressure (at) = 1kgf/cm2
The pressure indicated by H2O uses the density value of pure water at 4° C as the standard.
Rev. 1.30
135
March 15, 2011
Using Enhanced Holtek C
Chapter 10 Mixed Language –Assembly and C
When implementing control of external peripherals, using assembly rather than C may result
in higher execution efficiency. In such cases it may be beneficial to take a mixed language
approach to the application program. One way to do this is to use inline assembly in C, a
method which has been described in Chapter 4.9.3. The other method is to use a function
call method. This chapter will introduce how to implement these methods by calling assembly
language from within C and also calling C from within assembly language. The following items
and rules should be followed otherwise some functions may not execute properly.
→ Naming of variables, functions and parameters
→ Parameter passing
→ Return value setup
10.1 Naming of Variables, Functions and Parameters
■ Difference in Names
→ Words in C are Case-sensitive. For example, count and Count are considered as two
different words.
→ Words in assembly language are Case-insensitive. For example, Length and length have
the same meaning.
■ Global variables and function names after compilation
→→ When compiling global variables and functions with C, an underscore character will be
added in front of the original name.
The global variable count will become _count after compilation.
The global variable Length will become _Length after compilation.
The function GetTotalSize() will become _GetTotalSize() after compilation.
→→ After the assembly program has been compiled, the name will be changed to upper case,
such as
Variable count will be changed to COUNT
Variable Length will be changed to LENTGH
Function GetTotalSize() will be changed to GETTOTALSIZE()
■ Function Parameter Names after compilation
The function parameter name will be changed to the same name as the function itself after
compilation but will be attached with an index number. For example, the parameter x in the
function char GetSum(char x, char y) will be changed to GetSum0 while the parameter y
will become GetSum1. When C calls functions, ex. z = GetSum(1,4), the C compiler will
save the first parameter value 1 to the variable GetSum0, and the second parameter value
4 to GetSum1.
10.2 Parameter Passing
As the MCU stack cannot be used by the application program, the C compiler will save the
function parameters to the RAM Data Memory during parameter passing. No matter what type
the data is, they will all be defined in the byte format. For example, for void SetPos(int xpos,
in typos), the data parameter data type xpos and ypos is int (2 bytes) and will be changed to
SetPos0 and SetPos1 for which the format defined in the RAM Data Memory is:
SetPos0 DB 2 dup(?) ; xpos
SetPos1 DB 2 sup(?) ; ypos
The function SetPos will read the parameter value from the variable SetPos0 and SetPos1.
Rev. 1.30
136
March 15, 2011
Using Enhanced Holtek C
10.3 Return Value Setting
The C return value should, according to the return data type, decide which resources to use
for transmission media. The table below lists the registers or variables where the returns
values are saved.
Return Type
Return Value
LBLW
HBLW
LBHW
HBHW
void
0
—
—
—
—
char
1 (byte)
ACC
—
—
—
int/short
2 (byte)
ACC
RH
—
—
long/float
4 (byte)
ACC
RH
RM
RU
ACC A register
RH, RM, RU variable
Low bit character and low byte Return value Low Byte of the Low Word (LBLW)
Low bit character and high bye Return value High Byte of the Low Word (HBLW)
High bit character and low byte Return value Low Byte of the High Word (LBHW)
High bit character and high byte Return value High Byte of the High Word (HBHW)
10.4 Calling Assembly Functions from the C Program
To call functions from different language programs, the rules for calling functions from C and
defining the called functions and variables using assembly are as follows.
Assembly Language Program Function Definition Rules
→→ Add an underscore character prior to the function name and declare it as a public variable
(A-1)
→→ If the function includes parameters, setup the corresponding variables in RAM bank0 and
declare them as public variables (A-2)
→→ If the function includes return values which are int/short data types, then declare the
variable RH as an external variable. If the data types are long/float, then declare RH, RM
and RU as external variables (A-3).
→→ Set the corresponding variables, A, RH, RM or RU (A-4) before the function returns
according to the data type of the return value.
Rev. 1.30
137
March 15, 2011
Using Enhanced Holtek C
Ex.
EXTERN RH: byte ;; declare the high byte of the return value as an external value
(A-3)
PUBLIC_DISPLACE ;; add an underscore character to the beginning of the function
name and declare it as public (A-1)
PUBLIC DISPLACE0, DISPLACE1 ;; declare the parameters as public variables (A-2)
RAMBANK 0 DISPDATA ;; define the RAM to save the parameters as RAM bank 0
(A-2)
DISPDATA .section ‘data’ ;; (A-2)
DISPLACE0 DB ? ;; define the first parameter row (char, 1 byte) (A-2)
DISPLACE1 DB2 dup(?) ;; define the second parameter col (int, 2 byte) (A-2)
RESULT DB ? ;; execution result, low byte of the temporary variable
;; define function _DISPLACE
CODE .section ‘code’
_DISPLACE:
CLR [0Ah].0 ;; clear the CF flag
RLA DISPLACE0 ;; read the first parameter row, shift left one bit, save to A
ADD A, DISPLACE1 ;; read the low byte of the second parameter col and add
to A
MOV RESULT, A ;; save the low byte of the result to the temporary variable
MOV A, 0
ADC A, DISPLACE1[1] ;; add the high byte of the second parameter
MOV RH, A ;; save the high byte of the return value to RH (A-4)
MOV A, RESULT ;; save the low byte of the return value to A (A-4)
RET
■ Calling Rule of C
→ Uses capital letters to define and declare the called function name (C-1)
→→ Call the function (C-2)
Example:
extern int DISPLACE(char row, int col) ; // uses capital letter to define the function
name (C-1)
void main( )
{
int disp ; // return value
disp = DISPLACE(10, 20) ; // call the function (C-2)
}
In the above example, the return value is 40 after C calls DISPLAY(10, 20)
10.5 Calling C Function from Assembly Program
■ Calling Rule of C
→ Uses capital letters to define and declare the called function name (C-1)
Example:
int DISPLAY(char row, int col) ; // declare the function type (C-1)
int DISPLAY(char row, int col) // define function (C-1)
{
int retval ;
retval = (int)(row << 1) + col ;
return retval ;
}
Rev. 1.30
138
March 15, 2011
Using Enhanced Holtek C
■ Assembly Language Program Function Definition Rules
→ Declare the function name starting with underscored letters to be external functions (A-1)
→ If the function includes parameters, declare all the corresponding variables to be external
variables (A-2)
→ If the function includes return values whose data type is int/short, declare the variable RH
to be an external variable. If the data type is long/float, declare RH, RM, and RU to be
external variables (A-3)
→ Call the C function and read the return values form A, RH, RM or RU (A-4)
Example:
EXTERN RH:byte ;; declare the high byte of the return value as an external variable
(A-3)
EXTERN_DISPLACE: near ;; add underscored letters to function names and declare
them to be external (A-1)
EXTERN DISPLACE0: byte ;; declare parameters as external variables (A-2)
EXTERN DISPLACE1: byte ;; declare parameters as external variables (A-2)
;; call functions _DISPLACE
CODE .section ‘code’
Start :
MOV A, 10h
MOV DISPLACE0, A ;; save the value to the first parameter row
MOV A, 20h
MOV DISPLACE1, A ;; save to the col low byte of the second parameter
CLR DISPLACE1[1] ;; set the high byte of the second parameter to 0
CALL _DISPLACE ;; call the C function _DISPLACE
;; the return value 40 of the C function will be saved in A, RH by 0 (A-4)
……
RET__
Rev. 1.30
139
March 15, 2011
Using Enhanced Holtek C
Holtek Semiconductor Inc. (Headquarters)
No.3, Creation Rd. II, Science Park, Hsinchu, Taiwan
Tel: 886-3-563-1999
Fax: 886-3-563-1189
http://www.holtek.com.tw
Holtek Semiconductor Inc. (Taipei Sales Office)
4F-2, No. 3-2, YuanQu St., Nankang Software Park, Taipei 115, Taiwan
Tel: 886-2-2655-7070
Fax: 886-2-2655-7373
Fax: 886-2-2655-7383 (International sales hotline)
Holtek Semiconductor Inc. (Shenzhen Sales Office)
5F, Unit A, Productivity Building, No.5 Gaoxin M 2nd Road, Nanshan District, Shenzhen, China 518057
Tel: 86-755-8616-9908, 86-755-8616-9308
Fax: 86-755-8616-9722
Holtek Semiconductor (USA), Inc. (North America Sales Office)
46729 Fremont Blvd., Fremont, CA 94538, USA
Tel: 1-510-252-9880
Fax: 1-510-252-9885
http://www.holtek.com
Copyright© 2011 by HOLTEK SEMICONDUCTOR INC.
The information appearing in this Data Sheet is believed to be accurate at the time of publication. However,
Holtek assumes no responsibility arising from the use of the specifications described. The applications
mentioned herein are used solely for the purpose of illustration and Holtek makes no warranty or
representation that such applications will be suitable without further modification, nor recommends the use
of its products for application that may present a risk to human life due to malfunction or otherwise. Holtek's
products are not authorized for use as critical components in life support devices or systems. Holtek reserves
the right to alter its products without prior notification. For the most up-to-date information, please visit our
web site at http://www.holtek.com.tw.
Rev. 1.30
140
March 15, 2011