Escreva um código para fazer interface com o ADC de um microcontrolador genérico. O ADC deste microcontrolador possui 4 registradores para interface. O registrador ADC_CONFIG, posicionado sob o endereço 0x40001666, o registrador ADC_DATA_1, sob o endereço 0 times 40001687, o registrador ADC_DATA__2, sob o endereço 0x40001697 e o registrador ADC_START_WAIT, sob o endereço 0x40001660. Os registradores são de oito (8) bits. As tabelas abaixo ilustram o significado de cada bit dos registradores.
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 NOME Endereço
CH EN ADC_CONFIG |c|c|c|c|c|c|c|c|c|c| hline mu
habilita ADC e coloca em funcionamento
seleciona o canal para aquisição. Bit em nivel alto (a) para canal 1 e nivel baixo (0) para canal 2.
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 NOME Endereço
DATA Lo ADC_DATA_1 0×40001687
DATA Lo byte menos significativo da conversão
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 NOME Endereço
DATA Hi ADC_DATA_2
DATA Hi bits mais significatrivos do resultado da conversão
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 NOME Endereço
WAIT GO ADC_START_WAIT
GO = inicia a conversão
WAIT = bit fica preso em valor alto (1) enquanto a conversão está em curso.
Ele vai para zero (0) quando a conversão termina.
Tabela 1 - Datasheet Registradores ADC
Você deve escrever um código para efetuar a leitura de um potenciômetro, conectado ao canal 1 do ADC. A frequencia de amostragem deve ser 100 Hz e deve ser feita via pooling, com o auxilio da função
Template para código:
void main(void)
{

Passo 1

Beleza, vamos lá! O exercício pede para gente escrever um código que faça a leitura de um potenciômetro usando o ADC (Conversor Analógico para Digital) de um microcontrolador genérico. A gente vai precisar mexer com registradores específicos do ADC, entender como configurar esses registradores para selecionar o canal certo, iniciar a conversão, esperar ela terminar e, finalmente, ler os valores convertidos. Além disso, precisamos fazer isso com uma frequência de 100 Hz, ou seja, uma leitura a cada 10 milissegundos, usando polling (verificação contínua).

Passo 2

Primeiro, vamos configurar o ADC. Para isso, usamos o registrador ADC_CONFIG que está no endereço 0x40001666. Esse registrador tem dois bits importantes:
  • EN (bit0): Habilita o ADC.
  • CH (bit1): Seleciona o canal de leitura. Como queremos ler do canal 1, precisamos colocar esse bit em 1.
Então, nossa primeira tarefa é escrever esses valores no registrador ADC_CONFIG para habilitar o ADC e selecionar o canal 1.

Passo 3

Agora que o ADC está configurado, precisamos iniciar a conversão. Para isso, usamos o registrador ADC_START_WAIT no endereço 0x40001660. Esse registrador também tem dois bits importantes:
  • GO (bit0): Inicia a conversão quando colocado em 1.
  • WAIT (bit2): Fica em 1 enquanto a conversão está em andamento e volta para 0 quando termina.
Então, após iniciar a conversão colocando o bit GO em 1, vamos entrar num loop que vai verificar o estado do bit WAIT. Quando ele voltar para 0, sabemos que a conversão terminou.

Passo 4

Com a conversão concluída, os dados convertidos ficam armazenados nos registradores ADC_DATA_1 e ADC_DATA_2. O ADC_DATA_1 contém os bits menos significativos (LSB) e o ADC_DATA_2 os bits mais significativos (MSB) da conversão. Para obter o valor final, precisamos ler ambos os registradores e combinar esses bits. Isso vai nos dar o valor digital correspondente à posição do potenciômetro.

Passo 5

Por último, precisamos garantir que estamos fazendo as leituras a uma frequência de 100 Hz, ou seja, uma a cada 10 milissegundos. Para isso, vamos implementar um atraso (delay) de 10 ms após cada leitura. Em um microcontrolador real, isso pode ser feito usando timers, mas aqui vamos simplificar usando uma função de espera.

Resposta

#include <stdint.h>

// Definição dos endereços dos registradores
#define ADC_CONFIG       (*(volatile uint8_t*)0x40001666)
#define ADC_DATA_1       (*(volatile uint8_t*)0x40001687)
#define ADC_DATA_2       (*(volatile uint8_t*)0x40001697)
#define ADC_START_WAIT   (*(volatile uint8_t*)0x40001660)

// Máscaras para os bits do ADC_CONFIG
#define ADC_CONFIG_EN    (1 << 0) // Bit 0 - EN
#define ADC_CONFIG_CH    (1 << 1) // Bit 1 - CH

// Máscaras para os bits do ADC_START_WAIT
#define ADC_START_GO     (1 << 0) // Bit 0 - GO
#define ADC_START_WAIT_BIT (1 << 2) // Bit 2 - WAIT

// Função de delay simplificada (substituir por implementação real)
void delay_ms(int ms) {
    // Implementação de delay depende do microcontrolador
    // Aqui estamos apenas representando a ideia
    for(int i = 0; i < ms * 1000; i++);
}

void main(void)
{
    // Passo 2: Configurar o ADC
    // Habilita o ADC e seleciona o canal 1
    ADC_CONFIG = ADC_CONFIG_EN | ADC_CONFIG_CH;

    while(1)
    {
        // Passo 3: Iniciar a conversão
        ADC_START_WAIT |= ADC_START_GO;

        // Esperar a conversão terminar
        while(ADC_START_WAIT & ADC_START_WAIT_BIT)
        {
            // Loop de espera (polling)
        }

        // Passo 4: Ler os dados
        uint8_t data_lo = ADC_DATA_1; // Dados menos significativos
        uint8_t data_hi = ADC_DATA_2; // Dados mais significativos

        // Combinar os dados para obter o valor final
        uint16_t adc_value = (data_hi << 8) | data_lo;

        // Aqui você pode usar o valor adc_value conforme necessário
        // Por exemplo, enviar para uma porta serial, ajustar um display, etc.

        // Passo 5: Aguardar 10 ms para manter a frequência de 100 Hz
        delay_ms(10);
    }
}

Explicação do Código

  • Definições de Registradores: Usamos #define para mapear os endereços dos registradores para facilitar o acesso no código.
  • Máscaras de Bits: Definimos máscaras para os bits que vamos manipular em cada registrador, facilitando a configuração e verificação dos mesmos.
  • Função de Delay: Criamos uma função delay_ms simplificada para representar a espera de 10 ms. Em um microcontrolador real, você deveria usar timers ou métodos mais precisos.
  • Configuração do ADC: No início do main, configuramos o ADC para habilitar e selecionar o canal 1 escrevendo nos bits correspondentes do ADC_CONFIG.
  • Loop Principal:
    • Iniciar Conversão: Colocamos o bit GO em 1 para iniciar a conversão.
    • Esperar Conversão: Usamos um while para ficar verificando o bit WAIT até que ele volte para 0, indicando que a conversão terminou.
    • Ler Dados: Após a conversão, lemos os registradores ADC_DATA_1 e ADC_DATA_2, combinando-os para formar o valor final do ADC.
    • Delay: Implementamos um atraso de 10 ms para manter a frequência de amostragem de 100 Hz.
Esse código básico permite que você leia constantemente o valor de um potenciômetro conectado ao canal 1 do ADC, com as leituras acontecendo a cada 10 milissegundos.

Exercícios relacionados