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:
- 1x kit CPLD_7064;
- 1x placa de botões;
- 1x placa de chaves;
- 1x kit uCduíno;
- 1x placa de LCD.
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.
1 2 3 4 5 6 7 |
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.
1 2 3 4 5 |
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.
1 2 3 4 5 |
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.
1 2 3 4 5 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
process begin -- simulação do pressionamento do botão de reset. RESETn <= '0' after 0 ms, '1' after 1 ms, '0' after 15 ms; {/code} Em seguida, declara-se o bloco gerador de clock. {code} 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
-- 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:
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.
Figura 5: Montagem do circuito de teste
Montagem e Roteamento
A montagem na protoboard segue os esquemas das figuras a seguir.
Figura 6: Conexão entre a placa de chaves e o módulo CPLD_7064
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.
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.