USART part 1, schrijven naar usart. (Xmega)

Door mad_max234 op donderdag 12 december 2013 20:09 - Reacties (7)
Categorie: Software, Views: 5.433

Deel 1, het schrijven naar usart, deel 2 zal het lezen zijn. Zal in dit deel code bespreken hoe je de usart moet instellen en hoe je met printf een string kan versturen. De code bestaat uit twee functies, uart_intit en uart_putchar, en word met stdio ondersteunt om char één voor één naar de TX buffer te sturen. Voorbeeld code is voor 9600bps uart, uiteraard kan je dat aanpassen. :)

De uart_init functie

Port instellen:
Hier vul je de port in van de uart, TX moet hoog zijn en als output ingesteld worden, RX moet als input ingesteld worden, dat staat bij default goed dus hoeft niet ingesteld te worden, register heeft standaard 0.
C:
1
2
PORTD.DIRSET = PIN3_bm; //TX pin als output.
    PORTD.OUTSET = PIN3_bm; //TX pin hoog.



Bandbreedte instellen:
Om bandbreedte te bepalen is het makkelijkste om calculator te gebruiken.
http://www.avrcalc.elektr...mega/baud_rate_calculator

Je hebt twee waardes, BSCALE (BAUDCTRLB) en BSEL(BAUDCTRLA ). Word aangeraden om binnen de 0.5% error te blijven. Ik heb in voorbeeld code gekozen voor 9600bps usart en de xmega draait op zijn 2Mhz defualt snelheid. Vul bij fper [Hz]: 2000000 in en bij desired baud rate [bps]: 9600. Dan kijk je in de tabel en zoek je geschikte waarde uit. BSCALE 0 met BSEL 12 geeft 0.16% error, prima geschikt.
C:
1
2
USARTD0.BAUDCTRLB = 0;      
USARTD0.BAUDCTRLA = 12;



Modes instellen:
C:
1
2
USARTD0.CTRLA = 0;              // Geen usart interrupts.
    USARTD0.CTRLC = 0x03;           // async, no parity, 8 bit data, 1 stop bit.



Enable USART:
C:
1
USARTD0.CTRLB = USART_TXEN_bm;



De printf functie
Deze code hieronder is eigenlijk niks meer dan marco voor stdout, maakt een buffer tussen printf en uart_putchar. Is nodig om printf stream naar juiste functie te verwijzen. Zal hier nu niet veel verder op ingaan, stdio verdient een eigen post.
C:
1
static FILE mystdout = FDEV_SETUP_STREAM (uart_putchar, NULL, _FDEV_SETUP_WRITE);




De usart_putchar functie

Voordat we gaan zenden moeten we even kijken of de TX buffer klaar is. We kijken of de USART_DREIF(Data Register Empty Flag) gezet is, als buffer vol is blijft de while loop hier net zo lang hangen tot die leeg is.
C:
1
while ( !( USARTD0.STATUS & USART_DREIF_bm) );



We kunnen nu de buffer schrijven naar de USART
C:
1
USARTD0.DATA = c;




Volledige code:
* voorbeeld werkt zonder aanpassingen op de A4 serie, getest op atxmgea16a4, atxmgea32a4 en atxmgea32a4u.
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <stdio.h>
#include <avr/io.h>

static int uart_putchar(char c, FILE *stream);
static void uart_init (void);

static FILE mystdout = FDEV_SETUP_STREAM (uart_putchar, NULL, _FDEV_SETUP_WRITE);


int main (void)
{
    uart_init();
    stdout = &mystdout;
    
    while (1)
    {
        
    printf("Hallo wereld.\n");
    
    }   
}


static int uart_putchar (char c, FILE *stream)
{
    if (c == '\n') /
    uart_putchar('\r', stream);
    
    //Wachten dat de TX buffer leef is
    while ( !( USARTD0.STATUS & USART_DREIF_bm) );
    
    // stuur char naar de TX buffer
    USARTD0.DATA = c;
    
    return 0;
}

static void uart_init (void)
{
    PORTD.DIRSET = PIN3_bm; //TX pin als output.
    PORTD.OUTSET = PIN3_bm; //TX pin hoog.
    
    //Bandbreedte instellen. 
    USARTD0.BAUDCTRLB = 0;      
    USARTD0.BAUDCTRLA = 12;
    
    //Usart mode, 
    USARTD0.CTRLA = 0;              // Geen uart interrupts.
    USARTD0.CTRLC = 0x03;           // async, no parity, 8 bit data, 1 stop bit.
    
    // Enable usart
    USARTD0.CTRLB = USART_TXEN_bm;
}



Links:
http://www.atmel.com/Images/doc8408.pdf

Volgende: Wat is een Xmega? 12-'13 Wat is een Xmega?

Reacties


Door Tweakers user levik7, vrijdag 13 december 2013 16:39

Volgens mij vertel je een hoop interessants, maar ik snap er niks van. :/

Door Tweakers user afraca, vrijdag 13 december 2013 16:42

Voor enige context kun je natuurlijk naar de vorige blogpost van hem kijken, die op twee manieren op deze pagina ook vermeld staat, maar voor het gemak:

Xmega blog: Wat is een Xmega?

Door Tweakers user mad_max234, vrijdag 13 december 2013 16:45

Dat zal voor meerderheid opgaan denk ik. :)

Is ook bedoeld voor de tweakers die zich bezig houden met elektronica, is geen algemeen blogje maar specifiek voor bepaald groepje tweakers, al is iedereen welkom tweaker of niet.
En is zelfs specifiek voor bepaalde "cpu"(micro controller), echt niche hoekje dus.

Maar als je lang genoeg meeleest zul je vanzelf leren waar het over gaat. :P

Edit/
@ afraca
Of in header plaatje. "Alles over Atmel Xmega AVR"
Of rechts in about. "Blog waar Atmel atXmega serie word besproken, codes, hardware, etc."

:)

[Reactie gewijzigd op vrijdag 13 december 2013 16:49]



Door Tweakers user mad_max234, vrijdag 13 december 2013 22:35

Snap je vraag niet helemaal, kan je die wat beter stellen. Heb namelijk nog nooit gehoord van uart_destruct.

Door Tweakers user Infant, zaterdag 14 december 2013 14:50

Wat ook noemenswaardig is, ze noemen in de manual van bijv. de *A4U serie, een volgorde waarin je de USART moet initialiseren.
Dit is vrij belangrijk.

Als je bijv. na initialisatie wil wisselen van baudrate, moet eerst CTRLC op 0 gezet worden, en vervolgens de baudrate, de mode setting en dan pas weer enabelen.

Wellicht is het ook leuk om naar de interrupts te gaan kijken, want je kunt daar in de xmega serie echt heel veel mooie dingen mee doen.

Door Tweakers user mad_max234, zaterdag 14 december 2013 18:01

Inderdaad puntje van aandacht als je bandbreedte gaat aanpassen als je programma doorloopt, leuk onderwerp voor andere post, iets van bandbreedte switch bouwen of zo, zal even nadenken voor leuke toepassing. :)

Maar dat is niet van toepassing bij deze code. Zal het even onderbouwen voor mensen die afvragen waarom niet, je kan n dit geval niet de bandbreedte veranderen zonder de code opnieuw te uploaden en daarmee dus ook verplicht je programma te stoppen en opnieuw te starten waardoor initialiseren ook altijd weer opnieuw zal plaatsvinden. CTRLC is bij default namelijk 0, dus start je met juist waarde, zet pas na instellen van bandbreedte later naar 0x03 en dan enable we pas de usart.


Interrupts gestuurde usart komt later aanbod, net als interrupts in het algemeen.

Ga elke week één of meerder stukjes code posten en die kunnen dan besproken worden, verzoekjes mag. :)

Reageren is niet meer mogelijk