Sie sind auf Seite 1von 67

APPENDIX A for Laboratory 2 sheet

Note:

When file avr/io.h is included in the .c file of a ATmega32A device C/C++ project, the file iom32.h is
inhibitly included in the source file. This file contain declaration of constants values for keywords of
ATmega32 registers address, pins names, bitnames and other entities. The copy of the file iom32.h can
be found in the same folder of this document.

A.1. AVR Digital Input/Output


Atmel AVR 8-bits microcontrollers provide pins to take in/output information form/to the
outside world in the form of logic values. These pins are usually organised in groups of eight (8)
and referred to as a port. The AVR use the alphabet to name these port, example PortA, PortB,
etc. Figure A.1 shows the pins of ATmega32A which has four (4) digital I/O ports: PortA, PortB,
PortC and PortD. The pins of PortA are: PA0 - PA7.

Figure A.1

Note
Notice the alternate name of the Ports pins in brackets. The AVR microcontollers are designed to
allow dual use of most of its pins (though a few has single or triple use). This has the advantage
of allowing a developer to use these pins as I/O pins if the function they are provided for is not
being utilized.

In this AVR tutorial we are only concern with the pins in there Digital I/O function, so for now
just forget they have alternate capabilities.

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
Important

The pins of the AVR microcontroller are not fixed as input or output at the manufacturing stage,
these pins are software configurable which is the topic of the section below.

a) Associated I/O Registers


Each of the AVR Digital I/O ports is associated with three (3) I/O register. A Data Direction
Register (DDRx), A Pin Register (PINx) and a Port Register (PORTx). Where x is the port A,
B, C, etc. .

DDRx - Port X Data Direction Register

DDRx is an 8-bit register which stores configuration information for the pins of Portx.
Writing a 1 in the pin location in the DDRx makes the physical pin of that port an output pin
and writing a 0 makes that pin an input pin.

Note: Each physical pin of a port is configured independently and thus a port can have some
of its pins configured as input and the others as output pins.

PINx - Port X Input Pins Register

PINx is an 8-bit register that stores the logic value, the current state, of the physical pins
on Portx when DDRx is 0. So to read the values on the pins of Portx, you read the values
that are in its PIN register.

Logic values from the pins on Portx that are configured as input pins are read
from the PINx register.

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
PORTx - Port X Data Register

PORTx is an 8-bit register which stores the logic values that currently being outputted on
the physical pins of Portx if the pins are configured as output pins. So to write values to a
port, you write the values to the PORT register of that port when DDRx is 1.

Logic values written to the PORTx register is outputted to the pins on Portx that are
configured as output pins.

Logic values read from the PINx register is equivalent to the values presently on the
pins of Portx which are configured as input pins.

b) Digital I/O Assembly AVR Programming in AVR Studio 5 / AVR Studio 6

The AVR assembly code below shows how to configure the pins on portA of an AVR
ATMega32A micocontroller.

In AVR Assembly Language:

LDI R16, 0xFF ; Load 0b11111111 in DDRA


OUT DDRA, R16 ; Configure PortA as an Output port
; Pin PAn (n from 0 thru 7) at Chip
; is connected to bit PORTAn
LDI R16, 0x00 ; Load 0b00000000 in DDRB
OUT DDRB, R16 ; Configure PortB as an Input port
; Pin PBn (n from 0 thru 7) at Chip
; is connected to bit PINBn

LDI R16, 0xF0 ; Load 0b11110000 in DDRC


OUT DDRC, R16 ; Configure first four pins on PortC
; as input and the others as output
; Pin PCn (n from 4 thru 7) at Chip
; is connected to bit PORTCn
; Pin PCn (n from 0 thru 3) at Chip
; is connected to bit PINCn

Code section below shows how to write to or read from the pins of an AVR microcontroller
port once they are configured. Assume here the configurations from the assembly code
above.

LDI R16, 0xFF ; Load 0b11111111 in R16


OUT PORTA, R16 ; Write all 1's in R16 to the pins of PortA

IN R16, PINB ; Read the values on the pins of PortB


; and store in R16

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

In C/C++ Language:

#include <avr/io.h>

DDRA = 0xFF //Configure PortA as an Output port


DDRB = 0x00 //Configure PortB as an Input port
DDRC = 0xF0 /*Configure first four pins on PortC as input
and the others as output*/

Code section below shows how to write to or read from the pins of an AVR
microcontroller port once they are configured. Assume here the configurations from the
C/C++ code above.

volatile uint8_t DataFromPortB;


PORTA = 0xFF // Write all 1's to the pins of PortA
DataFromPortB = PINB /*Read the values on the pins of PortB
and store in R16*/

Important Note: Be reminded that in order for the recognize the I/O registers aliases,
such as DDRA, DDRB, PORTA, PINB, etc., you must include the header file avr/io.h.

There are several things to note here.

1. The ports must be configured before they are used. The first four (4) lines of the
program are for configuration.
2. Once the ports are configured you can then write to or read from them, were
applicable.

Program In Assembly Language

LDI R16, 0x00 ; Load 0b00000000 in R16


OUT DDRB, R16 ; Configure PortB as an Input port
LDI R16, 0xFF ; Load 0b11111111 in R16
OUT DDRC, R16 ; Configure PortC as an Output port

Again: IN R16, PINB ; Read the values on the pins of PortB


; and store in R16
OUT PORTC, R16 ; Write the value in R16 to the pins
; of PortC
RJMP Again

The keywords of I/O Registers (in this case PORTD DDRD, PORTB and DDRB) are
declared in file m32defA.inc which by default are included by Atmel Studio 6 after
you have selected ATmega32A as the device in the project.

Program In C/C++ Language

volatile uint8_t DataFromPortB;


DDRB 0x00; /* Load 0b00000000 in DDRB
Configure PortB as an Input port*/
DDRC = 0xFF; /* Load 0b11111111 in DDRC
Configure PortC as an Output port*/

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
do{
DataFromPortB = PINB; /*Read the values on the pins of PortB
and store in DataFromPortB */
PORTC = DataFromPortB; /*Write the value in DataFromPortB to the pin
of PortC*/
}while(1)

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
c) Pull-up Resistor (for Active Low Switch)
Lets say you have an MCU with one pin configured as an input. If there is nothing connected to
the pin and your program reads the state of the pin, will it be high (pulled to VCC) or low (pulled
to ground)? It is difficult to tell. This phenomenon is referred to as floating. To prevent this
unknown state, a pull-up or pull-down resistor will ensure that the pin is in either a high or low
state, while also using a low amount of current.

For simplicity, we will focus on pull-ups since they are more common than pull-downs. They operate
using the same concepts, except the pull-up resistor is connected to the high voltage (this is usually
3.3V or 5V and is often referred to as VCC) and the pull-down resistor is connected to ground.

Pull-ups are often used with buttons and switches.

With a pull-up resistor, the input pin will read a high state when the button is not pressed. In
other words, a small amount of current is flowing between VCC and the input pin (not to
ground), thus the input pin reads close to VCC. When the button is pressed, it connects the input
pin directly to ground. The current flows through the resistor to ground, thus the input pin reads
a low state. Keep in mind, if the resistor wasnt there, your button would connect VCC to ground,
which is very bad and is also known as a short.

Since pull-up resistors are so commonly needed, many MCUs, like the ATmega32A
microcontroller, have internal pull-ups that can be enabled and disabled.

i. Internal Pull-up resistors for the ATmega32/ ATmega32A Input/Output port.

All Input/Output port pins have individually selectable pull-up resistors with a supply-voltage
invariant resistance. Referring to Figure A.2 which is an excerpt from page 51 of file Atmega32
Reference manual.pdf, if PORTxn is written logic one when the pin is configured as an input pin,
the pull-up resistor is activated. To switch the pull-up resistor off, PORTxn has to be written logic
zero or the pin has to be configured as an output pin. The port pins are tri-stated when a reset
condition becomes active, even if no clocks are running.
If PORTxn is written logic one when the pin is configured as an output pin, the port pin is driven
high (one). If PORTxn is written logic zero when the pin is configured as an output pin, the port
pin is driven low (zero).

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

Figure A.2: Configuring Digital I/O port.


ii. Programming digital I/O pin to enable pull-up resistor

A Digital I/O pin configured as an active low interrupt pin or an input pin, pull-up resistor
are necessary so that a stable logic I/high level state when the input on open circuit
condition.
By default PUD=0 and is specifically programmed to change it.
Normally, the pull-up enabled state is fully acceptable, as a high-impedant environment will
not notice the difference between a strong high driver and a pull-up. If this is not the case,
the PUD bit in the SFIOR Register can be set to disable all pull-ups in all ports.

Port pins can provide internal pull-up resistors (selected for each bit). If PORTxn is written
logic one when the pin is configured as an input pin, the pull-up resistor is activated. To
switch the pull-up resistor off, PORTxn has to be written logic zero or the pin has to be
configured as an output pin. The port pins are tri-stated when a reset condition becomes
active, even if no clocks are running..

To enable internal pull-ups on PortA which will function as Input port, you can use the
following line of code in your setup process:

Program In Assembly Language

clr r16 ;set all pins of PORTA as input


out ddra,r16;
ser r16 ;enable internal pull-up resistor all of PINA pins
out porta,r16;

Program In C/C++ Language

DDRA = 0x00; //set all pins of PORTA as input


PORTA = 0xff; // enable internal pull-up resistor all of PINA pins

A.2. Built-in Timers in ATmega32/ATmega32A chip


ATmega32/ATmega32A Timers have three timers (TIMER0, TIMER1 and TIMER2): two of a
resolution of 8 bits (TIMER0 and TIMER2) and one of a resolution of 16 bits (TIMER1). 8 bit
timer is 8 bits wide so capable of holding value within 0-255 in the TCNTn (TCNT0 or TCNT1)
register. 16 bits timer is capable of holding value within 0-65535 (better resolution) in the
TCNT2 register. But this register has a property that increases automatically at a predefined rate
or stop (determined by user by setting the Prescaler). This is the timer clock. And this operation
does not need CPUs intervention.
7

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

Figure A.2(1): Basic Operation Of an 8 bit Timer

Since Timer works independently of CPU it can be used to measure time accurately. Timer upon
certain conditions takes some action automatically or informs CPU. One of the basic conditions is
the situation when timer OVERFLOWS i.e. its counted up to its maximum value (255 for 8 BIT
timers) and rolled back to 0. In this situation timer will issue an Overflow Flag (TOVn i.e. TOV0
for TIMER0), or can invoke an interrupt (TIMERn OVF i.e. TIMER1 OVF for TIMER0) but you
must write an Interrupt Service Routine (ISR) to handle the event.

TOVn 0 (TOVn 1)

TOVx 0

TOVx = 1

Timer (TCNTx) can be initialise between 0 and 255 (for 8 bit TIMER)

Figure A.2(2): Basic Operation Of an 8 bit Timer

a) Basic Concepts of ATmega32 Timer


Timers are an important concept in the field of electronics. All the microcontrollers work
at some predefined clock frequency, they all have a provision to set up timers. Timers
can do counting, monitoring external events, keeping time, frequency generation,
generating accurately timed pulses, increment, decrement, Pulse width modulation
(PWM) and for registering the timestamp of external events(Input capture mode).

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

Figure A.2(a)(i)The waveform of TCNT0 which is initialised to start from count from
value 0x05 every time it reaches peak value 0xFF
In principle, a timer is a simple counter. The input clock of microcontroller and operation
of the timer is independent of the program execution. The deterministic clock makes it
possible to measure time by counting the elapsed cycles and take the input frequency of
the timer into account.
All the Atmel microcontrollers have Timers as an inbuilt peripheral. In this article we are
going to use the target controller ATmega32. ATmega32 comes with two 8 bit and one
16 bit timer. This means that there are 3 sets of timers, each with the ability to count at
different rates. The two 8-bit counters can count to 255 whilst the 16 bit counter can
count to 65,535. Timers can run asynchronous to the main AVR core it means timers are
totally independent of CPU. A timer is usually specified by the maximum value to which it
can count called MAX beyond which it overflows and resets to zero is called BOTTOM.
The speed of counting can be controlled by varying the speed of clock input to it. In
ATmega32 we have three different kinds of timers as follows

Timer 0 8 bit counter Can count up to 255 = MAX

Timer 1 16 bit counter Can count up to 65,535 = MAX

Timer 2 8 bit counter Can count up to 255 = MAX

However the total count taken must be added by 1 considering 1 count is take for the roll
over of count from MAX to 0

Most of us know this following formula

Figure A.2(a)(ii)

Taking

1 Time count takes 1 Time Period

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
therefor x 1 Time count takes x Time Period
Timer Clock = Frequency
Clock Time Period = Time Period = 1/Timer Clock
For a Timer Operation,
Required Delay = Time Count +1 (adding roll over count from MAX to 1)
Therefore:

Figure A.2(a)(iii)
iii. The Prescaler

In short, the prescaler divide the CPU frequency (F_CPU ) drive a lower frequency into the
Timer, without effecting actual F_CPU. Thus the Prescaler allow limit of delay derived from
the CPU clock be increased.

iv. Why we need prescaler?

By decreasing the Timer Clock we can increase the Clock Time Period proportionally. Thus we
can get a longer delay limited to the MAX count of the Timer

Assume we supply a 1MHz signal to timer and an 8 bit timer which can count max up to
255. Using the formula, we discussed that we can get a maximum delay of 256 s. Just
imagine, what if we need delay greater than 250ms ? One of the easiest thing we can do is to
use the timers prescaler that reduces the Timer0 clock. Prescaler allows us to divide up the
incoming clock signal by power of 2. It reduces the resolution which means that the accuracy
has decreased but giving us the longer timer range.

Prescalar can be set to produce the following clocks for the Timers:
1. No Clock (Timer Stop).
2. No Prescaling (Clock = FCPU)
3. F_CPU/8
4. F_CPU/32
5. F_CPU/64
6. F_CPU/256
7. F_CPU/1024
8. Timer can also be externally clocked

v. Choosing Prescalers

Start with Lowest Prescaler


1. (MAX count+1) * F_CPU/Prescaler = maximum delay
2. If the Required Delay > maximum delay, Prescaler take next highest available prescaler and
repeat 1.
3. If the Required Delay <= maximum delay, Prescaler can be taken.
The following is an example to get a timer delay of 184ms:

10

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

Now out of these four prescalers, 8 cannot be used as the timer value exceeds the limit of
65535. Also, since the timer always takes up integer values, 1024 is not accurate as the timer
count is a decimal digit (no decimal point) so either a count 717 or 718 (the nearest) can be
chosen. Prescaler values of 64 and 256 are feasible if accurate timing is needed. But out of
these two, prescaler value of 64 provides greater resolution. Prescaler value of 256 if chosen
proved the timer a greater duration if needed.

Thus, choose prescaler which gives the counter value within the feasible limit (255 for 8
bit timer or 65535 16 bit timer) and the counter value should always be an integer.

b) Timer Calculation for ATmega32

c) Generating a 250ms delay using TIMER by polling method


The following table shows a various prescaler setting and Timer Count to generate a 250 mSec
delay required on both 8 bit TIMER and 16 bit timer.

Delay 0.25 Sec


F_CPU 1 MHz
For 8 bit timers
Timer Clock (Hz) Timer Count For 16 bit timers
Prescaler (TIMER0 and
(F_CPU/Prescaler) (Delay X Timer Clock 1) (TIMER1)
TIMER2)
1 1000000 249999 Too big Too big
8 125000 31249 Too big Acceptable
Acceptable but not
64 15625 3905.25 Too big
exact
Acceptable but not
256 3906.25 975.5625 Too big
exact
Acceptable but Acceptable but not
1024 976.5625 243.140625
not exact exact
Table A.2(c)

We will use 8 bit Timer with prescaler=1024 and Count = 243

11

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

A.3. Registers In Timers Accessed for Programming Purposes


a) Relevant Timers registers for Timer 0, Timer 1 and Timer 2

Timer 0 Timer 1 Timer 2 Description


TCCR1A
TCCR0 TCCR2 Timer/Counter Control Register
TCCR1B
TCNT1A
TCNT0 TCNT2 Timer/Counter Count Register
TCNT1B
OCR2A
OCR0 OCR2 Output Compare Register
OCR2B
TIMSK Timer/Counter Interrupt Mask Register
TIFR Timer/Counter Interrupt Flag Register

In this Lab the following registers are of concern because they are used in the program:

i. TCNT0/TCNT2 Register

The Timer/Counter Register (TCNT0/TCNT1) itself is what all timer modes base on. It
counts System Clock ticks, prescaled from system clock or from the external clock.

Based on the formula

In TCNT0 will be filled will value (255-Time Count) to start count of TCNT0 so that
Time Count is counted before the TOV0 flag is set.

12

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
ii. TCCR0/TCCR2 Register

The Timer/Counter Control register is used to set the timer mode, prescaler and to Start or Stop
Timer.

iii. TCCR0/TCCR2 Register

In Normal Mode and we are taking Timer 0 as the example, we will concentrate on the
highlighted bits. The other bits will be discussed as and when necessary. By selecting
these three Clock Select Bits, CS02:00, we set the timer up by choosing proper
prescaler. The possible combinations are shown below and the functions of each
selection are described in red font..

The highlighted three Clock Select Bits, CS22:20 in TCCR2 also has similar
function as in TCCR0 which are specified as follows:

13

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

In TIMER0 the prescalers available are 8, 64, 256 and 1024, whereas in TIMER2, we
have 8, 32, 64, 128, 256 and 1024

iv. TIFR Register

Here we are concerned with the 0th bit - TOV0 bit (Timer/Counter0 Overflow Flag) and the 6th bit
TOV2 (Timer/Counter2 Overflow Flag). These bits is set (one) whenever the corresponding timer
overflows. It is cleared automatically whenever the corresponding Interrupt Service Routine (ISR) is
executed. Alternatively, we can clear it by writing 1 to it.

TIFR register holds the TOV0/TOV2 (and the TOV1) bits that indicates that Timer overflow
occurred when the count has reached maximum (0xFF) and then rolls over to 0x00 (0xFFFF
for Timer 1).

v. TIMSK

The Timer/Counter Interrupt Mask TIMSK Register is a common register for all the
three timers. For TIMER0, bits 1 and 0 are allotted. For TIMER1 bits 2, 3, 4 and 5 are
allotted. For TIMER2, bits 6 and 7 are allotted.

Setting 0th bit - TOIE0 bit to 1 enables the TIMER0 overflow Flag interrupt. When we
enable the overflow interrupt, TIMER0_OVF interrupt will be triggered when TOV0
changes from 0 to 1.

14

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

Setting 6th bit TOV2 Timer/Counter2 Overflow Flag interrupt.

b) Relevant registers for Timer1

Timer 1 Description
TCNT1 16-bit counter register
TCCR1A Mode of operation and other settings
TCCR1B Mode of operation, prescaler and other settings
OCR1A 16-bit Compare Register A
OCR1B 16 bit Compare Register B
TIMSK Interrupt Mask Register
TIFR0 Timer/Counter Interrupt Flag Register

In this Lab the following registers are of concern because they are used in the program:

i. TCNT1 (TCNT1H: TCNT1L) Register

The Timer/Counter Register (TCNT1) itself is what all timer modes base on. It counts
System Clock ticks, prescaled from system clock or from the external clock.

Based on the formula

In TCNT1 will be filled will value (65535-Time Count) to start count of TCNT1 so that
Time Count is counted before the TOV1 flag is set.

ii. TCCR1B Register

The TCCR1B Timer/Counter Control register is used to set the timer mode, prescaler and to Start
or Stop Timer.

The bit 2:0 CS12:10 are the Clock Select Bits of TIMER1. Their selection is as follows:

15

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

iii. TIFR

It holds the TOV1 bit that indicates that Timer overflow occurred (count has reached
maximum (0xFFFF) and then rolls over to 0x0000.

iv. TIMSK Register

The Timer/Counter Interrupt Mask Register TIMSK Register is as follows.

This is a common register for all the timers. The bits associated with other timers are greyed out.
Bits 5:2 correspond to TIMER1. Right now, we are interested in the yellow bit only. Other bits are
related to CTC mode which we will discuss later. Bit 2 TOIE1 Timer/Counter1 Overflow
Interrupt Enable bit enables the overflow interrupt of TIMER1. When we enable the overflow
interrupt TIMER1_OVF interrupt will be triggered when TOV1 changes from 0 to 1.
.

A.4. Timers Operations


a) Timer Modes:

Timers are used in one of the following modes:

Normal
CTC
Fast PWM
Phase correct PWM

To use the Timer to generate Delay, Normal mode needs to be used. To select Normal mode, all
WGMxx bits in the respective TCCRx registers must be cleared. This can be done when selecting
the Prescaler of the respective Timers TCCRx Registers.

16

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

Example of Mode Selection bits on Timer 0 Registers

Figure A.4(f)

b) Algorithm to program Timer Operation in normal mode.

The following is the Algorithm

Set Starting count in TCNTx


Start Timer which by setting prescaler
Wait for TOVx bit (overflow bit) is set (while TCNTx counts up in background).
When TOVx bit is set, Clear TOVxbit by writing 1 to TOVx bit.
Stop Timer

Referring to Section A.3(g) in this document, in a subroutine (if in assembly language) or function
(if in C/C++ language), we start TCNT0 with (255-243) i.e. 12 and starts the counting up to the
255 (by setting TCCR with prescaler=1024) , after this state (count) TOV0 will be generated, the
time taken will be 250 mSec. We will keep check the TOV1 bit to identify the 250sec delay.

Then we can Clear TOV0 bit, and restart Timer when needed.

The code in Assembly Language assuming the subroutine name is Delay250msUsingTimer

Delay250msUsingTimer0:
/*Referring to the Theory and calculations in Section A.3
of "Appendix A For SKEE3732 Laboratory 2 Sheet"*/
// Refer Section A.3(k)
ldi r16,255-243
out TCNT0,r16 //start TCNT0 with (255-243) i.e. 12
ldi r16,(1<<CS02) | (1<<CS00)
out TCCR0,r16 //Set Prescaler =1024
wait: //Do
// {
in r16,TIFR
sbrs r16,TOV0 //Read status of TOV0 bit in TIFR
rjmp wait // }while TOV0==0
ldi r16,1>>TOV0
out TIFR,r16 //Clear TOV0 bit
ret

17

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

The code in C/C++ Language, assuming the function name is Delay500msUsingTimer0

void Delay250msUsingTimer0(void)
{
// Refer Section A.3(k)
TCNT0 = 255-243; /*start TCNT0 with (255-243) i.e. 12
*/
TCCR0 = (1<<CS02) | (1<<CS00); //Set Prescaler =1024
volatile uint8_t TIFRdata;
do //Wait
{
TIFRdata=TIFR&(1<<TOV0); //Read status of TOV0 bit in TIFR

} while (TIFRdata==0); //until TOV0==1


TIFR=TIFR|TIFRdata; //Clear TOV0 bit;
}

A.5. Interrupts.

Any reasonable microprocessor system must have several external devices connected to it and
must be able to communicate with these devices. All of these devices must have some sort of
AVAILABLE signal telling the microprocessor that data is available for it or that it is available for
use. There are two methods for a microprocessor to communicate with external devices: Polling
and interrupts.

Polling is the act of periodically querying the AVAILABLE lines on all the input devices to see if data is
available. The disadvantage of polling is that the polling routine must be entered periodically (very
often if high speed data is coming through) and there may be too little time for the microprocessor
to execute its program.

Interrupts is an alternative, more efficient method of communication. Here, when the I/O device
has data for the microprocessor or requires some other service it issues an interrupt request. An
interrupt request can come at any time during the execution of a program and generally comes
while the microprocessor is executing an instruction. The following figure shows the
microprocessor executing its main program when an interrupt request occurs.

18

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
Interrupts are basically events that require immediate attention by the microcontroller. When an
interrupt event occurs the microcontroller pause its current task and attend to the interrupt by
executing an Interrupt Service Routine (ISR) at the end of the ISR the microcontroller returns to
the task it had pause and continue its normal operations (executed by the RTI instruction).

An interrupt service routine in other words is just like a subroutine; except that it is not anticipated
by the processor to occur at a particular time, since there are no explicitly placed calls to it in the
program.

In order for the microcontroller to respond to an interrupt event the interrupt feature of the
microcontroller must be enabled along with the specific interrupt. This is done by setting the
Interrupt Enable bit of the specific interrupt and the Global Interrupt Enabled bit.

a. Interrupt vector table (Location of information to tell CPU where to find the service routine
of the respective interrupt)

An interrupt vector table: a table of interrupt vectors (pointers to Interrupt Service Routine
that handle interrupts). When source of Interrupt is generated (after it has been enabled and
Global Interrupt Enabled bit is set), PC (program Counter) will be initialised with value
Vector Address defined under the Program Address column of the interrupt generated. The
event of interrupt is given under the Interrupt Definition column.

For Example when RESET occur, PC will be initialised with $0000 (though the number is 3 hex
digit under Program Address, a 4 hex digit number will be stored to PC because PC is a 16 bit
register). If INT2 interrupt occurs, PC will be initialised with $0006. Except RESET that does
not have a current instruction that it is executing, when an interrupt occur, the CPU will
complete the current instruction that it is executing and save the address of PC (next
instruction to be executed) to the STACK before PC is initialised with interrupt vector Address.
Refer Section A.5(b) for example of implementation.

19

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

Figure A.5 (a)(i): Interrupt Vector Table reserved in Program Memory for ATmega32 (ATmega32A)

20

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

Vector Address Source ATmel Studio C/C++ Keywords Interrupt Definition


No. Name Event
1 $000 Reset Changes from High to No needed since it is by default External Pin, Power -on
Low at On Chips assigned by C/C++ compiler Reset, Brown -out Reset,
RESET Pin referencing to main() function Watchdog Reset, and JTAG
AVR Reset
2 $002 INT0 Status at On Chips INT0_vect External Interrupt Request 0
INT0 Pin as defined by
ISC01:ISC00 bits of the
MCUCR register
3 $004 INT1 Status at On Chips INT1_vect External Interrupt Request 1
INT1 Pin as defined by
ISC11:ISC10 bits of the
MCUCR register
4 $006 INT2 Status at On Chips INT2_vect External Interrupt Request 2
INT1 Pin as defined by
ISC2 bit of the
MCUCSR register
5 $008 TIMER1 COMPA TIMER1_COMPA_vect Timer/Counter1 Compare
Match A

