Portal - FPGA para Todos

Leitura do Conversor A/D de 12 bits MCP3202

            

Introdução

     O conversor analógico-digital (também conhecido como A/D ou ADC) é um dispositivo capaz de reproduzir uma representação digital a partir de um sinal analógico, como um nível de tensão ou intensidade de corrente elétrica. Os conversores analógicos digitais são bastante utilizados na interface entre os dispositivos digitais.

     Esse artigo apresenta um projeto desenvolvido em VHDL utilizando os conceitos de máquina de estado e projeto hierárquico para fazer a leitura do módulo do Conversor A/D do Projeto FPGA para Todos e mostrar os valores lidos em um mostrador de seis algarismos (para maiores informações sobre esta placa de seis algarismos clique aqui). O projeto foi desenvolvido no software Quartus II Web Edition e testado no kit de CPLD baseado no componente MAX V, e foi base para um projeto maior que faz a leitura simultânea de três conversores A/D.

     Os componentes utilizados:

  • Kit CPLD MAX_V
  • Placa do Conversor A/D
  • Placa Display de 6 Algarismos.

Módulo Conversor A/D de 12 Bits

     A placa do conversor A/D (Figura 1) que será utilizada para fazer a leituras dos sensores possui como componente principal o MCP3202 da fabricante Microchip Technology Inc.

Figura 1 - Módulo Conversor A/D de 12 Bits

        O MCP3202 pode operar em uma faixa de tensão que vai de 2.7V a 5.5V, e é um conversor de 12 bits, produzindo em sua saída valores binários de zero a 4095, ou seja, é capaz de capturar 4096 níveis de um determinado sinal. Sua comunicação é feita usando uma interface serial SPI, atuando como escravo na comunicação. Os pinos de entradas e saídas do CI são brevemente descritas na tabela 1.

Tabela 1 - Pinos Entradas e Saídas

     A comunicação entre Mestre (módulo de lógica programável) e Escravo (placa conversor AD) só ira começar quando pino CS/SS baixar para zero, nesse momento o Mestre manda os bits de configuração. Os bits de configuração são descritos na tabela 2.

Tabela 2 - Bits Configuração

     Os bits de configuração definem: o modo de operação (modo de entrada em canal isolado ou modo de diferencial entre dois canais), o canal selecionado e a forma que os dados serão enviados (menos ou mais significativo primeiro).

Após o envio do bit start e dos três bits de configuração, o adc envia os 12 bits de leitura para o mestre. Esse processo pode ser visto na figura 2.

 Figura 2 - Comunicaçào MCP3202

     O valor da tensão de entrada analógica gerada pelo conversor AD é dada pela equação:

Exemplo Le_SPI_AD

     Este é um projeto que faz a leitura de um Conversor A/D de 12 bits e mostra o valor lido em hexadecimal em um display de seis algarismos. Sua estrutura se caracteriza como um projeto hierárquico, baseado nos componentes seguintes: Bcd_7seg, Clock_256hz, Control_dispmux, Maquina_le_adc_12bits e Spimestre_12bits. Alguns destes blocos foram desenvolvidos previamente, em outros projetos descritos aqui no portal.  Outros, foram construídos especificamente para o leitor de ADC, e serão apresentados aqui. A figura abaixo mostra o diagrama esquemático do "topo de hierarquia", construido no arquivo Le_Spi_ADC.

 Figura 3 - Diagrama de Blocos

     Para o desenvolvimento de projetos que fizessem a leitura da placa do conversor A/D foi necessário a utilização de blocos já prontos (mostrados no site FPGA Para Todos) e o desenvolvimento de dois novos blocos para fazer a comunicação via SPI.

     Bcd_7seg: Decodificador binário para display de 7 segmentos, que apresentará o valor hexadecimal nos display (para maiores informações clique aqui).

     Control_dispmux:Controle da placa de display de 6 algarismos multiplexado. Valor lido pelo Conversor A/D será mostrado em três algarismos da placa de display de 6 algarismos (para maiores informações clique aqui).

     Clock_256hz:Bloco que divide o clock principal da placa de CPLD e FPGA que é de 24MHz e transforma em clock desejados pelo projeto.

     Spimestre_12bits: Esse bloco de comunicação SPI foi desenvolvido de forma que possa ser modificado e utilizado em outros projetos que necessitem fazer a comunicação de um mestre e escravo via SPI no Modo 0 (CPOL 0, CPHA 0).

