#include <string.h>
#define F_CPU 16000000UL //16MHz
#define UART_BAUDRATE 9600
#define MYUBRR (((F_CPU/16)/UART_BAUDRATE)-1)
volatile char usart_rx_buffer[50];
volatile unsigned int frame_status = 0;
static void _sei( void )
{
sei(); //Habilitar a chave geral das interrupções AVR-GCC;
/* cli(); //Desabilita a chave geral das interrupções; */
//Habilitar a interrupção da recepção serial (UART0);
UCSR0B |= (1 << RXCIE0); //Setar (1),
}
/**
* Vetor de Interrupção USART RX
* ORG 0x0018
*/
ISR(USART_RX_vect)
{
unsigned char data;
static unsigned int indice = 0; //Variável que será utilizada como indice do buffer;
/**
* Verifica se houve erro durante a recepção serial;
* FE0 = Frame Error;
* DOR0 = Data OverRun;
* UPE0 = USART Parity Error; //save context ISR
*/
data = UDR0; //buffer de recepção serial; É o registrador que armazena o byte recebido;
if((UCSR0A & ((1 << FE0) | (1 << DOR0) | (1 << UPE0))) == 0)
{
/**
* Buffer cheio? Caso sim, reinicia indice
*/
if(indice >= sizeof(usart_rx_buffer))
{
indice = 0;
}
/**
* Caractere indicador de fim de frame;
*/
if( data == '\n' )
{
usart_rx_buffer[indice] = '\0'; //
frame_status = 1;
indice = 0;
//void (*ptr)() = &serial_received;
//(*ptr)( usart_rx_buffer);
//if( serial_event )
//serial_event( usart_rx_buffer );
}
/* Armazena os bytes recebidos no buffer */
else {
usart_rx_buffer[indice++] = data;
}
}
}
void serial_init( void )
{
UBRR0H = (uint8_t)(MYUBRR>>8);
UBRR0L = (uint8_t)(MYUBRR);
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
UCSR0C = (3<<UCSZ00);
}
void serial_chr( unsigned char data )
{
while(!(UCSR0A & (1<<UDRE0)));
UDR0 = data;
}
unsigned char serial_read( void )
{
while(!(UCSR0A & (1<<RXC0)));
return UDR0;
}
void adc_init(void) //ATMEGA328p
{
//Configurando a tensão de referencia do conversor AD sendo VCC e GND (digital);
//Justificativa esquerda (byte menos significativo do resultado em LOW);
//Configura o canal do conversor AD em AN0 (A0 -> Arduino)
ADMUX = (1<<REFS0); //0B00000001 << 6 => 0B01000000
//ADMUX = 0B01000000;
//OR bit a bit;
//0B10000000 | 0B00000100 | 0B00000010 | 0B00000001
//ADCSRA = 0B10000111
//Habilitar o conversor AD ADEN;
//Stop na conversão AD;
//Prescaler do conversor AD configurado na razão de 1:128;
ADCSRA = (1<<ADEN) |(1<<ADPS2) |(1<<ADPS1) |(1<<ADPS0);
}
uint16_t adc_read( uint8_t ch ) //adc_read(1);logo CH = 1
{
ch &= 0B00000111;
//ch = ch & 0B00000111;
//ch = 0B00000001 & 0B00000111;
//ch = 0B00000001;
//Selecionou apenas o canal do convesor AD; Por exemplo: CH=1
//Garantiu que as demais configurações anteriores fossem mantidas;
ADMUX = (ADMUX & 0xF8) | ch;
//ADMUX = (0B01000000 & 0B11111000) | 0B00000001;
//ADMUX = (0B01000000) | 0B00000001;
//ADMUX = 0B01000001;
//Start na conversão AD;
ADCSRA |= (1<<ADSC); //Máscara OR é utilizada para Setar 1 (|=)
//ADCSRA = 0B10000111 | (1<<6);
//ADCSRA = 0B10000111 | (0B0100000);
//ADCSRA = 0B10000111 | (0B0100000);
//ADCSRA = 0B11000111;
//Aguarda o término da conversão AD;
//Iniciamos a conversão setando o bit ADSC em 1;
//O próprio perifério irá setar em zero quando a conversão for finalizada;
// ADCSRA & (1<<ADSC)
// 0B11000111 & (1<<6)
// 0B11000111 & 0B01000000
// 0B01000000 //VERDADEIRA
while(ADCSRA & (1<<ADSC)); //40 ~ 80 us
//return (ADCW);
return ((ADCH<<8)|(ADCL)); //Concatenando dois bytes, formando assim um 16bits;
}
void setup() {
serial_init();
//serial_chr('A');
_sei();
adc_init();
}
void serial_str(char * texto){
for(int i =0; texto [i] != '\0';i++ ){
serial_chr(texto[i]);
}
}
void loop() {
if(frame_status == 1) { //Indica que podemos ler os bytes recebidos e armazenados em
//usart_rx_buffer.
DDRB |= (1<<PB5); //Seta (1); Configura como saída;
//PB5 é o led builting do Arduino;
PORTB ^= (1<<PB5); //Toggle, ou seja, inverte o estado lógico de PB5;
frame_status = 0; //apaga para receber novamente um novo frame;
if(memcmp(usart_rx_buffer, "leradc0", strlen("leradc0")) == 0) {
char buffer [10];
uint16_t res = adc_read(0); //1234;
sprintf(buffer, "%d\n", res);
serial_str(buffer);
}
}
}