Mega4808 (AVR IoT WG) - USART device

Go To Last Post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi again.

 

I'm starting this new thread to ask questions about Mega4808 USART device.

I followed the tutorial for this device posted here.

 

I have the code divided by 2 files because I'm trying to use ADC device and show values via USART device and see them in my terminal window.

 

So, in onde file I have the ADC code and main() funciton:

/* 
 * File:   ADC_SingleConv.c
 * Author: narayan
 *
 * Created on 27 de Fevereiro de 2019, 22:45
 */

#define F_CPU 20000000UL

#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>

#include "usart.h"

#define ADC_SHIFT_DIV64 (6) /*Divide by 64*/

void CPU_Clk_Init(void){
    // Enable Protected Registers Write and select Internal Clock Oscillator of 20MHz and enable prescaler
    CPU_CCP = CCP_IOREG_gc;
    CLKCTRL_MCLKCTRLA = CLKCTRL_CLKSEL_OSC20M_gc;
    
    // Enable Protected Registers Write and set CPU clock prescaler
    CPU_CCP = CCP_IOREG_gc;
    CLKCTRL_MCLKCTRLB = CLKCTRL_PDIV_16X_gc | CLKCTRL_PEN_bm;
}

void ADC0_Init(void){
    // Disable Digital Input Buffer and Pull-Up
    PORTD_PIN6CTRL &= ~(PORT_ISC_gm | PORT_PULLUPEN_bm);
    PORTD_PIN6CTRL |= PORT_ISC_INPUT_DISABLE_gc;
    
    // Set ADC Prescaler and Reference Voltage
    ADC0_CTRLC = ADC_PRESC_DIV16_gc | ADC_REFSEL_INTREF_gc;
    
    // Set ADC resolution and Enable conversion
    ADC0_CTRLA = ADC_RESSEL_10BIT_gc | ADC_ENABLE_bm;
    
    // Set ADC channel
    ADC0_MUXPOS = ADC_MUXPOS_AIN5_gc;
    
    // Set ADC Mode to Accumulator - 64 values
    ADC0_CTRLB = ADC_SAMPNUM_ACC64_gc;
}

uint16_t ADC_Read(void){
    // Start selected Conversion
    ADC0_COMMAND = ADC_STCONV_bm;
    
    while( !(ADC0_INTFLAGS & ADC_RESRDY_bm) )
        /*wait*/;
    
    // Clear RESRDY register before starting new conversion
    ADC0_INTFLAGS = ADC_RESRDY_bm;
    
    return ADC0_RES;
}

/*
 * 
 */
int main(int argc, char** argv) {
    //uint16_t adcRead = 0;
    
    CPU_Clk_Init();
    ADC0_Init();
    USART0_Init();
    
    while(1){
        //adcRead = ADC_Read();
        //adcRead >>= ADC_SHIFT_DIV64;
        USART0_SendStr("A\n");
        //USART1_SendChar('\n');
        _delay_ms(10);
    }
    return (EXIT_SUCCESS);
}

 

and in the other file I have the USART code:

 

#ifndef F_CPU
#   define F_CPU 20000000
#endif

#include <avr/io.h>
#include <string.h>

#include "usart.h"

#define USART0_BAUD_RATE(BAUD_RATE) ((float)((20000000/16) * 64 / (16 * (float)BAUD_RATE)) + 0.5)

void USART0_Init(void){
    PORTA_DIR |= PIN0_bm;
    PORTA_DIR &= ~PIN1_bm;
    
    USART0_BAUD = (uint16_t) USART0_BAUD_RATE(9600);
    USART0_CTRLB |= USART_TXEN_bm;
}

void USART0_SendChar(uint8_t ch){
    while( !(USART0_STATUS & USART_DREIF_bm) )
        /*wait*/;
    USART0_TXDATAL = ch;
}

void USART0_SendStr(char* str){
    for(size_t i = 0; i < strlen(str); i++){
        USART0_SendChar(str[i]);
    }
}

 

For now I'm just trying to see if I'm sending the 'A' and the '\n' chars correctly and it looks like it is correct.

 

This picture is to show correct settings for 9600 baud rate. 1/104us = ~9615Hz

 

Then the complete transmission captured by my scopes LA.

 

And this is my interpretation of this pulse train

 

Going through it:

A is 0x41 or 65 decimal or 0100 0001. USART is LSB first,  then MSB, so it should be 1000 0010 excluding start and stop bits.

\n is 0x0a or 10 decimal or 0000 1010. USART is LSB first, then MSB, so it should be 0101 0000 excluding start and stop bits.

 

The fact is that I can't pick this up with minicom or cutecom! I can't see anything

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

99.9% of the time when UART doesn't work it's the bit timing (baud rate)

 

Hint: by default these chips do NOT run at the 20MHz your code appears to assume.

 

EDIT having said that I see you have the clock init but have you verified it worked? Another way to check is that 9600 baud UART bits should be 104us wide

Last Edited: Sun. Mar 3, 2019 - 04:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

99.9% of the time when UART doesn't work it's the bit timing (baud rate)

 

Hint: by default these chips do NOT run at the 20MHz your code appears to assume.

 

EDIT having said that I see you have the clock init but have you verified it worked? Another way to check is that 9600 baud UART bits should be 104us wide

 

I checked for that. 2nd image shows 1 bit width. 104us. Then I did 1/104 and I get 9615... It's approximately the 9600 baud rate.

Clock speed is actually 20Mhz divided by 16. I also added that to usart.c code. It's in the very first line of code (not comments) where I define that function to calculate the frequency baud rate parameter based on the main clock frequency.

 

I've changed the message to something else and it matches on the scope but still can't see anything in minicom/cutecom. I set 8N1, no Flow Control, activated Local Echo and CR+LF in minicom. I can't figure out what is wrong.

 

This is for string "Jose\n". I checked the 'J' bit stream and it matches 01001010 reversed and excluding start and stop bits.

Last Edited: Sun. Mar 3, 2019 - 04:50 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It seems pretty obvious the problem is outside the mega4808.

So, if you send some data to the serial port from the PC side, do you see something in the Rx line with the scope?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:

It seems pretty obvious the problem is outside the mega4808.

So, if you send some data to the serial port from the PC side, do you see something in the Rx line with the scope?

 

That could be the program I send from MPLAD to the chip, right? I should see bits coming in to this pin, right?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm not familiar with Linux, but I suppose, when you connect your board to the PC, there should appear some kind of virtual com port in the devices list? Something like /dev/ttyS2 or whatever?

When you use minicom, you are connected to which device?

You need to find out which of these devices is the dev board.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:

I'm not familiar with Linux, but I suppose, when you connect your board to the PC, there should appear some kind of virtual com port in the devices list? Something like /dev/ttyS2 or whatever?

When you use minicom, you are connected to which device?

You need to find out which of these devices is the dev board.

 

The device is /dev/ttyACM0. I also checked with Arduino IDE. With minicom I select this port and it doesn't complain about anything. And if I disconnect the board (unplug usb cable) minicom says it can't connect to ACM0 anymore. So I presume that minicom is able to connect but somehow can't see anything going through the port. I also tried to type chars in my terminal but I can't see anything either!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, I managed to do it with the help of a friend of mine via IRC (yes, it still exists).

 

I had to change to USART2 and use PF0 and PF1 as output ports of this device.

USART1 is being used for mikro Click board bus. USART0 I have no idea and USART2 is being used to communicate with my PC. Not sure how to call it.

 

Now I can see the string in minicom.

 

Now I'll try to see what is the ADC reading...