6 $00A TIMER2 OVF TIMER2_OVF_vect Timer/Counter2 Overflow

7 $00C TIMER1 CAPT TIMER1_CAPT_vect Timer/Counter1 Capture


Event
8 $00E TIMER2 COMP TIMER2_COMP_vect Timer/Counter2 Compare
Match

9 $010 TIMER1 COMPB TIMER1_COMPB_vect Timer/Counter1 Compare


Match B

10 $012 TIMER1 OVF TIMER1_OVF_vect TIMER1 OVF Timer/Counter1


Overflow

11 $014 TIMER0 COMP TIMER0_COMP_vect Timer/Counter0 Compare


Match
Changes on Status bit
of respective I/O
12 $016 TIMER0 OVF TIMER0_OVF_vect Timer/Counter0 Overflow
Register (Refer
Reference manual)
13 $018 SPI, STC SPI_STC_vect Serial Transfer Complete

14 $01A USART, RXC USART_RXC_vect USART Rx Complete

15 $01C USART, UDRE USART_UDRE_vect USART Data Register Empty

16 $01E USART, TXC USART_TXC_vect USART, Tx Complete

17 $020 ADC ADC_vect ADC Conversion Complete

18 $022 EE_ RDY EE_RDY_vect EEPROM Ready

19 $024 ANA_COMP ANA_COMP_vect Analog Comparator

20 $026 TWI TWI_vect Two -wire Serial Interface

21 $028 SPM_ RDY SPM_RDY_vect Store Program Memory


Ready

Figure A.5 (a)(ii): Atmel Studio C/C++ Interrupt Service Routine Keywords for the ATmega32/ATmega32A
Vector Table (Refer Figure A.5 (e) for pins defined for vector 1 thru 4)

21

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
b. Interrupt Service Routine or Interrupt Handler (The program that implement the function of
the Interrupt)

An Interrupt Service Routine (ISR) or Interrupt Handler is a piece of code that should be
executed when an interrupt is triggered. Usually each enabled interrupt has its own ISR. In
AVR assembly language each ISR MUST end with the RETI instruction which indicates the
end of the ISR.

In C language programming, when the Interrupt Service Routine Keywords is used as the
name of the function, the RETI instruction will be inserted by default by the Atmel Studio
C/C++ (GCC) compiler.

Example in Setting Up INT0, INT1 and INT2 ISR (Interrupt Service Routine)

.ORG 0X00//Vector Table


jmp Boot //On Reset, jump to Boot
jmp Int0ISR //On INT0 interrupt, jump to Int0ISR
jmp Int1ISR //On INT1 interrupt, jump to Int1ISR
jmp Int2ISR //On INT1 interrupt, jump to Int1ISR

//Somewhere in the Assembly Language Program


Int0ISR:
//Codes here
reti

Int1ISR:
//Codes here
reti

Int2ISR:
//Codes here
reti

The interrupt service routine will be set to be called by executing a jump <address of ISR> at
the vector address of interrupt defined in the Interrupt vector Table. Example of
implementation:

In C language programming, when the Interrupt Service Routine Keywords is used as the
jump <address of ISR> will be inserted by default by the C/C++ (GCC) compiler.

Example in Setting Up INT0, INT1 and INT2 ISR (Interrupt Service Routine)

//Interrupt Service Routine for trigger on Pin INT0


ISR(INT0_vect)
{
// Codes here;
}

//Interrupt Service Routine for trigger on Pin INT1


ISR(INT1_vect)
{
// Codes here;
}

//Interrupt Service Routine for trigger on Pin INT2

22

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
ISR(INT2_vect)
{
// Codes here;
}

c. Interrupt Flags and Enabled bits (Tell CPU that particular interrupts are enabled)

Each interrupt is associated with two (2) bits, an Interrupt Flag Bit and an Interrupt
Enabled Bit. These bits are located in the I/O registers associated with the specific interrupt:

The interrupt flag bit is set whenever the interrupt event occurs, whether or not
the interrupt is enabled.
The interrupt enabled bit is used to enable or disable a specific interrupt. Basically
is tells the microcontroller whether or not it should respond to the interrupt if it is
triggered.

In summary basically both the Interrupt Flag and the Interrupt Enabled are required for
an interrupt request to be generated as shown in the Figure A.5 (c).

Figure A.5 (c): Hardware implementation on External Interrupt in ATmega32 (ATmega32A)

d. Global Interrupt Enabled Bit (Tell CPU to service all interrupts are enabled)

Apart from the enabled bits for the specific interrupts the global interrupt enabled bit MUST
be enabled for interrupts to be activated in the microcontroller.

For the AVR 8-bits microcontroller this bit is located in the Status I/O Register (SREG). The
Global Interrupt Enabled is bit 7, the I bit, in the SREG.

In assembly language the SEI instruction set the I bit and the CLI instruction clear the bit.

In C/C++ language the sei() function set the I bit and the cli() function clears the bit. The functions
are declared in avr/interrupt.h which must be included in the program.

e. Interrupt Request sources provided with the AVR microcontroller


The AVR 8-bits microcontroller provides both internal and external interrupt sources. The
internal interrupts are associated with the microcontroller's peripherals. That is the
Timer/Counter, Analog Comparator, etc. The external interrupts are triggered via external
pins. The Figure A.5 (e) shows the pins, on which the external interrupts can be triggered, for
an AVR 8-bit microcontroller. When an Interrupt is triggered, the CPU will execute its service

23

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
routine whose starting address is defined in the Interrupt vector table. On
ATmega32/ATmega32A microcontroller there are four (4) external interrupts:

1. The RESET interrupt - Triggered from pin 9 (executed like an interrupt but does not
operate as an interrupt because RETI instruction cannot be used in RESET
Interrupt service routine.
2. External Interrupt 0 (INT0) - Triggered from pin 16.
3. External Interrupt 1 (INT1) - Triggered from pin 17.
4. External Interrupt 2 (INT2) - Triggered from pin 3.

Figure A.5 (e): Location of External Interrupt pins in ATmega32/ATmega32A

Important Notes:

As it relates to AVR microcontrollers - An interrupt vector is the program memory address


of an interrupt service routine (interrupt handler). The interrupt vector for each interrupt
provided by the AVR microcontrollers can be found in its datasheet. Figure A.5 (a)(i) is an
extract from the section of the ATMega32 datasheet that shows the interrupt vector table
that identify the interrupt vectors (address of respective ISR) for the interrupts provided
with this microcontroller (ATMega32/ ATMega32A).

Please note here that the memory location for interrupt vector table which should be
reserved for storing pointers to interrupt handlers (ISR) are not used to store regular
programs code. For ATmega32/ ATMega32A should not use address below 0x2A i.e. the
vector interrupt table memory area.

f. Very Important When Writing Assembly Codes Utilizing the Interrupt Feature

When writing assembly codes for ATmega32A utilizing the interrupt feature the following
MUST be observed:

The interrupt MUST be enabled by setting its enabled bit in the appropriate I/O
register i.e. the General Interrupt Control Register (GICR).
24

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
The Global Interrupt bit, the I bit, in the microcontroller's status register (SREG)
MUST also be enabled by using the SEI instruction.
The stack MUST be initialized (Normally at the beginning of the Main Program).
When an interrupt is being service the microcontroller needs to store critical
information on the stack.
The Triggering Condition (in MCUCR for INT0 and INT1 and in MCUSCR for INT2)
must be specifically set to suit hardware wiring configuration of the interrupt pin.
Enable internal pull-up resistor if external pull-up resistor is not wired for active low
interrupt input.
The Interrupt Service Routine (ISR) MUST end with the RETI instruction, which
indicates the end of the ISR. The microcontroller needs to know when it reaches the
end of the ISR so it can return to its previous task.

RETI will also set I bit so that Global interrupt is enabled because I bit is cleared
when CPU service any interrupt.

Refer AVR instruction Set.

A.6. Development Tools for ATMega32A


a) The JTAGICE mkII AVR Debugger
The AVR JTAGICE mklI from Atmel is a development tool for On-chip Debugging of all AVR 8-bit
RISC microcontrollers with IEEE 1149.1 compliant JTAG interface or debugWIRE Interface.
DebugWIRE enables on chip debug of AVR microcontrollers in small pin count packages, using
only a single wire for the debug interface.
The JTAGICE mkII and the AVR Studio user inter-face give the user complete control of the
internal resources of the microcontroller thus making hardware debugging easier.
The JTAGICE mkII performs Real Time emulation of the microcontroller while it is running in a
target system.

25

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

Figure A.6: JTAGICE mklI Device and its JTAG connector, USB port and USB cable

26

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
b) Gotronik Atmega32A Target Board

The board will power up when with 5V supply via the USB port. The ATmega32A RESET pin
switch connected to a push button as shown in Figure A.6(a) and Figure A.6(b). The VREF
voltage can be adjusted from 0 5V as shown in Figure A.6(c) and Figure A.6(d). Two pins
jumper terminals is connect to every I/O pins of the ATmega32A chip as shown in Figure A.6(d)
which will allow user to optionally connects it to peripheral devices.

