In the first part of this article, we had described the main features of the AVR microcontroller and the hardware/software required for an AT-PROG programmer board interfaced to the printer port of a PC. Further, we explained the methods for message display on a liquid crystal display (LCD).
This part dwells on the architecture of ATmega8535 along with application programs exploiting its important features for embedded control.
Architecture of ATmega8535
Pin configuration of ATmega8535 was shown in Fig. 1 of Part 1. The device has ports for input/output, interrupts, serial communication and various others functions. There are a total of 32 pins, which are arranged as ‘A,’ ‘B,’ ‘C’ and ‘D’ ports for various functions as shown in Table I.
A crystal of maximum 16MHz or 8MHz frequency can be connected across pins 12 and 13 of ATmega8535 or its low-voltage version ATmega8535(L), respectively. Pin 9 serves as the active-low reset pin.
The non-volatile program and data memories built into ATmega8535 are:
1. 8 kB of self-programmable flash for storing the software code of the application program.
2. 512 bytes of SRAM, which is a read/write memory.
3. 512 bytes of EEPROM for storing the data. Unlike the flash memory, it can be accessed in a program for writing and reading.
Programming the on-chip code/program memory
The on-chip flash memory is programmed by pulling up the reset pin and sending data through pins 6 (MOSI) and 7 (MISO), and pin 8 (SCK), which is used for clocking the the code data into the flash memory. This is accomplished by the host computer by sending appropriate instructions and the code bytes; data verification is done by reading the flash memory and comparing it with the original code data. Writing the lock bits to prevent reading of the code in the chip is accomplished through the instructions and the relevant data.
For using the AVR device, these instructions are built into the ATPROG program (explained in Part I), which is run on the host PC.
Selection of clock. There are some additional fuse bits, which can be programmed for some extra operational functions. Note that the AVR device, as shipped, is preset to work at 1 MHz with its internal oscillator. If you want to use an external crystal, say, of 8MHz frequency, you have to exercise this option by programming the fuse bits accordingly. A fuse bit is just like a flash code memory location.
The CKSEL fuse bits can be programmed to select the desired crystal. The device clocking options are selectable by Flash Fuse bits as shown in Table II. The clock from the selected source is input to the AVR clock generator and routed to the appropriate modules.
Since the default oscillator is 1MHz, unless we set the CKSEL bits to an appropriate value, the external crystal on pins 12 and 13 will not function for ATmega8535.
Programming the fuse bits. The fuse bit programming option is available on the screen when the AT-PROG is run on the PC. When this option is selected, it pops up a menu of its own. On this menu, you can write the necessary code for CKSEL programming. (Details of programming the fuse bits, lock bits and other options like boot memory option are given on pages 236 and 252 of the ATmega8535(L) manual provided in the EFY-CD of Nov. 2005.)
Internal registers. Six of the 32 registers can be used as three 16-bit indirect address register pointers for data space addressing, enabling efficient calculations. One of three address pointers (X, Y and Z registers, described under ‘register operations’ section) is also used for table look-up.
The I/O memory space contains 64 addresses for CPU peripheral functions like control registers, timers/counters and analogue-to-digital converter (ADC). It can be accessed directly or as the data space locations following those of the register files, i.e., after ‘20H’ and up to ‘5FH.’
The memory space contains important registers for use in interrupt selection, timer control, UART, SPI interface, watchdog and reset selection modes, etc. Table III shows the exact addresses of these I/O registers.
The bit description for the status register (SREG) is shown in Fig. 12.
Instruction set for ATmega8535
The instruction set comprises several arithmetic, logical, branch and bit-test type instructions. You can download a 150-page user manual for the AVR instruction set from Atmel’s site‘www.atmel.com/dyn/resources/prod_documents/doc0856.pdf.’ A summary of the instruction set is given on pages 299 through 301 of the Atmega8535(L) datasheet.
Some of the important instructions are given in Table IV.
Points to be noted
1. When the relative call or jump instruction is executed, the entire memory address space can be accessed.
2. During interrupts and subroutine calls, the return address value is stored in the stack space, which is to be defined by the user at the beginning of every program in SRAM space.
3. The 16-bit stack pointer is read-/write-accessible in the I/O space.
4. The 512-byte data RAM is easily accessed through five different addressing modes supported.
5. A flexible interrupt module has its control registers in the I/O space with an additional global interrupt enable bit in the status register. Every interrupt has a separate address for vectoring, where the instruction causing it to jump to the memory area of that particular interrupt has to be kept stored by the programmer.
There are many interrupts available in ATmega8535. In order to use any interrupt, you need to place the address of the program of the respective interrupt service routine at the vector address.
From location ‘001H’ to ‘014H, ’there are 20 such interrupt vector locations in the order of their priority. Address ‘000H’ is used for the reset vector. A reset may be caused by power-on reset, brownout reset and watchdog reset, or externally by making pin 9 low. Table 19 on page 45 of the datasheet lists the details of reset and interrupt vectors.
Note that here we are dealing with word addresses, so each location is actually two bytes long. In this twobyte location, if you place a RETI (return from interrupt) instruction, nothing will be done upon that interrupt. For example, if you place a jump instruction to the required routine, you can write:
Then you can use that interrupt to jump to the timer_routine.
As mentioned above, the interrupt vectors follow the reset address at ‘000H,’ wherein a jump instruction to the corresponding actual memory addresses, defined by the labels, is placed. For example, the instruction:
It means that the external interrupt routine has the label ‘Int0,’ to which the processor jumps upon pin 17 getting a high logic signal. Also, at the label ‘Int0,’ if a simple return instruction is entered as:
This instruction simply ignores such an interrupt and returns to the main program. In case you need to process the interrupt, enter the necessary code starting at label ‘Int0.’
After the interrupt processing instructions, the various subroutines are entered. Then comes the main program. In the main program, the first thing to write is the stack initialisation instructions. Here, the stack pointer is set to the highest end of the internal RAM, for which a temporary register is used, and the high and low addresses are written to the stack pointer using an instruction at the Ext_Int0 vector address (0x001) such as:
Register operations. Each register is assigned a data memory address, mapping it directly into the first 32 locations of the data space. Register pairs R26-R27, R28-R29 and R30-R31 serve as 16-bit registers, which are used for indirect addressing of the data memory space. These three 16-bit registers are known as ‘X’ (R27:R26), ‘Y’ (R29:R28) and ‘Z’ (R31:R30) registers, respectively. The last 16 registers in the register file (R16 through R31) cannot be used with the first 16 registers (R0 through R15).
The operating instructions for registers have direct and single-cycle access to the registers. The following instructions—constant arithmetic instructions—use the second half of the registers in the register file and cannot be used with the first half:
sbci, subi, cpi, andi, ori and ldi
The following general instructions that use two registers or only a single register can use the entire register file:
Sbc, sub, cp and & or
Embedded control functions and their applications
Here we’ll use the following four functions of ATMega8535 for typical control applications:
1. Timers; two 8-bit and one 16-bit with add-on features
2. Pulse-width modulated output
3. Analogue-to-digital converter
4. Serial RS-232 interface
Timers and their applications. Both timer 0 and timer 1 are 8-bit timers, while timer 1 is a 16-bit timer. The clock inputs to the timers can have a variety of selections. The CPU clock itself, divided by a prescaling divider with divisors of 8, 64, 256 and 1024, can be chosen. Further, it can also count an externally applied clock at T1 pin (for timer 1).
We shall use these timers for developing a real-time clock with time display on the LCD (see Fig. 1). For the purpose, the registers to be used in timer 0 are:
1. TCCR0: Timer counter control register 0
2. TIMSK: Timer interrupt mask register
TCCR0 register bits. Fig. 13 shows the bit details for TCCR0 register. Bits WGM01, COM00, COM01, WGM00 and FOC0 (bits 3 through 7) of TCCRO register are used with the timer-based comparators for waveform and pulsewidth-modulated output generation. Since these bits are not required for the normal timing operation of the timer, they have not been used here.
The timer clock is selected by using the remaining three bits (CS00, CS01 and CS02). We will set these bits to ‘0,’ ‘1’ and ‘1,’ respectively, for dividing the 1MHz default internal clock of ATmega8535 k (with no external crystal) by ‘64.’ This division gives 65 microseconds per clock. Then we accumulate the counts for getting one second and divide it by ‘60’ to get minutes and again by ‘60’ to get hours, which are counted up to ‘12’ and the process is repeated.
TIMSK register bits. Fig. 14 shows the bit details for TIMSK register. Bit 0 refers to ‘timer-overflow interrupt enable.’ It must be set to enable the interrupt action on overflow. The TIMO_OVF interrupt ($0009 address) is used to direct a vector at this address to the respective interrupt service routine, where we will perform the relevant action that is needed upon timer-0 overflowing, i.e., when the number in its TCNT0 register (timer counter 0) crosses ‘255’ (decimal). So in the software program for real-time clock, we initialise TIMSK to ‘01.’
Software program for real-time clock (8535clk.asm). The 8535clk.asm program with suitable explanations and comments is given at the end of this article. The assembled hex file ‘8535clk.hex’ is included in this month’s EFY-CD, which can be straightaway programmed in the ATmega8535 IC. The programmed IC can be fixed to the RTC circuit board to show real-time clock on the LCD.
To download source code: click here