Enviar dado via UART

Software e Hardware para linha x51

Moderadores: 51, guest2003, Renie, gpenga

Enviar dado via UART

Mensagempor baltazar » 02 Ago 2007 13:26

Senhores,

Pelo título da mensagem já deu pra ver que é dúvida de principiante né?! E antes de mais nada quero dizer que já revirei o fórum(inclusive o antigo) em busca de uma solução para o meu problema e até agora nada...

O que acontece é o seguinte, tenho um projeto aqui controlado por um 8052 e sem nenhum canal serial configurado, minha idéia é fazer com que esse projeto fale serialmente com um outro projeto que desenvolvi recentemente, controlado por um PIC.

Sempre trabalhei com PICs e agora estou tomando uma surra para implementar a bendita serial no 8052.

Consegui alguns exemplos na internet(inclusive aqui no fórum) que ecoam um byte recebido pela serial do microcontrolador e todos eles funcionaram perfeitamente bem o problema é o seguinte:

Como faço para simplesmente enviar um dado pela serial do 8052 ao invés de ficar respondendo?

Tentei de todas as maneiras aqui, mas até agora não consegui fazer o microcontrolador "iniciar a conversa", só responder mesmo...

Eu tenho que setar ou resetar algum pino além do TX e RX? É que todos os outros pinos já estão sendo utilizados como I/O.

Valeu aí pela força e desculpem o conhecimento limitado...rs

Abraços!
baltazar
Bit
 
Mensagens: 42
Registrado em: 10 Nov 2006 18:47

Mensagempor Maurício » 02 Ago 2007 16:22

Olá, baltazar.

No 8051, é necessário antes de usar a UART, configurar registradores e timers para que ela possa operar.
No 8051 o baud-rate é dado somente pelo TIMER1. No 8052, vc pode usar ou o TIMER1 ou o TIMER2, ou ambos simultaneamente para gerar os bauds.
Baixe o dataxit do 8052 no site da Atmel, que lá vc encontra uma tabela com os valores mais comuns de carga do timer em função dos baud-rates que vc precisa.
Depois de configurar o timer, vc precisa configurar o modo de operação da serial no registrador SCON.
Se for em C, pra enviar um dado pela serial depois de configurá-la é só escrever:

Código: Selecionar todos
 
while ( !TI );    // espera transmitir o byte;
TI = 0;     // reseta o flag de transmissão;
SBUF = dado;    // envia o dado


Baixe o arquivo abaixo e dê uma olhada nos exemplos: EXERC13_6/13_7 e 13_8, que tratam de comunicação através da serial.

http://www.editoraerica.com.br/download ... troladores

[]'s
"Não leve a vida tão à sério, afinal, nenhum de nós sairá vivo, dela!"
Avatar do usuário
Maurício
Word
 
Mensagens: 678
Registrado em: 14 Out 2006 17:23
Localização: São Paulo - SP

Mensagempor brasilma » 02 Ago 2007 21:13

O Mestre Maurício já explicou tudo em C, um outro exemplo em Assembler poderia ser assim para enviar continuamente um "20H":

MOV TMOD,#21H ; Timer 1 (2=timer 8 bits auto-reload)
MOV TH1,#0F3H ; 9600 (c/ cristal 24MHz)
MOV TL1,TH1
MOV SCON,#50H ; Serial Mode 1
MOV PCON,#80H ; SMOD 1

SETB EA ; Abilita Interrupcoes
SETB ES ; Abilita Serial
SETB TR1 ; Liga timer 1

ENVIASTRINGL1: MOV SBUF,#20H
JNB TI,$
CLR TI
JMP ENVIASTRINGL1

Abraços,
MArcos.
" A Teoria orienta e a Prática decide" ;-)
Avatar do usuário
brasilma
Dword
 
Mensagens: 3621
Registrado em: 11 Out 2006 15:39
Localização: Planeta Terra

Mensagempor baltazar » 03 Ago 2007 08:27

Valeu pela ajuda aí senhores!

As minhas rotinas estão assim:

Inicialização da serial(Timer 1, 9600, 11.0592Mhz):
Código: Selecionar todos
      MOV   PCON, #0x00
      MOV    SCON, #0x50
      ORL    TMOD, #0x20
      MOV    TH1, #0xFD
      MOV    TL1, #0xFD
      SETB    ES
      SETB   EA
      SETB    TR1



