Receptor/testador de dados UART portátil

Receptor/testador de dados UART portátil

O receptor/transmissor assíncrono universal (UART) é a interface de comunicação serial ponto a ponto (peer) mais comum usada em microcontroladores. É uma interface simples de dois fios que não requer sinal de clock ou qualquer dispositivo mestre para transmissão serial de dados entre dois dispositivos embarcados. Pode transmitir pacotes de dados de comprimento variável (5 a 9 bits) com o fornecimento de um bit de paridade para detecção de erros. É por isso que quase todos os microcontroladores possuem periféricos USART ou pelo menos UART integrados.
Na comunicação UART, dois dispositivos comunicam dados diretamente um com o outro. Esta comunicação de dados pode ser simplex (onde um dispositivo é o receptor e outro é o transmissor), full duplex (onde ambos os dispositivos recebem e transmitem dados um para o outro simultaneamente) ou half duplex (ambos os dispositivos transmitem e recebem dados um para o outro, mas um por vez). Um dispositivo com periférico UART pode se comunicar com outro dispositivo com periférico UART, seja diretamente (se ambos os dispositivos estiverem operando em níveis lógicos TTL) ou através de um chip de driver serial (se um ou ambos os dispositivos estiverem operando em outros níveis de sinal que não TTL). Os protocolos de driver serial foram desenvolvidos para facilitar uma comunicação de dados de longo alcance. Existem três protocolos de driver serial UART mais comumente usados ​​–
1) RS-232 – No protocolo do driver serial RS-232, um sinal de tensão na faixa de -25 V a +25 V é usado para comunicação de dados onde o sinal de -25 V a -3 V é equivalente à lógica HIGH (status do bit 1) e o sinal de +3 V a +25 V é equivalente à lógica LOW (status do bit 0). O chip driver RS-232 (como MAX232) converte esses níveis de tensão (como de um PC) em níveis de tensão TTL (0 a 5V) para transmissão de dados para um dispositivo TTL com periférico UART (como um microcontrolador). O chip driver (como MAX-232) recebe de forma semelhante bits em níveis lógicos TTL de um dispositivo TTL com periférico UART (como um microcontrolador) e os converte em níveis de sinal padrão RS-232 para transmissão ao dispositivo com interface RS-232 (como PC ). RS-232 permite a comunicação UART full-duplex ponto a ponto entre dois dispositivos. O chip do driver RS-232 usa pelo menos três fios (Tx, RX e Common Ground) para interface com a porta RS-232 ou interface de um dispositivo. No protocolo RS-232, um transmissor UART pode comunicar dados apenas para um receptor UART.
2) RS-422 – No protocolo do driver serial RS-422, sinais de tensão na faixa de -6 V a +6 V são usados ​​para comunicação de dados, onde o sinal de -6 V a -2 V é equivalente à lógica HIGH (status do bit 1) e O sinal de +2 V a +6 V é equivalente à lógica LOW (status do bit 0). O chip driver RS-422 converte esses níveis de tensão em níveis de tensão TTL (0 a 5V) para transmissão ao dispositivo TTL com periférico UART. O chip driver converte de forma semelhante bits em níveis lógicos TTL do dispositivo TTL com periférico UART para níveis de sinal padrão RS-422 para transmissão ao dispositivo com interface RS-422. RS-422 permite comunicação UART full-duplex e half-duplex entre dois dispositivos. O protocolo RS-422 utiliza sinais diferenciais (dois sinais invertidos em duas linhas para transmissão e recepção de dados no dispositivo final) para fornecer dados a longo alcance com melhores características de sinal-ruído. Portanto, o chip driver RS-422 usa pelo menos 5 fios para conectar-se à porta RS-422 de um dispositivo (dois Tx, dois Rx e terra comum). No protocolo RS-422, um transmissor UART pode comunicar dados para dois receptores UART.
3) RS-485 – RS-485 é uma versão half-duplex do protocolo RS-422. Geralmente, os chips do driver RS-422 também podem operar no modo RS-485. No protocolo RS-485, um transmissor UART pode comunicar dados para vários receptores UART.
Os dispositivos com periférico UART comunicam dados de forma assíncrona. Em vez de usar qualquer sinal de clock, os dispositivos com dados de quadro periférico UART (5 bits a 9 bits de comprimento) em um pacote de dados que começa com um bit de início e termina com um bit de parada. Quando o receptor UART detecta o bit inicial, ele começa a buscar pacotes de dados em uma frequência pré-determinada chamada taxa de transmissão. A taxa de transmissão é expressa em bauds por segundo, o que significa pacotes de dados ou palavras comunicadas por segundo. Idealmente, dois dispositivos que comunicam dados através de periféricos UART devem ter a mesma taxa de transmissão. Os periféricos UART podem gerenciar no máximo 10% de tolerância nas taxas de transmissão. Um bit de paridade opcional pode ser enviado no pacote de dados UART para detectar erros na comunicação de dados. Os pacotes de dados são enquadrados conforme mostrado na figura a seguir pelos dispositivos UART –
Formato do pacote de dados no protocolo serial UART

