ICCAVR7 Projekt erstellen

Ich möchte hier meinen C-Compiler vorstellen, den ICCAVR von Imagecraft.

Dieses Programm gibt es als 45 Tage Testsoftware kostenlos mit vollem Funktionsumfang
und "codesizelimited" auf 4kb "für immer".
Ich habe mir die Version bis 64kb gekauft und eigentlich nur gute Erfahrungen gemacht.

Besonders interessant ist der "Zauberhut" bzw. der applicationbuilder der sich dahinter versteckt.
Jede Menge fehlerträchtiger Register-Sucherei wird einem abgenommen und selbst nicht ganz
triviale Initialisierungen werden automatisch generiert.

Eine simple Testanwendung mit dem USART und dem Timer1 des Mega8 verdeutlicht das Prinzip:

Nach dem Start hat man ein komplett leeres Fenster vor sich, und der Zauberhut wartet in
der Werkzeugleiste. Allerdings muss vor seinem Einsatz ein Projekt erzeugt werden.

 

Die Projekteinstellungen:


Zweckmäßig ist es für jedes Projekt einen eigenen Ordner anzulegen. ICCAVR tut das nicht automatisch,
weshalb der Explorer zu bemühen ist. Danach kann der Compiler gestartet werden und das Projekt
erzeugt werden.




Diese Optionen einzustellen ist UNUMGÄNGLICH notwendig:



Als Erstes muss die CPU eingestellt werden. Unter der PRINTF Version verbirgt sich
das Verwenden von C-Lib Funktionen. Es leuchtet ein, dass die Konvertierungsroutinen
für das Gleitkommaformat einen Speicher größer als 8Kb erfordern.
Als Programmtyp ist Application die Standardwahl.

Click auf Register Projekt:



Im Dialog Project ist keine Änderung notwendig.



In jedem Fall ist es günstig einen speziellen Output-Ordner anzugeben.



Für das STK500 ist als Programmierformat IntelHEX zu wählen.

Das SalvoConfig-Fenster ist nicht relevant.

Mit dem "OK" Butten werden die Einstellungen gespeichert, und nun ist der Zauberhut
an der Reihe:




Nach Click meldet sich der Applicationbuilder mit seinen Dialogen:



Der Applicationbuilder bietet 6 Registerkarten an, und startet mit der "CPU" Auswahl.
Stand Sept. 2008 sind alle für mich interessanten AtmelAVR's angeboten. Für das Beispiel wähle ich
den ATMega8 und stelle als Taktfrequenz 8 MHz ein. Die ist wichtig, weil alle Timerfunktionen davon
abgeleitet werden. Die Externen Interrupts werden im Beispiel nicht verwendet INT0 und INT1 ohne Haken.
Auch der Watchdogtimer bleibt unbenutzt, ebenso das EEPROM.



Der Dialog "Ports" listet die verfügbaren Ports auf und ermöglicht die Richtungswahl und die
Vorbesetzung der Ausgänge. Im Beispiel Port B alle auf Ausgang und Logisch "O"



Timer0 bleibt unbenutzt, also kein haken bei "Use Timer0".



Der Timer 1 soll einen 150ms Takt erzeugen. Definitionen mit anderen Units, z.B. Hz sind auch
möglich. Use Timer1 muss  natürlich aktiviert werden, ebenso der Overflow interrupt.
Alle anderen Optionen sind für das Beispiel irrelevant und bleiben wie sie sind.



Wird im Beispiel auch nicht benutzt, Use Timer2 bleibt leer.



Die serielle Schnittstelle soll Zeichen empfangen und unter Programmkontrolle Zeichen senden.
Use UART0 wird aktiviert, ebenso der Empfang (RX) und das Senden (TX).

Das Datenübertragungs-Protokoll wird auf 9600 Bd, 8Bit, NoPar., 2 Stopbit eingestellt.
Weil das eintreffende Zeichen eine Aktion auslösen soll, wird der Empfangsinterrupt (RX complete)
gewählt.



Das Seriell Peripherie Inerface bleibt unbenutzt.

Mit den Analogfunktionen hat das Beispiel ebenfalls nichts im Sinn.

Damit ist der Applicationbuilder gefüttert, und nach Click auf den Button "OK" erhält
man ein fast fertiges Startprogramm.

 

//ICC-AVR application builder : 06.09.2008 17:06:53
// Target : M8
// Crystal: 8.0000Mhz

#include <iom8v.h>
#include <macros.h>

void port_init(void)
{
PORTB = 0x00;
DDRB = 0xFF;
PORTC = 0x00; //m103 output only
DDRC = 0x00;
PORTD = 0x00;
DDRD = 0x00;
}

//TIMER1 initialize - prescale:256
// WGM: 0) Normal, TOP=0xFFFF
// desired value: 150mSec
// actual value: 149,984mSec (0,0%)
void timer1_init(void)
{
TCCR1B = 0x00; //stop
TCNT1H = 0xED; //setup
TCNT1L = 0xB1;
OCR1AH = 0x12;
OCR1AL = 0x4F;
OCR1BH = 0x12;
OCR1BL = 0x4F;
ICR1H = 0x12;
ICR1L = 0x4F;
TCCR1A = 0x00;
TCCR1B = 0x04; //start Timer
}

#pragma interrupt_handler timer1_ovf_isr:iv_TIM1_OVF
void timer1_ovf_isr(void)
{
//TIMER1 has overflowed
TCNT1H = 0xED; //reload counter high value
TCNT1L = 0xB1; //reload counter low value
}

//UART0 initialize
// desired baud rate: 9600
// actual: baud rate:9615 (0,2%)
void uart0_init(void)
{
UCSRB = 0x00; //disable while setting baud rate
UCSRA = 0x00;
UCSRC = BIT(URSEL) | 0x0E;
UBRRL = 0x33; //set baud rate lo
UBRRH = 0x00; //set baud rate hi
UCSRB = 0x98;
}

#pragma interrupt_handler uart0_rx_isr:iv_USART0_RXC
void uart0_rx_isr(void)
{
//uart has received a character in UDR
}

//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
timer1_init();
uart0_init();

MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x04; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}


Ein solider Anfang, ordentlich kommentiert, und vor Allem fehlerfrei.
Hinzufügen muss man die main() Schleife in der als erstes die Initialisierungs-Routine
für die Peripherie gerufen wird.

In die Interruptserviceroutine RX-complete im einfachsten Fall ein direktes Echo. Mit dem
Lesen des Datenregisters URD wird auch das Int-Bit zurückgesetzt,
z.B.:                                    zeichen = URD;
und zum Echo senden:    URD = zeichen;


Jetzt muss nur noch dem neuen Projekt die Quelldatei hinzugefügt werden. Mit "File  > Save as" gibt
man der datei einen Namen mit Erweiterung .C und speichert im Projektorner ab.

Das Projekt kennt aber diese Datei noch nicht. Deshalb Click mit RECHTER Mousetaste auf Files:



und "Add File(s)" ruft den Browser auf mit dem die .C-datei hinzugefügt wird.

Mit "Project -> Make Project" oder Taste "F9" wird das Projekt compiliert und die HEX-datei erzeugt.

Zum Programmieren des Mikroprozessors verwende ich AVRStudio4 und das STK500.


Steinhart, September 2008