Rotina de interrupção para a recepção serial:
Código: Selecionar todos
InterSerial:
      JNB    RI,Fim_InterSerial
      CLR    RI
      MOV    A,SBUF
Fim_InterSerial:
      reti



Rotina de envio:

Código: Selecionar todos
      MOV   A,#0x31
      MOV   SBUF,A
      JNB   TI,$
      CLR   TI



Está tudo ok?

Acontece que o equipamento "trava" na linha "JNB TI,$", parece que o TI não está sendo setado em momento algum!

Só mais um detalhe, esse projeto trabalha também com interrupção por estouro do Timer0(um RTC). Faz alguma diferença para a serial do 8052?

Ah, uma última coisa, estou trabalhando agora com um AT89C55, mas pelo que vi no datasheet a serial é exatamente igual, correto?

Abraços!
baltazar
Bit
 
Mensagens: 42
Registrado em: 10 Nov 2006 18:47

Mensagempor Maurício » 03 Ago 2007 10:27

baltazar escreveu:Está tudo ok?


Está correto, sim. Só tem um detalhe que eu não sei se nos PICs é igual.
Tanto pra transmitir como para receber, a serial ocupa a mesma interrupção. Se algum dos flags for setado, o programa é desviado para o mesmo endereço que trata a serial. No seu caso vc não pode amarrar a transmissão ( usando JNB TI,$ ), se vc já está usando interrupção pra tratar a serial. Vc precisa eliminar essa instrução e na sub-rotina de interrupção, colocar o seu código de tratamento lá.
Faz tempo que eu não programo em ASM, mas, a lógica é a mesma:

Se houver ou uma recepção, ou uma transmissão, a CPU vai ser desviada para o endereço de tratamento da interrupção.
Dentro da rotina vc testa os bits. Se for RI, faz alguma coisa. Testa TI. Se for TI faz outras coisas.
Normalmente, se for TI, a única coisa que a gente faz é resetar o flag dentro da interrupção e voltar pra execução do programa.

Acontece que o equipamento "trava" na linha "JNB TI,$", parece que o TI não está sendo setado em momento algum!


Não sei porque, mas acho que é por causa do que eu falei acima.
Talvez a CPU esteja resetando TI dentro do tratamento da interrupção e dessa forma, seu programa nunca mais vai sair do mesmo lugar.

Só mais um detalhe, esse projeto trabalha também com interrupção por estouro do Timer0(um RTC). Faz alguma diferença para a serial do 8052?


Não. Só que por construção, o MCU vai atender primeiro a interrupção do TIMER, que tem prioridade maior. Se vc quer que a serial tenha prioridade nas interrupções, basta setar o bit PS no registrador IP.

Ah, uma última coisa, estou trabalhando agora com um AT89C55, mas pelo que vi no datasheet a serial é exatamente igual, correto?


Correto.

Uma outra coisa que eu não sei se vc sabe é que nos vetores de interrupção do 51, só existem uns poucos bytes separando um vetor de outro, o que na maioria dos casos não dá pra colocar o código de tratamento da interrupção nesses bytes. Neste caso, o que se faz, é simplesmente colocar um JUMP pra um outro lugar onde haja mais espaço para codificar um tratamento. Uma coisa mais ou menos assim:

Código: Selecionar todos
org 23h            // endereço do vetor da interrupção serial
JMP TRATA_SERIAL

org 100h         // inicio do programa
;seu código aqui

TRATA_SERIAL:
JNB RI, verifica_TI
;código de RI
CLR RI
verifica_TI:
JNB TI, exit
;código de TI
CLR TI
exit:
RETI


Espero ter ajudado. O 8051 é meio chatinho, mas depois, se torna uma máquina bem eficiente.

[]'s
"Não leve a vida tão à sério, afinal, nenhum de nós sairá vivo, dela!"
Avatar do usuário
Maurício
Word
 
Mensagens: 678
Registrado em: 14 Out 2006 17:23
Localização: São Paulo - SP

Mensagempor baltazar » 03 Ago 2007 15:20

Nobre Maurício,

Muito obrigado pela ajuda, mas ainda não consegui fazer esse negócio funcionar...