Figura 4 - Bloco Spimestre_12bits

     O bloco foi projetado utilizando os conceitos de máquina de estado e foi configurado para fazer a leitura de um conversor A/D de 12 bits. Essa máquina é o mestre da comunicação SPI, ela faz a passagem de dados entre a placa do conversor A/D e o CPLD/FPGA. As Entradas e Saídas do bloco podem ser vistas na figura 4.

     Maquina_le_adc_12bits: Bloco que comanda o bloco Spimestre_12bits e armazenar o dado de 12 bits vindo do bloco Spimestre_12bits (mostrando anteriormente), esse dado fica disponível na saída “DADO_LIDO”. As Entradas e Saídas do bloco podem ser vistas na figura 5

Figura 5 - Bloco Maquina_le_adc_12bits

Funcionamento e Códigos dos Blocos Desenvolvidos

     Spimestre_12bits

     O primeiro trecho do bloco Spimestre_12bits refere-se às bibliotecas e as entradas e saídas do programa. As entradas e saídas da comunicação SPI são as seguintes: MISO, MOSI, SS e SCK.

 
-- Bibliotecas: Define as bibliotecas utilizadas.
libraryieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_bit.all;
use ieee.numeric_std.all;
 
-- Entidade: Define componente e entrada/saída.
entity spimestre_12bits is 
port
(
     --Entradas
     CLOCK, MISO, SPI_TRANSFER : in std_logic;
     --Saidas
     MOSI, SPI_LIVRE, SS, SCK : out std_logic;
     DADO_SAIDA : out std_logic_vector (11 downto0)
);
endentity;
 

     Os Estados da máquina são os seguintes: ESPERA, COMUNICANDO E FINALIZA. A máquina de estado pode ser vista em forma simplificada na figura a seguir.

Figura 6 - Máquina de Estado Spimestre_12bits

     O estado da máquina será armazenado no signal “spi_master”. As variáveis são declaradas na arquitetura: conta_bits, divide_clock, sclock, reg_desl, buffer_entrada e buffer_saida.

     Conta_bits: variável do tipo integer de zero a dezessete, conta quantas vezes a variável reg_desl é deslocada para formar uma palavra de 12 bits.

     Reg_desl: variável do tipo logic vector de 13 bits. Os bits que serão enviados e recebidos viam SPI pelos pinos MISO e MOSI são armazenados nessa variável.  

     Buffer_entrada: variável do tipo logic vector de 12 bits. A palavra que se deseja mandar para a saída MOSI é armazenada nessa variável.

     Buffer_saida: variável do tipo logic vector de 12 bits. Os 12 bits vindo da comunicação SPI pela entrada MISO são armazenados nessa variável, esses bits ficaram disponíveis na saída DADO_SAIDA do projeto.

-- Arquitetura: implementa a lógica do projeto.
architecture maquina of spimestre_12bits is
 
type estado is (ESPERA, COMUNICANDO, FINALIZA);

signalspi_master: estado := ESPERA;

 
begin
     process (CLOCK)  
     variable conta_bits: integer range 0 to 17 := 0;  
     variable divide_clock : integer range 0 to 7 := 0;
     variable sclock: std_logic := '0';
     variable reg_desl: std_logic_vector (12 downto 0);
     variable buffer_entrada:  std_logic_vector (11 downto 0) := x"000";
     variable buffer_saida: std_logic_vector (11 downto 0) := x"000";

     Após a declaração das variáveis é definido o valor que será enviado via SPI pela saída MOSI, esse valor é armazenado na variável buffer_entrada(F00 H).

     O estado inicial é o ESPERA. Nesse estado são definidos alguns valores das saídas da comunicação SPI e das variáveis. Saída SPI_LIVRE em nível lógico alto indica que não está acontecendo transição dos bits via SPI. Saída SS em nível lógico alto.

     Os 12 bits mais significativos da variável reg_desl recebem os bits da variável buffer_entrada.

     A mudança para o estado COMUNICANDO só ira acontecer quando a entrada SPI_TRANSFER passar para nível lógico alto.

 
begin
 
 buffer_entrada := x"F00"; 

 
 if CLOCK' event and CLOCK = '1' then
 
     case spi_master is
 
     -- Estado ESPERA
     when ESPERA =>
          SPI_LIVRE<= '1';
          MOSI<= 'Z';
          SS<= '1';
          SCK<= '0';
          reg_desl (12 downto 1) := buffer_entrada;
          conta_bits:= 0;
     if SPI_TRANSFER = '0' then
          spi_master<= ESPERA;
     else
          spi_master<= COMUNICANDO;
     end if;

     No estado COMUNICANDO a saída SPI_LIVRE vai para nível lógica zero, informando que está acontecendo a comunicação via SPI.  SS vai para nível lógico baixo, iniciando a comunicação SPI e a Saída MOSI já começa a receber o bit mais significativo da variável reg_desl.

     O clock principal é dividido por 12, esse novo clock com freqüência menor é a variável sclock. Na descida do sclock reg_desl é deslocado uma casa para esquerda e é somado 1 na variável conta_bits. Na subida do sclock o bit que vem da entrada MISO é armazenado no bit menos significativo da variável reg_desl. Essa seqüência ira parar quando conta_bits chegar a 16. O número 16 equivale aos três bits de configuração que são enviados pelo MOSI, um bit nulo e os doze bits vindos da entrada MISO.

     -- Estado COMUNICANDO
     when COMUNICANDO =>

          SPI_LIVRE <= '0';

          SS<= '0';
          MOSI<= reg_desl(12);

          SCK<= sclock;
 
          if conta_bits /= 16 then
 
               if divide_clock = 6 then
                    divide_clock := 0;
                    sclock := not sclock;
                     if sclock = '0' then
                         reg_desl (12 downto 1) := reg_desl (11 downto 0);
                         conta_bits := conta_bits +1;
                     else

                         reg_desl (0) := MISO; 

                     end if;
               end if;
               divide_clock := divide_clock + 1;
          else   

               spi_master<= FINALIZA;

          end if;

     Quando conta bits for igual a 16 a máquina de estado passa para o estado FINALIZA.

     No estado FINALIZA a variável buffer_saida recebe os 11 bits menos significativos da variável reg_desl e passa para o estado ESPERA e a saída DADO_SAIDA recebe os bits do buffer_saida.

     -- Estado FINALIZA
     when FINALIZA =>
          buffer_saida := reg_desl (11 downto 0);
          spi_master<= ESPERA;
 
   end case;
 
   DADO_SAIDA<= buffer_saida;
 
end if;
 
end process;
end architecture;

     Maquina_le_adc_12bits

     O primeiro trecho do bloco Maquina_le_adc_12bits refere-se às bibliotecas e as entradas e saídas do programa. A entrada DISPARA ira comandar o inicio da comunicação SPI, a entrada SPI_LIVREinformara que a os dados já foram armazenados na entrada LEITURA_ADC, a saída SPI-TRANSF inicia o estado comunicando do bloco Spimestre_12bits, DADO_LIDO armazena o dado de 12 bits vindo do bloco Spimestre_12bits.

 
Library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_bit.all;
use ieee.numeric_std.all;
 
-- Entidades
entity Maquina_le_adc_12bits is
port
     (-- Entradas
     CLOCK, DISPARA, SPI_LIVRE: in std_logic;
     LEITURA_ADC:in std_logic_vector (11 downto 0);
     -- Saidas
     SPI_TRANSF: out std_logic;
     DADO_LIDO :  out std_logic_vector (11 downto 0)
     );
end entity;

     Os Estados da máquina são os seguintes: ESPERA, ARMAZENA_DADO, ENVIA_DADO E ESPERA_2. A máquina de estado pode ser vista de forma simplificada na figura a seguir.

Figura 7 - Máquina de Estado Maquina_le_adc_12bits

     O estado da máquina será armazenado no signal “estado_maquina”.  A variável declarada na arquitetura ébuffer_dado.

     Buffer_dado: Armazena os dados vindo da entrada LEITURA_ADC, esses dados armazenados vão para a saída DADO_LIDO.

 
