Hallo zusammen,
wie bereits im vorherigen Beitrag erwähnt, möchte ich euch ein wenig Beispielcode an die Hand geben, mit dem ihr den Xmega128A1 auf dem Mikrocontrollermodul schnell zum laufen bekommt.
Betrachten wir zuerst die Hardware auf dem Mikrocontrollermodul. Wir haben hier folgende Bereiche, die wir in unserer Software berücksichtigen müssen:
Im folgenden findet ihr den Kern-Beispielcode, dieser ist kommentiert, so dass ich hier nicht weiter auf den Sourcecode eingehen werde.
Das gesamte Projekt (AVRStudio + WinAVR) habe ich angehängt.
Im Beispielcode habe ich bereits einige Konfigurationswerte für unterschiedliche Baudraten angegeben, diese gelten für einen Systemtakt von 32MHz. Wenn ihr Baudraten benötigt, die ich nicht aufgeführt habe oder wenn ihr einen anderen Systemtakt verwendet, könnt ihr das Excel-File Baudrate_Calculations.xls nutzen, um die gewünschte Baudrate einzustellen. Das Excel-File befindet sich im angehängten Projektverzeichnis (zip).
Wenn ihr das Hex-File Xmega-A1-USB.hex programmiert, sollte die Status LED mit einer Periodendauer von 1 Sekunde blinken, bei Betätigung des Sub-Miniaturtasters PQ2, verringert sich die Periodendauer (200ms), die LED blinkt hier also schneller.
Ich hoffe, euch erleichtert der Beispiel-Sourcecode den Einstieg in die Xmega-Familie.
Schöne Grüße,
Dirk
Projektstruktur:
Projekt Optionen und Konfiguration:
wie bereits im vorherigen Beitrag erwähnt, möchte ich euch ein wenig Beispielcode an die Hand geben, mit dem ihr den Xmega128A1 auf dem Mikrocontrollermodul schnell zum laufen bekommt.
Betrachten wir zuerst die Hardware auf dem Mikrocontrollermodul. Wir haben hier folgende Bereiche, die wir in unserer Software berücksichtigen müssen:
- Quarz 16MHz an XTAL1/2, der Systemtakt (32MHz) soll aus diesem Takt erzeugt werden.
- Quarz 32,768kHz an TOSC1/2 (der Ozillator kann für Systemtakt, RTC und als Referenz für die digital frequency locked loops (DFFL) genutzt werden, im Beispiel behandel ich diese Features noch nicht).
- Sub-Miniaturtaster an PQ2, diesen wollen wir abfragen (Wenn der Bootloader einmal fertig ist, wird diese Taste für die Zwangsaktivierung des Bootloaders nach einem Reset verwendet werden).
- Status LED an PQ3, diese wollen wir ansteuern
- USART0 von PORTF ist das Interface zum CP2102 (USB-UART-Bridge), dieser muss initialisiert werden.
Im folgenden findet ihr den Kern-Beispielcode, dieser ist kommentiert, so dass ich hier nicht weiter auf den Sourcecode eingehen werde.
Code:
#define F_CPU 32000000UL
#include "avr_compiler.h"
#include "clksys_driver.h"
#include "usart_driver.h"
/* LED */
#define LEDPORT PORTQ // Port PORTQ
#define LEDMASK (1<<PIN3) // Status LED an PQ3
/* Taster */
#define SWITCHPORT PORTQ // Port PORTQ
#define SWITCHMASK (1<<PIN2) // Taster an PQ2
/* USART */
#define USART USARTF0 // USART0 von PORTF wird als Interface zu der
// USB-UART-Bridge CP2102 genutzt.
int main( void )
{
/* Set up user interface. */
LEDPORT.DIRSET = LEDMASK;
LEDPORT.OUTSET = LEDMASK;
SWITCHPORT.DIRCLR = SWITCHMASK;
SWITCHPORT.PIN2CTRL |= ( 0b011 << 3 ); // Pullup PQ2 aktivieren
/* Variable definition */
uint8_t buffer[512]; // wird für Testroutine 2 benötigt
uint16_t i;
/******************************************************************
* System Clock 32MHz (XOSC Quarz 16MHz, PLL Faktor 2)
******************************************************************/
/* Nach dem Reset ist die Quelle des Systemtaktes der interne
2MHz RC-Oszillator (System Clock Selection: RC2MHz)
*/
// Oszillator XOSC konfigurieren (12..16MHz, 256 clocks startup time)
CLKSYS_XOSC_Config( OSC_FRQRANGE_12TO16_gc,
false,
OSC_XOSCSEL_XTAL_256CLK_gc );
// Oszillator XOSC enable
CLKSYS_Enable( OSC_XOSCEN_bm );
// Warten bis der Oszillator bereit ist
do {} while ( CLKSYS_IsReady( OSC_XOSCRDY_bm ) == 0 );
// PLL source ist XOSC, Multiplikator x2
CLKSYS_PLL_Config( OSC_PLLSRC_XOSC_gc, 2 );
// Enable PLL
CLKSYS_Enable( OSC_PLLEN_bm );
// Prescalers konfigurieren
CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_1_gc );
// Warten bis PLL locked
do {} while ( CLKSYS_IsReady( OSC_PLLRDY_bm ) == 0 );
// Main Clock Source ist Ausgang von PLL
CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_PLL_gc );
// Nun ist der System Clock 32MHz !
/* Hinweis:
32kHz TOSC kann nicht in Verbindung mit PLL genutzt werden, da
die minimale Eingangsfrequenz des PLLs 400kHz beträgt.
*/
/******************************************************************
* Usart initialisieren, 8N1 250kBit
******************************************************************/
PORTF.DIRSET = PIN3_bm; // Pin3 von PortF (TXD0) ist Ausgang
PORTF.DIRCLR = PIN2_bm; // Pin2 von PortF (RXD0) ist Eingang
// USARTF0, 8 Data bits, No Parity, 1 Stop bit.
USART_Format_Set(&USART, USART_CHSIZE_8BIT_gc, USART_PMODE_DISABLED_gc, false);
/* Bitrate einstellen
Beispiele BSEL in Abhängigkeit von der Bitrate, fck = 32MHz, Error < 0,8%
7 = 250.000bps
30 = 128.000bps
34 = 57.600bps
51 = 38.400bps
68 = 28.800bps
103 = 19.200bps
138 = 14.400bps
207 = 9.600bps
416 = 4.800bps
832 = 2.400bps
1666 = 1.200bps
Bemerkung: Geprüft wurde mit 250.000bps im USBxpress Modus
*/
USART_Baudrate_Set(&USART, 7 , 0); // 250.000bps (BSEL = 7)
/* Enable RX and TX. */
USART_Rx_Enable(&USART);
USART_Tx_Enable(&USART);
USART_GetChar(&USART); // Flush Receive Buffer
/******************************************************************
* Test 1
******************************************************************/
/* Testroutine 1
Mit dieser Testroutine kann man den Taster (PQ2) und die
Status LED (PQ3) überprüfen. Man erkenn auch schnell,
ob der System Clock driver richtig konfiguriert ist.
*/
while(1) {
LEDPORT.OUTTGL = LEDMASK;
if (( SWITCHPORT.IN & SWITCHMASK ) == SWITCHMASK ) {
// Taste PQ2 nicht betätigt, Status LED blinkt langsam
delay_us( 500000 ); // 500ms
} else {
// Taste PQ2 betätigt, Status LED blinkt schnell
delay_us( 100000 ); // 100ms
}
}
/******************************************************************
* Test 2
******************************************************************/
/* Testroutine 2
Diese Routine wird im Beispiel Sourcecode nicht ausgeführt, sie diente
zum Testen der Signalqualität. Übertragen wurde hierbei mit 250.000bps.
Beschreibung des Tests:
Ein PC-Programm erzeugt ein 512 Byte großes Byte-Array mit Zufallszahlen,
die 512 Byte werden mit einer Bitrate von 250.000bps zum Mikrocontrollermodul
übertragen. Der XmegaA1 empfängt diese Daten und legt sie in einem Array (buffer)
ab. Danach sendet der XMegaA1 die Daten wieder zuürck, das PC-Programm empfängt
diese Daten und vergleicht sie mit den zuvor gesendeten Daten. Wird ein Fehler
festgestellt, wird der Test abgebrochen und es erfolgt eine Fehlermeldung.
Bemerkung:
Wenn man große Datenpakete ohne Software-Handshaking übertragen möchte, muss
man den maximal verfügbaren Fifo-Buffer im CP2102 beachten:
576 Byte Receive Buffer, 640 Byte Transmit Buffer
*/
while(1) {
// Receive 512 byte and copy to buffer array
for (i=0; i<512; i++) {
while(!USART_IsRXComplete(&USART));
buffer[i] = USART_GetChar(&USART);
}
// Send 512 byte content of buffer array
for (i=0; i<512; i++) {
while(!USART_IsTXDataRegisterEmpty(&USART));
USART_PutChar(&USART, buffer[i]);
}
// Toggle Status LED
LEDPORT.OUTTGL = LEDMASK;
}
return 0;
}
Das gesamte Projekt (AVRStudio + WinAVR) habe ich angehängt.
Im Beispielcode habe ich bereits einige Konfigurationswerte für unterschiedliche Baudraten angegeben, diese gelten für einen Systemtakt von 32MHz. Wenn ihr Baudraten benötigt, die ich nicht aufgeführt habe oder wenn ihr einen anderen Systemtakt verwendet, könnt ihr das Excel-File Baudrate_Calculations.xls nutzen, um die gewünschte Baudrate einzustellen. Das Excel-File befindet sich im angehängten Projektverzeichnis (zip).
Wenn ihr das Hex-File Xmega-A1-USB.hex programmiert, sollte die Status LED mit einer Periodendauer von 1 Sekunde blinken, bei Betätigung des Sub-Miniaturtasters PQ2, verringert sich die Periodendauer (200ms), die LED blinkt hier also schneller.
Ich hoffe, euch erleichtert der Beispiel-Sourcecode den Einstieg in die Xmega-Familie.
Schöne Grüße,
Dirk
Projektstruktur:
Projekt Optionen und Konfiguration: