Portal - FPGA para Todos

Transmissão Serial - RS232

Transmissão Serial - RS232

 

O projeto a seguir tem por objetivo receber um byte de forma paralela e transmiti-lo através do modo serial, utilizando como base o protocolo RS232. O artigo recepção serial - RS232 é complementar a este projeto.

O artigo a seguir é um exemplo de projeto descrito em VHDL, o qual é simulado no software Modelsim-Altera®, através de um testbench utilizado como entrada de dados da simulação.

Serão utilizados nesse projeto:

Descrição do Funcionamento

 

O protocolo RS232 inicia a transmissão com o envio de um start bit, em nível lógico baixo, para sincronizar a transmissão do dado, em seguida envia bit por bit, do LSB para o MSB, e por ultimo envia um stop bit, em nível lógico alto. O protocolo RS232 pode transmitir com diversas temporizações, neste caso se usará 9600 bits/s.

Figura 1: Forma de onda protocoloRS232

 

Para a transmissão do dado, será necessário registrar o dado, agrupá-lo com o start bit e o stop bit e então enviá-lo. Também é necessário esperar até que a transmissão tenha acabado para começar outra.

Figura 2: Ilustração esquemática do projeto

Descrição em VHDL

Neste projeto serão usadas 11 portas como entrada: Clock, Reset, Dado (8bits), bit de requisição de envio (sendn) e apenas uma saída, txd, bit de transmissão.

 

CLOCK, RESETn : std_logic;
DADO : in std_logic_vector (7 downto 0); -- Declaração do DADO de entrada 
SENDn : in std_logic; -- Sinal de requisição de envio de DADO 
TXD, BUSY : out std_logic -- Declaração da saída serial e da saída para o LED 

Dentro da architecture será necessário um sinal para armazenar o valor do dado e uma máquina de estados com os estados disponível e transmitindo.

 

  
signal PALAVRA_TRANSMITIR: std_logic_vector (9 downto 0) := "1111111111"; -- Vetor que guardará a palavra a ser enviada via serial      
type TRANSMISSOR is (DISPONIVEL, TRANSMITINDO, ESPERA); -- Declaração do tipo da máquina de ESTADOs   
signal ESTADO: TRANSMISSOR; -- Declaração da máquina de ESTADOs 

Como será usado a taxa de 9600 bits/s, será necessário dividir o clock para a transmissão, pois o clock do kit é 24MHz. Para isso será necessário dividir o clock por 2500 no momento da transmissão. A variável contagem tem essa função. A variável conta_bits resgistrará quantos bits ja foram enviados.

 

process (CLOCK, RESETn)
variable CONTAGEM : integer range 0 to 2800 := 0; -- Variável usada para fazer a divisão do CLOCK para 9600 bits/s no momento da transmissão 
variable CONTA_BITS : integer range 0 to 15 := 0; -- Variável usada para registrar quantos bits já foram enviados na transmissão

O projeto pode ser dividido em duas partes: Reset, transmissão.

Quando Reset é pressionado, o programa volta às configurações iniciais.

 

    if (RESETn = '0') then -- Função para quando o botão de reset for pressionado
        CONTAGEM := 0;
        ESTADO <= DISPONIVEL;

Na transmissão, se está disponível, o programa verifica se foi solicitado o envio de dados, se sim ele muda o estado da maquina de estado, registra o dado a ser enviado concatenado com o start bit e o stop bit e zera a variável contagem.

    elsif  CLOCK'event and CLOCK = '1' then -- Função principal
        case ESTADO is
        when DISPONIVEL =>
-- Quando está no ESTADO disponível e foi requisitado o envio de um DADO, muda-se a máquina de ESTADOs para
-- o ESTADO TRANSMITINDO, concatena-se o DADO a ser enviado com o start bit e o stop bit e atribui-se zero 
-- a variável responsável pela divisão do CLOCK.
            if SENDn = '0' then
                ESTADO <= TRANSMITINDO;
                PALAVRA_TRANSMITIR <= '1' & DADO & '0';
                CONTAGEM := 0;
            end if;

Quando já está transmitindo, o programa precisa fazer a divisão do clock, portanto a cada pulso de clock é somado um na variável contagem. Quando contagem chega a 2500, o programa rotaciona os valores da variável que contém o dado para enviar o próximo bit, soma um a variável que conta a quantidade de bits enviado e atribui zero a variável contagem. Caso conta_bit seja 10, ou seja, já enviou 10 bits e a transmissão está encerrada, essa variável é zerada e o estado volta para disponível. O valor de txd (porta de envio de dados) que é enviado corresponde ao bit menos significativo da variável palavra_transmitir. Por ultimo, se atribui um sinal visual para o funcionamento, enquanto está transmitindo o circuito acenderá um LED.

        when TRANSMITINDO =>
-- Quando esta TRANSMITINDO, incrementa-se a variável CONTAGEM e é verificado se ela chegou a 2500, caso  sim,
-- rotaciona-se a variável de saída, de forma ao próximo bit a ser enviado vá para o LSB, incrementa-se a 
-- variável responsável pelo registro da quantidade de bits enviados e atribui-se zero a variável CONTAGEM.
            CONTAGEM := CONTAGEM + 1;
            if CONTAGEM = 2500 then
                for cont in 0 to 8 loop
                    PALAVRA_TRANSMITIR(cont) <= PALAVRA_TRANSMITIR (cont + 1);
                end loop;
                CONTA_BITS := CONTA_BITS + 1;
                CONTAGEM := 0;
            end if;
