Como posso consertar esse código para permitir que meu AVR fale sobre a porta serial?

StackOverflow https://stackoverflow.com/questions/846206

  •  21-08-2019
  •  | 
  •  

Pergunta

Ultimamente, tenho puxado meu cabelo tentando obter um ATMEGA162 no meu STK200 para conversar com meu computador ao longo de Rs232. Eu verifiquei e certifiquei -me de que o STK200 contenha um chip MAX202CPE.

Eu configurei o chip para usar seu relógio interno de 8MHz e o dividi por 8.

Tentei copiar o código da folha de dados (e fiz alterações onde o compilador reclamou), mas sem sucesso.

Meu código está abaixo, alguém poderia me ajudar a resolver os problemas que estou tendo?

Confirmei que minha porta serial funciona em outros dispositivos e não está com defeito.

Obrigado!

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

#define BAUDRATE 4800

void USART_Init(unsigned int baud)
{
    UBRR0H = (unsigned char)(baud >> 8);
    UBRR0L = (unsigned char)baud;

    UCSR0B = (1 << RXEN0) | (1 << TXEN0);

    UCSR0C = (1 << URSEL0) | (1 << USBS0) | (3 << UCSZ00);
}

void USART_Transmit(unsigned char data)
{
    while(!(UCSR0A & (1 << UDRE0)));

    UDR0 = data;
}

unsigned char USART_Receive()
{
    while(!(UCSR0A & (1 << RXC0)));

    return UDR0;
}

int main()
{

    USART_Init(BAUDRATE);

    unsigned char data;

    // all are 1, all as output
    DDRB = 0xFF;

    while(1)
    {
        data = USART_Receive();

        PORTB = data;

        USART_Transmit(data);


    }
}
Foi útil?

Solução 4

Depois de ler a folha de dados um pouco mais detalhadamente, eu estava definindo incorretamente o Baudrate. A folha de dados ATMEGA162 tinha um gráfico de frequências de relógio plotadas contra taxas de transmissão e o erro correspondente.

Para uma taxa de transmissão de 4800 e uma frequência de relógio de 1 MHz, o erro foi de 0,2%, o que foi aceitável para mim. O truque estava passando 12 para a função USART_INIT (), em vez de 4800.

Espero que isso ajude outra pessoa!

Outras dicas

Eu comentei a resposta de Greg, mas gostaria de adicionar mais uma coisa. Para esse tipo de problema, o método padrão -ouro de depuração é primeiro Compreendo Comunicações em série assíncronas, depois obter um osciloscópio e ver o que está acontecendo na linha. Se os caracteres estiverem sendo trocados e é apenas um problema baudrato, isso será particularmente útil, pois você pode calcular o Baudrate que está vendo e depois ajustar o divisor de acordo.

Aqui está uma cartilha super rápida, sem dúvida que você pode encontrar algo muito mais abrangente na Wikipedia ou em outro lugar.

Vamos assumir 8 bits, sem paridade, 1 parada (a configuração mais comum). Então, se o caractere transmitido for disse 0x3f (= ascii '?'), Então a linha se parece com isso;

...--+   +---+---+---+---+---+---+       +---+--...
     | S | 1   1   1   1   1   1 | 0   0 | E
     +---+                       +---+---+

O nível alto (1) é +5V no chip e -12V após a conversão em níveis de RS232.

O nível baixo (0) é 0V no chip e +12V após a conversão em níveis de RS232.

S é o bit de início.

Em seguida, temos 8 bits de dados, menos significativos primeiro, então aqui 00111111 = 0x3f = '?'.

E é o bit Stop (E for End).

O tempo está avançando da esquerda para a direita, assim como uma tela de osciloscópio, se o Baudrate for 4800, cada bit se estende (1/4800) segundos = 0,21 milissegundos (aprox).

O receptor trabalha amostrando a linha e procurando uma borda em queda (uma linha inquieta é simplesmente lógica '1' o tempo todo). O receptor conhece o Baudrate e o número de bits de início (1), por isso mede meio tempo a partir da vantagem de queda para encontrar o meio do bit de início e depois amostra a linha 8 vezes em sucessão depois disso para coletar o bits de dados. O receptor aguarda mais um tempo (até a metade do bit de parada) e começa a procurar outro bit de partida (ou seja, a borda caindo). Enquanto isso, a leitura do personagem é disponibilizada para o restante do sistema. O transmissor garante que a próxima borda que caia não começará até que o bit de parada esteja concluído. O transmissor pode ser programado para sempre esperar mais (com bits de parada adicionais), mas esse é um problema herdado, bits extras de parada eram necessários apenas com configurações de hardware e/ou software muito lentas.

Não tenho material de referência à mão, mas o registro da taxa de transmissão UBRR geralmente contém um valor de divisor, em vez da própria taxa de transmissão desejada. UMA Pesquisa rápida do Google indica que o valor correto do divisor para 4800 baud pode ser 239. Portanto, tente:

divisor = 239;
UBRR0H = (unsigned char)(divisor >> 8);
UBRR0L = (unsigned char)divisor;

Se isso não funcionar, verifique com os documentos de referência para o seu chip específico para a fórmula de cálculo do divisor correta.

Para depurar a comunicação UART, há duas coisas úteis a fazer:

1) Faça uma volta no conector e verifique se você pode ler de volta o que escreve. Se você enviar um personagem e recuperá -lo exatamente, sabe que o hardware está conectado corretamente e que pelo menos o conjunto básico de configuração do registro UART está correto.

2) Envie repetidamente o caractere 0x55 ("u") - O padrão de bit binário 01010101 permitirá que você veja rapidamente a largura do bit no osciloscópio, o que permitirá que você verifique se a configuração de velocidade está correta.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top