AVR PROGRAMMING ENVIRONMENT

The ENV AVR Programming Environment

By Murray Greenman ZL1BPU

An easy start to your next embedded microprocessor development project, using an AVR processor.


INTRODUCTION

One of the most difficult things an engineer or hobbyist experiences on starting a new project with an embedded processor is actually getting started! Without previous experience with the processor, or one very similar, it can be both difficult and very time consuming to set up all the assembler settings, processor definitions, parameters, the registers, timers, UARTs and I/O ports to work correctly. In effect, without having done it before, the chances of success are either poor, or delayed by a steep learning curve.

Another problem that besets anyone starting a new micro project, especially if an expensive In-Circuit Emulator is not available, is how to communicate with the device to know what is going on during the debugging phase.

The simple ENV Programming Environment introduced here solves both of these problems for newbie programmers, whether they are just new to the AVR processor family, or genuine newcomers to microprocessor assembly programming. While designed for the highly adaptable and very capable Atmel AT90S4433, the ENV is applicable to all the AVR family with some simple adaptation. It allows you to make a simple prototype on "Veroboard", spot board or wire wrap, and not only program the processor on the board, but control, debug and operate the user's target application as well.

The AVR family of processors is a joy to program. While there is a certain satisfaction involved in writing succinct code for RISC processors with very limited instruction sets, there is equally a pleasure to be experienced in using classical programming techniques with a processor with something close to the classic register based Harvard architecture, and with a reasonably orthogonal instruction set. Several things about the AVR family make them particularly useful for the small-time programmer:

  • Good and completely free development tools - an excellent symbolic assembler, an awesome simulator, and a simple but effective programming tool, with in-system programming capability.
  • All the processors have Flash based program memory, easy to program and reprogram in-circuit. Most parts also have EEPROM for storage of parameters, data and tables. Some have RAM memory as well.
  • The processor is register based, and most instructions will operate between any of the registers. This makes programming much more flexible and concise than that for accumulator based processors.
  • The architecture of the various family members is very similar, as are the register allocations and the instruction set, so adapting code from one to another is generally straight-forward.
There are many helpful resources for AVR programming on the internet, and they are reasonably easy to find. Here are some examples with a Amateur Radio / hobbyist flavour:

Richard VK6BRO offers several projects, including a frequency counter.
Henry N2RVQ has several neat projects.
Murray ZL1BPU offers an HF/VHF Super Beacon Keyer.
D.V. Gadre has plenty of AVR ideas.
The AVR Web Ring has it all!

There are numerous web-based tutorials about micro programming, what to do and how to do it. Try to find one based on the AVR family. Here's one to start with: www.avr-asm-tutorial.net/avr_en/. The author also offers an email microprocessor course for the absolute newbie. Email the author or write to the address below for details.

DESCRIPTION

ENV is in effect a cut-down program, which will operate as-is in an AVR AT90S4433 processor. It contains just about everything a program requires, except the actual user application! For example, it defines most of the registers, many of the bit-wise flags, sets up the timers, the UART, the A-D converter, and sets up the ports. These are all areas which are difficult for the new user.

Four main files are provided -

  • ENV.ASM (the source code)
  • ENV.INC (the source definitions)
  • ENV.EXE (a DOS executable monitor)
  • ENV.HTML (this file)
Other files include the source code for the PC monitor program ENV.BAS, the schematic, the parts list and some screen shots.

ENV.ASM
The ENV assembler program provides six particular assets:

  1. It provides all the "getting started" code that daunts the beginner. It also explains what it does.
  2. It handles the six channel Analog to Digital Converter, storing the results in RAM, so you don't have to mess around with it (which isn't easy).
  3. It sets up and demonstrates use of a UART in polled manner.
  4. It provides telemetry with which the user can see a "window" into the operating program, while it is running, very useful for debug. This feature should be turned off or adapted when final code is working, to save processor time and allow the UART to be used for other purposes.
  5. It provides a sample timer interrupt and a simple slow timer which the user can adapt to time various activities.
  6. A number of useful subroutines are included, such as a binary to ASCII conversion, UART polled transmit and receive.
The software has comments which show clearly how to adapt it to user requirements, and where to add user functions. Other than the features described above, this program intentionally does nothing useful, although a couple of simple applications are provided as an illustration. If you assemble it and run it, it will send the telemetry, but that is about all.

The examples included are:

  • A simple timer based tone generator, which sends "V" in Morse code, and also illustrates controlling a transmitter to send this signal. The design includes a "radio port", to demonstrate how a simple system like this could be used for an Amateur radio Morse keyer, signal generator or transmitter signal source.
  • A small loop which moves the contents of RAM into some of the registers. This illustrates a technique for ensuring that the ENV monitor has "visibility" into RAM as well as registers. This example hints at how easily a microprocessor based digital voltmeter or data logger could be created.