O mais estranho é que ele não seta o desgraçado do TI de jeito nenhum!!!

Já habilitei a interrupção por recepção serial, desabilitei, habilitei de novo “sem utilizar” (Inter_Serial: reti) e nada...

Estava desconfiado que em alguma parte do código houvesse alguma rotina que alterasse o IE, daí fiz o seguinte:

Código: Selecionar todos
      jnb   Libera_Transmissao,Nao_Transmite
      clr   TI
      clr   RI
      mov   Temp,IE
      mov   IE,#0x00
      setb   EA
      setb   ES
      mov   a,#0x31
      MOV   SBUF,a
Aguarda_Transmissao:
      jnb   TI,Aguarda_Transmissao
      clr   TI
      mov   IE,Temp
      clr   Libera_Transmissao
Nao_Transmite:


No vetor de interrupção serial eu deixei apenas um reti.

E esse flag "Libera_Transmissao" é setado a cada virada de minuto do meu RTC, e sempre que isso ocorre o firmware trava aguardando o TI subir.

Não sei mais o que tentar aqui, já li e reli o datasheet do 89c55, também aquele databook da Intel sobre a família 51 e até agora não encontrei nada parecido...

Vou continuar na luta aqui, qualquer novidade eu aviso.

Abraços!
baltazar
Bit
 
Mensagens: 42
Registrado em: 10 Nov 2006 18:47

Mensagempor Maurício » 03 Ago 2007 16:37

Lamento.

Em ASM eu não posso te ajudar mais, porque eu nem me lembro como é a formatação de um programa. Sinto muito.

Boa sorte aí, mas, não é difícil fazer esse trem funcionar... :cry:

O livro do Denys Nicolosi (Microcontrolador 8051 Detalhado, da ed. Érica) é um bom ponto de partida.

[]'s
"Não leve a vida tão à sério, afinal, nenhum de nós sairá vivo, dela!"
Avatar do usuário
Maurício
Word
 
Mensagens: 678
Registrado em: 14 Out 2006 17:23
Localização: São Paulo - SP

Mensagempor brasilma » 03 Ago 2007 17:18

Baltazar,

Ok para o RETI no vetor de interrupção serial.

Viu, tenta fazer aquilo que coloquei, apenas monte o código a partir do endereço 30H (fora do espaço dos vetores de interrupção), que funciona, a partir dai vá fazendo as modificações que deseja.

Abraços,
MArcos.
" A Teoria orienta e a Prática decide" ;-)
Avatar do usuário
brasilma
Dword
 
Mensagens: 3621
Registrado em: 11 Out 2006 15:39
Localização: Planeta Terra

Mensagempor baltazar » 06 Ago 2007 16:40

Senhores,

Consegui resolver!!!

Montei um circuitinho apenas com o microcontrolador e um MAX232 e escrevi um firmware que apenas enviava um byte pela porta serial, como o exemplo que os senhores postaram aqui.

Pois bem, mesmo assim nada funcionou...

Mas aí sempre que eu ligava e desligava o circuito ele jogava um lixo na serial, fui ligando e desligando até que em um determinado momento ele “partiu”! E daí passou a funcionar certinho!

Desconfiei de um possível problema de power-up timer, daí coloquei um delay de alguns milisegundos antes da inicialização dos registradores e pronto, problema resolvido!

Ainda estou pesquisando aqui pra saber se a família 8051 exige esse retardo na inicialização ou se foi um golpe de sorte mesmo(em outras palavras, uma cagada!:D), mas o que importa é que por agora está tudo funcionando e posso continuar com minhas outras implementações aqui.

Mais uma vez obrigado pela ajuda aí moçada!

Abraços!
baltazar
Bit
 
Mensagens: 42
Registrado em: 10 Nov 2006 18:47

Mensagempor brasilma » 06 Ago 2007 16:44

Só se suas rotinas precisarem, pois o controlador não precisa não.

Verifique se o circuito de reset do controldador está de acordo com a recomendação do fabricante.
" A Teoria orienta e a Prática decide" ;-)
Avatar do usuário
brasilma
Dword
 
Mensagens: 3621
Registrado em: 11 Out 2006 15:39
Localização: Planeta Terra


Voltar para 8051

Quem está online

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

x