Segunda UART

Software e Hardware para ATMEL

Moderadores: 51, guest2003, brasilma

Segunda UART

Mensagempor sandrini » 17 Jan 2007 15:08

Caros colegas,

Estou tentando fazer uma segunda serial num ATMEGA16 e quando eu compilo e faço a simulação no AVRSTUDIO, tudo está em ordem... os tempos de aquisição estão dentro do necesserário...
No proteus, quando envio algum caracter ou texto.... está bem legal... mas quando tento receber algo.... fica tudo meio esquisito, parece que está deslocando em 1 bit a mais, por exemplo, ao digitar a letra "b" (01100010) aparece "1" (00110001).... já fiz de tudo e não consegui entender o que pode estar acontecendo no meu código....

Será que alguém pode me dar alguma dica....
Segue abaixo uma parte do código para receber um dado.
Obs.: os tempos 140 de delay é para que se espera mais ou menos 156 microsegundso até o próximo bit e aí, 77 dá em torno de 104,5 microsegundos entre um bit e outro...

//==============================================

char Le_Carac(void)
{
unsigned char x=0;

conta = 8;

while (x = (PIND & 0x08)); //Aguarda STARTBIT
_delay_loop_2(140); //Aguarda o tempo do STARTBIT
while(conta)
{
if (PIND & 0x08)
lc = 0x80;
else
lc =0;
rc >>= 1;
rc = rc + lc;
_delay_loop_2(77);
conta--;
}
_delay_loop_2(77);
return rc;
}

//=============================================

Grato
sandrini
Nibble
 
Mensagens: 65
Registrado em: 12 Out 2006 10:16

Mensagempor sandrini » 17 Jan 2007 15:38

Consegui fazer funcionar meu programa com uma serial por software, ou seja, segunda UART.... Fiz isso para colocar num projeto onde preciso de mais uma UART para comunicação com outro equipamento....

Segue abaixo o programa e também serve como dica...
Se alguém quiser dar uma corrigida no que pode estar errado ou dar mais alguma dica... sintam-se à vontade, ok?

Código: Selecionar todos
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/delay.h>

struct var_pin
       {
       unsigned int P0 : 1;
      } var;


int tx_cnt, tx_wrk;
int lc, conta;
int rc, rec;



void Esc_Carac(unsigned char c)
{
tx_cnt = 0;
tx_wrk = 1;


PORTD = (0<<PD2);
_delay_loop_2(87);
while ( tx_cnt <= 8 )
   {
          var.P0 = c;
          c >>= 1;
          PORTD = var.P0<<PD2;
        _delay_loop_2(83);
        tx_cnt++;
   }
PORTD = (1<<PD2);
tx_wrk = 0;
}

void Esc_Text(char *s)
{
  while(*s)
           {
           if (tx_wrk == 0)
            {
             Esc_Carac(*s);
             s++;
            }
         }
}

char Le_Carac(void)
{
unsigned char x=0;

conta = 8;

while (x = (PIND & 0x08));   //Aguarda STARTBIT
_delay_loop_2(140); //Aguarda o tempo do STARTBIT
while(conta)
      {
      
       if (PIND & 0x08)
         lc = 0x80;
      else
         lc =0;
      rc >>= 1;
       rc = rc + lc;
      _delay_loop_2(77);
      conta--;
      }
_delay_loop_2(77);

return rc; 
   
}


int main(void)
{
tx_wrk = 0;
DDRD = 0x04;
DDRB = 0xFF;
PORTB = 0X00;
PORTD = (1<<PD2);


Esc_Text("Teste\n\r");


for ( ;; ) {
           Esc_Carac(Le_Carac());
       }
}
sandrini
Nibble
 
Mensagens: 65
Registrado em: 12 Out 2006 10:16

Mensagempor chrdcv » 17 Jan 2007 16:22

Prezado amigão,
Apesar de não concordar muito com emulação de serial por polling, principalmente recepção de dados por vários motivos, dentre eles o mais sério de sempre ter que "esperar" pela ocorrência do start bit, ocorrência esta totalmente atemporal...mas vamos lá...

Inicialmente gostaria que informássemos o baud rate esperado em bps. Analisando o seu código, pude perceber que ao esperar o start bit para iniciar a recepção do dado serial, o flag global de interrupção não é desabilitado, ou seja se alguma interrupção ocorre a uma dada taxa significativa, o atendimento do isr bem como as das funções que vc. chama dentro da isr podem interferir a posteriori. Portanto, antes de entrar no laço while, desabilite o seu flag global de interrupção, depois, espere o tempo de 1 bit + 1/2 bit e comece a ler os dados até o stop bit! simples não? Exemplo: se desejares uma taxa de 1200bps, tem-se que:
Tempo de 1 bit: 833.333us
Tempo de 1/2 bit: 416.667us

Uma outra forma bem mais elegante de realizar uma serial bit banging seria a utilização de dois timer sendo um na função capture e o outro na função compare, utilizando o mesmo princípio acima descrito. Já utilizei este método em várias arquiteturas outras arquiteturas com sucesso!

chrdcv
Avatar do usuário
chrdcv
Dword
 
Mensagens: 1580
Registrado em: 13 Out 2006 14:13

Mensagempor sandrini » 18 Jan 2007 11:57

Valeu chrdcv,

Fiz esse código com a intenção de utilizar em outro projeto onde preciso de 2 seriais... uma para "conversar" com o PC e outra com um equipamento, além de outros controles...
Na realidade, eu esqueci de tirar os headers de interrupção e sinal... neste código não uso nenhuma interrupção.
Para o meu projeto é até bom que se fique esperando um start bit, faz parte do sistema de controle esta espera...
Bem, eu também me esqueci de dizer que o baud rate é de 9600 bps...

Valeu também pela dica da utilização dos timers... ainda não tive tempo de estudar essa outra possibilidade.

Valeu
sandrini
Nibble
 
Mensagens: 65
Registrado em: 12 Out 2006 10:16

Mensagempor chrdcv » 19 Jan 2007 21:21

Oka Sandrini, qualquer coisa, estamos aí cara...
Avatar do usuário
chrdcv
Dword
 
Mensagens: 1580
Registrado em: 13 Out 2006 14:13


Voltar para AVR

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

cron

x