There are variations in programming style included, which show that the same results can be achieved using different programming techniques.

ENV.INC
A standard assembler include file, this file has all the definitions used in the assembly. All the I/O registers used and many of the I/O bits are defined. In addition, the few registers dedicated to the Environment are also defined and indicated. Two 6-bit digital ports, the UART and a six bit analog input port are pre-defined. Of course all these values are easily changed, and the user is encouraged to add to and improve on this file. The more values pre-defined, the easier the code is to read and maintain. This file should reside in the same directory as ENV.ASM when the latter is assembled.

ENV.EXE
This is a DOS executable monitor program, which gives you a "window" into the processor while the code is running. This monitor feature operates via the telemetry sent from the AVR UART at 9600 or 19200 bps. While a similar result can be achieved by running a terminal program (such as Windows Terminal) at 19200,N,8,1 and with a line width of 132 characters, ENV.EXE has the advantage of a static display, and representation of the data in Binary, Hex, decimal and ASCII. This program operates on COM1 or COM2 of the PC at 9600 or 19200 bps.


The ENV.EXE display

The telemetry output from the AVR is in "human readable" form, a list of hexadecimal register values in ASCII, of all 32 registers in order, and terminated with <CR><LF>. Here's an example, captured from Windows Terminal:

8F8F4AB40450EB00C2817320D980CA3573EED72403FF0000920022300D1D1E00 
8C8C4AB40450EB00C5817320D780193A73EEC71400FF000092002230341D1E00 
8B8B4AB40450EB00C57F7320DB80143573EEB70400FF0000920022300D1D1E00 
8E8EBAF40450EB00C2817320D980943773EEA7D003FF000000002230341D1E00 
8C8CBAF40450EB00C67F7320D980B93873EE97C003FF000000002230011D1E00 
8F8FBAF40450EB00C3807320D980163673EE87B001FF000000002230151D1E00 
The line of register contents repeats every few seconds, and of course can be slowed down or adapted to suit. The advantage of a special monitor program like ENV.EXE is that it provides a static display. It is not difficult to write your own to include logging, graphical display, HEX to decimal conversion, scaling of units and names for variables.

Here's an example of a specialised AVR monitor program which exhibits most of these features. Note that the register values are converted to current, voltage and temperature, and graphed in colour!


A specialised monitor example

DEFINITIONS

REGISTERS
Although some registers are predefined in the ENV environment, that does not mean they can't be used elsewhere. For example, HUNDS and SECS (see below) are provided purely for the convenience of the user. The following registers are predefined:
Reg	Name		Description
R2 *	ADCCHAN		The current A-D channel, used in the A-D interrupt
R6	HUNDS		Software timer, decremented every 10 ms, reaches zero once/sec
R7	SECS		Software timer, decremented every second
R16	TEMP		A temporary working register
R17	XFR		A transfer register
R18 *	DEBUG		A register pointer used in the debug telemetry, counts from 0 - 31
R26	XLO		X register pair LO byte
R27	XHI		X register pair HO byte
R28	YLO		Y register pair LO byte
R29	YHI		Y register pair HO byte
R30	ZLO		Z register pair LO byte
R31	ZHI		Z register pair HO byte
* The two registers marked should not be meddled with while the monitor telemetry is in use.

PORTS
To make life easier, most of the I/O ports used, and the more common register bits are predefined. You are encouraged to add your own definitions to the ENV.INC file. These definitions make the code easier to read. For example, you can check the UART UDRE flag in the UCSRA status register for incoming characters with simple descriptive code, such as:

SEND:	sbis	UCSRA, UDRE	;UDRE is set when UART TX is ready
	rjmp	SEND
	out	UDR, XFR	;send char
	ret
This is achieved by pre-defining values for the UCSRA and UDR register addresses, and the bit value for the UDRE bit. Check in the ENV.INC file or the list below to see how this is done.

The external ports are set up as follows:

PORT B: A combined I/O port, set up for radio and audio applications.
PORT C: The six channel analog input port.
PORT D: The UART; general purpose I/O.
The complete list of pre-definitions follows:
Port	Name		Description
0x18	PORTB		Port B Data register
0x17	DDRB		Port B Data Direction register
0x16	PINB		Port B Input Pins register
Bit 4	PTT		PTT control, PB4
Bit 1	AUDIO		AUDIO (tone) out, PB1/OC1
Bit 2	DATA		DATA (baseband) out, PB2

0x15	PORTC		Port C Data register
0x14	DDRC		Port C Data Direction register
0x13	PINC		Port C Input Pins register

