Author Topic: Using both USART channels on AVR64DD28  (Read 679 times)

0 Members and 1 Guest are viewing this topic.

Offline jezel123Topic starter

  • Contributor
  • Posts: 14
  • Country: ch
Using both USART channels on AVR64DD28
« on: July 05, 2023, 09:13:37 am »
This is my code

Code: [Select]
#include "driverAVR64DD28.h"


int main(void)
{
    initInternalHFClock(0,0);
   
    initUsart0Full(9600);
    initUsart1Full(9600);
   
    _delay_ms(100);
    transmitUsart0('S');
    _delay_ms(10);
    transmitUsart0('t');
    _delay_ms(10);
    transmitUsart0('a');
    _delay_ms(10);
    transmitUsart0('r');
    _delay_ms(10);
    transmitUsart0('t');
    uint16_t buffer = 0;
    while (1)
    {
        while (!(USART1.STATUS & 0x80));
        buffer = receiveUsart1();
        transmitUsart0(buffer);
       
    }
}


Now those are the definitions for usart functions:


Code: [Select]
void initUsart0Full(uint64_t baudrate)
{
    usart0OutputPins(0x2);
    uint16_t baud = (double)FREQUENCY*1000000/baudrate*4;
    USART0.BAUDL = baud;
    USART0.BAUDH = baud>>8;
    USART0.CTRLC = 0b00001011;
    PORTA.DIRSET = 0b00000100;
    USART0.CTRLB |= 0b11000100;

}

void transmitUsart0(uint16_t data)
{
    USART0.TXDATAH = data>>8;   
    USART0.TXDATAL = data;
    while (!(USART0.STATUS & 0b01000000));
}

uint16_t receiveUsart0(void)
{
    return (USART0.RXDATAH&1)<<8 | USART0.RXDATAL;
}



void initUsart1Full(uint64_t baudrate)
{
    usart1OutputPins(0x2);
    uint16_t baud = (double)FREQUENCY*1000000/baudrate*4;
    USART1.BAUDL = baud;
    USART1.BAUDH = baud>>8;
    USART1.CTRLC = 0b00001011;
    PORTD.DIRSET = 0b01000000;
    USART1.CTRLB |= 0b11000000;
}

void transmitUsart1(uint16_t data)
{
    USART1.TXDATAH = data>>8;
    USART1.TXDATAL = data;
    while (!(USART1.STATUS & 0b01000000));
}

uint16_t receiveUsart1(void)
{
    return (USART1.RXDATAH&1)<<8 | USART1.RXDATAL;
}

void usart0OutputPins(uint8_t val)
{
CCP = 0xD8;
PORTMUX.USARTROUTEA = val;
}

void usart1OutputPins(uint8_t val)
{
uint8_t buffer = val << 3;
CCP = 0xD8;
PORTMUX.USARTROUTEA = buffer;
}


Now if I change the order of initializing USARTs (first 1 than 0) i get the desired output from USART0 but USART1 doesnt register input. if I do it like in the code i get no output on USART0 but it registers input on USART1. Can someone help me?
 

Offline ArdWar

  • Frequent Contributor
  • **
  • Posts: 721
  • Country: sc
Re: Using both USART channels on AVR64DD28
« Reply #1 on: July 05, 2023, 10:32:31 am »
Code: [Select]
void usart0OutputPins(uint8_t val)
{
CCP = 0xD8;
PORTMUX.USARTROUTEA = val;
}

void usart1OutputPins(uint8_t val)
{
uint8_t buffer = val << 3;
CCP = 0xD8;
PORTMUX.USARTROUTEA = buffer;
}
You're overwriting previous register setting. Use the usual |= assignment instead.

Although the way you're taking the parameter here is very prone to unexpected values.
 

Offline jezel123Topic starter

  • Contributor
  • Posts: 14
  • Country: ch
Re: Using both USART channels on AVR64DD28
« Reply #2 on: July 05, 2023, 10:38:27 am »
THANK YOU! I knew i did something wrong. Would a switch case be a better way to process the parameter?
 

Online cv007

  • Frequent Contributor
  • **
  • Posts: 880
Re: Using both USART channels on AVR64DD28
« Reply #3 on: July 05, 2023, 10:22:26 pm »
With multiple uarts (and possibly more than 2 if you move to another similar avr with more pins), it is nice to get something in place that can handle all the uarts and all the possible pins. It then becomes code which is created one time only and allows for easier changing of uarts/pins. These newer avr's are ideal for doing this since the peripherals are an 'instance' type (register layout is the same for each instance of a peripheral).

Something such as-
https://godbolt.org/z/f5axdPjWj

There are various ways to go about doing this, and this version is one way to do it. The use of print/scan is optional and can be bypassed (I rarely use scanf, so just added it to show it can also be done similar to the print function). The use of print (printf) will simplify uart output in a big way, and for the avr it costs about 1.5k of code but is a one time cost (once used, use everywhere you can). If you end up going to buffer use (interrupts), its not much more work to get the code to deal with a buffer instead of directly accessing the rx/txdata registers (isr code will deal with the buffer).

Using C++ is a little nicer for various reasons, but if not your thing you just live without it-
https://godbolt.org/z/89Pjfvzcv


fyi- portmux is not CCP protected.


edit- the scanf code is wrong as it is using non-blocking uart reads (with -1 meaning no data available), but scanf has no provision for non-blocking reads so would need to provide a FILE.get function that blocks on rx data available.
« Last Edit: July 06, 2023, 09:28:39 am by cv007 »
 
The following users thanked this post: uliano


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf