Prévia do material em texto
DISCIPLINA: SISTEMAS MICROPROCESSADOS - DAE01228 - SEMESTRE : 2021.2 Roteiro No 5 CONVERSÃO ANALÓGICA DIGITAL Prof. Eng. Dr. Ciro J. E. Montero 1 1 Fundação Universidade Federal de Rondônia - UNIR, Núcleo de Tecnologia - NT, Departamento de Engenharia Elétrica - DEE, Sala 314 - Bloco 4H Porto Velho, Rondônia, Brasil e-mail: ciro.egoavil@unir.br RESUMO Este roteiro explica o módulo de conversão analógico-digital para a realização da leitura de um potenciômetro, o que emula a leitura de um sensor analógico. O resultado é mostrado em um display LCD. 1 INTRODUÇÃO Conversores analógicos-digitais (A/D) são de suma impor- tância, pois, sinais existentes na natureza são analógicos e o processo de conversão (A/D) realizado através de Mi- crocontroladores permite infinitas aplicações que traduzem para o cotidiano social. A compreensão desses fenômenos analógicos existentes na natureza não são de fácies inter- pretação e muitas das vezes invisíveis a visão humana [1]. Os Microcontroladores geralmente trabalham conectados a sensores, e. g. sensor de temperatura que converte um valor físico (temperatura em tensão) em uma ambiente. Esse valor de tensão é analógico e precisa ser convertido para digital, para ser lido por um microcontrolador ou microprocessa- dor, onde será feita a análise e tratamento dos dados. Um módulo de conversão (A/D) de 10 bits de resolução e 8 canais está disponível no PIC16F877A [2]. Esse tipo de aplicação não permite que seja efetuado os pulling ou delays nos códigos, porque esse modo de programação prende o Microcontrolador por um certo tempo em uma determinada parte sem que mais nada possa ser processado até o fim do tempo especificado, o que compromete por um todo o monitoramento de quaisquer fenômeno físico, pois, pode acontecer que o sensor leia o valor apropriado para atuar, mas o Microcontrolador esteja atendendo a rotina de pul- ling determinado pelo programador [1]. Para se desvenci- lhar disso, a maioria dos Microcontroladores da Microchip possuem rotinas de interrupção, como o próprio nome já sugere, os Microcontroladores interrompem sua execução em quaisquer instante de tempo e atendem a rotina de interrup- ção predeterminada [2]. São importantes pois economizam tempo de processamento, nesses microcontroladores, há uma interrupção dedicada ao fim de uma conversão (A/D). Uma característica importante desses Microcontroladores é que eles possuem apenas um módulo de conversão (A/D), no entanto, trabalha internamente de forma multiplexada com o PORTA e com esse recurso permite utilizar todos os canais disponíveis de transmissão, para a entrada de diferentes sinais [2]. Esse recurso pode ser observado através do diagrama de bloco do PIC16F877A (vide o datasheet). 2 OBJETIVOS Oss objetivos deste roteiro são os seguintes: • Explicar o funcionamento da conversão (A/D); • Mostrar a como realizar a conversão (A/D); • Mostrar diferentes configurações que podem ser defini- das no PIC16F877A para conversão A/D; • Estabelecer a rotina de interrupção baseado em conver- são (A/D); e • Esperar o fim da conversão de algum sinal para estabe- lecer algum evento externo. 3 SOFTWARES UTILIZADOS • MPLAB X • PICSimLab • XC8 4 DESENVOLVIMENTO TEÓRICO Os Registradores ADRESL e ADRESH são os Registra- dores utilizados para armazenar, o resultado final de uma conversão analógica para digital (ADC). Dois Registradores são utilizados no processo (ADC) é porque os Microcon- troladores PICs normalmente executam conversões (ADC) através de módulos de 10 bits ou mais. Um único Registrador tem apenas 8 bits (vide o datasheet), portanto, ele não pode conter todos os valores amostrados. Consequentemente, uma Roteiro 5, 2021.2 1 conversão (ADC) deve armazenar seus valores em dois Re- gistradores (16 bits). ADRESH e ADRESL, como os nomes indicam, esses Registradores armazenam um byte High e um byte Low. Por si só, um Registrador somente pode contar até 256 (28 = 256). Uma conversão através de módulos de 10 bits gera 210 = 1024 amostras, para que não se perca nem um ponto de resolução, surge a necessidade da utilização de 2 Registradores (16 bits) e isso se explica através da quantidade de amostras que se consegue obter com um módulo conversor de 10 bits [2]. O byte baixo ADRESL1 contará até 256 overflow2. O byte alto ADRESH3 é incrementado sempre que ADRESL transborda. A junção do trabalho desses dois Registradores agrupam os valores digitais capturados em todo o processo. Para trabalhar com conversão analógico-digital através do PIC16F877A, é necessário o conhecimento e entendimento de como funciona o setup, via código, de quatro Registrado- res, (vide o datasheet) ADCON0 e ADCON1 para configura- ção do módulo, e ADRESH e ADRESL onde é armazenado o resultado da conversão, como descrito anteriormente. Vale ressaltar, além disso, um Registrador importante em traba- lhos mais elaborados com Microcontroladores é o CMCON, (vide o datasheet), pois esse Registrador é responsável pela ativação dos comparadores internos dos PICs da Microchip [2]. Também precisa-se entender como funciona em si o pro- cesso de conversão, pois, como já informado, o PIC16F877A possui uma resolução que varia de 0 a 1023 (210 − 1), o que possibilita que se tenha 1024 representações (1024 amostras desse sinal) do sinal convertido e muitas vezes, o sinal analó- gico a ser digitalizado não possui variação a partir de 0V. Por isso, necessita que primeiramente se realize uma interface de adequação, entre o sinal analisado e o Microcontrolador para que não se perca parte da resolução [1]. 4.1 SETUP PARA EXPERIMENTOS Através do Registrador ADCON1 faz-se a configuração do modo que a justificação dos valores convertidos se darão, justificando os bits nos Registradores ADRESH e ADRESL (justificação à direita ou à esquerda, Figura 1) - bit 7. Figura 1: Modo de disposição dos valores convertidos. Fonte: modificado [2] 1“L” de low em inglês 2bit c do Registrador STATUS - carry-out 3“H” de high em inglês Resultado = ADRESL + (ADRESH *256) A expressão (ADRESH * 256) equivale a expressão (ADRESH « 8), e é utilizada para rotacionar valores amos- trados que já estão salvos no Registrador ADRESH, isso possibilita a justificação já citada. Em binário, (12 « 8 = 25610), o que se realiza para que se desloque o dígito em 8 posições e os agrupem de forma adequada. O byte baixo ADRESL conta até 256 estouros para que ocorra o primeiro carry-out. O carry-out implica que byte High, ADRESH, é incrementado em uma unidade sempre que ADRESL trans- borda. ADRESH está contando quantos 256 existiram, e. g. quantos fins de conversão aconteceram ou quantas vezes houve overflow do TMR0. Isso possibilita a contagem de tempos para que se determine uma tarefa. Faz-se a seleção da frequência de conversão através do bit 6, os bits 5 e 6 não são implementados e lidos como zero, e faz-se a configuração do modo, como os bits do PORT se comportarão durante o processo de conversão - analógico ou digital e de quais tensões/referências serão utilizadas - VDD, VREF+, VREF− e VSS através dos bits de 3 - 0 [2]. Em modo de linguagem de programação C, uma configuração possível é mostrado a seguir (vide o datasheet): ADCON1 = 0b10000100; A sequência em binário (0b00000100) específica que foram realizadas as seguintes instruções: frequência de conversão foi defina como Fosc/8, configuraram-se AN0, AN1 e AN3 como entradas analógicas, e definidas as tensões de refe- rência como VDD e VSS . Para conversões (A/D) corretas, a frequência de conversão deve ser escolhida para garantir um tempo mínimo de conversão de 1, 6µs, TAD - tempo de aqui- sição de dados [2]. Esse tempo é algo que mal configurado compromete toda a conversão, pois, esse tempo é o gasto, de acordo com o tempo de cada ciclo de máquina. E deve-se perceber que o sinal analógico que está sofrendo o processo de conversão é um evento independente da conversão e não “espera” - contínuo no tempo, e. g.: o sinal analógico é con- tínuo e se o TAD é grande perderá muitas amostras dos sinal analógico e por conseguinteterá uma leitura imprecisa de dados. Por outro lado, se o TAD for excessivamente pequeno é possível que Microcontrolador não consiga “acompanhar” o estabelecido, (vide o datasheet). O Registrador ADCON0 configura, nos bits 7 e 6 jun- tamente com ADCON1 a frequência de conversão. Define quais canais serão utilizados para conversão, bits 5 a 3. Inicia a conversão e indica o término no bit 2 (GO/DONE), bit 1 não implementado, lido como zero e ativa-se o módulo de conversão no bit 0. Programando em linguagem C, uma configuração possível é mostrada a seguir, (vide o datasheet) [2]: ADCON0 = 0b01001001; A sequência em binário (0b00000100) específica que fora realizado as seguintes instruções: a frequência de conversão de Fosc/8, seleciona o canal AN0, e ligar o módulo de 2 Roteiro 5, 2021.2 conversão. Após a escolha do canal analógico, é necessário que o microcontrolador aguarde um tempo máximo de 20µs, para que o capacitor utilizado carregue, (vide o datasheet). 5 EXPERIMENTO 1 Primeiramente, crie um projeto no MPLAB X (vide Roteiro No 1) e faça as configurações básicas escolhendo o Microcon- trolador e o Compilador adequados (PIC16F877A, XC8), e crie um arquivo em c. Em seguida, faça a configuração do Microcontrolador e escolha a frequência de trabalho de- sejada (4 MHz), (vide Roteiro No 1). Após executadas as configurações, pode-se criar um laço infinito usando while e será iniciada a conversão (A/D) ativando o bit (GO/DONE). Então, deve ser verificado se a conversão finalizou, caso sim, poderá utilizar-se desse processo para controlar um evento externo, e. g., O laço while deve ser: while(1){ GO_nDONE = 1; while(GO_nDONE){ AD_Value = (ADRESH<<8)|ADRESL; Lcd_Cmd(0x01); sprintf(s,"AD_Value = %d",AD_Value); Lcd_String(s); __delay_ms(200); } } A linha “while(GO_nDONE)” verifica se a conver- são (A/D) finalizou, testando o bit GO/DONE. Enquanto GO/DONE = 1, a conversão está em andamento. A variável “AD_Value” deve ser criada no início da função main() com o tipo “unsigned int [3] AD_Value;” Lembre-se que o con- versor é de 10 bits [2]. A linha “AD_Value = (ADRESH«8) | ADRESL;” (significa um («) - shift left, (|) - ou bit a bit) rotaciona (desloca) os bits de ADRESH 8 vezes à esquerda e os guarda junto ao valor de ADRESL em AD_Value, pois estão justificados à direita. “Lcd_Cmd(0x01);”, (vide Roteiro No 4)" limpa o display. “sprintf(s, “AD_Value = %d”, AD_Value);” formata o array4 s com os caracteres “AD_Value = ” é o valor lido da conversão. Compõe uma string com o mesmo texto que seria impresso se o formato fosse usado em printf, mas em vez de ser impresso, o conteúdo é armazenado como uma string em linguagem (c) no ponteiro apontado por str. A array “s” deve ser declarado no ínicio da função main() como “char s[11];” [4]. “Lcd_String(s)” (vide Roteiro No 4) mostra s no display. A função sprintf() é definida na Biblioteca stdio.h, do tipo .h - header, que deve ser incluída no código, logo após a inclusão de xc.h., como: #include <stdio.h> Após a compilação, no PICSimlab carregue o arquivo .hex gerado e selecione a frequência adequada. O display 4Protótipo: int sprintf(char * restrict s, const char * restrict format, ...);); mostrará resultados da conversão. Mas mudá-los basta des- lizar o slider5 esquerdo sob Pot. P2. O código da biblioteca LCD está no Apêndice A e deve ser incluído (#include lcd.h) antes da função main(). O código principal está no Apêndice B. 6 EXPERIMENTO 2 Neste experimento será mostrado o uso de interrupção por fim de conversão analógica (A/D). AS interrupções possuem Registradores que deverão ser configurados de forma ade- quada para habilitar a interrupção deseja (vide o datasheet). O Registrador INTCON é o Registrador responsável para habilitar a interrupção global através do bit GIE (habilita a interrupção global), a Figura 2 ilustra o descrito aqui. A in- Figura 2: Diagrama de bloco das interrupções dos Pic16f87XA, Fonte: extraída [2] terrupção por fim de conversão (A/D) é uma interrupção por periférico. Para utilizar as interrupções, a Figura 2, mostra de forma clara o porquê do bit GIE dever ser setado (1). Visto que, compõe uma das entradas de uma porta lógica AND que finaliza a saída do diagrama em bloco de toda lógica de interrupção do PIC16F877A, (vide o datasheet). O bit PEIE do Registrador INTCON (interrupção por periféricos) deve ser habilitado. Além disso, deve ser habilitada a interrupção específica que no caso do conversor (A/D) é habilitada por ADIE do Registrador PIE1 (vide o datasheet). Crie um novo projeto, (vide Roteiro No 1). Desta vez, será utilizada justificação à esquerda, (vide o datasheet). Os ou- tros bits de ADCON0 e slider esquerdo sob Pot. P2. serão deixados como estão. Assim, dentro de main() faça GIE = 1; PEIE = 1; ADIE = 1; ADCON1 = 0b00000100; ADCON0 = 0b01001001; __delay_us(20); 5Tecla de ajuste de um potenciometro Roteiro 5, 2021.2 3 while(1) { GO_nDONE = 1; __delay_ms(200); } O protótipo da rotina de interrupção deve ser definida antes da função main(), a função em si deve ser desenvolvida após a função main(). Ela é definida da seguinte maneira: void __Interrupt()Isr() { if(ADIF){ char s[11]; Lcd_Cmd(0x01); sprintf(s, ‘‘pot = %d’’,(ADRESH<<2) | (ADRESL >> 6)); Lcd_String(s); ADIF = 0; } } Para o PIC16F877A só existe uma rotina de interrupção e nela são executadas todas as interrupções ativas. Devido a isso, deve-se testar a flag de cada interrupção para saber qual aconteceu. O bit ADIF é a flag de interrupção de fim de conversão (A/D) por isso a primeira linha da rotina é “if (ADIF)”. Em seguida são executadas as linhas como no experimento anterior com exceção da linha "sprintf(s, "pot = %d", (ADRESH«2) | (ADRESL » 6));" que são feitos os ajustes necessários para trabalho com os bits justificados à esquerda. Por último, a flag ADIF é colocada como 0 para encerrar a rotina. Após a compilação, a execução deve ser da mesma forma como no exemplo anterior. 7 EXERCÍCIOS 1) Fazer conversão (A/D) com justificação à esquerda, aguardando o fim de conversão, e mostrar resultado nos bits 0, 1, 2 e 3 do PORTB (Dica: trata-se de uma conversão de 10 bits para 4 bits, ou seja, haverá perda de precisão e só os bits mais significativos serão necessários). 2) Mudar o código do exercício anterior para utilizar justificação à direita e interrupção por fim de conversão (A/D). Referências [1] E. W. Rambo, “Wrkits channel: Curso de assembly para pic.” [2] MICROCHIP, “Pic16f87xa: Data sheet, 28/40/44-pin enhanced flash micro- controllers.” [3] Microsoft, “Documentação: Intervalos de tipos de dados.” [4] E. Casavella, “Intellectuale: Tecnologia & treinamento.” 4 Roteiro 5, 2021.2 APÊNDICE A - BIBLIOTECA LCD.H void _delay(unsigned long cycles); void _delaywdt(unsigned long cycles); void _delay3(unsigned char cycles); //delay for 30 cycles void Lcd_Enable(); void Lcd_Init(); void Lcd_Cmd(unsigned char Cmd); void Lcd_Char(char Data); void Lcd_String(char *String_Address); void Lcd_CursorPosition(unsigned char X, unsigned char Y); void SpecialChar(); #define RS RE0 //Mnemônico para RE0 #define EN RE1 //|| || RE1 #define RW RE2 //|| || RE2 #define DB PORTD //Diretiva de byte void Lcd_Enable(){ _delay(20); //delay for 20 cycles, 1us EN = 1; _delay(500); //delay for 500 cycles, 1us EN = 0; _delay(500); //delay for 500 cycles, 1us } void lcd_init(){ TRISE &= 0x08; //Bits 0 and 1 and two from PORTE as output (TRISE = TRISE & 0b00001000) TRISD = 0x00; //Define PORTD as output lcd_cmd(0x38); //8 bit mode ON, 2 lines, 5*8 font lcd_cmd(0x38); //8 bit mode ON, 2 lines, 5*8 font lcd_cmd(0x06); //increase cursor position, scroll display OFF lcd_cmd(0x0F); //display ON, cursor ON, blink ON lcd_cmd(0x01); // Clear display lcd_cmd(0x80); //Go to position (1,1) } void lcd_cmd(char cmd){ RS = 0; //A command will be sent to the display DB = cmd; Lcd_Enable(); } void lcd_char(char data){ RS = 1; //Data will ve sent to the display DB = data; Lcd_Enable(); } void lcd_string(char *string_address){ while(*string_address) { lcd_char(*(string_address++));} } void lcd_cursorPosition(char x, char y){ //char position = 0x80 + 0x40 * (x - 1) + (y - 1); // 0x3F + 0x40*x + y char position; if (y==1) { position = 0x80 + x - 1; } else { position = 0xC0 + x - 1; } lcd_cmd(position); } Roteiro 5, 2021.2 5 void SpecialChar(){ Lcd_Cmd(0x40); Lcd_Write(0b0); Lcd_Write(0b0); Lcd_Write(0b0); Lcd_Write(0b0); //0x00 1 caracter da CGRAM Lcd_Write(0b0); Lcd_Write(0b0); Lcd_Write(0b0); Lcd_Write(0b0); } 6 Roteiro 5, 2021.2 APÊNDICE B - CÓDIGO PARA EXPERIMENTO 1 // CONFIG #pragma config FOSC = HS // Oscillator Selection bits (HS oscillator) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled) #pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled) #pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming // Enable bit (RB3 is digital I/O, // HV on MCLR must be used for programming) #pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM // code protection off) #pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection // off; all program memory may be written to by EECON control) #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off) #define _XTAL_FREQ 4000000 #include lcd.h #include <xc.h> #include <stdio.h> void main() { lcd_init(); int value; char s[11]; ADCON1 = 0b10000100; // Right justified, Fosc/8, AN0, 1 and 3 as analog inputs ADCON0 = 0b01001001; // Fosc/8, AN1, ADON = 1 __delay_us(20); // Delay to charge capacitor while(1) { GO_nDONE = 1; // Start AD conversion while(GO_nDONE) {} // Wait for AD conversion to finish value = (ADRESH<<8) | ADRESL; // Save ADRESH and ADRESL in value lcd_cmd(0x01); // Clear display sprintf(s, ‘‘value = %d’’, value); lcd_string(s); // Proceed to other tasks __delay_ms(200); } } Roteiro 5, 2021.2 7 APÊNDICE C - CÓDIGO PARA EXPERIMENTO 2 // CONFIG #pragma config FOSC = HS // Oscillator Selection bits (HS oscillator) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled) #pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled) #pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming // Enable bit (RB3 is digital I/O, // HV on MCLR must be used for programming) #pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM // code protection off) #pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection // off; all program memory may be written to by EECON control) #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off) #define _XTAL_FREQ 4000000 #include <xc.h> #include <stdio.h> void __interrupt() isr() { if (ADIF) { char s[11]; lcd_cmd(0x01); // Clear display sprintf(s, "value = %d", (ADRESH<<2) | (ADRESL >> 6)); lcd_string(s); ADIF = 0; } } void main() { lcd_init(); // Start LCD GIE = 1; // Enable global interrupt PEIE = 1; // Enable peripheral interrup ADIE = 1; // Enable A/D interrupt ADCON1 = 0b00000100; // Left justified, Fosc/8, AN0, 1 and 3 as analog inputs ADCON0 = 0b01001001; // Fosc/8, AN1, ADON = 1 __delay_us(20); // Delay to charge capacitor while(1) { GO_nDONE = 1; // Start AD conversion // Proceed to other tasks __delay_ms(200); } } 8 Roteiro 5, 2021.2 Introdução Objetivos Softwares Utilizados Desenvolvimento Teórico SETUP para Experimentos Experimento 1 Experimento 2 Exercícios Referências