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:
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:
- 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.
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.
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 -
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 source code)
- ENV.INC (the source definitions)
- ENV.EXE (a DOS executable monitor)
- ENV.HTML (this file)
ENV.ASM
The ENV assembler program provides six particular assets: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.
- It provides all the "getting started" code that daunts the beginner. It also explains what it does.
- 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).
- It sets up and demonstrates use of a UART in polled manner.
- 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.
- It provides a sample timer interrupt and a simple slow timer which the user can adapt to time various activities.
- A number of useful subroutines are included, such as a binary to ASCII conversion, UART polled transmit and receive.
The examples included are:
There are variations in programming style included, which show that the same results can be achieved using different programming techniques.
- 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.
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 displayThe 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:
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. 8F8F4AB40450EB00C2817320D980CA3573EED72403FF0000920022300D1D1E00 8C8C4AB40450EB00C5817320D780193A73EEC71400FF000092002230341D1E00 8B8B4AB40450EB00C57F7320DB80143573EEB70400FF0000920022300D1D1E00 8E8EBAF40450EB00C2817320D980943773EEA7D003FF000000002230341D1E00 8C8CBAF40450EB00C67F7320D980B93873EE97C003FF000000002230011D1E00 8F8FBAF40450EB00C3807320D980163673EE87B001FF000000002230151D1E00Here'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
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:* The two registers marked should not be meddled with while the monitor telemetry is in use.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 bytePORTS
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 retThis 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.The complete list of pre-definitions follows:
PORT C: The six channel analog input port.
PORT D: The UART; general purpose I/O.
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
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:
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).
- 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
The software is designed for a clock speed (crystal) of 3.68640 MHz, which makes choice of accurate baud rates easy. For example:The software will operate at other frequencies (for example 4 MHz), and the source code includes alternative code lines for this purpose.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.00The 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:
Since the timer T0 is an up-counter, the value loaded (see table) is 256 - n.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 msThe 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:
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: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.16As suggested above, the software will operate fine with a 4.000 MHz crystal (as in the Atmel STK200) provided you make the following changes: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.00These changes are included in the ENV.ASM file, but commented out.
- 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
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:The items in bold are already running!
- 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
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