• Welcome to LusoRobótica - Robótica em Português.
 

Problemas com a USART

Started by Electropepper, 16 de September de 2014, 23:54

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Electropepper

Estou a tentar imprimir no terminal do PC a string "Hello", a unica coisa que me sai é H ou He outras vezes lixo, e apenas quando o ligo.
Já googlei dezenas de exemplos e passei horas a ler o datasheet, estou completamente encalhado e é provavelmente alguma coisa mesmo á minha frente.
O micro é o atmega328p.
Já agora aqui ficam os fuses lidos pelo avrdude : avrdude: safemode: Fuses OK (H:07, E:D9, L:E2)
Aqui fica o código :
#define F_CPU 1000000UL

#include <avr/io.h>
#include <util/delay.h>

#define UART_BAUDRATE 4800// Set serial baud HERE
#define BAUD_PRESCALE (((F_CPU / (UART_BAUDRATE * 16UL))) - 1)


void setup(void);
void USART_Init(void);
void USART_send( unsigned char data);

int main(void) {

    setup();

    while (1) {

        USART_send('H');
        USART_send('e');
        USART_send('l');
        USART_send('l');
        USART_send('o');
        USART_send('\n');

        _delay_ms(4000);
    }
return 0;
}void setup(void) {

    DDRC = 0x01;
    DDRD = 0x00;

// Set clock to 1 MHZ, also necessary to change F_CPU aproprietly
// to take effect in the delay routines.
    CLKPR = 0x80;
    CLKPR = 0x03;
    USART_Init();
}

void USART_Init(void) {

    UBRR0H = (uint8_t)(BAUD_PRESCALE>>8);
    UBRR0L = (uint8_t)(BAUD_PRESCALE);
    UCSR0C = ((1<<UCSZ00)|(1<<UCSZ01));
    UCSR0B = (1<<RXEN0)|(1<<TXEN0);

}

void USART_send( unsigned char data){

    while(!(UCSR0A & (1<<UDRE0))){};
    UDR0 = data;

}

senso

UART com oscilador interno nos atmegas é para esquecer, podes calibrar o oscilador interno, mas dado que isso é algo mais complicado e penso que precisas de um programador ISP reconhecido no avr-studio, mete antes um cristal.

No entanto os teus fuses estão configurados para usar um cristal externo, meter o sinal do clock no pino PB0, com espaço para bootloader de 2K, mas sem estar a fazer o salto para o bootloader no reset, divisão do clock por 8 e brown out a 4.3v, combinação meio estranha, estás a usar um cristal, ou não?
Avr fanboy

dropes

A velocidade de um atmega com oscilador interno vai funcionar com a frequência programada nos fusebits, mas infelizmente também vai variar bastante com a tensão de alimentação e precisão do oscilador, sem contar com outros factores menos importantes que o UART tolera.
Seja como for o micro tem de levar cristal ou o sincronismo é mentira e tem de se andar a fazer reset constantemente no micro e no UART do pc cada vez que bloqueia a comunicação.

Existem valores de cristais adequados para a comunicação UART, isto para que a variação seja a mais baixa possível.

Electropepper

Não estou a usar cristal, mas com esta configuração como está já pisquei um LED sem problemas, e o unico fuse que toquei foi no low fuse para tirar o divisor por 8 que vem de fábrica, tudo o resto está com veio de fábrica.

senso

De certeza que isso não era um atmega já programado com um bootloader?
Porque até acho estranho o micro funcionar assim sem um cristal.
Avr fanboy

Electropepper

Não tem nenhum bootloader, usei o avrdude com o buspirate para o programar por SPI, e este chip tem cristal interno, é so usar o presacler para dividir o clock.

Electropepper

Página 28 do datasheet :
Default Clock Source
The device is shipped with internal RC oscillator at 8.0MHz and with the fuse CKDIV8 programmed, resulting in
1.0MHz system clock. The startup time is set to maximum and time-out period enabled. (CKSEL = "0010", SUT
= "10", CKDIV8 = "0"). The default setting ensures that all users can make their desired clock source setting
using any available programming interface.

E foi assim que veio, o unico fuse que toquei foi o tal CKDIV8 que desliguei para ter o chip sempre a arrancar a 8.0MHZ certinhos.

senso

Usa isto e vê por ti então..
http://www.engbedded.com/fusecalc/
Com low fuse de 07 o CKSEL tem o valor de 0111, full swing crystal.
E não tem um cristal interno, tem um oscilador RC interno com uma variação de +/-10 ou +/-20%

Os valores de fábrica é de low: 0x62, high: D9, extended: FF
Avr fanboy

Electropepper

Por acaso foi esse calculator que usei  :D.
De qualquer maneira já aqui tenho na mão um crystal de 3.6864Mhz mais logo já esperimento.
Agora fiquei um pouco confuso com os Low Power Crystal Oscillator e os Full Swing Crystal Oscillator,
não estou a perceber bem a diferença e têm configuração de fuse diferentes.

P.s - Sim oscilador RC interno era isso a que me referia.

jmiguelff

Isto pode não fazer sentido mas eu vendo esse código e tendo esse problema a primeira coisa que tentava era por delays entre os 'sends'.


jm_araujo

#10
Que software de terminal estás a usar no PC?
É que a última versão do meu favorito (o Bray++ 1.91b - https://sites.google.com/site/terminalbpp/ ) tem um erro que perde caracteres se tiveres os sidepanel "Dec", "Bin" ou "Hex" ligados.
A ultima versão beta (https://sites.google.com/site/terminalbpp/Terminal20140703.zip?attredirects=0) porta-se melhor.

dropes

Se estás a dizer que alteraste os fusebits para ter um oscilador interno de 8MHz, então no teu código também devias ter alterado a velocidade na 1ª linha onde está 1MHz.

beirao

Quote from: jm_araujo on 17 de September de 2014, 11:10
Que software de terminal estás a usar no PC?
É que a última versão do meu favorito (o Bray++ 1.91b - https://sites.google.com/site/terminalbpp/ ) tem um erro que perde caracteres se tiveres os sidepanel "Dec", "Bin" ou "Hex" ligados.
A ultima versão beta (https://sites.google.com/site/terminalbpp/Terminal20140703.zip?attredirects=0) porta-se melhor.

Correcto! Perde bytes e fica lento! se tiver tudo selecionado (Dec, Bin, Hex) e enviar um conjunto de bytes, os bytes são mostrados aos "soluços"

Costumo usar o Hercules; é menos intuitivo que o bray++ mas também gosto bastante.
"O único lugar onde o sucesso vem antes do trabalho, é no dicionário" - Albert Einstein

Electropepper

Ok agora com o crystal continua basicamente na mesma, entretanto reparei que tinha o fuse, WDTON e tentei ativalo com o comando :
avrdude -p atmega328p -c buspirate -P /dev/ttyUSB0 -U hfuse:w:0x17:m
Agora estraguei tudo, já não consigo programar mais o chip  >:(
Agora quando o tento programar ou alterar os fuses recebo :
avrdude -p atmega328p -c buspirate -P /dev/ttyUSB0 -U hfuse:w:0x07:m -F

Attempting to initiate BusPirate binary mode...
avrdude: initialization failed, rc=-2
avrdude: AVR device initialized and ready to accept instructions
avrdude: Device signature = 0x58246b
avrdude: Expected signature for ATmega328P is 1E 95 0F

avrdude done.  Thank you.

E pronto já não sai disto, e insistindo reparo que o Device signature está sempre a mudar.
Voltei á estáca -1.  :o

senso

Para cristais deves SEMPRE usar full swing cristal oscilator, usa um pouco mais de corrente, o low power é mais indicado para frequencias baixas, tipo 32Khz e por ai assim, tambem se pode usar com os ressonadores cerâmicos.

E porque é que querias activar o watch-dog?
É util, mas para aplicações simples é melhor não usar isso, provavelmente está sempre a fazer resets devido ao watch-dog.

Re-confirma todas as conexões do programador.
Avr fanboy