External Circuits Connections to ATMEGA Processor

Reset Button:

Figure A.6(b): Press this button to


generate a LOW voltage to the RESET
LINE

Figure A.6(a)

27

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
Voltage reference Aref

Figure A.6(d): Adjust this Potentiometer


to adjust the Analog Reference
Voltage(AREF). Voltage can be measured
at the Vref pin.
Figure A.6(c)

Figure A.6(f)
Figure A.6(e)

The board is built-in with the following peripherals which can be connected to the ATmega32A
using jumper wires:

1. 8 bits LED panel

2. Multiplexed four 7-segment LED-displays Panel

3. 8 bit Push Button Panel

4. Potentiometers

5. Power transistors "open collector" ULN2803

6. Buzzer

28

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
i. 8 bits LED panel (Layout and Circuits)

Figure A.6(g)

29

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
ii. Multiplexed four 7-segment LED-displays Panel (Circuits and Pins Layout)

Figure A.6(h): Circuits


DS4 DS3 DS2 DS1 DS1
DS4 DS3 DS2

Figure A.6(i): Layout


30

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

Interfacing Seven-Segment Display with the AVR Microcontroller

The seven LEDs in the seven segment display are labelled with the letters a, b, c, d, e, f and as indicated in Fig A6(d) below. Some seven segment
display may include 1 or 2 additional LEDs which are used as decimal point(s).

Fig A.6(j)

Here letter "a" represents pin 7.

Similarly

Letter "b" represents pin 6.

Letter "c" represents pin 4

Letter "d" represents pin 2

Letter "e" represents pin 1

Letter "f" represents pin 9

Letter "g" represents pin 10

31

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

1. Common cathode display - As we know seven segment display are made by combining 8 LED's. So in this configuration negative lead of all
LED's are connected together and remaining leads used as segment display. Current limiting resistors are connected in series with each
individual segment. To switch ON any of the LED, the segment lead must be given a logical HIGH voltage.

2. Common anode display- In this configuration positive pin of all 8 LED's connected together and negative leads are used as segment display
pin's. To switch ON any of the LED, the segment lead must be given a logical HIGH voltage.

Now suppose you want to make numeric "2" than segment which we have to switch ON are "a", "b", "g", "e", "d".

Now suppose you want to display numeric "4", the segment which are switched ON is "4" are "f", "g", "b", "c".

Now suppose you want to display alphabet "L", then segment which are switch ON are "f", "e", "d".

Figure A.6(ii) show possible alphabet character that can be display by a 7-segment Display

Fig A6(k)

Example Seven Segment (SS) code for Active Low Characters A b and c are 0x77, 0b01111100 and 0x4e respectively.

32

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
iii. 8 bit Push Button Switch Panel (Layout and Pins Circuits)

Figure A.6(l)

33

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
iv. Potentiometers (Pins Layout and Circuits)

Figure A.6(m)

Figure A.6(n)

34

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
v. Buzzer (Pins Layout and Circuits)

Layout

Figure A.6(o) Circuits

Figure A.6(p)

vi. Buffer
s
ULN2
803

Figure A.6(r)Circuit
Figure A.6(q): Layout

35

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
A.7. Connecting the JTAGICE MkII to the Gotronik Atmega32A Target Board
a) Physical Connection

Correct JTAG connection: The red stripe of the cable must be pointing towards the edge of the
board.

Important, if JTAGICE MkII JTAG connected to the Gotronik Atmega32A Target Board:

1. Always switch ON JTAGICE MkII first before the Gotronik Atmega32A Target Board.
2. Always switch OFF the Gotronik Atmega32A first Target Board before JTAGICE MkII
3. Or remove JTAG connection and either device can be independently switch ON of OFF.
4. You may at any time JTAG connect or disconnect them if both device already ON of OFF.

36

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
A.8. Building A Simple Firmware for the ATmega32A Target Board
To build a firmware we must know the specifications of Input/Output devices on ATmega32A
target board to determine what signal we can receive or send out, the specifications of the
Processor architecture. A useful computer needs Input and Output interface to the external world
which is call peripherals from where commands or data can be received and response can be sent
out. For a simple ATmega32A microcontroller application, the input for command can be
received from push buttons, the input for Data can be received from the ADC (but we are going to
use the ADC in experiment 2 only) and output can be sent to LEDs panels and/or Seven Segment
Display. We will be using Timers for both Experiment 1 and Experiment 2.

a) Wiring of Peripherals to ATmega32A Chip


Referring section A.6, the ATmega32A Target Board is to be wired up with the following
Input/Output connections:

Table A.8(a)
Atmega32A Chip Peripheral connectors
PortA pins 8 bits LED panel connector (Leftmost LED connected to MSB of PortA)
(External logical connection to PORTA)

PortD pins Push Buttons connector


SW7 wired to PD7 (External logical connection to PIND7)
SW6 wired to PD6 (External logical connection to PIND6)
SW5 wired to PD5 (External logical connection to PIND5)
SW4 wired to PD4 (External logical connection to PIND4)

37

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

b) Function of a Firmware on a Microcontroller


A firmware is an operating system programmed to the Flash Memory (non-volatile) that gives life
to the microcontroller when powered-up (RESET) and have intelligence to process command
received. How a firmware is built is dependent on the peripherals connect to it and the function
the microcontroller is intended to be built with. Referring to section A.1 (c) as an example

Generically, a basic operating system does as :

On RESET initialize STACK, peripherals controls and environment variables.


And repetitively (called in a shell loop)
Display Prompt (Indicating Alive signal)
Get Command (Interaction from User)
Execute Command (response from user Input: the Switch by polling method
or interrupt request trigger). Refer Section A.4 of this document.

This basic operating system can be described with the following flowchart:

38

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

Reset

initialise peripherals controls

initialise environment variables

Any Display prompt (Indicating Alive)


Command?

Comman
d
Get Command

Execute Command

Figure A.8(b)

i. Environment Variables

Information on properties or characteristic of the OS Shell which can be change/set by OS


itself, from input of peripherals, events from interrupt or subroutine. They are unlimited
number, of any data type that tells OS about anything and everything in order for the OS to
behave. As simple example the Environment Variables will hold information of sources of
input, destination of display, size of display information, current process, pending process,
command received from user, etc. etc.

ii. Prompt

Some kind of output, e.g. buzzer, LED blinks, cursor blinks, clock display, etc. etc. showing
that the system is alive and in a shell waiting for a command (input)

iii. Shell Loop

The heart of the OS that repetitively check for command and execute command received.

iv. Get Command and Execute Command

These two processes complement each other as the brain of the OS. Without these two
processes the OS has no intelligence receiving command or executing commands received.
Command may not be from human. It can be from switches, sensors or communication device.
output may be to transducers, display device or communication device.

v. A Simple OS that uses Polling method to receive command for the ATmega32 Target board

Based on the connections given in Table A.8(a), and flowchart in Figure A.8(b) we will build a
OS on the ATmega32 which will have the following functions:
39

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
1. When powered up or RESET you will see the Digit DS4 of the seven segment panel
counting from 0 to 9 and roll over to 0 every 1 sec.

2. The counting from 0 to 9 and roll over to 0 is stored in a variable which ore updated in
the Shell Loop.

3. If any of the following condition occur on any of the Push Button switches (become the
command), the respective Function as shown in Table A.8(b) will occur (executed):

Table A.8(b)
Push Button # Function at LED panels (at pace of 250 millisecond)
pressed
SW7 Display Running Light sequence
SW6 Display Flashing Light sequence (to be implemented by
Students)
SW5 Display Knight Rider Lights sequence
SW4 Display Alternate Light sequence (to be implemented by
Students)

40

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
c) Program Design
The flowchart of the firmware is given in Figure A.8(c).

The Program of the firmware, Lab2Pre.asm.c is given in Figure A.8(d) which is built based on the
flowchart in Figure A.8(c) .
Table A.8(c)
Description of objects in Flowchart

Object Example Description

Curve Edge Square On Reset


Entry into program or
Termination from program

Black 4 edge diamond Decision box: Determines the


condition the program flow
Count F
<10? split up
T

Black rectangle Process: A single, a set of


Count 0
instruction or subroutine or
functions that implements a
certain task

41

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

On Reset

Initialise I/O Registers for Peripherals

Initialise background program

Abbreviation:

T = True
Initialise all Environment variables F = False

T F
Any
Switch
Pressed?

SW7
pressed T RunningLights()
?
F
Display Count character at DS1

Wait 250ms
SW6
T FlashingLights()
pressed?
Update Count
F

SW5
pressed? T KRiderLights()

SW4
pressed? T AlternatLights()

Figure A.8(c)
42

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
d) Experiment 1: A Firmware using Polling Method to Receive Command
/*
* Lab2Exp1.c
*
* Created: 27/9/2016 11:07:25 PM
* Author: Zuraimi bin Yahya
*/
/*
This program is configured for the Connections to an ATmega32A chip the Gotronik board
as specified in Table A.8(a) of "Appendix A For SKEE3732 Laboratory 2 Sheet.pdf"
*/

/*
When Debugger and Target board is already connected,
you can check the CPU clock from the Tools|Device Programming and after JTAGICE MkII ATmega32A,
JTAG,
Apply and Read if the Device Signature display 0x1E9502 then select Fuses Tab, and under Fuse Name
in SUT_CKSEL Tab. INTRCOSC_1MHZ_6CK_64MS_DEFAULT denotes the 1Mz CPU clock
*/

/*
Connections:
Refer A.8 of "Appendix A For SKEE3732 Laboratory 2 Sheet.pdf"
Wiring connections are specified in Table A.8(a)
The Seven Segment Display Panel SEGMENT lines (dp, g, f, e, d, c, b and a) are
connected to Port B (PB7, PB6, PB5, PB4, PB3, PB2, PB1 and PB0 pins respectively).

The Seven Segments Panels are Common Anode LEDs.


Each of Common Anode pins of DS4, DS3 DS2 and DS1 Seven Segments
at the CYFRA jumper (S4, S3 S2 and S1 respectively) which are Active low input
and are respectively connected to PC7, PC6, PC1, PC0 pins of the ATmega32 chip

8 bit LEDs of the LED panel is connected to Port A pins of ATmega32 chip

SW7, SW6, SW5 and SW4 which are connected to PD7, PD6, PD5 and PD4 respectively.
SW1 and SW0 is connected to PD3(INT1) and PD2(INT0)
SW7, Sw6, Sw5, SW4, SW3, SW2, SW1 and SW0 are Active Low Inputs.
Input from SW3, SW2, SW1 and SW0 are ignored in this program

Functions of program Lab2Exp1.c:


When Switched ON or RESET occur, at all time Seven Segment Panel will display
a single digit count up at DS1 and ON all LEDs at LED panel,
and waits input from SW7, SW6, SW5 and SW4 which are connected to PD7, PD6, PD5
and PD4 respectively and implement the following task:

SW7 Pressed: Perform Running Light sequence on LED Panel at a 1 sec pace
SW6 Pressed: Perform Flashing Light sequence on LED Panel
SW5 Pressed: Perform Knight Rider Light sequence on LED Panel
SW4 Pressed: Perform Alternate Light sequence on LED Panel
None pressed: Last LED display when switch is released
*/

/*In this Laboratory 2a, we will use standard C99 data types instead of the ANSi C
defined as follows:
int8_t instead of char
uint8_t instead of unsigned char
int16_t instead of int
uint16_t instead of unsigned int
uint32_t instead of unsigned long
int32_t instead of long
int64_t instead of long long
uint64_t instead of unsigned long long
*/

/*
Headers of Library used
Refer http://www.nongnu.org/avr-libc/user-manual/modules.html
*/
#include <avr/io.h>

43

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
#include <avr/pgmspace.h>
#define F_CPU 1000000 //Define CPU speed as 1MHz
#include <util/delay.h>
#include <avr/interrupt.h>
#include <math.h>

/*
Identifier that represent constant value which logically represent
the functional use of the constant
*/

#define ActveLowOutput 0xff


#define OnDS1 0b11111110
#define OutPort 0xff
#define InPort 0x00
#define MaskOffLowerNibbleHigh 0b00001111
#define AllOff 0b11111111
#define True 0xff
#define False 0x00
#define InvertData 0b11111111

/*
Push Button switches Panel Data
A '0' denotes that switch on the respective bit is pressed
*/
#define SW7Pressed 0b01111111
//#define SW6Pressed 0b10111111
#define SW5Pressed 0b11011111
//#define SW4Pressed 0b11101111

/*
Look-up table in Program Memory for Numeric Digit
Refer Section C.2 of "Appendix C For SKEE3732 Laboratory 1 Sheet.pdf"
*/
const uint8_t SS_table[10] PROGMEM = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d, 0x07, 0x7f, 0x6f};

/*When Debugger and Target board is already connected,


you can check the CPU clock from the Tools|Device Programming and after JTAGICE MkII ATmega32A, JTAG,
Apply and Read if the Device Signature display 0x1E9502 then select Fuses Tab, and under Fuse Name
in SUT_CKSEL Tab. INTRCOSC_1MHZ_6CK_64MS_DEFAULT denotes the 1Mz CPU clock
*/

//Global Variables (environment variables)


static volatile uint8_t CountData;
static volatile uint8_t RunningLEDdata;
//static volatile uint8_t FlashingLEDdata;
static volatile uint8_t KnightRiderLEDdata;
//static volatile uint8_t AlternateLEDdata;
static volatile uint8_t MSBlookahead;
static volatile uint8_t LSBlookahead;
static volatile uint8_t RunningLeft;
static volatile uint8_t RunningInwards;
static volatile uint8_t DS1Count;

/*
Prototypes declaration
*/
void OutLED(volatile uint8_t);
void DelaymsUsingTimer2(volatile uint8_t);
/*
Function name: Delay2sUsingTimer1()
-----------------------------------
Operation: Wait for 1 sec before exiting
*/
/*
Theory:
Referring to the Theory and calculations in Section A.2
of "Appendix A For SKEE3732 Laboratory 2 Sheet"

Note: Maximum count (highest value +1) for 16 bit register = 65536 .

44

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
for a F_CPU at 1000000Hz, the delay taken for the maximum count of 65536 before
TOV1=1 (TIMER1 overflow will occur):
prescaler TimerClock Delay(s)
--------- ---------- ---------
1 1000000 0.065536
8 125000 0.524288
64 15625 4.194304
256 3906.25 16.777216
1024 976.5625 67.108864

So if we take a prescaler of 64 we can get a delay from 0 to 4.194304 sec


This would be an optimum Precaler for a 2 sec delay.

if 4.194304ms(calculated from 65536*64/1000000) = 65536 count


then for 1 ms = 256/(256*64/1000) = 1/(64/1000)
Therefore for Delays sec = (Delays/(64/1000000) count
We will use this expression to calculate count from the input parameter Delayms
For a 2 sec delay, Count = 2/(64/1000000) = 31250 (rounded)

Since 1 count is added in the count process (changes from 0xFFFF to 0x0000
before the TOV2 bit is set)
Actual count = Count -1
*/
void Delay2sUsingTimer1(void)
{
// Refer Section A.3 and A.4 of "Appendix A For SKEE3732 Laboratory 2 Sheet"
TCNT1 = 65535-31249; /*start TCNT1 with (65535-31249) i.e. 34286
so that counter TCNT1 will count 31249*/
TCCR1B = (1<<CS11) | (1<<CS10); //Set Prescaler =64
static volatile uint8_t TIFRdata;
do //Wait
{
TIFRdata=TIFR&(1<<TOV1); //Read status of TOV0 bit in TIFR
} while (TIFRdata==0); //until TOV0==1
TCCR1B = 0; //Set Prescaler = 0, no clock and thus stop timer
TIFR=TIFR|1<<TOV1; //Clear TOV0 bit by writing 1 to TOV0 bit;
}

/*
Function name: OutDataDS1()
---------------------------
Operation: Display character in received in "data" at DS1 Seven Segment
*/
void OutDataDS1(uint8_t data)
{
volatile uint8_t SSData;
SSData=pgm_read_byte_near(&SS_table[data]); //Get Seven Segment Character Code for data
DDRB=OutPort;
DDRC=OutPort;
PORTB=SSData^ActveLowOutput; //Write to Port B from !tempdata
PORTC=OnDS1;
}

/*
Function name: DoRunningLight()
-------------------------------
Operation: Display one pattern of the current sequence, wait 250ms,
update RunningLEDdata with the next pattern of the sequence and exit
Input: Environment Data "RunningLEDdata"
output: updated "RunningLEDdata"
*/
void DoRunningLight(void)
{
OutLED(RunningLEDdata); //Write RunningLEDdata at LED panel
/*
Update RunningLEDdata for next sequence
*/
if (RunningLeft==True) //If LEDs is running Left
{
if (RunningLEDdata==0b10000000) // If Leftmost is reached
{

45

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
RunningLEDdata=RunningLEDdata>>1; // Shift LEDs right
RunningLeft=False; // Flags to Shift right
}
else // Else
{
RunningLEDdata=RunningLEDdata<<1; // Shift LEDs left
}
}
else
{
if (RunningLEDdata==0b00000001) // If Rightmost is reached
{
RunningLEDdata=RunningLEDdata<<1; // Shift LEDs left
RunningLeft=True; // Flags to Shift left
}
else
{
RunningLEDdata=RunningLEDdata>>1; // Shift LEDs right
}
}
DelaymsUsingTimer2(250); //wait for 250ms
}

/*
Function name: DoKnightRiderLight()
-----------------------------------
Operation: Display one pattern of the current sequence, wait 250ms,
update KnightRiderLEDdata with the next pattern of the sequence and exit
Input: Environment Data "KnightRiderLEDdata"
output: updated "KnightRiderLEDdata"
*/
void DoKnightRiderLight(void)
{
OutLED(KnightRiderLEDdata); //Write KnightRiderLEDdata at LED panel
DelaymsUsingTimer2(250); //wait for 250ms
if (RunningInwards==True) //If sequence is running Inwards
{
switch(KnightRiderLEDdata)
{
case 0b10000001:
KnightRiderLEDdata=0b01000010;
break;
case 0b01000010:
KnightRiderLEDdata=0b00100100;
break;
case 0b00100100:
KnightRiderLEDdata=0b00011000;
break;
case 0b00011000:
RunningInwards=False;
break;
}
}
else //Else (sequence is running Oytwards)
{
switch(KnightRiderLEDdata)
{
case 0b00011000:
KnightRiderLEDdata=0b00100100;
break;
case 0b00100100:
KnightRiderLEDdata=0b01000010;
break;
case 0b01000010:
KnightRiderLEDdata=0b10000001;
break;
case 0b10000001:
RunningInwards=True;
break;
}

46

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
}

/*
Function name: OutLED()
-----------------------
Operation: Write inverted content of "data" to Port A
*/
void OutLED(volatile uint8_t data)
{
DDRA=OutPort; //Set PortA as Output port
PORTA=data^ActveLowOutput; //Port A after inverting "data" (because active low output)
}
/*
Function name: DelaymsUsingTimer2()
-----------------------------------
Receives value delay in parameter Delayms
Operation: Wait for Delayms msec before exiting

*/
/*
Referring to the Theory and calculations in Section A.2(b) and (c)
of "Appendix A For SKEE3732 Laboratory 2 Sheet"

Note: Maximum count for 8 bit register = 256 .


for a F_CPU at 1000000Hz, the delay taken for the maximum count of 256 before
TOV2 bit=1 (TCNT2 Overflow will occur):
prescaler TimerClock Delay(msec) CS22 CS21 CS20
--------- ---------- --------- --------------
1 1000000 0.256 0 0 1
8 125000 2.048 0 1 0
32 31250 8.192 0 1 1
64 15625 16.384 1 0 0
128 7812.5 32.768 1 0 1
256 3906.25 65.536 1 1 0
1024 976.5625 262.144 1 1 1

So if we take a prescaler of 1024 we can get a delay from 0 to 262.44 ms


if 262.144 ms(calculated from 256*1024/1000) = 256 count
then for 1 ms = 256/(256*1024/1000) = 1/(1024/1000)
Therefore for a Delayms msec = (Delayms/(1024/1000) count
We will use this expression to reverse calculate count from the input parameter Delayms
If delayms = 262 , Count =262/(1024/1000) = 255.859375 = 256 (rounded)

Since 1 count is added in the count process (changes from 0xFF to 00


before the TOV2 bit is set)
Actual count to be stored to TCNT2 = Count -1

*/
void DelaymsUsingTimer2(volatile uint8_t Delayms)
{

volatile uint8_t CountforDelayms=round(Delayms/(1024.0/1000)-1);


TCNT2 = 255-CountforDelayms; /*start TCNT2
*/
TCCR2 = (1<<CS22) | (1<<CS21)| (1<<CS20); //Set Prescaler =1024
static volatile uint8_t TIFRdata;
do //Wait
{
TIFRdata=TIFR&(1<<TOV2); //Read status of TOV2 bit in TIFR

} while (TIFRdata==0); //until TOV2==1


TCCR2 = 0; //Set Prescaler = 0, no clock and thus stop timer
TIFR=TIFR|1<<TOV2; //Clear TOV2 bit by writing 1 to TOV2 bit;
}

uint8_t DoNothing(volatile uint8_t dummy)


{
dummy++;
}

47

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

//Main Program
int main(void)
{
volatile uint8_t SWData; //Storage to store Switch data
volatile uint8_t dummy; //Storage to store dummy data
//Refer Section A.1
//Initialised PD7, PD6, PD5 and PD4 as Input Port
DDRD = 0x00; //A 8 bit of Port D bits set as input
//and enable respective pull-up resistor
PORTD = 0xff; //Enable pull-up resistor on PIND
//Dummy use of DelaymsUsingTimer2() so that it be used to
//determine actual delay during debug
DelaymsUsingTimer2(250);
//Initialise all Environment variables
MSBlookahead=False;
LSBlookahead=False;
RunningLeft=True;
RunningInwards=True;
RunningLEDdata=0b00000001;
// FlashingLEDdata=0x0;
KnightRiderLEDdata=0b10000001;
// AlternateLEDdata=0b00001111;
DS1Count=0;
while(1)
{
SWData=PIND|MaskOffLowerNibbleHigh; /*SWdata = PIND|0b00001111
lower nibbles of PIND set to 0b1111*/
if (SWData!=0b11111111) //If Any Switch pressed
{
switch (SWData) //{
{
case SW7Pressed: // If SW7 Pressed
DoRunningLight(); // Do RunningLight sequence
break;
case SW5Pressed: // If SW5 Pressed
DoKnightRiderLight(); // Do Knight Rider Light sequence
break;
default:
dummy=DoNothing(dummy); //Dummy function to allow breakpoint be set here
break;

}
} //}
else //else
{ //{
OutDataDS1(DS1Count); //Display DS1Count at DS1 of Seven
DelaymsUsingTimer2(250); // Segment Panel
DS1Count++; // Increment DS1Count
if(DS1Count>9) // If (DS1Count>9)
DS1Count=0; // DS1Count=0
} //}
}
}
Figure A.8(d)

A.9. Software connection in Atmel Studio to the JTAGICE MkII


a) Referring to Section A.6 connect the Window system running project Lab2Exp1 to the
JTAGICE mkII via USB interface. Then connect the JTAGICE MkII to the Gotronik
Atmega32A Target Board JTAG interface (make sure the Red wire edge is pointing the
screw head). Swicth ON the JTAGICE mkII device and connect Power to the Gotronik
ATmega32A board.

48

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
b) After creating an C/C++ project (in this case named Lab2Pre) whose program is given
in Figure A.8(d) with device selected ATmega32A, select Project|Properties from the
Main Menu.
c) After selecting Project|Properties from the Main Menu:
To make the JTAGICE mkII as the Hardware Emulator/Debugger to the Atmel Studio

i. Select Tools" Tab and the click "Selected Programmer/Debugger" pull down menu
to select available simulator/hardware (which is JTAGICE mkII)

If the selection of JTAGICE mkII07000004699 is not available, make sure that the JTAGICE mkII
is connected via USB interface and is switched ON.

49

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
To check the connection to THE ATmega2A chip and confirm that the CPU frequency (F_CPU)
is 1Mhz

ii. Select Tool Device Programming.

Checking the JTAGICE mkII Connections in Atmel Studio 6

iii. To Confirm connection with JTAG ICE MkII, after selecting ToolsDevice Programming, then
select Tool=JTAGICE MK II and Interface=JTAG, click Apply and finally click Read.

If you get Device Signature=0x1E9502, connection to an ATmega32A board is confirmed.

50

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
iv. Checking/Setting Clock Speed

To Check/Set Clock Speed, after select ToolsDevice Programming if tools selected is JTAG
mkII and Device selected is ATmega32A click "Apply" and then click "Read".

If connection is OK you will get a signature reading "0x1e9502" Select "Fuses" tab and scroll
down the "Fuse name" to view the SUT_CKSEL which should read
"INTRCOSC_1MHZ_6CK_64MS_DEFAULT which should be as follows.

Otherwise makes sure Fuse Register value is set at High = 0x91 and Low = 0xE1. Inform
the technician before making changes of the Fuses by clicking Program button.

51

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
d) Target board not connected
If any the message as above is display, most likely target boad is not connected through JTAG
interface or not powered up.

52

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
e) One click programming to the target - Program and run
The Start without Debugging command is a one-click alternative to the programming dialog.
Execute it by selecting DebugStart without Debugging from the menu, or press

the button on the toolbar.

This will build the solution (if any changes are made) and program the target device without
starting a debug session. Any breakpoints set will have no effect.

Start without Debugging uses the tool and interface settings specified in the project options. This
is different from what takes place when using the stand-alone Programming Dialog, which is not
related to the project at all.

i. If the following message is displayed, then remove USB cable to JTAGICE mkii and reconnect. Then
repeat Procedure A.9(c).

ii. Otherwise ATmega32A programming completed and can be confirmed by noting that the Digit 1
on the Gotronik Atmega32A Target Board flash a - character (the system is alive) every a
250ms interval and when any of the switch specified in Table A.8(b) is pressed, the corresponding
specified Function at LED panels is displayed at the LED panel .

f) Confirming the operation of the program Lab2Exp1.c

