October 1, 2015 The C-Language ready MCU. [email protected] Introduction The C...
-
Upload
margery-conley -
Category
Documents
-
view
215 -
download
0
Transcript of October 1, 2015 The C-Language ready MCU. [email protected] Introduction The C...
April 21, 2023
The C-Language ready MCUThe C-Language ready MCU
Introduction
The C Programming Language is a powerful, flexible and potentially portable high-level programming language.
The C language may be used successfully to create a program for an 8-bit MCU, but to produce the most efficient machine code, the programmer must carefully construct the C Language program.
The programmer must not only create an efficient high level design, but also pay attention to the detailed implementation.
C Language
Facts about the C language
Excellent programming tool for Microcontrollers
C is a HLL that deeply interacts with the underlaying computer hardware
C is an easily understood language
Is a programming language widely standardized
Is very productive
Allows code re-use and code borrowing
Allows hardware abstraction maintainability
Assembly vs. C
A compiler is no more efficient than a good assembly programmer.
It is much easier to write good code in C which can be converted in to efficient assembly code than it is to write efficient assembly code by hand.
C is a means to an end and not an end itself.
ANSI C for 8-Bits MCUs
Pure ANSI C is not always convenient for embedded systems because:
Embedded systems interact with hardware. ANSI C provides extremely crude tools for addressing registers at fixed memory locations.
Almost all embedded systems use interrupts
ANSI C has various type promotion rules that are absolute performance killers to an eight-bit machine.
Some microcontroller architectures don’t have hardware support for a C stack.
Many microcontrollers have multiple memory spaces
One should use standard C as much as possible...
However, when it interferes with solving the problem at hand, do not hesitate to bypass it.
- Nigel Jones
Embedded vs. Desktop Programming
Main characteristics of an Embedded progamming environment:
• Limited RAM
• Limited ROM
• Limited stack space
• Hardware oriented programming
• Critical Timing (ISR, tasks, ...)
• Many different pointer kinds (far/near/rom/uni/paged/...)
• Special keywords/tokens (@, interrupt, tiny, ...)
Compiler Requirements
.h.h
.c.c
.cpp.cpp
.o.o
listinglisting
Compiler
• ROM-able code
• Optimized code
• Re-entrant code
• Support for Different Member in CPU Family
• Support for different memory models
• Non Obvious optimization
Compiler’s little Details
While choosing a compiler, you must remember that the Devil is in the details
Nice features that can make a huge difference: Inline Assembly Interrupt Functions Assembly Language Generation Standard Libraries Startup code
C Example for Embedded Systems
The Hello World Application for the HC08
#include <stdio.h>
void main(void){printf (“Hello World!\n”);while(1);
}
• Standard libraries
• Startup code
- Startup code is an extra piece of software that executes prior to main().
- A standard set of function libraries. These include various routines like printf, memcpy, strcmp, scanf and so on.
Example #1
Startup Routine
The startup code is generally written in assembly language and linked with any executable that you build. It prepares the way for the execution of programs written in a high-level language.
1. Disable interrupts
2. Copy any initialized data from ROM to RAM
3. Zero the uninitialized data area
4. Allocate space for and initialize the stack
5. Create and initialize the heap (if available)
6. Enable interrupts
7. Call main()
Standard Library
Performing Input/Output using the C library functions
getchar gets printf putchar puts scanf sprintf sscanf.
#include <stdio.h>
void main(void){printf (“Hello World!\n”);while (1);
}
All input/output performed by C library functions is supported by underlying calls to getchar and putchar.
The C source code for these and all other C library functions are commonly included
Some natural Questions...
After seeing the previous code, some natural questions may arise:
Where is my code? Where are my variables? How do I access I/O Registers? How do I handle interrupts?
Where is my code?
In the PRM file, you can define where you want to allocate each segments you have defined in your source code.
In order to place a segment into a specific memory area; just add the segment name in the PLACEMENT block of your PRM file.
The Linker Parameter File (PRM)
Where are my variables?
The variables are placed into the Default_RAM PLACEMENT unless otherwise stated with a #pragma...
It is important to define a segment into the Zero Page RAM ($40 -$FF) to place the most frequently used variables.
This way, the compiler will optimize the code using direct addressing mode (8-bit address) instead of extended mode (16-bit address).
How to access I/O Registers?
Many I/O and control registers are located in the direct page and they should be declared as such, so the compiler can use the direct addressing mode where possible.
One of the first questions that arises when programming embedded is:
How do I access I/O Registers?
The answer is as simple or complicated as you want...
Defining I/O Registers
One common and very useful form is:#define PortA ( * ( volatile unsigned char * ) 0x0000 )
This makes PortA a variable of type char at address 0x0000
This is a compiler-specific syntax...
It is more readable, but we pay the price loosing portability.
An easier way to do this is:
volatile unsigned char PortA @0x0000;
How do I handle interrupts?
The CodeWarrior compiler provides a non-ANSI compliant way to specify directly the interrupt vector number in the source:
Vector Number
Vector AddressVector
Address Size
0 0xFFFE - 0xFFFF 2
1 0xFFFC – 0xFFFD 2
2 0xFFFA – 0xFFFB 2
... ... ...
n 0xFFFF – ( n*2 ) 2
interrupt 17 void TBM_ISR (void){
/* Timebase Module Handler*/
}
Introduction to CodeWarrior
Let’s see how to...
• Create empty project from stationary• Add and remove files from a project• Startup Code• Default.prm Settings• Use of file editor• Compiling (successful and unsuccessful)• Enable debugging and debugging a project• Setting a breakpoint• Viewing variables in debugger
Example #2
Data types Facts
• The greatest savings in code size and execution time can be made by choosing the most appropriate data type for variables.
• The natural internal data size for 8-bit MCU is 8-bits (one byte), whereas the C preferred data type is ‘int’.
• 8-bit machines can process 8-bit data types more efficiently than 16-bit types.
• “int” and larger data types should only be used where required by the size of data to be represented.
• Double precision and floating point operations are particularly inefficient and should be avoided wherever efficiency is important.
Scalar Types for the HC08
The ANSI standard does not precisely define the size of its native types, but CodeWarrior does...
All scalar types (except char) are signed by default
Example: ‘int’ = ‘signed int’
0 255
Data Type Selection
There are 3 Rules for Data Type Selection on 8-bit MCUs:
• Use the smallest possible type to get the job done.
• Use unsigned type if posibble.
• Use casts within expressions to reduce data types to the minimum required.
Modifiers
Three key words, together, allow us to write not only better code, but also tighter code:
static
volatile
const
Static Variables
• The variable doesn’t disappear between successive invocations of a function.
• When declared at the module level, it is accessible by all functions in all the module, but by no one else.
Note:
These variables won’t be stored in the Stack.
When applied to variables, static has two primary fuctions:
Static variable Example
FILE1.c
#include <FILE2.h> includes functions contained in file FILE2.c
void main (void){
MyFunction(); included in FILE2.c
MyFunction(); included in FILE2.c
}
FILE2.c
void MyFunction (void){ Definition of MyFunction in FILE2.C
static char myVar = 0; local variable declared static
myVar = myVar + 1;
}
Before entering to MyFunction the first time, myVar = 0
Before entering to MyFunction for the second time:
myVar = 1
The static Variable keeps its value even though myVar is local
Static Functions
Features: • Only callable by other functions within its module.• Good structured programming practice.• Can result in smaller and/or faster code.
Advantages: Since the compiler knows at compile time exactly what functions can call a given static function, it may strategically place the static function such that may be called using a short version of the call or jump instruction.
Volatile Variables
In embedded systems, there are two ways this can happen:
• Via an interrupt service routine• As a consequence of hardware action
A volatile variable is one whose value may be changed outside the normal program flow.
It is very good practice to declare volatile all Peripheral Registers in embedded devices.
Volatile variables are never Optimized
Access to variables defined as volatile are never optimized by the compiler !!!
volatile unsigned char PORTA @0x00;volatile unsigned char SCS1 @0x16;unsigned char value;
void main(void){
PORTA = 0x05; /* PORTA = 00000101 */ PORTA = 0x05; /* PORTA = 00000101 */ SCS1; value = 10; }
MOV #5,PORTALDA #10STA @value
Without Volatile keyword
MOV #5,PORTAMOV #5,PORTALDA SCS1LDX #10STX @value
With Volatile keyword
volatilevolatile
Volatile variable Example
/* MC68HC908GP20/32 Official Peripheral Register Names */
volatile unsigned char PORTA @0x0000; /* Ports and data direction */volatile unsigned char PORTB @0x0001;volatile unsigned char PORTC @0x0002;volatile unsigned char PORTD @0x0003;volatile unsigned char PORTE @0x0008;
volatile unsigned char DDRA @0x0004; /* Data Direction Registers */volatile unsigned char DDRB @0x0005;volatile unsigned char DDRC @0x0006;volatile unsigned char DDRD @0x0007;volatile unsigned char DDRE @0x000C;
volatile unsigned char PTAPUE @0x000D; /* Port pull-up enables */volatile unsigned char PTCPUE @0x000E;volatile unsigned char PTDPUE @0x000F;
Const variables
The compiler keeps the program memory address of that location. Since it is in ROM, its value cannot be changed.
An initialization value must be declared.
Example:
const double PI = 3.14159265;
The Declaration const is applied to any variable, and it tells the compiler to store it in ROM code.
Const constrains
• Some compilers create a genuine variable in RAM to hold the const variable. On RAM-limited systems, this can be a significant penalty.
• Some compilers, like CodeWarrior, store the variable in ROM. However, the “read only” variable is still treated as a variable and accessed as such, typically using some form of indexed addressing (16-bit). Compared to immediate addressing (8-bit), this method is normally much slower.
Const volatile variables
Can a variable be both, const and volatile?
This modifier form should be use on any memory location that can change unexpectedly (volatile) and that is read-only (const).
Yes!Yes!
The most obvious example of this is a hardware status register:
/* SCI Status Register */
const volatile unsigned char SCS1 @0x0016
MC68HC908GP32
TBM
ADC
KBI
COP
LVI
BRK
MON
SCI
SPI
TIM1
TIM2
PO
RT
AP
OR
TB
PO
RT
CP
OR
TD
PO
RT
E
8
8
7
8
2
CPU08
Flash
RAM
SIM
IRQ
CGMC
Upward HC05 Object Code Compatible
512 Bytes RAM
32,292 Bytes Flash
Single-Wire Development Interface
Address-Match Hardware Breakpoints
Reset / Interrupt Priority Control
External Interrupt
Watchdog
Low-Voltage Inhibit
32kHz Clock Generator Module
Time Base Module
8 Keyboard Interrupts
8 Channel / 8-BitAnalog-to-Digital Converter
33 Bi-directional I/OAll Ports Pins Rated for
• 10mA Sink• 10mA Source
Dual 2 Channel 16-Bit Timers• Input Capture• Output Compare• Pulse Width Modulation
Asynchronous SerialCommunications Interface
Synchronous SerialPeripheral Interface
DIP 40, QFP 44
HC08GP32 Memory Organization
Can Perform Data Operationson Program Memory!
(No Special I/O Instructions!)
Program and Data MemoryALL Addressable from Same Memory Map!(Easy to Use!)
Direct Bit Manipulationin Page 0 Memory
(Fast and Code Space Efficient!)
No Special Memory Pages!(Easy to Use!)
Memory-MappedRegisters & Peripherals!(No Special I/O Instructions!)
PeripheralRegisters
RAM
$0000
$003F$0040
$023F$0240
ROM orFLASH
Vectors
Monitor ROM
$FFFF
$FF80
$FE10Control Registers
$FE00
Unimplemented$7FFF$8000
32K
FLASH
512B
RAM
CPU08 Register Model
Index Register (X)16-bit
16-bit
16-bit
Easier Signed Arithmetic V
X X X X X
0 0 0 0 0 1 1
Accumulator (A)
Stack Pointer (SP)
Program Counter (PC)
7 0
7 0
Condition Code Register (CCR)1 1 H I N Z C
Carry/Borrow (MSB)ZeroNegative (MSB = 1)Interrupt MaskHalf-Carry (for BCD)
15
Two’s Compliment Overflow
Index Register (HX)XH
CPU08 Registers
The accumulator is a general purpose 8-bit register. The CPU uses the accumulator to hold the operands and results of operations.
Index Register
Accumulator
The CPU08 has 5 registers which are not part of the memory map
The 16-bit index register is called H:X and is used by indexed addressing modes to determine the effective address of an operand. The index register can access a 64K byte address space in this mode.
The lower byte X is used to hold the operand for the MUL and DIV instructions. H:X can also serve as a temporary data storage location.
CPU08 Registers
The 16-bit stack pointer is used to hold the address of the next available location on the stack. The CPU uses the contents of the stack pointer register as an index to access operands on the stack in stack pointer offset addressing modes.
The stack can be located anywhere where there is RAM in the 64K byte address space.
The SP can also be used as an index like HX
Stack Pointer
CPU08 Registers
Program Counter The 16-bit program counter contains the address of the next instruction or operand to be fetched. The program counter can access a 64K byte address space.
Condition CodeRegister
The 8-bit condition code register contains the global interrupt mask bit and five flags that indicate the results of the instruction just executed.
Bits 5 and 6 are permanently set to logic 1.
HC08 Addressing Modes
Inherent This instructions have no operand to fetch and require no operand address. Most are one byte long.
Immediate The operand for immediate instructions is contained in the bytes immediately following the opcode. Immediate instructions therefore have constant operands.
The CPU08 has 16 different addressing modes
HC08 Addressing Modes
Direct Direct instructions are used to access operands in the direct page, i.e. in the address range $0000 to $00FF. The high-order byte of the address is not included in the instruction, thus saving one byte and one execution cycle compared to extended addressing.
Extended Extended instructions can access operands at any address in a 64K byte memory map. All extended instructions are 3 bytes long.
Relative All conditional branch instructions use relative addressing to evaluate the effective address. If the branch condition is true, the CPU evaluates the branch destination by adding the signed byte following the opcode to the program counter. The branch range is –128 to +127 bytes from the address after the branch instruction.
HC08 Addressing Modes
Indexed Indexed instructions use the contents of the 16-bit index register HX to access operands with variable addresses, such as variables accessed through a pointer.
There are five modes of indexed addressing:
• No offset
• 8-bit offset
•16-bit offset
• No offset w/ post increment
• 8-bit offset w/ post increment
HC08 Addressing Modes
Stack pointer Stack pointer instructions are similar to indexed instructions only they use the contents of the stack pointer as an address of the operand instead of the index register.
There are two modes of stack pointer addressing:
• 8-bit offset
• 16-bit offset
Stack pointer instructions require one extra byte and one extra execution cycle compared to the equivalent indexed instruction.
The Stack Pointer Importance
A Stack Pointer Register supports very key features of C:
• Passing variables to subroutines
• Allows the use of recursion
• Is the base of Automatic variables
typedef struct {unsigned char ID;unsigned short Time;
} ObjectType;
void foo (unsigned char value) {
volatile ObjectType instance;instance.ID = value;
}
foo:B00B A7FB AIS #-3B00D 9EE701 STA 1,SPB010 A707 AIS #3B012 81 RTS
Assembly:
HC08 Addressing Modes
Memory to Memory
Memory to memory instructions copy data from one location to another. One of the locations is always in the direct page.
There are four modes of memory to memory instructions:
• Move immediate to direct
• Move direct to direct
• Move indexed to direct with post increment
• Move direct to indexed with post increment
Time Reference Program
Example #3
Let’s make a program to output a 1 Hz square signal through Port C of the 68HC908GP32
Assume: XTAL = 4.9152MHz
The TBM on the MC68HC908GP32
Time Base Module (TBM)
The TBM will generate periodic interrupts at user selectable rates using a counter clocked by the external crystal clock. The TBM uses 15 divider stages, eight of which are user selectable.
• User selectable oscillator clock source enable during stop mode to allow periodic wakeup from stop
• The Time Base Module Only has One Register for Status and Control
TBM Programming Sample
2 2 2
TBON
2 2 2 2 2 2
CGMXCLK
TB
R2
TB
R1
TB
R0
TBIF
32.768kHz
0 0 1
TBON
2 2 2 2
2 2
Signal the event
Turn On the TBM
Select Timebase Rate( 8,192 for this example )
250ms0 0 0 0 0 10 1 00 1 11 0 01 0 11 1 01 1 1
8
1
6
3
2
6
4
1
28
2
04
8
8
19
2
3
27
68
Time Base Control Register(TBCR)
TBIF — Timebase Interrupt FlagThis read-only flag bit is set when the timebase counter has rolled over.
1 = Timebase interrupt pending0 = Timebase interrupt not pending
TACK— Timebase ACKnowledgeThe TACK bit is a write-only bit and always reads as 0. Writing a logic 1 to this bit clears TBIF, the timebase interrupt flag bit. Writing a logic 0 to this bit has no effect.
1 = Clear timebase interrupt flag0 = No effect
TBIE — Timebase Interrupt EnabledThis read/write bit enables the timebase interrupt when the TBIF bit becomes set. Reset clears the TBIE bit.
1 = Timebase interrupt enabled0 = Timebase interrupt disabled
TBON — Timebase EnabledThis read/write bit enables the timebase. Timebase may be turned off to reduce power consumption when its function is not necessary. The counter can be initialized by clearing and then setting this bit. Reset clears the TBON bit.
1 = Timebase enabled0 = Timebase disabled and the counter initialized
Test bit should always be 0
TBR2:TBR0 — Timebase Rate Selection
These read/write bits are used to select the rate of timebase interrupts.
See Rate Selection Table
Building the TBM C module
Defining the TBM Register Object:
#define TBCR *((volatile BYTE *)0x1C)typedef unsigned char BYTE;
volatile BYTE TBCR @0x1C;
Definitions in “iogp20_32.h”
Main Program
#include "hidef.h"#include "iogp20_32.h"
#define COUNT 75 /* Interrupts per sec */unsigned char cCounter=0x00; /* Interrupt Events Counter */
void main(void) {CONFIG1 = 0x0B; /* COP dis, STOP En, LVI En @5v */CONFIG2 = 0x03; /* SCI using Int Clk, Osc En @STOP */
DDRC = 0xFF; /* Configure PortC as Output */PORTC = 0xFF; /* Initialize PortC */
TBCR = 0x04; /* Configure TimeBase Status & Control RegTBM OFF & interrupt enabledSelect Timebase Rate (Div 2^15) @XTAL=4.9152MHz -> Freq=150Hz */
cCounter = COUNT; /* Initialize the Counter */ EnableInterrupts;
TBCR |= TBON /* Turn TBM on */while(1);
}/* END main() */
Creating a Interrupt Service Routine
An ISR in CodeWarriorAddress
$FFDC$FFDE
Vector
Time Base Module VectorADC Conversion Complete
$FFE0 Keyboard Vector
$FFE2 SCI Transmit Vector
$FFE4 SCI Receive Vector
$FFE6 SCI Error Vector
$FFE8 SPI Transmite Vector
$FFEA SPI Receive Vector
$FFEC
$FFEE
Timer 2 Overflow Vector
Timer 2, Channel 1 Vector
$FFF0 Timer 2, Channel 0 Vector
$FFF2 Timer 1 Overflow Vector
$FFF4 Timer 1, Channel 1 Vector
$FFF6 Timer 1 Channel 0 Vector
$FFF8 PLL Vector
$FFFA IRQ Vector
$FFFC Software Interrupt Vector
$FFFE Reset
Vector
1716
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
-
MC68HC908GP20 Interrupt Vector Table
Time Base Module Vector Location in memory
Note: The TBM has the lowest vector priority of all interrupts
interrupt 17 void TBM_ISR (void){
TBCR |= TACK; // Acknowledge Int
...
}
B051 PSHH B052 BSET 3,0x1CB054 PULHB055 RTI
TBM Interrupt Subroutine
interrupt 17 void TBM_ISR (void){
TBCR |= TACK; /* TimeBase Interrupt Acknowledge */
if( !(--cCounter) ){ /* If Counter is ZERO then */ PORTC = ~PORTC; /* Toggle LED */ cCounter = COUNT; /* Reinitialize the Counter */ }
}/* END TBM_ISR() */
The TBM Interrupts subroutine looks like this...
8
8
7
8
2
TBM
ADC
CGMC
COP
BRK
KBI
LVI
MON
SCI
SPI
TIM1
TIM2
PO
RT
AP
OR
TB
PO
RT
CP
OR
TD
PO
RT
E
CPU08
FLASH
RAM
SIM
IRQ
MC68HC908GP32
ADS-MOT908GP32Block Diagram
32.768 kHz
4.9152 MHz
MC68HC908GP32
MON08 SCI
RESET
TEMP
b
ADS-MOT908GP32Board Layout
MC68HC908GP32
4.9152MHz Oscillator32.768kHz CrystalReset Switch
LED
MON08 SCI
MotorolaMC68HC908GP32MotorolaMC68HC908GP32
ON
OFF
ON OFF
b
MotorolaMC68HC908GP32MotorolaTime 15 : 23 : 57
OFFOFF
OFF
Clock Example
Combining the Hello_LCD.c code and the TBM.c program, we can now create a Real Time Clock and display the time on the LCD.
Let’s just now put both codes together...
Clock: Initialization Segment
#include <hidef.h>#include "iogp20_32.h"#include “LcdDrv.h”#include <stdio.h>
#define COUNT 75 /* Interrupts per half sec */
unsigned char cCounter = 0x00; /* Interrupt Events Counter */unsigned char cHalfSec = 2; /* Half Seconf Events Counter */
unsigned char buffer [17] = {0}; /* 16 char LCD Buffer */ unsigned char hr=18, min=24, sec=00; /* Initial Time */
void main(void) {CONFIG1 = 0x0B; /* COP dis, STOP En, LVI En @5v */CONFIG2 = 0x03; /* SCI using Int Clk, Osc En @STOP */
DDRC = 0xFF; /* Configure PORTC as Output */PORTC = 0xFF; /* Initialize PORTC */
TBCR = 0x04; /* Config TBM Status & Control Reg */cCounter = COUNT; /* Initialize the Counter */ EnableInterrupts;
LCDInit(); /* Initializes LCD */TBCR |= TBON /* Turn TBM on */
#include “LcdDrv.h”#include <stdio.h>
unsigned char cHalfSec = 2; /* Half Seconf Events Counter */
unsigned char buffer [17] = {0}; /* 16 char LCD Buffer */ unsigned char hr=18, min=24, sec=00; /* Initial Time */
LCDInit(); /* Initializes LCD */
Clock: Time Algorithm
while( 1 ){ if(!cHalfSec){ /* If 1 second elapsed */ cHalfSec = 2; /* Reinitializes HalfSec counter */
if(++sec == 60){ /* If 60 seconds elapsed ... */ min++; /* increment the minutes */ sec = 0;
if(min == 60){ /* If 60 minutes elapsed ... */ hr++; /* increment the hours */
min = 0;
if(hr == 24) /* If 24 hours elapsed ... */ hr = 0;
} }/* END if(sec) */
sprintf (buffer, "Time %2d:%02d:%02d", hr, min, sec); PrintMsg (buffer);
}/* END if(!cHalfSec) */
}/* END While(1) */
sprintf (buffer, "Time %2d:%02d:%02d", hr, min, sec); PrintMsg (buffer);
MotorolaMotorola Time 13 : 59 : 57 Time 13 : 59 : 58 Time 13 : 59 : 59 Time 14 : 00 : 00 Time 14 : 00 : 01 Time 14 : 00 : 02 Time 14 : 00 : 03 Time 14 : 00 : 04 Time 14 : 00 : 05
Clock: TBM Interrupt Subroutine
interrupt 17 void TBM_ISR (void){
TBCR |= TACK; /* TimeBase Interrupt Acknowledge */
if( !(--cCounter) ){ /* If Counter is ZERO then */ PORTC = ~PORTC; /* Toggle LED */ cCounter = COUNT; /* Reinitialize the Counter */
}
}/* END TBM_ISR() */
The Interrupt Service Subroutine will be kept almost intact...
cHalfSec --; /* Countdown 1 half second */
We just have to add the Half Second Counter to know when to update the Display...
b
DigitalDNA Academy
Time 13 : 59 : 57 Time 13 : 59 : 58 Time 13 : 59 : 59 Time 14 : 00 : 00 Time 14 : 00 : 01 Time 14 : 00 : 02 Time 14 : 00 : 03 Time 14 : 00 : 04 Time 14 : 00 : 05
Clock Example
11100101 01110110 11000010
10111100 00100100 11001111
Set up the Time via SCI
As every nice clock, we should be able to setup the time...
Let’s modify the Clock example and generate a program to communicate with the PC through the Serial Communication Interface (SCI) of the MCU using a Baud Rate of 9600 bps
11100101 01110110 11000010
10111100 00100100 11001111 11100101 01110110 11000010
10111100 00100100 11001111
11100101 01110110 11000010
10111100 00100100 11001111
b
MotorolaMC68HC908GP32MotorolaTime 15 : 23 : 57
OFFOFF
OFF
...but to make it more eEngineer appealing, we’ll do it via the Serial Port of the PC
• Full-duplex high speed asynchronous operation
• Standard mark/space non-return-to-zero (NRZ) format
• 32 programmable baud rates
• Programmable 8-bit or 9-bit character length
• Two receiver wakeup methods: Idle line wakeup Address mark wakeup
• Separately enabled transmitter and receiver
• Double buffered receive and transmit
• Advanced data sampling and re-synchronization logic
• Programmable transmitter output polarity
SCI Features
• Interrupt-driven operation with eight interrupt flags: Transmitter empty Transmission complete Receiver full Idle receiver input Receiver overrun Noise error Receiver framing error Parity error
SCI Interrupt Overview
• Receive Interrupt Request and Vector
• Transmit Interrupt Request and Vector
• Error Interrupt Request and Vector
These I/O registers control and monitor SCI operation
SCC1: SCI control register 1
SCC2: SCI control register 2
SCC3: SCI control register 3
SCS1: SCI status register 1
SCS2: SCI status register 2
SCDR: SCI data register
SCBR: SCI baud rate register
SCI I/O Registers
SCI Control Register 1 (SCC1)
LOOPS — Loop Mode Select Bit
This read/write bit enables loop mode operation. In loop mode the PTE1/RxD pin is disconnected from the SCI, and the transmitter output goes into the receiver input. Both the transmitter and the receiver must be enabled to use loop mode. Reset clears the LOOPS bit.
1 = Loop mode enabled
0 = Normal operation enabled
ENSCI — Enable SCI Bit
This read/write bit enables the SCI and the SCI baud rate generator. Clearing ENSCI sets the SCTE and TC bits in SCI status register 1 and disables transmitter interrupts. Reset clears the ENSCI bit.
1 = SCI enabled
0 = SCI disabled
TXINV — Transmit Inversion Bit
This read/write bit reverses the polarity of transmitted data. Reset clears the TXINV bit.
1 = Transmitter output inverted
0 = Transmitter output not inverted
M — Mode (Character Length) Bit
This read/write bit determines whether SCI characters are eight or nine bits long. The ninth bit can serve as an extra stop bit, as a receiver wakeup signal, or as a parity bit. Reset clears the M bit.
1 = 9-bit SCI characters
0 = 8-bit SCI characters
PEN —Parity Enable Bit
This read/write bit enables the SCI parity function. When enabled, the parity function inserts a parity bit in the most significant bit position. Reset clears the PEN bit.
1 = Parity function enabled
0 = Parity function disabled
WAKE — Wakeup Condition Bit
This read/write bit determines which condition wakes up the SCI: a logic1 (address mark) in the most significant bit position of a received character or an idle condition on the PTE1/RxD pin. Reset clears the WAKE bit.
1 = Address mark wakeup
0 = Idle line wakeup
ILTY — Idle Line Type Bit
This read/write bit determines when the SCI starts counting logic1s as idle character bits. The counting begins either after the start bit or after the stop bit. Reset clears the ILTY bit.
1 = Idle character bit count begins after stop bit
0 = Idle character bit count begins after start bit
SCS2
SCC1
SCC2
SCC3
SCS1
SCDR
SCBR
PTY — Parity Bit
This read/write bit determines whether the SCI generates and checks for odd parity or even parity. Reset clears the PTY bit.
1 = Odd parity
0 = Even parity
SCTIE — SCI Transmit Interrupt Enable Bit
This read/write bit enables the SCTE bit to generate SCI transmitter CPU interrupt requests. Reset clears the SCTIE bit.
1 = SCTE enabled to generate CPU interrupt
0 = SCTE not enabled to generate CPU interrupt
TCIE — Transmission Complete Interrupt Enable Bit
This read/write bit enables the TC bit to generate SCI transmitter CPU interrupt requests. Reset clears the TCIE bit.1 = TC enabled to generate CPU interrupt requests0 = TC not enabled to generate CPU interrupt requests
SCRIE — SCI Receive Interrupt Enable Bit
This read/write bit enables the SCRF bit to generate SCI receiver CPU interrupt requests. Reset clears the SCRIE bit.
1 = SCRF enabled to generate CPU interrupt
0 = SCRF not enabled to generate CPU interrupt
ILIE — Idle Line Interrupt Enable Bit
This read/write bit enables the IDLE bit to generate SCI receiver CPU interrupt requests. Reset clears the ILIE bit.
1 = IDLE enabled to generate CPU interrupt requests
0 = IDLE not enabled to generate CPU interrupt requests
TE — Transmitter Enable Bit
Setting this bit begins the transmission by sending a preamble of 10 or 11 logic 1s from the transmit shift register to the PTE0/TxD pin. If software clears the TE bit, the transmitter completes any transmission in progress before the PTE0/TxD returns to the idle condition (logic 1). Reset clears the TE bit.
1 = Transmitter enabled
0 = Transmitter disabled
RE — Receiver Enable Bit
Setting this read/write bit enables the receiver. Clearing the RE bit disables the receiver but does not affect receiver interrupt flag bits. Reset clears the RE bit.
1 = Receiver enabled
0 = Receiver disabled
RWU — Receiver Wakeup Bit
This bit puts the receiver in a standby state during which receiver interrupts are disabled. The WAKE bit in SCC1 determines whether an idle input or an address mark brings the receiver out of the standby state and clears the RWU bit. Reset clears the RWU bit.
1 = Standby state
0 = Normal operation
SCS2
SCC1
SCC2
SCC3
SCS1
SCDR
SCBR
SBK — Send Break Bit
Setting and then clearing this read/write bit transmits a break character followed by a logic 1. The logic 1 after the break character guarantees recognition of a valid start bit. Reset clears the SBK bit.
1 = Transmit break characters
0 = No break characters being transmitted
SCI Control Register 2 (SCC2)
R8 — Received Bit 8
When the SCI is receiving 9-bit characters, R8 is the read-only ninth bit (bit 8) of the received character. R8 is received at the same time that the SCDR receives the other 8 bits. When the SCI is receiving 8-bit characters, R8 is a copy of the eighth bit (bit 7). Reset has no effect on the R8 bit.
T8 — Transmitted Bit 8
When the SCI is transmitting 9-bit characters, T8 is the read/write ninth bit (bit 8) of the transmitted character. T8 is loaded into the transmit shift register at the same time that the SCDR is loaded into the transmit shift register. Reset has no effect on the T8 bit.
DMATE — DMA Transfer Enable Bit
The DMA module is not included on this MCU. Writing a logic 1 to DMARE or DMATE may adversely affect MCU performance!
ORIE —Receiver Overrun Interrupt Enable Bit
This read/write bit enables SCI error CPU interrupt requests generated by the receiver overrun bit, OR.
1 = SCI error CPU interrupt requests from OR bit enabled
0 = SCI error CPU interrupt requests from OR bit disabled
NEIE — Receiver Noise Error Interrupt Enable Bit
This read/write bit enables SCI error CPU interrupt requests generated by the noise error bit, NE. Reset clears NEIE.
1 = SCI error CPU interrupt requests from NE bit enabled
0 = SCI error CPU interrupt requests from NE bit disabled
FEIE — Receiver Framing Error Interrupt Enable Bit
This read/write bit enables SCI error CPU interrupt requests generated by the framing error bit, FE. Reset clears FEIE.
1 = SCI error CPU interrupt requests from FE bit enabled
0 = SCI error CPU interrupt requests from FE bit disabled
PEIE — Receiver Parity Error Interrupt Enable Bit
This read/write bit enables SCI receiver CPU interrupt requests generated by the parity error bit,PE. Reset clears PEIE.
1 = SCI error CPU interrupt requests from PE bit enabled
0 = SCI error CPU interrupt requests from PE bit disabled
SCS2
SCC1
SCC2
SCC3
SCS1
SCDR
SCBR
SCI Control Register 3 (SCC3)
SCS2
SCC1
SCC2
SCC3
SCS1
SCI Status Register 1 (SCS1)
SCTE – SCI Transmitter Empty Bit
This clearable, read-only bit is set when the SCDR transfers a character to the transmit shift register. In normal operation, clear the SCTE bit by reading SCS1 with SCTE set and then writing to SCDR.
1 = SCDR data transfered to transmit shift register0 = SCDR data no transfered to transmit shift register
SCDR
SCBR
TC – Transmission Complete Bit
This read-only bit is set when the SCTE bit is set, and no data, preamble, or break character is being transmitted. TC is automatically cleared when data, preamble or break is queued and ready to be sent
1 = No transmission in progress0 = Transmission in progress
SCRF – SCI Receiver Full Bit
This clearable, read-only bit is set when the data in the receive shift register transfers to the SCI data register. In normal operation, clear the SCRF by reading SCS1 with SCRF set and then reading the SCDR.
1 = Received data available in SCDR0 = Data not available in SCDR
IDLE – Receiver Idle Bit
This clearable, read-only bit is set when 10 or 11 consecutive logic 1s appear on the receiver input. Clear the IDEL bit by reading SCS1 with IDLE set and then reading the SCDR.
1 = Receiver input idle0 = Receiver input active
OR – Receiver Overrun Bit
This clearable, read-only bit is set when software fails to read the SCDR before the receive shift register receives the next character. The data in the shift register is lost, but the data already in the SCDR is not affected. Clear the OR bit by reading SCS1 with OR set and then reading the SCDR.
1 = Receive shift register full and SCRF=10 = No receiver overrun
NF – Receiver Noise Flag Bit
This clearable, read-only bit is set when the SCI detects noise on the RxD pin. Clear the NF bit by reading SCS1 with NF set and then reading the SCDR.
1 = Noise detected0 = No noise detected
FE – Receiver Framing Error Bit
This clearable, read-only bit is set when a logic 0 is accepted as the stop bit. Clear the FE bit by reading SCS1 with FE set and then reading the SCDR.
1 = Framing error detected0 = No framing error detected
PE – Receiver Parity Error Bit
This clearable, read-only bit is set when the SCI detects a parity error on incoming data. Clear the PE bit by reading SCS1 with PE set and then reading the SCDR.
1 = Parity error detected0 = No parity error detected
7 6 5 4 3 2 1 0H L
SCI Double Buffering
PTE0/TxD
SCI Data Register
ST
OP
ST
AR
T
TRANSMITSHIFT REGISTERMSB
INTERNAL DATA BUS
CLK From Baud Rate Generator
SCI Transmitter
SCI Data RegisterData from CPU
7 6 5 4 3 2 1 0
Transmitter Empty Event
SCTE = 1
1 011
Transmission in Progress
TC = 0
Transmission Complete Event
TC = 1
SCI Status Register 2 (SCS2)
SCS2
SCC1
SCC2
SCC3
SCS1
SCDR
SCBR
BKF – Brake Flag Bit
This clearable, read-only bit is set when the SCI detects a brake character on the RxD pin. BRK does not generate interrupt requests. Clear the BRK bit by reading SCS1 with BRK set and then reading the SCDR.
1 = Brake character detected0 = No brake character detected
RPF – Reception in Progress Flag Bit
This clearable, read-only bit is set when the receiver detects a logic 0 during the RT1 time period of the start bit search. RFP does not generate interrupt requests. RPF is reset after the receiver detects false start bits o when detects an idle character
1 = Reception in progress0 = No reception in progress
R7/T7 - R0/T0 — Receive/Transmit Data Bits
• Reading SCDR accesses the read-only received data bits, R7:R0
• Writing to SCDR writes the data to be transmitted, T7:T0
SCI Data Register (SCDR)
SCS2
SCC1
SCC2
SCC3
SCS1
SCDR
SCBR
SCI Baud Rate Register (SCBR)
SCR2–SCR0 — SCI Baud Rate Divider BitsThese read/write bits select the SCI baud rate divisor. Reset clears SCR2–SCR0.
SCR2 - SCR0000001
Baud Rate Divisor (BD)12
010 4011 8100 16101 32110 64111 128
SCP1 and SCP0 — SCI Baud Rate Prescaler BitsThese read/write bits select the baud rate prescaler divisor. Reset clears SCP1 and SCP0.
SCP1 and SCP0
00
01
Prescaler Divisor (PD)
1
3
10 4
11 13
SCS2
SCC1
SCC2
SCC3
SCS1
SCDR
SCBR
Baud Rate =
f bus
64 X PD X BD
4.9152 MHz
SCR2 - SCR0000001
Baud Rate Divisor (BD)12
010 4011 8100 16101 32110 64111 128
SCP1 and SCP00001
Prescaler Divisor (PD)13
10 411 13
00 1
011 8
01 512= 9600
SCBR $0019
SCBR $0019
To Generate a Baud Rate of 9600:
Programming the SCI Baud Rate
08
SCBR
SCI- Clock: Configuration
void main(void){
...
SCBR = 0x03; /* Select 9600 Baud rate over a clock = 4.9152 MHz */
SCC1 = 0x40; /* Enable SCI */
SCC2 = 0x2C; /* Receive and Transmit enabled, Rx Int Enabled */
...
}
These 3 lines configure the SCI to Transmit and Receive at a Baud Rate of 9600:
0 0 10 1
SCR2 - SCR0000001
Baud Rate Divisor (BD)12
010 4011 8100 16101 32110 64111 128
SCP1 and SCP00001
Prescaler Divisor (PD)13
10 411 13
00 1
011 8
SCBR = 0x03; /* Select 9600 Baud rate over a clock = 4.9152 MHz */
0 0 0
SCI- Clock: Terminal Interaction
SCS1; /* Ackowledge any pending interrupts */
Transmit ("Teclee la Hora actual (formato 24hrs)\n\r");
Transmit("Horas (hh):"); hr = Receive();
Transmit("Minutos (mm):"); min = Receive();
Transmit("Segundos (ss):"); sec = Receive();
Here is the piece of code to interact with the Terminal...
void Transmit (unsigned char sMessage[17]){
unsigned char k=0;
while(sMessage[k] != 0){ SCDR = sMessage[k]; k++;
/* Polling for transmitter to empty */ while( !(SCS1 & SCTE) ); }}
unsigned char Receive (void){
unsigned char tens=0, units=0;
/* Wait until <CR>+<LF> */ while (sTime[i-1] != 0x0A );
/* If two digits number */ if(i == 4) tens = 10*( sTime[0] - 0x30);
units = sTime[i-3] - 0x30; i=0;
return( tens + units );}
SCI- Clock: Receive Interrupt Subroutine
interrupt 13 void SCI_Rx_ISR (void){ /* SCI Receive vector (UART RX) */
SCS1; /* SCI Interrupt Acknowledge */sTime[i++] = SCDR; /* Store the Received Data */
} }/* END SCI_Rx_ISR() */
The Interrupt Service Subroutine is as follows...
LED Dimmer Example
The purpose of this example is to make a LED blink every second, but gradually dimming the light instead of abruptly turn it on and off!!!
We are going to do this generating a PWM signal using the on-chip Timer we have on the GP32...
Timer Interface Module (TIM)
TIM Capabilities Output Compare Function Input Capture Function Pulse Width Modulation Function
Unbuffered vs. buffered PWMs
Available in 2, 4, 6, or 8 channel implementations
All timer channels in a timer module share a common 16-bit time reference with prescaler
Each timer channel is individually programmable to perform the following functions:
- Output Compare
- Input Capture
- Pulse Width Modulation (PWM)
TIM Overview
Features:
• Two input capture/output compare channels: – Rising-edge, falling-edge, or any-edge input capture trigger – Set, clear, or toggle output compare action• Buffered and unbuffered pulse-width-modulation (PWM) signal generation• Programmable TIM clock input with 7-frequency internal bus clock prescaler selection• Free-running or modulo up-count operation• Toggle any channel pin on overflow• TIM counter stop and reset bits• Modular architecture expandable to eight channels• I/O port bit(s) software configurable with pullup device(s) if configured as input port bit(s)
TIM Features
TIM1
TIM2
PTD4/T1CH0
PTD6/T2CH0
PTD5/T1CH1
PTD7/T2CH1
T[1,2]CH 1T[1,2]CH 0
Full TIM Pin Names
TIM Generic Pin Names:
The two TIMs share four I/O pins with four port D I/O port pins. The full names of the TIM I/O pins are listed in the Table. The generic pin names appear in the text that follows.
Pin Name Conventions
16-bit Comparator
TCH0
16-bit Latch
ELS0B
MS0A
CH0F
ELS0A
TOV0
CH0MAX
CH0IE
PortLogic
InterruptLogic
MS0B
16-bit Comparator
TCH1
16-bit Latch
ELS1B
MS1A
CH1F
ELS1A
TOV1
CH1MAX
CH1IE
PortLogic
InterruptLogic
TOF
TOIE
InterruptLogic16-bit Comparator
TMOD
16-bit Counter
Inte
rnal
Bus
PS2 PS1 PS0
Prescaler TSTOP
TRST
InternalBus Clock
TnCH0
TnCH1
TIM Block Diagram
Timer 1 Registers Register Description
T1SC Timer Status And Control Register (8-bit)$0020
T1CNT Timer Counter Register (16-bit)$0021
T1MOD Timer Counter Module Register (16-bit)$0023
T1SC0 Timer Channel 0 Status and Control Register$0025
T1CH0 Timer Channel 0 Counter Register (16-bit)$0026
T1SC1 Timer Channel 1 Status and Control Register$0028
T1CH1 Timer Channel 1 Counter Register (16-bit)$0029
Addrs:
TIM Registers for Timer 1
Timer 2 Registers
T2SC
T2CNT
T2MOD
T2SC0
T2CH0
T2SC1
T2CH1
Timer Status And Control Register (8-bit)
Timer Counter Register (16-bit)
Timer Counter Module Register (16-bit)
Timer Channel 0 Status and Control Register
Timer Channel 0 Counter Register (16-bit)
Timer Channel 1 Status and Control Register
Timer Channel 1 Counter Register (16-bit)
Register Description
$002B
$002C
$002E
$0030
$0031
$0033
$0034
Addrs:
Timer Registers are sequentially allocated
in memory
TIM Registers for Timer 2
A Software Advantage!:
#define Byte unsigned char#define Word unsigned int
struct TimerChannel {Byte Status;Word Count;
};
struct Timer {Byte Status;Word Count;Word Modulo;struct TimerChannel Ch0;struct TimerChannel Ch1;
};
void main (void) {
struct Timer TimerOne @0x0020;Word Value;
TimerOne.Status = 0x12;TimerOne.Modulo = 0x07FF;TimerOne.Ch0.Status = 0x15;TimerOne.Ch1.Status = 0x12;Value = TimerOne.Ch0.Count;
// Application Main Loop AppLoop {
... }
}
Advantages of sequential allocation
• The central component of the TIM is the 16-bit TIM counter that can operate as a free-running counter or a modulo up-counter.
• The TIM counter provides the timing reference for the input capture and output compare functions.
• The TIM counter modulo registers, TMODH:TMODL, control the modulo value of the TIM counter.
• Software can read the TIM counter value at any time without affecting the
counting sequence.
TIM Functional Description
The central component of the TIM is the 16-bit TIM counter that can operate as a free-running counter or a modulo up-counter.
Counter Module Register
16-bit Counter
16-bit Comparator
Clock rate = Internal bus clk divided by the
prescaler
TxCNT
(Free running counter)
TxMODCounter Module Register
16-bit CounterEvent flag
Free-running Counter andModulo operation
Time
0x0000 0xFFFF / 0x0000 0xFFFF / 0x0000
The modulo up-counter sets the period of the free-running counter!!. Period when TMOD = 0xFFFF
Free running Output
Time
0x0000 0x5BFF / 0x0000 0x5BFF / 0x0000 0x5BFF / 0x0000 0x5BFF / 0x0000
If we set TMOD = 0x5BFF
Free runnig Output
Modulo functionality
16-bit Comparator
TCH0
16-bit Latch
ELS0B
MS0A
CH0F
ELS0A
TOV0
CH0MAX
CH0IE
PortLogic
InterruptLogic
MS0B
16-bit Comparator
TCH1
16-bit Latch
ELS1B
MS1A
CH1F
ELS1A
TOV1
CH1MAX
CH1IE
PortLogic
InterruptLogic
TOF
TOIE
InterruptLogic16-bit Comparator
TMOD
16-bit Counter
Inte
rnal
Bus
PS2 PS1 PS0
Prescaler TSTOP
TRST
InternalBus Clock
TnCH0
TnCH1
The TIM counter provides the timing reference for the input capture and output compare functions.
16-bit Counter
TCH0
TCH1
Input captureOutput compare
TMOD
Timer Functions
• With the input capture function, the TIM can capture the time at which an external event occurs.
• When an active edge occurs on the pin of an input capture channel, the TIM latches the contents of the TIM counter into the TIM channel registers, TCHxH:TCHxL.
• The polarity of the active edge is programmable. Input captures can generate TIM CPU interrupt requests.
Input Capture
Input Capture Concept
When an active edge occurs on the pin of an input capture channel...
The TIM latches the contents of the
Counter into the Channel Registers,
TCHxH:TCHxL
16-bit Latch
16-bit Free Running Counter
T1 T2
0xFFFF / 0x0000 0xFFFF / 0x0000
RAM Memory
Localidad 0x0062
Localidad 0x0060
Input Signal on Channel Pin
0x71FF0xCA45
0x71 0xFF
The ISR stores the value in memory
0xCA 0x45
The ISR stores the NEW value in RAM
To measure the pulse width we simple substract the first capture to the last one:
PulseWidth = 0xCA45 - 0x71FF = 0x5846 clk cycles.
Input Capture Example
• Capture on rising edge only
• Capture on falling edge only
• Capture on rising or falling edge
Types of Input Capture
• With the output compare function, the TIM can generate a periodic pulse with a programmable polarity, duration, and frequency.
• When the counter reaches the value in the registers of an output compare channel, the TIM can set, clear, or toggle the channel pin.
• Output compares can generate TIM CPU interrupt requests.
Output Compare
Output Compare Concept
Period
The pulse width is equal to the 16-bit value stored on the Channel Counter Register
Time
The TIM 16-bit free running counter always counts when enabled.
0x0000 0xFFFF / 0x0000 0xFFFF / 0x0000
The free running counter period is given by a 65536 pulse count.
When the contents of the 16-bit Channel Counter register match to those of the free running counter the MCU triggers an “Output on Compare” event.
Output Compare Example
• Toggle output on compare The channel pin toggles its preset value.
• Clear output on compare On compare, the channel pin set its value to 0.
• Set output on compare On compare, the channel pin set its value to 1
Types of Output Compare
• Enables TIM overflow interrupts
• Flags TIM overflows
• Stops the TIM counter
• Resets the TIM counter
• Prescales the TIM counter clock
TCH0
TSC0
TCNT
TMOD
TCH1
TSC1
TSC
TIM Status and Control Register(TSC)
TOF — TIM Overflow Flag Bit
This read/write flag is set when the TIM counter resets to $0000 after reaching the modulo value programmed in the TIM counter modulo registers. Writing a logic 1 to TOF has no effect.
1 = TIM counter has reached modulo value
0 = TIM counter has not reached modulo value
TCH0
TSC0
TCNT
TMOD
TCH1
TSC1
TSC
TOIE — TIM Overflow Interrupt Enable Bit
This read/write bit enables TIM overflow interrupts when the TOF bit becomes set. Reset clears the TOIE bit.
1 = TIM overflow interrupts enabled
0 = TIM overflow interrupts disabled
TSTOP — TIM Stop Bit
This read/write bit stops the TIM counter. Counting resumes when TSTOP is cleared. Reset sets the TSTOP bit, stopping the TIM counter until software clears the TSTOP bit.
1 = TIM counter stopped
0 = TIM counter active
TRST — TIM Reset Bit
Setting this write-only bit resets the TIM counter and the TIM prescaler. Setting TRST has no effect on any other registers. Counting resumes from $0000. TRST is cleared automatically after the TIM counter is reset.
1 = Prescaler and TIM counter cleared0 = No effect
PS2–PS0 — Prescaler Select Bits
These read/write bits select either the TCLK pin or one of the seven prescaler outputs as the input to the TIM counter.
Reset clears the PS[2:0] bits.
TIM Status and Control Register(TSC)
TCH0
TSC0
TCNT
TMOD
TSC
TCH1
TSC1
PS2-PS0 TIM Clock Source
000 Internal bus clock ÷ 1
001 Internal bus clock ÷ 2
010 Internal bus clock ÷ 4
011 Internal bus clock ÷ 8
100 Internal bus clock ÷ 16
101 Internal bus clock ÷ 32
110 Internal bus clock ÷ 64
111 Not available
Prescaler Select Table
TCH0
TSC0
TCNT
TMOD
TSC
TCH1
TSC1
Each of the TIM channel status and control registers:
Flags input captures and output compares
Enables input capture and output compare interrupts
Selects input capture, output compare, or PWM operation
Selects high, low, or toggling output on output compare
Selects rising, falling or any edge as the active input capture trigger
Selects output toggling on TIM overflow
Selects 100% PWM duty cycle
Selects buffered or unbuffered output compare/PWM operation
TIM Channel Status and Control Registers
TCH0
TSC0
TCNT
TMOD
TSC
TCH1
TSC1
CHxF — Channel x Flag Bit
This read/write bit is set when an active edge occurs on the channel x pin or when a compare occurs. Reset clears the CHxF bit. Writing a logic 1 to CHxF has no effect.
1 = Input capture or output compare on channel x0 = No input capture or output compare on channel x
CHxIE — Channel x Interrupt Enable Bit
This read/write bit enables TIM CPU interrupts. Reset clears the CHxIE bit.
1 = Channel x CPU interrupt requests and DMA service requests enabled0 = Channel x CPU interrupt requests and DMA service requests disabled
Mode, Edge, and Level Selection bitsProgram the Timer to perform the output compare, input capture or PWM functions.
TIM Channel Status and Control Registers
TCH0
TSC0
TCNT
TMOD
TSC
TCH1
TSC1
TIM Channel Status and Control Register
TOVx — Toggle On Overflow Bit
When channel x is an output compare channel, this read/write bit controls the behavior of the channel x output when the TIM counter overflows. When channel x is an input capture channel, TOVx has no effect. Reset clears the TOVx bit.
1 = Channel x pin toggles on TIM counter overflow.
0 = Channel x pin does not toggle on TIM counter overflow.
CHxMAX — Channel x Maximum Duty Cycle Bit
When the TOVx bit is at logic 0, setting the CHxMAX bit forces the duty cycle of buffered and unbuffered PWM signals to 100%. The CHxMAX bit takes effect in the cycle after it is set or cleared. The output stays at the 100% duty cycle level until the cycle after CHxMAX is cleared.
TIM Channel Status and Control Registers
TSC0
TCNT
TMOD
TSC
TCH1
TSC1
TSC0
TCNT
TMOD
TSC
TSC1
TCH0TCH0
TCH1
TIM Channel Registers
TIM Channel Interrupts
In Input Capture mode (MSxB:MSxA = 00), reading the high byte of the TIM Channel x Registers (TCHxH)...
In Output Compare mode (MSxB:MSxA 00), writing to the high byte of the TIM Channel x Registers (TCHxH)...
inhibits input captures until the low byte (TCHxL) is read
inhibits output compares until the low byte (TCHxL) is writen
• The TIM can generate a PWM signal by using the toggle-on-overflow feature with an output compare channel, the TIM can generate a PWM signal.
• The value in the TIM counter modulo registers determines the period of the PWM signal.
i.e. the time between overflows is the period of the PWM signal
• The output compare value in the TIM channel registers determines the pulse width of the PWM signal.
Pulse Width Modulation
PERIOD
Overflow Overflow Overflow Overflow
Pulse Width
Output Compare
Output Compare
Output Compare
We have total PWM control!
PWM Period and Pulse Width
PWM Calculations
Fxtal = 4.9152MHz
To obtain a nice and smooth light variation, let’s use a PWM frequency of 120Hz...
60Hz works just fine, but 120Hz looks smoother!!!
To find the amount of Ticks per cycle we require, let’s make the following Calculation:
This means the Timer will count at a rate of 1,228,800 ticks per sec
= 10,240 ticks/cycle
This number give us the period of the PWM signal
TxMOD = 0x2800
1228800 ticks/sec
120 cycles/ sec=
4= 1.2288MHzFbus =
Fxtal
Fbus
Fdes
TxMOD =
More calculations...
Since we are forcing the Timer to generate 120 overflows events per second...
Let’s modify the Pulse Width or Output Compare Register at this rate.
The LED has to Turn ON and OFF within this period, so we only have 60 Overflow events to turn it on to the Maximum intensity, and another 60 events to take it down to the OFF stage...
This lead us to:
10,240 ticks/cycleIncrement =
60= 170.67 170
This number give us 60 increments to reach the maximum LED light intensity
INC = 0xAA
T2CH1 Configuration
/*************** Defines ***************/
#define Clr_Output_on_Compare 0x18#define Prescaler_by_1 0x00
#define INCREMENT 0xAA /* Inc to modify the OC Reg */#define MODULO 0x2800
void main(void){
...
T2SC = TOIE | TSTOP | TRST | Prescaler_by_1; T2MOD = MODULO; /* Modulo Setup */ T2CH1 = INCREMENT; /* OC Register Init */
T2SC1 = CHIE | Clr_Output_on_Compare | TOV;
EnableInterrupts; T2SC &= ~TSTOP; /* Start Timer Counter */
...
}
TIM2 Overflow Interrupt Subroutine
interrupt 9 void TIM2_OV_ISR (void){ // Timer 2 Overflow
static unsigned char i = 0; static unsigned char sentido = UP;static unsigned int temp = 0;
T2SC; /* Condition to Acknowledge TIM OV Interrupt */T2SC &= ~TOF; /* Read the T2SC and write logic 0 to TOF */
PORTC = ~PORTC; /* Toggles the LED */
if( sentido == UP ){ /* If lighting up */ if(i < 60){
temp += INCREMENT; /* This is to force CodeWarrior to write first */ T2CH1 = temp; /* to the High byte and then the Low byte */
i++; } else sentido = DOWN;}if( sentido == DOWN ){ /* If lighting down */ if( i > 1 ){ temp -= INCREMENT; T2CH1 = temp; i--; } else{ sentido = UP;
temp += INCREMENT; /* To avoid OC of zero, 2 consecutive times */ T2CH1 = temp;
i++; }}
}
temp += INCREMENT; /* This is to force CodeWarrior to write first */ T2CH1 = temp; /* to the High byte and then the Low byte */
static unsigned int temp = 0;
TIM2 Channel1 Interrupt Subroutine
interrupt 8 void TIM2_CH1_ISR (void){ // Timer 2 Channel 1
T2SC1; /* Condition to Acknowledge OC Interrupt */ T2SC1 &= ~CHF; /* Read the T2SC1 and write logic 0 to CHF */ PORTC = 0; /* Turn OFF LED on OC */
}
April 21, 2023
Thermometer
Thermometer Example
The purpose of this example is to create a Thermometer displaying the Room Temperature on the LCD.
The sensor device is a thermistor located on-board.
We will adquire the thermistor’s data with the on-chip A/D Converter
Temp = 27°C
8
8
7
8
2
TBM
ADC
CGMC
COP
BRK
KBI
LVI
MON
SCI
SPI
TIM1
TIM2
PO
RT
AP
OR
TB
PO
RT
CP
OR
TD
PO
RT
E
CPU08
FLASH
RAM
SIM
IRQ
MC68HC908GP32
4.9152 MHz
Temp = 27°C
TEMP
Thermometer Diagram
ADC
PO
RT
B
• 8-bit or 10-bit resolution depending on derivative
• Linear successive approximation with monotonicity
• Single- or Continuous conversion
• Conversion complete indication by Flag or Interrupt
• Selectable ADC input clock
ADC Introduction
• Separate VREFH and VREFL for improved accuracy, route carefully and place bypass capacitors
• When the input voltage equals VREFH, the ADC converts the signal to $FF
• If the input voltage equals VREFL, the ADC converts it to $00
• Input voltages between VREFH and VREFL are a straight-line linear conversion
• The conversion process is monotonic and has no missing codes
ADC Voltage Conversion
• ADC Status and Control Register (ADSCR)
• ADC Clock Register (ADCLK)
• ADC Data Register (ADR)
$003C
$003D
$003E
$003C
$003D
$003E
All ADC Registers are memory mapped All ADC Registers are memory mapped
ADC Module Registers
ADC Status and Control Register (ADSCR)
COCO/IDMAS (Genera la Interrupcion)
Conversion complete flag.
1 = Conversion complete
0 = Conversion NOT complete
AIEN (ADC Interrupt Enable Bit)
Enable a Conversion Complete IRQ.
1 = ADC interrupt enable
0 = ADC interrupt disabled
ADCO (Continuous Conversion Bit)
When set ADC will convert continuously
1 = Continuous ADC conversion
0 = One ADC Conversion at a Time
ADCHx (ADCH4 - ADCH0 Channel Select bits)
Selects one of the 16 ADC channels.
-5 are reserved, 1 for VREFH, 1 for VSSAD.
ADC Input Channel Selection
A Read-Only Register from which the converted Data is read
ADC Data Register (ADR)
ADC Clock Register (ADCLK)
ADICLK (ADC Input Clock Select Bit)
Selects either the bus clock or CGMXCLK as the input clock.
ADIVx (ADIV2 - ADIV0 ADC Clock Rate Select bits)
ADIV2-ADIV0 Selects the divide ratio used by the adc to generate the internal ADC clock.
ADC input clock 1, 2, 4, 8 or 16.
The ADC Clock frequency must
be 1MHz
Conversion starts after a write to the ADSCR register
One conversion will requires between 16 and 17ADC clock cycles to complete
Conversion Time = 16 to 17 ADC cycles
ADC frequency
= 16 µs or 17 µs with 1 MHz ADC clock
ADC Conversion Time
ADC Module Tips
• Reduce the noise that is introduced into the A/D subsystem
• Careful lay out to separate noisy signals from the sensitive A/D signals
• Reduce the noise coupling as much as possible
• Refer to application note AN1059/D, System Design and Layout Techniques for Noise Reduction in MCU Based Systems
• Allow for A/D on current stabilization
• Minimize the source impedance
• Take multiple conversions and average the results if possible
ADC Cofiguration
unsigned char buffer [17] = {0}; /* 16 char LCD Buffer */unsigned char cTemp = 255;
void main(void) {
CONFIG1 = 0x0B; /* COP dis, STOP En, LVI En @5v */ CONFIG2 = 0x02; /* SCI using Ext Clk, Osc En @STOP */
ADCLK = 0x10; /* Configure the ADCLK Register Selects Internal Clock (4.9152MHz/4 = 12288 MHz) ADC input Clock/1 = 1.2288 MHz (aprox. 1MHz) */
ADSCR = 0x00; /* Configure the ADSCR Register Select AD0 Channel One ADC Conversion Disable ADC Interrupts */
LCDInit(); /* Initialize LCD */ EnableInterrupts;
while(1){ MeasureTemp(); } }/* END main() */
ADCLK = 0x10; /* Configure the ADCLK Register Selects Internal Clock (4.9152MHz/4 = 12288 MHz) ADC input Clock/1 = 1.2288 MHz (aprox. 1MHz) */
ADSCR = 0x00; /* Configure the ADSCR Register Select AD0 Channel One ADC Conversion Disable ADC Interrupts */
/* --------------------------------------------------------------------------------- * Meassure temperature using an ADC channel, and display the results * Resolution of ADC is assumed to be 5/255 = 0.019608V * The Sensor selected for this project(Analog Devices, TMP37) * has a linear output factor of 20mV/degC. * Therefore, with a 5V reference 1 bit is approximately equal to 1 degC * ---------------------------------------------------------------------------------*/
void MeasureTemp (void){
if( (ADSCR & COCO) == COCO){ /* If Conversion Complete... */ if(cTemp != ADR){ /* If any changes in Temperature... */ sprintf(buffer,"Temp = %2d C",cTemp); /* Display new Temperature */
buffer[9] = 0xDF; /* Inserts the degree char (°) into buffer */ PrintMsg(buffer); cTemp = ADR; /* Updates temp and Clear COCO Flag */ }
ADSCR &= ~ADCO; /* Starts next convertion */ }
}
Data Adquisition
Features:
• Eight keyboard interrupt pins with separate keyboard interrupt enable bits and one keyboard interrupt mask
• Hysteresis buffers
• Programmable edge-only or edge and level interrupt sensitivity
• Exit from low-power modes
• I/O (input/output) port bit(s) software configurable with pullup device(s) if configured as input port bit(s)
Keyboard Interrupt Module
Share PORTA pins
MC68HC908GP20
Writing to the KBIE7–KBIE0 bits in the keyboard interrupt enable registerindependently enables or disables PORTA pin as a keyboard interrupt pin.
Pin Locations
The Keyboard module only has two registers:
(1) Keyboard Status and Control Register (INTKBSCR)
(2) Keyboard Interrupt Enable Register (INTKBIER)
• Flags keyboard interrupt requests• Acknowledges keyboard interrupt requests• Masks keyboard interrupt requests• Controls keyboard interrupt triggering sensitivity
• The Keyboard interrupt enable register enables or disables each port A pin to operate as a keyboard interrupt pin.
KBI Registers
KBI Vector
Address
$FFDC$FFDE
Vector
Time Base Module VectorADC Conversion Complete
$FFE0 Keyboard Vector
$FFE2 SCI Transmit Vector
$FFE4 SCI Receive Vector
$FFE6 SCI Error Vector
$FFE8 SPI Transmite Vector
$FFEA SPI Receive Vector
$FFEC
$FFEE
Timer 2 Overflow Vector
Timer 2, Channel 1 Vector
$FFF0 Timer 2, Channel 0 Vector
$FFF2 Timer 1 Overflow Vector
$FFF4 Timer 1, Channel 1 Vector
$FFF6 Timer 1 Channel 0 Vector
$FFF8 PLL Vector
$FFFA IRQ Vector
$FFFC Software Interrupt Vector
$FFFE Reset
Vector
1716
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
-
MC68HC908GP20 Interrupt Vector Table
Keyboard Vector Location in memory
Fuctional Description
• Enabling a keyboard interrupt pin also enables its internal pull up device.
• The MODEK bit in the keyboard status and control register controls the triggering mode of the keyboard interrupt.
• A logic 0 applied to an enabled keyboard interrupt pin latches a keyboard interrupt request.
•The keyboard flag bit (KEYF) in the keyboard status and control register can be used to see if a pending interrupt exists.
• The KEYF bit is not affected by the keyboard interrupt mask bit (IMASKK) which makes it useful in applications where polling is preferred.
KEYF — Keyboard Flag BitThis read-only bit is set when a keyboard interrupt is pending. Resetclears the KEYF bit.1 = Keyboard interrupt pending0 = No keyboard interrupt pending
ACKK — Keyboard Acknowledge BitWriting a logic 1 to this write-only bit clears the keyboard interrupt request. ACKK always reads as logic 0. Reset clears ACKK.
IMASKK — Keyboard Interrupt Mask BitWriting a logic 1 to this read/write bit prevents the output of thekeyboard interrupt mask from generating interrupt requests. Resetclears the IMASKK bit.1 = Keyboard interrupt requests masked0 = Keyboard interrupt requests not masked
MODEK — Keyboard Triggering Sensitivity BitThis read/write bit controls the triggering sensitivity of the keyboardinterrupt pins. Reset clears MODEK.1 = Keyboard interrupt requests on falling edges and low levels0 = Keyboard interrupt requests on falling edges only
Keyboard Status and Control Register(INTKBSCR)
KBIE7–KBIE0 — Keyboard Interrupt Enable BitsEach of these read/write bits enables the corresponding keyboardinterrupt pin to latch interrupt requests. Reset clears the keyboardinterrupt enable register.1 = PTAx pin enabled as keyboard interrupt pin0 = PTAx pin not enabled as keyboard interrupt pin
Keyboard Interrupt Enable Register(INTKBIER)
False Interrupt Prevention
When a keyboard interrupt pin is enabled, it takes time for the internal pullup to reach a logic 1. Therefore, a false interrupt can occur as soon as the pin is enabled.
To prevent a false interrupt on keyboard initialization:
1. Configure the keyboard pins as outputs by setting the appropriateDDRA bits in data direction register A.2. Write logic 1s to the appropriate port A data register bits.3. Enable the KBI pins by setting the appropriate KBIEx bits in thekeyboard interrupt enable register.
Keyboard Interrupt Module Note:
Gracias!!!