Figura 1: Formato do pacote de dados no protocolo serial UART

Neste projeto, foi projetado um dispositivo portátil que pode ler dados (até 500 bytes) de um transmissor UART e permitir ao usuário inspecionar os dados transmitidos em um LCD de caracteres. O usuário pode definir a taxa de transmissão, um número de bits de dados, paridade e bit de parada no dispositivo para corresponder ao transmissor UART. O usuário pode ajustar esses parâmetros no dispositivo até que os pacotes de dados corretos sejam observados na tela. Desta forma, um usuário pode identificar a taxa de transmissão, o número de bits de dados, a paridade e o bit de parada do transmissor UART e definir os mesmos parâmetros em um receptor UART não configurado.
Normalmente, para verificar a transmissão USART de um dispositivo embarcado baseado em microcontrolador, os pinos Rx e Tx do controlador são conectados à PORTA COM de um PC através de um chip de driver serial (como MAX232 para protocolo RS-232). Em seguida, programas como o HyperTerminal são usados ​​para verificar a transmissão de dados. Neste método, ainda é difícil verificar/identificar os caracteres não imprimíveis na tela do computador. O dispositivo desenvolvido neste projeto exibe os pacotes de dados lidos em LCD de caracteres nos formatos texto, hexadecimal, decimal e octal para fácil identificação de caracteres não imprimíveis. Este dispositivo também é capaz de comunicar um fluxo fixo de pacotes de dados (uma sequência de teste contendo caracteres de A a Z e dígitos de 0 a 9) a um receptor UART para determinar se o dispositivo receptor está funcionando corretamente ou não.
Este dispositivo foi projetado usando o microcontrolador AVR ATMega8. ATMega8 possui Serial USART programável para que possa se comunicar facilmente com UART ou periférico USART de qualquer outro microcontrolador. ATMega8 possui EEPROM interna de 512 bytes que é usada para buscar até 500 bytes de dados seriais de um transmissor UART para inspeção. Um LCD de 20X4 caracteres foi conectado ao ATMega8 para exibir e inspecionar os pacotes de dados UART buscados.
Este dispositivo foi projetado para ser usado em um ambiente industrial, portanto o ATMega8 foi conectado ao chip do driver serial MAX485. MAX485 é um chip de driver serial UART que pode ser usado para comunicação UART com dispositivos com interface RS-422 ou RS-485. O dispositivo também pode se comunicar diretamente com a interface USART/UART de um dispositivo TTL (como outros microcontroladores). Para leitura de dados de dispositivos com interface RS-232, o MAX-232 deve ter interface externa com este dispositivo.
Componentes necessários –
Nome do componente Quantidade
IC microcontrolador ATMega8 ou ATMega8A 1
CI MAX485 1
LCD de 20 x 4 caracteres 1
Cristal de 11,0592 MHz 1
trimpot 5K 1
LEDS de 3mm 3
Interruptores de botão 6
Capacitores de disco 22pF 2
Capacitor de disco 0,1uF 1
Resistores de 10K ohm 0,25 W 7
Resistor de 4,7K ohm 0,25 W 1
Resistor de 3,3K ohm 0,25 W 1
Resistores de 2,2K ohm 0,25 W 2
Resistor de 470 ohms 0,25 W 1
Resistor de 100 ohms 0,5 W 1
Base IC de 28 pinos 1
Base IC de 8 pinos 1
Conector de 6 pinos 1
Faixa de Berg – Masculino 1
Faixa de Berg – Feminino 1
PCB adequada 1
Programador AVR 1
Diagrama de circuito –
Diagrama de circuito do receptor de dados UART universal baseado em AVR ATmega8 e testador UART

Fig. 2: Diagrama de circuito do receptor de dados UART universal baseado em AVR ATmega8 e testador UART

Conexões de Circuito –
Este dispositivo é baseado no AVR ATMega8. ATMega8 é um microcontrolador de 8 bits que pode operar até 16 MIPS de taxa de transferência com clock de 16 MHz. ATMega8 tem interface com um LCD de 20X4 caracteres e um chip de driver serial MAX485 para fazer o dispositivo. Existe um Trimpot (mostrado como VR1 no diagrama de circuito) que é usado para ajustar o contraste do LCD. Há um LED amarelo com interface paralela a todo o circuito que é usado para indicar que o dispositivo está funcionando. Há um LED vermelho conectado ao bit 2 da Porta D do Atmega8 que é usado para indicar que o dispositivo está enviando dados de teste para um receptor UART. Há um LED branco conectado ao bit 7 da Porta D do ATMega8 que indica que o microcontrolador está ativo e aguardando o pressionamento de um botão de menu piscando.
Existem 6 interruptores de botão interligados na porta B do ATMega8 para entrada do usuário. O dispositivo pode operar em dois modos – 1) Modo Menu que exibe taxa de transmissão, bits de dados, paridade e bit de parada e 2) Modo Visualização que exibe os pacotes de dados buscados em seu buffer de um transmissor UART. Os interruptores de botão são usados ​​para alterar o modo e operar o dispositivo nos dois modos. Os botões são interligados nos pinos do microcontrolador através de seis resistores pull-up.
As configurações e o controle dos dados seriais podem ser operados usando esses seis botões (mostrados como SW1 a SW6 no diagrama de circuito). O botão com interface no bit 5 da porta B (mostrado como SW6 no diagrama de circuito) é uma chave seletora usada para alternar entre o modo Visualização e o modo Menu. Os botões SW2, SW3, SW4 e SW5 possuem funções diferentes em ambos os modos. O SW1 funciona no MODO VIEW apenas para enviar dados de teste para um receptor UART.
Os pinos Rx e Tx do ATmega8 podem ser usados ​​para receber pacotes de dados de transmissão de dados USART/UART de qualquer microcontrolador. O pino Rx e Tx do ATmega8 também faz interface com o IC do driver serial MAX485. MAX485 pode receber dados UART de qualquer dispositivo com interface RS-485 ou RS422. O RS-485 e o RS-422 são protocolos de comunicação serial mais comumente usados ​​nas indústrias. Para receber dados UART da interface RS-232, este dispositivo precisa ter interface externa com o IC MAX232.
Todo o circuito opera em 5V DC que pode ser obtido de um banco de energia de 5V ou bateria de 9V com fonte de alimentação regulada de 5V usando 7805 IC. Um cristal de frequência de 11,0592 MHz é usado com ATmega8 para obter uma taxa de transmissão precisa durante o teste.
Como funciona o circuito –
Após a montagem do circuito, a porta ISP do ATmega8 deve ser conectada a qualquer programador AVR e SerialDataTester.HEX O arquivo deve ser atualizado no microcontrolador. Em seguida, desconecte o circuito do programador AVR. Agora o dispositivo está pronto para operação.
Quando o dispositivo é ligado, o LED Blinker e os LEDs RX-MODE acendem por um tempo e o LCD começa a exibir o título do projeto e as configurações atuais do USART. Após alguns segundos, o LCD exibe a mensagem NO DATA ou BUFFER EMPTY se não houver dados recebidos de um transmissor UART.
Agora, o dispositivo pode ser usado para testar dados seriais de um transmissor UART ou para testar um receptor UART enviando pacotes de dados de amostra. Os botões SW1 a SW6 podem ser usados ​​para navegar pelo modo Visualização e modo Menu. O modo View exibe os dados seriais recebidos de um transmissor UART, enquanto o modo Menu permite ajustar as configurações UART.
1) Modo de menu – Para testar dados seriais de um transmissor UART, o usuário primeiro precisa fazer as configurações UART no dispositivo. A taxa de transmissão, o número de bits de dados, as configurações de paridade e bit de parada do dispositivo devem ser iguais às do transmissor UART para receber os pacotes de dados corretamente. A taxa de transmissão esperada, o número de bits de dados, a paridade e o bit de parada devem ser definidos navegando até o modo menu. O usuário pode entrar no modo menu pressionando o botão SW6. Ao pressionar a chave, o LCD exibe o menu USART contendo parâmetros (Baud Rate, Data bits, Parity e Stop Bits) com valores atuais. Para selecionar um parâmetro, o botão SW4 deve ser pressionado. O parâmetro selecionado é indicado pelo cursor piscando. Para alterar o valor do parâmetro, o botão SW5 deve ser pressionado contra o parâmetro selecionado. Os parâmetros podem ser configurados com os valores necessários através dos botões SW4 e SW5. Uma vez configurados os parâmetros, seus valores podem ser salvos pressionando o botão SW3. Esses valores são salvos permanentemente na EEPROM interna do microcontrolador. Para alterar os valores, se necessário, o usuário precisa navegar novamente para o modo menu pressionando o botão SW6. As configurações de parâmetro padrão para taxa de transmissão, bits de dados, paridade e bit de parada são 9600, 8, 0 e 1, respectivamente. O usuário pode redefinir as configurações padrão do USART (9600, 8, 0, 1) pressionando o botão SW2.
2) Modo de visualização – É o modo padrão para visualização dos dados seriais recebidos. Para mudar do modo Menu para o modo Visualização, o usuário precisa pressionar o botão SW6 mais uma vez ou aguardar 10 segundos sem operar nenhum botão. No modo Visualização, quatro pacotes de dados recebidos são mostrados em quatro linhas do LCD de caracteres. Cada linha consiste em posição, caractere, código hexadecimal, código decimal e código octal do pacote de dados serial recebido no buffer. Se o pacote de dados recebido não for um caractere imprimível, um ponto será exibido no lugar do caractere. O tamanho máximo do buffer é definido como 500 bytes, pois o ATmega8 possui 512 bytes de EEPROM embutido. O número total de bytes recebidos (no buffer) é exibido no canto inferior esquerdo do LCD.
No modo Visualização, os pacotes de dados recebidos podem ser rolados para cima e para baixo pressionando os botões SW5 e SW4. Ao pressionar o botão SW3, o display mostra os dados do primeiro pacote de dados recebido no buffer. Se o botão SW2 for pressionado, o buffer recebido será limpo e o LCD exibirá a mensagem “NO DATA or BUFFER EMPTY”.
3) Testando um receptor UART – Para testar um receptor UART, o usuário precisa pressionar o botão SW1. Ao pressionar este botão, uma string de teste contendo os caracteres de A a Z e 0 a 9 é transmitida através do pino Tx, bem como dos pinos A e B do MAX485. Ao pressionar esta chave, o buffer recebido também é limpo para recepção de dados novos. O LED vermelho brilha por um curto período, o que é uma indicação de que os dados estão sendo transmitidos do microcontrolador para o receptor UART.
Imagem mostrando o modo de menu do testador de dados seriais UART baseado em ATmega8

Fig. 3: Imagem mostrando o modo de menu do testador de dados seriais UART baseado em ATmega8

Imagem mostrando o modo de visualização do testador de dados seriais UART baseado em ATmega8

Fig. 4: Imagem mostrando o modo de visualização do testador de dados seriais UART baseado em ATmega8

Guia de programação-
Este dispositivo é baseado em AVR ATmega8 e é programado com C embarcado usando AVR Studio 4. Outras ferramentas de programação como Atmel Studio ou Notepad++ também podem ser usadas para escrever e compilar o código. O ATmega8 está programado para receber configurações UART do usuário por meio de botões e receber dados seriais de um transmissor UART de acordo. O buffer de dados recebidos é exibido em um LCD de 20X4 caracteres, onde os pacotes de dados recebidos podem ser rolados para cima e para baixo. O ATmega8 também está programado para testar qualquer receptor UART enviando uma string de teste para ele.
Constantes usadas no código-
#define F_CPU 11059200L: – Constante usada para definir a frequência do clock do MCU
#define F_CPU_BY_100 F_CPU/100 :- Frequência dividida por 100 para cálculo da taxa de transmissão.
#define UMS 500: – Inicialização do tamanho da mensagem USART para array
#define LCD_P PORTC: – Porta C para interface com LCD
#define LCD_EN 0b00010000 :- En pin do LCD conectado ao 4º pino da porta C
#define LCD_RS 0b00100000 :- Pino Rs do LCD conectado ao 5º pino da Porta C
#define BTN_SW6 0b00100000 :- Switch 6 conectado ao 5º pino da Porta B
#define BTN_SW1 0b00000001: – Switch 1 conectado ao pino 0 da Porta B
#define BTN_SWS 0b00011110 :- Chave para 4 pinos 2,3,4,5
#define BTN_SW5 0b00010000 :- Switch 5 conectado ao 4º pino da Porta B
#define BTN_SW4 0b00001000 :- Switch 4 conectado ao 3º pino da Porta B
#define BTN_SW3 0b00000100 :- Switch 3 conectado ao 2º pino da Porta B
#define BTN_SW2 0b00000010 :- Switch 2 conectado ao 1º pino da Porta B
#define TX_L 0b00000100 :- LED Tx conectado ao 2º pino da Porta D
#define TX_C 0b00001000: – Modo RX ou TX habilitado em MAX485
#define BLK 0b10000000 :- LED piscante conectado ao 7º pino da Porta D que indica que o MCU está funcionando.
Variável usada no código-
caractere não assinado URD(UMS+1); : – Este array é usado para ler dados do USART
char USD = “ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789”; :-Este array é usado para enviar dados no USART
char HEX (16) = {'0′,'1′,'2′,'3′,'4′,'5′,'6′,'7′,'8′,'9', 'A' ,'B','C','D','E','F'}; : – Este array é usado para converter dados recebidos em hexadecimal
intUBRL(12)={ 3, 6, 12, 24, 48, 96, 144, 192, 288, 384, 576, 768}; // X 100 :- taxas de transmissão a serem alteradas
uint8_t U_B=5; : – typedef unsigned char 8 bits para taxa de transmissão
uint8_t U_D=8; : – typedef unsigned char 8 bits para bits de dados
uint8_t U_P=1; : – typedef unsigned char 8 bits para paridade
uint8_t U_S=1; : – typedef unsigned char 8bit para Stop bit
caractere não assinado USART_RXD=0; :- finalidade variável de receber dados
int URDP = 0; : – Para fins de leitura de dados do pin
intUSDP = 0; :- Para fins de envio de dados do pin
uint8_tUSCH = 1; :- para atualizar dados USART
uint8_t VCCH = 1; :- para atualizar o modo de visualização
Arquivo de cabeçalho e bibliotecas usadas no código –
#include : – Cabeçalho AVR padrão para entrada/saída
#include : – Cabeçalho AVR padrão para fornecer atrasos de tempo
#include : – Cabeçalho AVR padrão para interrupções
#include : – Cabeçalho AVR padrão para lidar com os dados EEPROM
Função usada no código-
getString: – manipula string para impressão no LCD
rdE: – Ler dados da EEPROM
wrE: – Grava dados da EEPROM
P_init: – inicializando portas para uso
LCD_E: – habilita o pino E do LCD
LCD_WN: – para ativar e desativar o modo RS
LCD_WCM: – Para conectar comandos
LCD_init: – Para inicializar o LCD
LCD_WC: – Escrever caractere
LCD_WS: – Escrever string
LCD_CS: – Para limpar a tela
LCD_POS: – Pausa o cursor
USART_init: – inicializa USART
USART_SC: – Para enviar caracteres
USART_SM: -Para definir o modo Menu
ISR: – Para receber dados
VUSCR: – Ver configuração da tela
USART_UPD: – atualização de dados USART
USART_SD: -Envio de dados USART
USART_MN: – O menu USART pode ser alterado por switch
VWL: – controla os dados do buffer por interruptores
Algoritmo:
O código para este receptor/testador de dados UART portátil funciona da seguinte forma –
1) Quando o circuito testador de dados serial é ligado, em primeiro lugar, as portas são inicializadas que definem a porta B como entrada, a porta C como saída e os 7 pinos da porta D como saída. Também passa o bit zero para “TX_C, TX_L, LCD_RS, LCD_EN“ para torná-los BAIXOS.
 void P_init ( ) 

{

DDRB = 0x00;

DDRC = 0xFF;

DDRD = 0xFE;

PORTD &= (~TX_C);

PORTD &= (~TX_L);

LCD_P &= (~LCD_RS);

LCD_P &= (~LCD_EN ); 

}
2) Após a inicialização das Portas, o LED TX_L e o LED BLK acendem por 2.000 milissegundos e apagam, o que indica que o programa foi iniciado.
PORTD  = BLK;

PORTD  = TX_L;

_delay_ms ( 2000 );

PORTD &= ~BLK;

PORTD &= (~TX_L);
3) O LCD é inicializado e imprime uma mensagem de boas-vindas que é exibida para verificar se o LCD está funcionando corretamente.
LCD_init(  );

LCD_CS ( );

LCD_POS (1,1);

LCD_WS ( " SERIAL DATA TESTER ");

LCD_POS (2,1);

LCD_WS ( "====================");

LCD_POS (3,1);

LCD_WS ( "for USART & MAX485  ");

LCD_POS (4,1);

LCD_WS ( "      communications");
4) Agora ele lê os valores atuais da EEPROM para atualizar o modo de menu e então configura o valor do buffer recebido no USART.
_delay_ms ( 3000 );

rdE ( );

_delay_ms ( 100 );

USART_SM (  ); 

sei ;

_delay_ms ( 2000 );
5) Em um loop while, o led piscante fica aceso para indicar que está pronto para funcionar. Aqui, os dados USART são atualizados e o modo de visualização também é atualizado no LCD. Agora, o usuário pode ver os dados do buffer e os dados de comunicação serial salvos na EEPROM.
  if ( USCH )

USART_UPD ( );


if ( VCCH )

{

VUSCR ( );

_delay_ms ( 200 );

}
6) Quando a chave 1 é pressionada no modo de visualização, ele envia os dados para o USART. O usuário pode ver os dados no LCD, bem como no receptor UART como terminal serial de um PC conectado.
if ( ( PINB & BTN_SW1 ) == 0 )

USART_SD ( );
7) Quando o interruptor 6 é pressionado, ele exibe o modo de menu para que o usuário possa alterar a taxa de transmissão, bits de dados, paridade e configurações de bit de parada. Se o interruptor 6 for pressionado novamente, ele muda o dispositivo do modo de menu para o modo de visualização, onde os dados do buffer são mostrados.
if ( ( PINB & BTN_SW6 ) == 0 )

isMenuPressed = 1;


if ( isMenuPressed )

{

USART_MN ( );

LCD_WCM ( 0x0C ); 

}

else

VWL ( );
Confira o código completo e comece rapidamente a construir este projeto interessante.

Código-fonte do projeto

//Program to

/*

filename : SerialDataTester.C

author : fhn

Dtd : 22-mar-2018

MCU : ATmega8 (A) @ 11.0592 MHz

display ; LCD 4 rows X 20 columns

others: menu driven

buttons : 6

*/


#define F_CPU 11059200L

#define F_CPU_BY_100  F_CPU/100