Without setting any breakpoint, run the program by selecting F5 or the the button. Note the
display on the Seven Segment LED and confirm the result is as in Table A.9(f)

53

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
Table A.9(f)(i)

Input Describe Pattern generated at Seven Segment Panel


and LED Panel
No Push Button
pressed

SW7 pressed

SW6 pressed

SW5 pressed

SW4 pressed

SW3 pressed

SW2 pressed

SW1 pressed

SW0 pressed

A.10. Debugging the Program


Debugging a program is covered in Section B.3 of Appendix B For SKEE3732 Laboratory 1
Sheet.pdf"

If menu Debug|Start Debugging is selected or if F5 is pressed or the button is selected, the


Atmel IDE will get into in running mode which does no allow you to debug the program. To stop
the running, you can always select any of the following command to break the running.

Debug Stop Debugging


Debug Restart
Debug Break All
Debug Reset
However if we want to monitor/analyse the operation the program we use the Breakpoint,
Step Over, Step into feature that will allow us to watch amond others variables (using any of
the Watch window), Processor status (using Processor window), I/O status (using IO view
window) and memory locations (using of the Memory window).
54

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

You can open any of the above mention debugging windows, when and only if you are in
Debugging mode by selecting Debug|Window |<select the window yo want to open> as
shown below.

If you want to continue debugging by running through the program until another breakpoint is

met, select Debug|Continue or select the button.

Notes on Using Breakpoint

Breakpoints are a method of halting execution flow. By adding a breakpoint in the assembly code we
can run the program at full speed, and it will be stopped at the line with the breakpoint. We will add a
breakpoint at the by placing the cursor on the instruction in the source view window and press <F9> (or
the "Toggle Breakpoint" in the "Debug" menu ). A red circle will appear in the left margin of the source
view window as shown. By pressing <F5> or "Run" from the "Debug" menu the program will start
running and break (stop) at the instruction with the breakpoint.

There may be situations where we have single stepped through far in the program but you may need to
reverse a few steps back to review a result. We will need to Stop Debugging and start over sequential
single stepping again until we reach the instruction we want to review which can be unnecessarily
tedious.

The best method to overcome this is to set a breakpoint at the instruction we want to stop, RUN the
program so that it will stop at the breakpoint it meets. Then you may single step through from there.

To set a breakpoint, click on any row to put the cursor on the line of the statement where you want to
break (stop) and then press F9 (or click the leftmost column on the row of the statement as shown in
Figure A.10). If the program runs by the breakpoint, it will stop at the statement.

Notes:

55

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

In Figure A.10 and referring to Table 3 of SKEE3732 uP Laboratory 2 Sheet 20162017, break points at
respective first statement of codes for the processes (which were prefilled) of Initialise peripherals
controls, Shell Loop, Get Command and Execute Command(If SW7 Pressed).

56

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

Figure A.10

57

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

a) Example on Reading from I/O views and Watch View


After setting breakpoints as shown if Figure A.10 (in your case you will need to set all breakpoint at
first statement of all process specified in Table 3 of SKEE3732 uP Laboratory 2 Sheet 20162017) we
can start debugging the program. You can always Stop Debugging or Restart if you feel necessary
whenever you realized that you are at lost (which you will always do).

i. For the breakpoint settings in Figure A.10, when start debugging command is selected, the
program will first stop at breakpoint set at statement DDRA = 0xFF as shown in Figure
A.10(a)(i).

Figure A.10(a)(i)

58

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
ii. Reading Data in I/O view

With the Gotronik Atmega32A Board is JTAG connected to the AVR JTAGICE mkII, and the AVR
JTAGICE mkII is USB connected to the PC running the Lab2Exp1 project, on the Atmel Studio IDE,
press F9 or click the Start Debugging button. The program should break at the first breakpoint
that it passes which is DDRD= 0x00 as shown in Figure A.10(b). Note that on the left window the
IO view has been selected and the I/O PORTD is selected so the all of the Port registers is displayed
at the bottom left window. The respective memory address and contents are given under the
Address and Value column. The Binary digit of Value is iconised as boxes under the Bits
column. You will need to expand the Bits column (after expanding the IO view window) so that
you will see complete 8 bit icons as shown in the Figure A.10(a)(ii).

Figure A.10(a)(ii)
59

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
iii. Step over the statement DDRA = 0xFF; and you will see DDRA changes uo 0xFF as shown in
Figure A.10(a)(iii) symbolised by the fonts and boxes.

Figure A.10(a)(iiii)

iv. Reading Data in Watch 1 view

Select Debug|Continue and the program will stop the next break point it passes which is at
at statement of SWData=PIND|MaskofLowerNibbleHigh.

60

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

If you inspect IO View, PIND = 0xFF and if you open the Watch 1 window and adding the
SWData under the Name column, you will find that content of SWData (under the
Value column) = 0x00 (0b00000000) as shown in Figure A.10(a)(iv).

Figure A.10(a)(iv)

61

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
v. Add another breakpoint at statement switch (SWData) (you can add or remove breakpoint
during debugging). Then On the Gotronik Board press and hold the SW7 button.

While holding the SW7 button, select Debug|Continue which will executes statement of
SWData=PIND|MaskoffLowerNibbleHigh.

The program will stop the next break point it passes which is at at statement of switch (SWData)
as shown in Figure A.10(a)(v).

Checking the IO View and Watch, we will find that PIND=0x7f (0b01111111) and SWData also
equals 0x7f. This is because when statement SWData=PIND|MaskofLowerNibbleHigh, PIND
which is connected to the active low Push Button switches is read (refer Table A.8(a) and Figure
A.6(l)).

Since SW7 which is pressed (at logic 0) that PIND bit 7 get 0 which give the value PIND=0x7F.

Lower nibble of PIND is being mask off to force bit 3 thru 0 of SWData to be set to all 1s. no
matter what the respective value are in PIND.

By masking OFF the lower nibbles, any input from the mask bits is omitted,

vi. Statement switch (SWData) if executed will compare with its cases parameter declared under
the switch structure. These value the parameter for each case is different from each other are
equal to the data from the Push Button switch panel connected to PIND (declared under Push
Button switches Panel Data comment at top of program LAB2Exp1.c).

The statement under case whose parameter equals the SWData of the statement switch
(SWData) will be executed.

Then if you select Debug|Continue program will breaks at statement DoRunningLight() which is
under the case SW7Pressed of which value SW7Pressed equals data in SWData

b) Testing conditions of Switch inputs detected in the program.

i. Referring to Table 3 of SKEE3732 uP Laboratory 2 Sheet 20162017 (assuming it have been


correctly filled (you may confirm with supervising lecturer in Laboratory), and Figure A.8(c) of this
document set a breakpoints at the following statement after removing any existing breakpoints
(by selecting Debug Delete All Breakpoints):

ii. Set Breakpoints at the following instructions as shown Figure A.10(f)(ii):

DoRunningLight()
DoFlashingLight()
DoKnightRiderLight()
DoAlternateLight()

62

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
iii. or after Restarting (DebugRestart) the program (JTAGICE mkII and Target boad connected):

iv. The program will be in Running mode and you will notice that a - is flashing at the DS1 Seven
Segment.

v. If you press any of the buttons of SW7, SW6, SW5 and SW4 you will notice that the program
breaks. Record the value of SWdata for each different Swicth pressed.

63

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet

Figure A.10(f)(ii)

64

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
c) Confirming Actual Delay Timer with Calculated Timer Delay
Assuming Preliminary Preparation (6) has been correctly completed (you may confirm with
supervising lecturer in Laboratory).

i. Remove all breakpoints (DebugDisable All Breakpoints)

ii. Then set a breakpoint at the statement DelaymsUsingTimer2() and a second one after the
statement DelaymsUsingTimer2().

iii. Set Select Debugger as simulator (ProjectLab2Pre PropertiesTool) as shown in Figure


A.10(b)(i).

Figure A.10(b)(i)

d) To confirm the Delay generated by DelaymsUsingTimer2

65

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
i. After selecting Debug|Delete All Breakpoint, set breakpoint at the
DelaymsUsingTimer2 statement as shown in Figure A.10(c)(i). This is a dummy
process just for this delay measurement use.

ii. Restart the program, and when it breaks at statement the DelaymsUsingTimer2 note the Stop
Watch Counter on the Processor window.

iii. Step over the statement DelaymsUsingTimer2 and after a short while, the program will stop at
the next statement. Note the Stop Watch Counter on the Processor window.

iv. The difference between the two Stop Watch Counter will give the duration to execute the
statement in this case DelaymsUsingTimer2.

Figure A.10(c)(i)

66

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)


APPENDIX A for Laboratory 2 sheet
v. Start program without Debugging, and confirm Timer delay with the calculation by checking the in
the shell loop, the difference of Cycle Count at DelaymsUsingTimer2() and the statement after
DelaymsUsingTimer2().

67

Appendix A For SKEE3732 Laboratory 2 Sheet (Rev 111017)

Das könnte Ihnen auch gefallen