Olá, hoje vou postar este exemplo de como usar o conversor analógico digital do ATmega328P.
O código fonte:
//***********************************************************************************************************
// Usando o conversor analogico/digital
//
// no gravador configurar os fuses assim:
// EXTENDED 0XFF
// HIGH 0XD8 - neste modo funciona com qualquer valor de cristal usei um de 16Mhz
// LOW 0XC7
// LOKBITS 0XFF - sem proteção
//
//
// versão : 1
// descrição : Voltimetro
// Autor : Aguivone
// microcontrolador : ATmega328P
// compilador : AVR-GCC / Atmel AVR Studio 6.1
// Data do projeto : 07/08/2014
//*************************************************************************************************************
#include <avr/io.h>
#include <string.h>
#include <stdio.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>// AVRJazz Mega328 SPI I/O
////////////////////////funçoes auxiliares/////////////////////////////
#define alterna_pino(x,y) x ^= _BV(y)
#define LED PD2
#define TENSAO PC2
char caracter;
void RS232_inicializa(unsigned int BAUD)
{
unsigned int velocidade = F_CPU/16/BAUD-1;
//veja que na simulação do proteus dá erros nas velocidade diferentes de 9600 mas na pratica funciona.
UCSR0A = 0X20;
/* habilita receiver and transmitter buffers */
UBRR0H = (unsigned char)(velocidade>>8);
UBRR0L = (unsigned char)velocidade;
UCSR0B = 0X98;//deve se habilitar somente a interrupção de recepção para não travar o microcontrolador
/* 8 bits , 1 stop bit, assincrono , sem paridade,modo nornal */
UCSR0C = (1<<USBS0)|(3<<UCSZ00);
}
void escreve_caracter(unsigned char carac)
{
_delay_loop_1(1);//tempo para estabilizar tensão
while ( !( UCSR0A & (1<<UDRE0)) ); //espera transmitir para enviar um novo
UDR0 = carac;
while ( !( UCSR0A & (1<<UDRE0)) ); //espera transmitir desabilita a transmissão
_delay_loop_1(1);//tempo para garantir o envio
}
void impri_serial(const char frase[80])
{
unsigned int indice=0;
unsigned int tamanho = strlen(frase);
while(indice<=tamanho)///veja que o programa pode travar se aqui não tiver as duas aspas
{
escreve_caracter(frase[indice]);
indice++;
}
}
//////////////////////////interrupções requerida para usar a recepção serial///////////////////////////////////
ISR(USART_RX_vect)
{
caracter = (char)UDR0;
escreve_caracter(caracter);
}
///long para char
void long_to_char(unsigned int quant)
{
char texto[6];
texto[1] = '0';
texto[2] = '0';
texto[3] = ',';
texto[4] = '0';
texto[5] = '0';
if(quant>9999)//||(quant<10))
{
texto[1] = 'F';
texto[2] = 'A';
texto[3] = 'L';
texto[4] = 'H';
texto[5] = 'A';
}
else
{
while(quant>=1000)
{
quant=quant-1000;
texto[1]++;
}
while(quant>=100)
{
quant=quant-100;
texto[2]++;
}
while(quant>=10)
{
quant=quant-10;
texto[4]++;
}
while(quant>=1)
{
quant=quant-1;
texto[5]++;
}
}
escreve_caracter(texto[1]);
escreve_caracter(texto[2]);
escreve_caracter(texto[3]);
escreve_caracter(texto[4]);
escreve_caracter(texto[5]);
}
////////////rotina de leitura de tensão /////////////////////////////////
void ler_adc() {
ADCSRA |= _BV(ADSC);//inicia conversão analogico/digital
while ( (ADCSRA & _BV(ADSC)) );//espera terminar leitura
float valor = ADC*5/10.23;
long_to_char(valor);
return;
}
void inicializa_adc()
{
ADMUX = 0X02;// vai usar o pino PC2 como entrada, justificado a direita
// ADMUX = 0X08;// sensor de temperatura, justificado a direita
ADCSRA = 0XA0;//habilita o conversor adc clock dividido por 2 e trigger
ADCSRB = 0X41;//habilita o comparador e o trigger usará a saida dele
DIDR0 = 0XFB;////desabilita entrada analogico(reduz consumo), deixa apenas PC2 como analogico
}
////////////////////função principal/////////////////////////////////////
int main(void)
{
//////////////////inicializa port D /////////////////////////////////////////////////////////////////////
DDRD = 0XFE; //inicializa portD,4 a 7 entrada
DDRC = 0x18;//configura port C como entradas exceto C3 e C4
PORTD = 0x00;//desabilita pull ups
DDRB = 0x2F;//configura port B
PORTB = 0x02;//inicia com o pino de reset e desliga wiznet em nivel alto
RS232_inicializa(9600);
inicializa_adc();
sei();//habilita interrupções
impri_serial("Voltimetro serial ... \n\r");
///////////////////////////////////////////////////////
for(;;)
{
impri_serial("->");
ler_adc();
impri_serial(".\n\r");
_delay_ms(1000);
alterna_pino(PORTD,LED);//led
}//chave do laço infinito (for)
}//chave de main
A simulação do proteus, veja no detalhe o valor lido na serial e no multímetro do programa:
Nenhum comentário :
Postar um comentário
olá,digite aqui seu comentário!