Tutorial for learning avr assembler language of AVR-single-chip-processors AT90S, ATtiny, ATmega, ATxmega of ATMEL using practical examples. Variable frequency sine generator m324 |

- 1x8 LCD for frequency display in Hz,
- two potentiometers to regulate the resolution and the delay separately,
- active key to update the adjusted parameters, no automatic adjustment,
- 8-bit R/2R network,
- selectible and configurable crystal,
- either 256, 128, 64, 32, 16 or 8 resolution steps,
- large 16-bit delay counter, usable for very low frequencies,
- very fast algorithm (minimum cycle length = 17 cycles).

The generator has

- the usual R/2R network with 8 bit resolution, attached to Port D,
- a crystal for exact timing, here: 16 MHz,
- a driver that protects the network and provides enough output power, here a 741 operation amplifier (CA3140 or TL071 would also fit, but provide less output power than the 741),
- an LC low-pass filter that rips off remaining rectangles,
- a standard six-pin ISP interface to program the controller within the system.

- two complete ports with 8 bits each available, one for the LCD's bi-directional data bus and one for the R/2R network, and
- the option to be clocked with an external crystal, and
- it has ADC channels for measuring the potentiometers, and
- it provides an external INT that can be configured to interrupt on falling edges solely (INT2).

The LC network for filtering the higher rectangle frequencies produced by the R/2R network depends from the frequency range that the generator shall provide. If you want to operate the generator with smaller resolutions, such as 8 or 16, to achieve higher frequencies or a finer resolution, the clipping frequency has to be smaller than your desired highest frequency, muliplied with the smallest resolution.

I built my one with L=3.3mH and C=150nF, the output capacitor is 470nF.

Red dots in the component picture are 0.8mm holes, violett ones are 1.0mm. The total size is 80-by-100mm (half Euro size). Note that I used a coil with 22µH instead of the 10 that is listed in the schematic.

If you have Linux, you can work with tgif on the originals. The copper side and all components in color layers are here, the component plan is here.

Note that earlier versions of the schematic had the LCD control lines on different port-pins.

- define the desired frequency (in mHz) and leave the selection of the resolution and the delay constant for the Assembler, or
- the frequency and the resolution (256/128/64/32/16/8), for which the Assembler calculates the delay constant, or
- the frequency and the delay constant (0 to 65535, 0 is 65536!), for which the Assembler determines the necessary resolution, or
- define the resolution and the delay constant.

Note that the names of the constants

The conversion of the ADC1 result to delay values is a little bit different. The AD result is divided by 64 and one is added. This number is multiplied with the original AD 16-bit result. At maximum this yields 65,472. That limits the lowest frequency range slightly (from 262,157 down to 261901, at 16 MHz from 0.2384 to 0.2386 Hz).

This shows why it is recommendable to either use a 10-turn or a log potentiometer: at small delay constants the frequency changes more rapidly (see the division section below).

The new values come immediately in effect, if the debouncing protection time of 250 ms has been absolved without additional external interrupts.

As I have foreseen a very small LCD with 8 characters on one single line, calculation and display of the frequency is a little bit tricky.

The delay constant is written to a 32-bit wide register area. It is multiplied by 4 and 13 is added. This will be the divisor.

The 64-bit divident representing the multiplied clock frequency is then divided by the 32-bit divisor to yield a 32-bit result. The result is the frequency in mHz.

The 32-bit integer is then converted to decimal ASCII, with the decimal dot behind the Hz. This conversion uses a space in SRAM, examples look like this:

0001234567.123 ; All three decimal digits are non-zero 0001234567.120 ; The last decimal digit is zero 0001234567.100 ; The last two decimal digits are zero 0001234567.000 ; All three decimal digits are zero 0123456789.123 ; The number is larger than 99,999

Then all preceding ASCII zeroes are replaced with blanks. If the first non-blanked digit is too far to the left (the number has more than eight digits) digits of the mHz behind the decimal dot are removed (removed digits from 5 and above round the preceeding number up).

The eight digits are then finally written to the LCD.

in the section

**testR2R**: On the R2R port the number is placed that is determined with the parameter**testR2ROut**.**testSine**: The two parameters**testSineRes**and**testSineDly**are used to generate a sine on the R/2R port. Using 128 for testSineRes and 28 for testSineDly brings a perfect 1.000 kHz sine to the R/2R network.**testKey**: The attached key is read. If open, the R/2R voltages is set to 3.0 Volt, when closed it is 2.0 Volt.**testAdc0, testAdc1**: This measures the voltage on the two ADC inputs and adjusts the R/2R output to the measured voltages.**testPortC**: The port C (data port to the LCD) is made output and all pins are pulled high.**testLcd**: The LCD is initialized and the text "SineM324" is displayed.

Then re-assemble and burn the hex code to the flash's memory. Do not forget to change the following fuses:

- Disable JTAG, otherwise the LCD will not work properly.
- Disable CLKDIV8, otherwise your sine will be too slow.
- Select an external crystal as clock source, otherwise it will be too slow.

This is what the generator produces with a resolution of 256 and a delay of 1: a sine wave with 3.676 kHz.

This is what results from a resolution of 256 and a desired frequency of 1,000 Hz. Unfortunately the integer math produces a frequency of 961.538 Hz as the nearest possible. Not very accurate.

This is the result if you reduce the resolution down to 8. The frequency is nearer to 1,000 Hz, but the sine looks rather angled.

To the top of that page

©2020 by http://www.avr-asm-tutorial.net