0x12	PORTD		Port D Data register
0x11	DDRD		Port D Data Direction register
0x10	PIND		Port D Input Pins register

0x1E	EEAR		EEPROM Address register
0x1D	EEDR		EEPROM Data register
0x1C	EECR		EEPROM Control register
Bit 2	EEMWE		EEPROM EEMWE bit
Bit 1	EEWE		EEPROM EEWE bit
Bit 0	EERE		EEPROM EERE bit

0x33	TCCR0		TC0 Control register
0x32	TCNT0		TC0 Counter register

0x30	GIMSK		General Interrupt Mask register
0x3A	GIFR		General Interrupt Flag register
0x39	TIMSK		Timer/Counter Interrupt Mask register
0x38	TIFR		Timer/Counter Interrupt Flag register

0x06	ADCSR		ADC Control & Status register
0x05	ADCH		ADC High Data Register
0x04	ADCL		ADC Low Data Register
0x07	ADMUX		ADC Multiplex Selection register

0x35	MCUCR		Processor Sleep and things register
0x21	WDTCR		Watchdog Control register
0x3F	SREG		Processor Status register
0x3D	SP			Processor Stack Pointer

0x2B	OCR1H		TC1 Counter register H
0x2A	OCR1L		TC1 Counter register L
0x2F	TCCR1A			TC1 Output Compare register A
0x2E	TCCR1B			TC1 Output Compare register B
0x2D	TCNT1H			TC1 Count register H
0x2C	TCNT1L			TC1 Count register L

0x09	UBRR		UART Baud Rate register L
0x03	UBRRHI			UART Baud Rate register H
0x0C	UDR		UART Data I/O register
0x0B	UCSRA		UART Control & Status register A
0x0A	UCSRB		UART Control & Status register B
0x05	UDRE		UART UDRE TX data register empty flag

PROGRAM OPERATION

In effect, three different programs operate in the Environment, and apparently all at the same time. These are the main program, a timer interrupt and the A-D interrupt.

The main program is used to set up the ports, the timers and UART, and then does nothing (except for the simple examples). This is where the user places the application program code. This is well described in the ENV.ASM file. A program placed here is of the type that executes over and over, looping around and around at high speed.

The timer interrupt is based on the 8 bit T0 timer. It can also have user code added, although the amount of code added needs to be kept to a minimum, since the timer interrupt occurs every 10ms. Program segments placed here execute once at precisely timed intervals.

The timer is used to increment a pair of simple timers, which between them count seconds. As a demonstration, the diagnostic telemetry is also added here. This is an example of code which executes a new value every time control is passed to it. The diagnostics could be moved to the main program, but not without modification, as it would otherwise hog all the processor time. A subroutine called every 100ms or so would be suitable. This could be achieved using a flag-passing technique.

The A-D interrupt reads the conversion from the latest channel, and places the data in two consecutive bytes of RAM. The channel number is incremented and the process continues. This interrupt makes the A-D process transparent to the user, and demonstrates RAM access techniques. The A-D is complicated by the fact that the result read is for the channel before the one currently requested!

The user could add further functions at this point, although they would need to be of short duration. This would be the appropriate place for A-D input filtering or other repetitive sample relasted statistical processing.

By using interrupts, three essentially independent 'threads" (program sections) can operate at the same time, either independently, or in conjunction with one another. Operating in conjunction is achieved by passing data and flags between the processes.

Be aware however that re-use of registers already used in other threads can lead to confusing results that are difficult to debug, so assign register use (in particular) with great care. It is best to:

  • Assign a register to use only in one of the threads
  • Push and pop the register whenever it is used in an interrupt
  • Use dedicated RAM locations for data passing
In order to be sure that the main program contents of the registers is preserved. Great care should be taken passing flags between an interrupt and the main program. Use of flags in the processor SREG processor status register is particularly tricky as this register is frequently pushed during interrupt. It is better to dedicate a register to provide eight separate and independent flags. (Flags are one-bit messages often used to convey status information between processes).

TIMING

The software is designed for a clock speed (crystal) of 3.68640 MHz, which makes choice of accurate baud rates easy. For example:
Baud	UBRR    	Error
Rate	Value   	%
38400	5       	0.00
19200 *	11      	0.00	Default value in ENV.ASM
9600	23      	0.00
4800	47      	0.00
2400	95      	0.00
1200	191     	0.00
600	383     	0.00
300	767     	0.00
The software will operate at other frequencies (for example 4 MHz), and the source code includes alternative code lines for this purpose.

The A-D interrupt operates at the lowest speed (128 prescale) and the timer interrupt, which uses T0, has a 256 prescaler. Thus the timer T0 clock is 3686400 / 256 = 14,400 Hz, and if the timer is not reloaded, will provide an interrupt at 56.25 Hz (17.77 ms). By reloading, many other useful rates are possible, for example:

Timer T0	Reload	Interrupt	Interrupt
"n" Value	Value	Frequency	Period
12		244	1200 Hz		0.833 ms
15		241	960 Hz		1.04 ms
16		240	900 Hz		1.11 ms
18		238	800 Hz		1.25 ms
24		232	600 Hz		1.67 ms
30		226	480 Hz		2.08 ms
32		224	450 Hz		2.22 ms
36		220	400 Hz		2.50 ms
72		184	200 Hz		5.00 ms
144 *		112	100 Hz		10.0 ms	Default value in ENV.ASM
240		16 	60 Hz   	16.67 ms
Since the timer T0 is an up-counter, the value loaded (see table) is 256 - n.

The software can be easily adapted for other crystal frequencies. For example, with a 4 MHz crystal as in the Atmel STK200 development kit, the timer T0 clock will be 15,625 Hz, and if the timer is not reloaded, the interrupt rate will be 61.035 Hz. 3.6864 MHz and 7.3728 MHz are the most versatile frequencies to use, as the choice of accurate baud rates with other crystals is more limited:


3.58 MHz Crystal			4.00 MHz Crystal

Baud	UBRR    Error		Baud	UBRR	Error
Rate	Value   %			Rate	Value	%
38400	-       -			38400	-	-
19200	-       -			19200	12	0.16
9600	22      1.31		9600	25	0.16
4800	46      0.83		4800	51	0.16
2400	92      0.23		2400	103	0.16
1200	185     0.23		1200	207	0.16
The other timer, T1, is used in the ENV to generate accurate audio tones. It can also be used in PWM mode to control equipment, generate sine waves or other waveforms from a table etc, but in this example simply generates a fixed square wave tone which can be turned on and off in software - for Morse code, in the example. The prescaler for T1 is 8, so the T1 clock is 460,800 Hz. Here are some typical frequencies and the T1 OCR1H and OCR1L reload values:
Freq Hz	OCR1H   OCR1L	Actual Hz
2400      0      96     2400.00
1200      0     192     1200.00
1000      0     230     1001.74
 980 *    0     235      980.43 	Default value in ENV.ASM
 800      1      32      800.00
 500      1     205      499.78
 440      2      12      439.70
 400      2      64      400.00
 100      9       0      100.00
 50      18       0       50.00
 10      90       0       10.00
  4     255       0        4.00	
As suggested above, the software will operate fine with a 4.000 MHz crystal (as in the Atmel STK200) provided you make the following changes:
  • Baud rate (9600 baud) UBRR = 25
  • Timer0 reload TCNT0 = 100 (and tweak HUNDS reload for accuracy if necessary)
  • Timer1 count for 1 kHz OCR1L = 255
These changes are included in the ENV.ASM file, but commented out.

THE FUTURE

A number of exciting projects have been designed, or are planned, using adaptations of this software approach and circuitry only slightly adapted from the schematic included here. For example:
  • A fully featured HF or VHF beacon keyer, with multiple modes (including Hellschreiber!), ASK and FSK modulation, audio and keying outputs and 10 telemetry channels.
  • A six channel digital voltmeter and slow oscilloscope, suitable for data logging or chart recording. This unit consumes so little power that it will operate from a PC serial port!
  • A contest Morse Keyer with programmable memories
  • FAX, SSTV or FSTV pattern generator
  • A version of ENV with LCD display and all the necessary display routines
  • Automatic NiCd and NiMH battery charger and discharger
  • Remote automatic SWR meter or antenna bridge
  • Weather station and data logger
  • Micro controlled regulated 50 Hz inverter, with autostart, protection and telemetry
  • Accurate audio signal generator using direct digital synthesis, 0 - 100 kHz
  • Computer controlled antenna switch, rotator controller and remote automatic SWR bridge
  • APRS message generator (with telemetry of course!)
  • GPS position / heading / UTC time display / ASCII Terminal
  • Receiver Frequency Counter LCD display with IF offsets and S-meter
  • 40 MHz Frequency Counter with LCD display and PC telemetry for drift monitoring
  • Direct reading VHF Frequency Counter for divide by 10, 64 and 256 prescalers.
  • GPS based frequency transfer standard
The items in bold are already running!

HOME       Download Project Archive (includes source code)


I trust you will find ENV useful. Please send any feedback or questions direct to me.
While the software is offered free for private use, donations to cover development
costs and to encourage further development are especially welcome.
zl1bpu@nzart.org.nz

Murray Greenman CSc, ZL1BPU
94 Sim Rd, Karaka,
RD1 Papakura
NEW ZEALAND

© Copyright M. Greenman 2000-2002. All Rights Reserved. See Legal Information for details.