#include 

#include 

#include 

#include 


#define UMS 500  



#define LCD_P PORTC


#define LCD_EN   0b00010000 

#define LCD_RS   0b00100000  


#define BTN_SW6 0b00100000 

#define BTN_SW1 0b00000001 

#define BTN_SWS 0b00011110 


#define BTN_SW5 0b00010000 

#define BTN_SW4 0b00001000 

#define BTN_SW3 0b00000100 

#define BTN_SW2 0b00000010  


#define TX_L 0b00000100  

#define TX_C 0b00001000  

#define BLK 0b10000000  



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


unsigned char URD(UMS+1);

char USD  = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";


char HEX(16) = {'0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F'};

int UBRL(12)={ 3, 6, 12, 24, 48, 96, 144, 192, 288, 384, 576, 768}; // X 100


uint8_t U_B=5;

uint8_t U_D=8;

uint8_t U_P=1;

uint8_t U_S=1;

unsigned char USART_RXD=0;

int URDP = 0;

int USDP = 0;

uint8_t USCH = 1;

uint8_t VCCH = 1;


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

void getString ( long val, char *str, char fc, int width ) 

{

long v=val,i=0;

int nst=0, p=0;

long hvl=1;

for ( int w=0; w=1 ; i=i/10 )

{

if( (v/i)>=1 && nst==0 )

nst = 1;

if ( nst==1 )

{

str(p++) = (v/i) + '0';

}

else

{

str(p++) = fc; 

}

v = v%i;

}

str(p)=0;

if (str(p-1)==' ')

{ str(p-1)='0'; }

}

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

void rdE ( )

{

int rval = 0;

rval = eeprom_read_byte ( (void *)1); 

if ( rval<1    rval>2 )

return;

U_S = rval;

rval = eeprom_read_byte ( (void *)2);

if ( rval<0    rval>2 )

return;

U_P = rval;

rval = eeprom_read_byte ( (void *)3); 

if ( rval<5    rval>8 )

return;

U_D = rval;

rval = eeprom_read_byte ( (void *)4); 

if ( rval<0    rval>13 )

return;

U_B = rval;

}

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

void wrE ( )

{

eeprom_write_byte ( (void *)1, U_S); 

_delay_ms(10);

eeprom_write_byte ( (void *)2, U_P ); 

_delay_ms(10);

eeprom_write_byte ( (void *)3, U_D); 

_delay_ms(10);

eeprom_write_byte ( (void *)4, U_B);; 

_delay_ms(10);


}

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

void P_init ( ) 

{

DDRB = 0x00;

DDRC = 0xFF;

DDRD = 0xFE;

PORTD &= (~TX_C);

PORTD &= (~TX_L);

LCD_P &= (~LCD_RS);

LCD_P &= (~LCD_EN ); 

}

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

void LCD_E ( )

{

LCD_P  = LCD_EN; 

_delay_us(10);

   LCD_P &= (~LCD_EN ); 

   _delay_us(15);

}

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

void LCD_WN ( unsigned char nibl , unsigned char RS)

{


LCD_P &= 0xF0;  

_delay_us(5);


if ( nibl > 0b00001111)

LCD_P  = ( (nibl>>4) & 0x0F);   

else

LCD_P  = (nibl & 0x0F); 


if (RS)

LCD_P  = LCD_RS;

else

LCD_P &= (~LCD_RS);


LCD_E ( );

}

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

void LCD_WCM ( unsigned char cmd )

{

LCD_WN ( cmd & 0xF0 , 0);

LCD_WN ( cmd & 0x0F , 0);

_delay_us(2);

}

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

void LCD_init(  )

{

unsigned char initval = 0x20; 


_delay_ms ( 50 ); 

LCD_WN  ( 0x30 , 0);

_delay_ms ( 20 );

LCD_WN ( 0x30 , 0);

_delay_us ( 200 ); 

LCD_WN  ( 0x30 , 0);

_delay_ms ( 100 );

LCD_WN  ( 0x20 , 0 );

_delay_ms ( 25 );

initval  = 0b00001000;  

initval  = 0b00000100;  

LCD_WCM ( initval ); 

_delay_ms ( 25 );

LCD_WCM ( 0x0C ); 

_delay_ms ( 25 );

LCD_WCM ( 0x06 ); 

_delay_ms ( 250 );

}

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

void LCD_WC ( unsigned char c )

{

LCD_WN ( c & 0xF0 , 1);

LCD_WN ( c & 0x0F , 1);

_delay_us(1);

}

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

void LCD_WS ( char s  )

{

for (int i=0; s(i)!=0; i++)

{

LCD_WC ( s(i) );

_delay_us ( 5 ); 

}

}

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

void LCD_CS ( )

{

LCD_WCM ( 0x01 );

_delay_ms(3);

}

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

void LCD_POS ( unsigned char R, unsigned char C )