-- Quando termina de enviar os 10 bits, a máquina vai para o ESTADO de ESPERA, utilizado para que a mesma palavra
-- não seja enviada duas vezes e para diminuir as influencias devido a ruídos.
            if CONTA_BITS = 10 then
                CONTA_BITS := 0;
                ESTADO <= ESPERA;
            end if;    
        when ESPERA =>
-- Quando está em ESPERA, aguarda até o sinal de requisição voltar a 1 para voltar a ficar disponível.
            if SENDn = '1' then
                ESTADO <= DISPONIVEL;
            end if;  
        end case;
    end if;
end process;
-- O bit enviado é sempre o LSB da variável contendo os bits de transmissão, que é rotacionado no ESTADO TRANSMITINDO.
TXD <= PALAVRA_TRANSMITIR (0);
-- O sinal BUSY tem como função apresentar um sinal visual para informar se o circuito esta TRANSMITINDO ou disponível
LED_TRANSMITINDO: BUSY <= 
'1' when ESTADO = TRANSMITINDO else
'0';

Figura 3: Resultado da analise e Sintese

Simulação

Para simular o funcionamento se usará o simulador Modelsim-Altera©. Na simulação basta mandar enviar alguns dados e verificar se os dados são enviados corretamente, lembrando que o envio ocorre do LSB para o MSB. A simulação do estado espera é feito no último bloco do teste, onde o valor da variável sendn continua em zero, de forma que a saída não deverá se alterar, mesmo com a alteração do bit de entrada.

Primeiramente, inicia-se a simulação com o botão de reset pressionado.

process
begin
-- simulação do pressionamento do botão de reset.
    RESETn <= '0' after 0 ms,
    '1' after 1  ms,
    '0' after 15 ms;

Em seguida, declara-se o bloco gerador de clock.

    CLOCK <= '0';
    wait for 1 ms;
-- rotina de geração de CLOCK
    while RESETn = '1' loop
        CLOCK <= not CLOCK;
        wait for 20833 ps;
    end loop;  
wait;
end process;

 

Para o teste do envio de dados, atribui-se valor de dados e envia um pulso no sendn para requisitar o envio do dado.

-- Na partida, coloca-se um DADO e faz SENDn = '1'
DADO <= x"AA";
SENDn <= '1';  
-- Espera um tempo e envia o DADO AA (10101010)
wait for 2 ms;
SENDn <= '0';
wait for 500 ns;
SENDn <= '1';  
-- Espera um tempo e envia o DADO 55 (01010101)
wait for 2 ms;
DADO <= x"55";
SENDn <= '0';
wait for 500 ns;
SENDn <= '1';  
-- Espera um tempo e envia o DADO 00 (00000000)
wait for 2 ms;
DADO <= x"00";
SENDn <= '0';
wait for 500 ns;
SENDn <= '1';  
-- Espera um tempo e envia o DADO FF(11111111)
wait for 2 ms;
DADO <= x"FF";
SENDn <= '0';
wait for 500 ns;  
-- Rotina para o teste do estado espera, com DADO AC(10101100).
-- Note que a variavel SENDn continua em zero.
wait for 2 ms;
DADO <= x"AC";
wait for 500 ns;
SENDn <= '1';
wait for 5 ms;  
wait;

A simulação no Modelsim-Altera© apresentou as seguintes formas de ondas:

env_ser_sim

Figura 4: Simulação da transmissão de dados.

Estrutura Física

O funcionamento do projeto depende apenas do módulo CPLD_7064, mas para efetuar o teste, será utilizado a placa de chaves como dado de entrada, a placa de botões, usando apenas um botão para a requisição de envio, e um kit uCduíno para fazer a leitura do dado enviado e apresentá-lo em um display LCD, como mostra a figura 4. O componente usado para a gravação foi o EPM7064, da família MAX7000S.

Circuito_teste

Figura 5: Montagem do circuito de teste

Montagem e Roteamento

A montagem na protoboard segue os esquemas das figuras a seguir.

env_ser_mont1

Figura 6: Conexão entre a placa de chaves e o módulo CPLD_7064

env_ser_mont2

Figura 7: Conexão entre a placa de botões e o módulo CPLD_7064

Para a implementação do projeto, basta a utilização do módulo, devendo ser determinados os 8 pinos para o dado de entrada, um para o sinal de requisição de envio, um sinal de reset e um para o txd. Como a entrada será a placa de chaves, atribui-se os pinos da conexão CON2, de acordo com D0 até D7, sendo D0 o menos significativo. Quanto aos botões de requisição, optou-se pela tecla B0, correspondentes ao pino 39 do CPLD. Por ultimo, se atribuiu o pino 5 para txd. Para esse teste o sinal busy foi ignorado, pois o tempo em que ficaria ligado seria muito pequeno. Repare que o clock global 1 da placa (24MHz) corresponde ao pino 43 e o reset global no pino 1.

 pinagem

Figura 8: Atribuição de pinos para o projeto.

Gravação e Teste

A gravação pode ser feita seguindo o tutorial.

Para o teste, monta-se o módulo CPLD_7064 juntamente com o modulo das chaves, que funcionarão como dado de entrada, e a placa de botões para a requisição do envio do dado. Para isso, montou-se o circuito segundo a figura acima, em que o fio azul corresponde ao txd, o verde ao terra e o laranja a Vcc, dessa forma a placa do uCduíno está sendo alimentada pelo módulo CPLD_7064. O código utilizado no uCduíno está disponível juntamente com os arquivos de projeto. Durante o teste, foram feitos o envio de diversos dados e observado o dado transmitido no display LCD, como mostra o vídeo no início da página.

Arquivos de Projeto

Quem está Online

Temos 32 visitantes e Nenhum membro online

Apoio

Login Form