-- Arquitetura
architecturemaquina of Maquina_le_adc_12bits is
type estado is (ESPERA, ARMAZENA_DADO, ENVIA_DADO, ESPERA_2);
signal estado_maquina : estado := ESPERA;
 
begin
 
     process (CLOCK)
     variable buffer_dado : std_logic_vector (11 downto 0);

     O estado ESPERA configura a saída SPI_TRANSF em nível lógico baixo e fica aguardando a entrada DISPARA ir para nível lógico alto, se dispara for um o estado da máquina passa para ARMAZENA_DADO.

     begin
 
          if CLOCK' event and CLOCK = '1' then
 
          case estado_maquinais
 
               -- Estado espera
               when ESPERA =>
                    SPI_TRANSF <= '0';
 
                         if DISPARA = '0' then
                              estado_maquina<= ESPERA;
                         else
                              estado_maquina<= ARMAZENA_DADO;
                         end if;

     No estado ARMAZENA_DADO a saída SPI_TRANSF vai para um (iniciando a comunicação do bloco Spimestre_12bits). A variável buffer_dado recebe os valores que chegaram à entrada LEITURA_ADC. Quando a entrada SPI_LIVREfor para um o estado da máquina vai para ENVIA_DADO.

 
               -- Estado armazena_dado

               when ARMAZENA_DADO =>
                    SPI_TRANSF <= '1';

                    buffer_dado := LEITURA_ADC;
 
                         if SPI_LIVRE = '0' then
                              estado_maquina<= ARMAZENA_DADO;
                         else
                              estado_maquina<= ENVIA_DADO;
                         end if;

     O estado ENVIA_DADO configura a saída SPI_TRANSF para zero parando a comunicação SPI. A saída DADO_LIDOrecebe os dados da variável buffer_dado e o estado da máquina vai para ESPERA_2.

     No estado ESPERA_2 quando a entrada DISPARA for zero a máquina retorna para o estado ESPERA.

          -- Estado registra dado na saída
          when ENVIA_DADO =>
               SPI_TRANSF <= '0';
               DADO_LIDO <= buffer_dado (11 downto0);
               estado_maquina<= ESPERA_2;
 
          when ESPERA_2 =>
               if DISPARA = '1' then
                    estado_maquina<= ESPERA_2;
               else
                    estado_maquina<= ESPERA;
               end if;
 
  end case;
 
end if;
 
end process;
end architecture;

Atribuição dos Pinos

     As entradas e saídas do exemplo Le_Spi_ADC podem ser visualizadas no código a seguir, esse código é a entidade do arquivo que é top de Hierarquia do projeto.  

 
entity Le_Spi_ADC is
 
port
     (
          clock, Miso: in std_logic;
          mosi, ss, sck : out std_logic;
          a, b, c, d, e, f, g, p : out std_logic;
          ac_display: out std_logic_vector (1 to 6)
);
end entity Le_Spi_ADC;

     A montagem pode ser feita como ilustra a foto abaixo.

Figura 8 - Montagem Kit

     Com base na montagem e na pinagem da placa, podemos definir o Pin Planner para as entradas e saídas do projeto.

Figura 9 - Pin Planner

Conclusão

     Esse artigo foi produzido com o intuito de demonstrar a leitura do Módulo de Conversor A/D MCP3202 do projeto FPGA para todos através do exemplo Le_spi_adc. O protocolo de comunicação da componente MCP3202 é a comunicação SPI, por esse motivo dois blocos especiais utilizando os conceitos de máquina de estado em VHDL foram desenvolvido (Spimestre_12bits e Máquina_Le_ADC_12bits) esses blocos respectivamente fazem a comunicação via SPI e o controle da SPI. Além dos dois blocos especiais o exemplo Le_spi_adc contém outros blocos menores como: bcd_7seg, clock_256hz e control_dispmux.Todos os componentes utilizados no exemplo foram declarados e suas portas foram mapeadas e instanciadas utilizando os conceitos de projeto hierárquico.

     Esse exemplo foi gravado e testado na placa do Kit CPLD MAX_V, os resultados podem ser vistos no vídeo do inicio do artigo.

Quem está Online

Temos 31 visitantes e Nenhum membro online

Apoio

Login Form

 

Artigos Relacionados