Gostaria de compartilhar com os amigos do fórum uma excelente explicação sobre UART que achei no fórum do Mikrobasic, poderia publicar no tópico do MK aqui do forum porem alguns que passam por aqui e não usam esse software não olham muito para esse tópico. Porem os moderadores podem ficar a vontade para movê-lo se acharem melhor.
A única coisa que fiz foi traduzir para o português e adapta-lo ao meu idioma, mais pelo seu conteúdo quero compartilhar com vocês.
Esta explicação pode facilmente ser adaptada ate mesmo para o Proton e Pic Basic
Espero que gostem e ajude aqueles que tenham duvidas como eu.
Esta todo traduzido e o programa todo comentado.
O original esta neste endereço.
http://www.mikroe.com/forum/viewtopic.php?t=9280 programa Soft_Uart_GPIO
Por Warren Schrorder
traduzido por Ivan Braga
Usando mikroBasic 5.02 .. March 11, 2007
Repordução somente com a permissão do autor
Abaixo está uma curta explicação para ajudar a um programador a criar uma versão por SOFT_UART para series microcontrollers PIC12. Isto foi eleborado como um guia e sendo uma aproximação à teoria e à aplicação do UART.
O código exemplo foi escritos para um 12F683 @ 4MHz. O Baud rate da UART esta a 19200.
Os conceitos básicos dos seguintes exemplos podem ser executados com algumas mudanças para todas as famílias de PIC.
O UART é um método de comunicação assíncrono que necessita de um transmissor e receptor e que tenham uma taxa comum de velocidade para comunicação, também conhecida como o baud rate, ou bit rate.
Exige somente 2 linhas de interconexão entre o transmissor e receptor. Desde que não haja nenhuma linha comum de sincronização, como encontrado em “comunicações sincrônicas”, o receptor deve testar o estado de sua linha de RX para cada um dos 8 “bits de dados” (um byte simples) de informação no mesmo baud rate que está sendo transmitido.
Como o receptor sabe quando começar testar para os bits de dados?
Um método engenhoso é primeiro detectar um BIT de STAR, e depois seguido por 8 ou 9 bits de dados, e finalmente um BIT de STOP. A linha RX do receptor é uma linha de entrada que esta sempre HIGH pela linha de saída TX do transmissor quando não houver nenhuma comunicação.
Quando o transmissor vai enviar algum dado a ele coloca a linha de transmissão em baixo “low” um bit-rate para medir o período de tempo. Isto é o BIT START. Na primeira detecção do BIT START o receptor é alertado e deve começar a testar a entrada de RX no baud rate esperado para cada um dos seguintes 8 ou 9 bits de dados (LSBit, primeiro bit menos significante), e sequencialmente o BIT STOP.
O BIT STOP é obrigatoriamente colocado em nível elevado “HIGH” depois de ler os 8 ou 9 bits de dados. Se o de nível elevado “HIGH” não é detectado, isto é uma indicação de um erro na transmissão.
Desde que foi bit transmitido houve um período de tempo específico, é ideal testar a linha de RX no meio deste período. Por exemplo, um baud rate 19.200 é o mesmo que 19200 bits por o segundo, ou 1 bit cada 52us (1/19200). Como é esperado o byte de 8 bits de dados, e também os BITS de START e de STOP, então 10 testes totais de bit são executados pelo receptor “RX” durante 10 x 52us = 520us = .52ms. Para teste no meio de um período de teste é então o mesmo que 1/2 período de bit-rate. Em nosso exemplo, 1/2 de 52us = 26us.
Criar leituras confiáveis do UART, e otimiza-las aproveitando-se da caraterística como edge-triggered GP2/INT interrupção encontrada no pino de entrada do PIC12. A "interrupt-on-change”, característica esta que também está disponível em todos os pinos GPIO, exceto no MCLR.
Se as interrupções não forem usadas o programador teria que estar atento e verificar o pino RX para procurar o BIT START pelo menos uma vez que cada 1 período de bit-rate, quanto antes melhor.
Neste exemplo a interrupção GP2 edge-triggered é executada captando o high-to-low da transmissão. Quando esta interrupção for habilitada e esta interrupção ocorrer->(flag = 0), ou seja, a transmissão do BIT STAR provocará o salto ao ISR (Interrupt Service Routine). Quando dentro do ISR você pode ler o dado da transmissão.
Esta é a seqüência que testará o pino RX, será uma transmissão de 8 bits de dados:
'
' 1. Testa a linha RX para encontrar o BIT START... detecta um ponto baixo
' 2. Período de espera 1 bit-rate
' 3. Agora no primeiro bit de dados mas espera por um período de 1/2 bit-rate a mais ao teste.
' 4. Testa o nível do bit 0 de dados, move à direita do buffer RX, e coloca o valor no 7ºbit do buffer de RX
' 5. Período de espera 1 bit-rate
' 6. Testa o nível do bit 1 de dados, move à direita do buffer RX, e coloca o valor no 7ºbit do buffer de RX
' 7. Período de espera 1 bit-rate
' 8. Testa o nível do bit 2 de dados, move à direita do buffer RX, e coloca o valor no 7ºbit do buffer de RX
9. Período de espera 1 bit-rate
' 10. Testa o nível do bit 3 de dados, move à direita do buffer RX, e coloca o valor no 7ºbit do buffer de RX
' 11. Período de espera 1 bit-rate
' 12. Testa o nível do bit 4 de dados, move à direita do buffer RX, e coloca o valor no 7ºbit do buffer de RX
' 13. Período de espera 1 bit-rate
' 14. Testa o nível do bit 5 de dados, move à direita do buffer RX, e coloca o valor no 7ºbit do buffer de RX
' 15. Período de espera 1 bit-rate
' 16. Testa o nível do bit 6 de dados, move à direita do buffer RX, e coloca o valor no 7ºbit do buffer de RX
' 17. Período de espera 1 bit-rate
' 18. Testa o nível do bit 7 de dados, move à direita do buffer RX, e coloca o valor no 7ºbit do buffer de RX
' 19. Período de espera 1 bit-rate
' 20. Testa o BIT de STOP... deve ser HIGH ou é um ERRO
'
Para a transmissão é quase a mesma a não ser que não haja nenhuma necessidade para o sincronismo de 1/2 bit-rate.
Esta é a seqüência para enviar 8 bits de dados no pino da saída TX:
'
' 1. Fazer a pino de TX baixo...inicia com START BIT
' 2. Período de espera 1 bit-rate
' 3. Le o bit 0 do buffer de TX... set/reset o pino TX respectivamente
' 4. Período de espera 1 bit-rate
' 5. Move à direita o TX Buffer e le bit 0 ... set/reset o pino TX respectivamente
' 6. Período de espera 1 bit-rate
' 7. Move à direita o TX Buffer e le bit 0 ... set/reset o pino TX respectivamente
' 8. Período de espera 1 bit-rate
' 9. Move à direita o TX Buffer e le bit 0 ... set/reset o pino TX respectivamente
' 10. Período de espera 1 bit-rate
' 11. Move à direita o TX Buffer e le bit 0 ... set/reset o pino TX respectivamente
' 12. Período de espera 1 bit-rate
' 13. Move à direita o TX Buffer e le bit 0 ... set/reset o pino TX respectivamente
' 14. Período de espera 1 bit-rate
' 15. Move à direita o TX Buffer e le bit 0 ... set/reset o pino TX respectivamente
' 16. Período de espera 1 bit-rate
' 17. Move à direita o TX Buffer e le bit 0 ... set/reset o pino TX respectivamente
' 18. Período de espera 1 bit-rate
' 19. Coloca o pino TX em HIGH... envia o STOP BIT
'
'
' O sincronismo é essencial em comunicações assíncronas. Isto significa que o tempo para o deslocamento do bit, a leitura do bit, e as operações de bit-writing é necessário ao cálculos de sincronismo. Sendo assim, o período bit-rate deve ser ajustado adequadamente. Preste atenção aos comentários no seguinte código
para explanações como estes ajustes são feitos.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
' PROGRAMA:
' clock de Instrução é 1us (Fosc/4)
' 19200 Baud é 52us por bit... or 52 instruções ciclos de clock
' Importante verificar o RXBuffer aproximadamente à cada 500us
symbol RXpin = GPIO.2 ' GP2 tem função especial edge-interrupt
symbol TXpin = GPIO.1 ' TX saída
symbol RX = 2 ' RX número do pino
symbol TX = 1 ' TX número do pino
dim RXBuffer as byte ' UART buffer de recepção
dim BitCnt as byte ' contador do bit de dados
dim MyByte as byte
sub procedure interrupt ' 11 ciclos (11us) usados a este ponto após o BIT START
BitCnt = 8 ' isto pode ser ajustado a 9 para transferência de 9 dados do bit
delay_us(39) ' deduzir 13 ciclos (52-13=39us) para a chamada da interrupção e o carregar o "bitcnt"
delay_us(13) ' 1/2 bit-rate tempo … deduz 13 ciclos para troca seguinte da move & bit transfer
Do
RXBuffer = RXBuffer >> 1 ' move os dados para a direita para a leitura seguinte
RXBuffer.7 = RXpin ' lê o pino RX e o guarda no bit 7
delay_us(33) ' deduz 19 ciclos para a troca, a transferência do bit, e o tempo do loop
Loop Until dec(BitCnt) = 0 ' nós recebemos todos os bits dos dados?
If RX = 0 Then
RXBuffer = 0 ' limpa byte RX se o BIT STOP não está presente
End If
INTCON.INTF = 0 ' flag de interrupção limpa... está pronto para o byte seguinte de RX
end sub
sub procedure TX_19200(dim TXBuffer as byte)
INTCON.GIE = 0 ' desabilita interrupções
BitCnt = 0
TXpin = 0 ' inicia BIT START
delay_us(43) ' deduzir 9 ciclos para transferência do bit seguinte
Do
TXpin = TXBuffer.0 ' lê o buffer LSB e o envia
TXBuffer = TXBuffer >> 1 ' move o bit seguinte para posição de leitura
delay_us(35) ' deduzir 17 ciclos para a troca , a transferência do bit, e o tempo do loop
Loop Until inc(BitCnt) = 8 ' nós transmitimos todos os bits dos dados?
TXpin = 1 ' inciar STOP BIT
INTCON.GIE = 1 ' habilita interrupções
end sub
sub function Read_RXBuffer as byte ' retorna o valor de RXBuffer
result = RXBuffer
RXBuffer = 0 ' limpa o buffer de RX
end sub
sub procedure Init
TRISIO.RX = 1 ' RX é entrada
TRISIO.TX = 0 ' TX é saida
TXpin = 1 ' manter o pino de TX high
OPTION_REG = 0 ' interrupção edge é high-to-low trigger
ANSEL = 0 ' ADC's off... all digital I/O
CMCON0 = 7 ' Comparators off... all digital I/O
INTCON = 0 ' GP2/INT Flag é limpo
INTCON.GIE = 1 ' Global interrupções habilitadas
INTCON.INTE = 1 ' GP2/INT habilitada
end sub
main:
Init
While true
If RXBuffer <> 0 Then
MyByte = Read_RXBuffer
End If
TX_19200($FF)
Wend
end.
NOTA: O autor sugere uma mudança no codigo. Como não conheço muito bem os PICs da familia 12F não realizei esta mudança no codigo. Mas ela esta descrita aqui, qualquer coisa consultem o site original. Last line in ISR is wrong:
Change:
Code:
INTCON.INTE = 0 ' clear interrupt flag... be ready for next RX byte
To:
Code:
INTCON.INTF = 0 ' clear interrupt flag... be ready for next RX byte