{

switch (R)

{

case 3: LCD_WCM ( 0x94 + C-1 );  break;

case 4: LCD_WCM ( 0xD4 + C-1  ); break;

case 2: LCD_WCM ( 0xC0 + C-1 ); break;

case 1:

default: LCD_WCM ( 0x80 + C-1 ); break;

}

_delay_ms ( 3 );

}

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

int USART_init ( int bd, int db, int prt, int stb)

{


int ubrr = 0;

int bd_rate=bd;  

unsigned int ucsrc = (1<=0)

{

UBRRL = ubrr;

UBRRH = (ubrr>>8);

}

else

return (-1);

UCSRB = (1< break;

case 6: ucsrc  = (1< break;

case 7: ucsrc  = (2< break;

case 8: ucsrc  = (3< break;

default:  return (-1);

}

if (stb==2)  

ucsrc  = (1< 

getString(UBRL(U_B), str,' ', 3); 

LCD_WS ( str ); LCD_WS ( "00" );

LCD_POS ( 2,1 ); 

LCD_WS ( "DataBits : "); 

LCD_POS ( 2,12 );

LCD_WC ( U_D+'0');

LCD_POS ( 3,1 );

LCD_WS ( "Parity   :  " );

LCD_POS ( 3,12 );

switch( U_P )

{

case 1: LCD_WS ( "ODD " );  break;

case 2: LCD_WS ( "EVEN" );  break;

default:LCD_WS ( "NONE" );  break;


}

LCD_POS ( 4,1 );

LCD_WS ( "StopBits :  " );

LCD_POS ( 4,12 );

LCD_WC ( U_S+'0');

LCD_POS ( 1,12 );


}

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

ISR ( USART_RXC_vect )

{

USART_RXD = UDR;  


if ( URDP < UMS )

{

URD(URDP++) = USART_RXD;

}


 }

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

void VUSCR ( )

{

char str(10);

LCD_CS ( );

if ( URDP<=0)

{

LCD_POS (2,1);

LCD_WS ( "NO DATA or" );

LCD_POS (3,1);

LCD_WS ( "BUFFER EMPTY" );

return;

}

for ( int i=0; i<4 && URDP>(USDP+i); i++ )

{

LCD_POS ( i+1 , 1 );

LCD_WC ( '@' );

getString(USDP+i, str,'0',3); 

LCD_WS ( str ); 


LCD_WS ( "= " );


if ( URD(USDP+i)<32   

URD(USDP+i)>126 )

LCD_WC ( '.' );

else 

LCD_WC ( URD(USDP+i) );

LCD_WC ( ' ' );

LCD_WC ( HEX(URD(USDP+i)/16) ); 

LCD_WC ( HEX(URD(USDP+i)%16) ); 

LCD_WS ( "h " ); 

getString(URD(USDP+i), str,'0',3); 

LCD_WS ( str ); 

LCD_WS ( "d " );

int n = URD(USDP+i);

LCD_WC ( n/64 + '0' ); 

n = n%64;

LCD_WC ( n/8 + '0' ); 

LCD_WC ( n%8 + '0' ); 

}

LCD_POS(4,1);

LCD_WC ( '(' );

getString(URDP, str,'0', 3); 

LCD_WS ( str ); 

LCD_WC ( ')' );

}

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

void USART_UPD ( )

{

USART_init ( UBRL(U_B),

U_D,

U_P,

U_S );

URDP=0;

USDP = 0;

VCCH = 1;

wrE ( );

rdE ( );

}

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

void USART_SD ( )  

{

LCD_CS ( );

PORTD  = BLK;

LCD_POS (1,1);

LCD_WS ( "SENDING.... " );

PORTD  = TX_C;

PORTD  = TX_L;

_delay_ms(10);

LCD_POS ( 2,1 );

for ( int i=0; USD(i)!=0 ;i++)

{

if ( i==18 )

LCD_POS ( 3,1 );

LCD_WC ( USD(i) );

USART_SC (  USD(i) );

_delay_ms(1);

}

_delay_ms(50);

PORTD &= (~TX_C);

LCD_POS (4,1);

LCD_WS ( "SENT (Check LSB)" );

_delay_ms(50);

PORTD &= (~TX_L);

_delay_ms(1500);

VCCH = 1;

}

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

void USART_MN ( )

{

uint8_t wtl = 100;

uint8_t btn_sws = 0;

uint8_t editpos = 0;

char str(10);

uint8_t sU_B = U_B;

uint8_t sU_D = U_D;

uint8_t sU_P = U_P;

uint8_t sU_S = U_S;


USART_SM (  );

_delay_ms ( 300 );


LCD_WCM ( 0x0F ); 


while ( wtl > 0)

{

PORTD ^= BLK;

LCD_POS (editpos+1,12);

btn_sws = PINB & BTN_SWS;

if ( btn_sws != BTN_SWS)

{

wtl = 100;

_delay_ms ( 300 );


if ( ( btn_sws & BTN_SW4 ) ==0 )

{

editpos++;

if (editpos>3)

editpos = 0;

_delay_ms ( 300 );

}

else if ( ( btn_sws & BTN_SW5 ) ==0 )

{

switch (editpos)

{

case 0:

sU_B++;

if (sU_B>11)

sU_B=0;

LCD_POS ( 1,12 ); 

getString(UBRL(sU_B), str, ' ', 3); 

LCD_WS ( str ); LCD_WS ( "00" );

break;

case 1:

sU_D ++;

if ( sU_D>8)

sU_D=5;

LCD_POS ( 2,12 );

LCD_WC ( sU_D +'0' );

break;

case 2:

sU_P++;

if ( sU_P>2)

sU_P=0;

LCD_POS ( 3,12 );

switch( sU_P )

{

case 1: LCD_WS ( "ODD " ); break;

case 2: LCD_WS ( "EVEN" ); break;

default:LCD_WS ( "NONE" ); break;

}

break;

case 3:

sU_S ++;

if ( sU_S>2)

sU_S=1;

LCD_POS ( 4,12 );

LCD_WC ( sU_S +'0' );

break;

default:

break;


}

}

else if ( ( btn_sws & BTN_SW3 ) ==0 )

{

U_B = sU_B;

U_D = sU_D;

U_P = sU_P;

U_S = sU_S;

USCH = 1;

USART_SM (  );

LCD_POS ( 4,15 );

LCD_WS ( "SAVED" );

_delay_ms ( 2000 );

return;

}

else if ( ( btn_sws & BTN_SW2 ) ==0 )

{

U_B = 5;

U_D = 8;

U_P = 1;

U_S = 1;

USCH = 1;

USART_SM (  );

LCD_POS ( 4,15 );

LCD_WS ( "RESET" );

_delay_ms ( 2000 );

return;

}

}

else

{

wtl--;

}

if ( ( PINB & BTN_SW6 ) == 0 )

{

wtl = 0;

_delay_ms ( 300 );

}

_delay_ms ( 100 );

}


VCCH = 1;

}

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

void VWL ( ) 

{

int btn_sws = 0;

PORTD ^= BLK;


btn_sws = PINB & BTN_SWS;

if (( btn_sws & BTN_SW2 ) == 0 )

{

URDP=0;

USDP = 0;

VCCH = 1;

_delay_ms ( 100 );

}

else if ( ( btn_sws & BTN_SW4 ) == 0 )

{

USDP += 3;

if ( USDP>=URDP)

USDP = URDP-1;

VCCH = 1;

_delay_ms ( 100 );

}

else if ( ( btn_sws & BTN_SW5 ) == 0 )

{

USDP -= 3;

if ( USDP<0)

USDP = 0;

VCCH = 1;

_delay_ms ( 100 );

}

else if ( ( btn_sws & BTN_SW3 ) == 0 )

{

USDP = 0;

VCCH = 1;

_delay_ms ( 100 );

}

}

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

int main ( )

{

int isMenuPressed = 0;

int usart_recd_data_pos = -1;



P_init ( );

PORTD  = BLK;

PORTD  = TX_L;

_delay_ms ( 2000 );

PORTD &= ~BLK;

PORTD &= (~TX_L);

LCD_init(  );

LCD_CS ( );

LCD_POS (1,1);

LCD_WS ( " SERIAL DATA TESTER ");

LCD_POS (2,1);

LCD_WS ( "====================");

LCD_POS (3,1);

LCD_WS ( "for USART & MAX485  ");

LCD_POS (4,1);

LCD_WS ( "      communications");


_delay_ms ( 3000 );

rdE ( );

_delay_ms ( 100 );

USART_SM (  );


USCH = 1;

VCCH = 1;


sei ;


_delay_ms ( 2000 ); 


while ( 1 )

{

PORTD ^= BLK;

if (usart_recd_data_pos != URDP)

VCCH = 1;


usart_recd_data_pos = URDP;


if ( USCH )

USART_UPD ( );


if ( VCCH )

{

VUSCR ( );

_delay_ms ( 200 );

}

isMenuPressed = 0;

USCH = 0;

VCCH = 0;

_delay_ms ( 50 ); 


if ( ( PINB & BTN_SW1 ) == 0 )

USART_SD ( ); 


if ( ( PINB & BTN_SW6 ) == 0 )

isMenuPressed = 1;


if ( isMenuPressed )

{

USART_MN ( );

LCD_WCM ( 0x0C ); 

}

else

VWL ( );

}

return 0;

}

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




###

Diagramas de circuito

AVR-ATmega8-Universal-UART-Data-Tester-1

Vídeo do projeto

Conteúdo Relacionado

Voltar para o blog

Deixe um comentário

Os comentários precisam ser aprovados antes da publicação.