[AVRcomC] Sensor Ultrassom

Arquivo principal (ligaUtrassom.ino)

#include "def_principais.h"//inclusão do arquivo com as principais definições#include "LCD.h"
#define DISPARO PB1
unsigned int Inicio_Sinal, Distancia;const prog_char mensagem1[] = "Distanc = cm\0";const prog_char mensagem2[] = "xxx\0";//------------------------------------------------------------------------------------ISR(TIMER1_CAPT_vect){ //interrupção por captura do valor do TCNT1 cpl_bit(TCCR1B,ICES1); //troca a borda de captura do sinal if(!tst_bit(TCCR1B,ICES1)) //lê o valor de contagem do TC1 na borda de subida do sinal Inicio_Sinal = ICR1; //salva a primeira contagem para determinar a largura do pulso else //lê o valor de contagem do TC1 na borda de descida do sinal Distancia = (ICR1 - Inicio_Sinal)/58 ;/*agora ICR1 tem o valor do TC1 na borda de descida do sinal, então calcula a distância */}//---------int main(){ unsigned char digitos[tam_vetor]; //declaração da variável para armazenagem dos digitos DDRD = 0xFF; DDRB = 0b00000010; //somente pino de disparo como saída (PB1), captura no PB0 (ICP1) PORTB = 0b11111101; TCCR1B = (1<<ICES1)|(1<<CS11); //TC1 com prescaler = 8, captura na borda de subida TIMSK1 = 1<<ICIE1; //habilita a interrupção por captura sei(); //habilita a chave de interrupções globais inic_LCD_4bits(); escreve_LCD_Flash(mensagem1); while(true){ //pulso de disparo set_bit(PORTB,DISPARO); _delay_us(10); clr_bit(PORTB,DISPARO); cmd_LCD(0x8A,0); if(Distancia<431){ // se o pulso for menor que 25 ms mostra o valor da distância ident_num(Distancia/2, digitos); cmd_LCD(digitos[2],1); cmd_LCD(digitos[1],1); cmd_LCD(digitos[0],1); } else //senão escreve xxx no valor escreve_LCD_Flash(mensagem2); _delay_ms(50);//mínimo tempo para uma nova medida de distância }}//===========

Arquivo secundário 1/3 (def_principais.h)

#ifndef _DEF_PRINCIPAIS_H#define _DEF_PRINCIPAIS_H
#define F_CPU 16000000UL //define a frequência do microcontrolador - 16MHz
#include <avr/io.h> //definições do componente especificado#include <util/delay.h> //biblioteca para o uso das rotinas de _delay_ms e _delay_us()#include <avr/pgmspace.h>//para a gravação de dados na memória flash
//Definições de macros para o trabalho com bits#define set_bit(y,bit) (y|=(1<<bit)) //coloca em 1 o bit x da variável Y#define clr_bit(y,bit) (y&=~(1<<bit)) //coloca em 0 o bit x da variável Y#define cpl_bit(y,bit) (y^=(1<<bit)) //troca o estado lógico do bit x da variável Y#define tst_bit(y,bit) (y&(1<<bit)) //retorna 0 ou 1 conforme leitura do bit
#endif

Arquivo secundário 2/3 (LCD.ino)

//================================================================================// Sub-rotinas para o trabalho com um LCD 16x2 com via de dados de 4 bits// Controlador HD44780 - Pino R/W aterrado// A via de dados do LCD deve ser ligado aos 4 bits mais significativos ou// aos 4 bits menos significativos do PORT do uC//================================================================================
#include "LCD.h"
//-----------------------------------------------------------------------------------// Sub-rotina para enviar caracteres e comandos ao LCD com via de dados de 4 bits//-----------------------------------------------------------------------------------//c é o dado e cd indica se é instrução ou caractere (0 ou 1)
void cmd_LCD(unsigned char c, char cd){ if(cd==0) //instrução clr_bit(CONTR_LCD,RS); else //caractere set_bit(CONTR_LCD,RS); //primeiro nibble de dados - 4 MSB #if (nibble_dados ) //compila o código para os pinos de dados do LCD nos 4 MSB do PORT DADOS_LCD = (DADOS_LCD & 0x0F)|(0xF0 & c); #else //compila o código para os pinos de dados do LCD nos 4 LSB do PORT DADOS_LCD = (DADOS_LCD & 0xF0)|(c>>4); #endif pulso_enable(); //segundo nibble de dados - 4 LSB #if (nibble_dados) //compila o código para os pinos de dados do LCD nos 4 MSB do PORT DADOS_LCD = (DADOS_LCD & 0x0F) | (0xF0 & (c<<4)); #else //compila o código para os pinos de dados do LCD nos 4 LSB do PORT DADOS_LCD = (DADOS_LCD & 0xF0) | (0x0F & c); #endif
pulso_enable(); if((cd==0) && (c<4)) //se for instrução de retorno ou limpeza espera LCD estar pronto _delay_ms(2);
} //fim void cmd
//-----------------------------------------------------------------------------------//Sub-rotina para inicialização do LCD com via de dados de 4 bits//-----------------------------------------------------------------------------------void inic_LCD_4bits(){//sequência ditada pelo fabricando do circuito integrado HD44780 //o LCD será só escrito. Então, R/W é sempre zero. clr_bit(CONTR_LCD,RS );//RS em zero indicando que o dado para o LCD será uma instrução clr_bit(CONTR_LCD,E);//pino de habilitação em zero _delay_ms(20); //tempo para estabilizar a tensão do LCD, após VCC //ultrapassar 4.5 V (na prática pode ser maior)
//interface de 8 bits #if (nibble_dados) DADOS_LCD = (DADOS_LCD & 0x0F) | 0x30; #else DADOS_LCD = (DADOS_LCD & 0xF0) | 0x03; #endif pulso_enable(); //habilitação respeitando os tempos de resposta do LCD _delay_ms(5); pulso_enable(); _delay_us(200); pulso_enable(); //até aqui ainda é uma interface de 8 bits.
//interface de 4 bits, deve ser enviado duas vezes (a outra está abaixo) #if (nibble_dados) DADOS_LCD = (DADOS_LCD & 0x0F) | 0x20; #else DADOS_LCD = (DADOS_LCD & 0xF0) | 0x02; #endif
pulso_enable(); cmd_LCD(0x28,0); //interface de 4 bits 2 linhas (aqui se habilita as 2 linhas) //são enviados os 2 nibbles (0x2 e 0x8) cmd_LCD(0x08,0); //desliga o display cmd_LCD(0x01,0); //limpa todo o display cmd_LCD(0x0C,0); //mensagem aparente cursor inativo não piscando cmd_LCD(0x80,0); //inicializa cursor na primeira posição a esquerda - 1a linha
}// fim sub rotina
//------------------------------------------------------------------------------------//Sub-rotina de escrita no LCD - dados armazenados na RAM//------------------------------------------------------------------------------------void escreve_LCD(char *c){ for (; *c!=0;c++) cmd_LCD(*c,1); } // fim void
//------------------------------------------------------------------------------------//Sub-rotina de escrita no LCD - dados armazenados na FLASH//------------------------------------------------------------------------------------void escreve_LCD_Flash(const char *c){ for (;pgm_read_byte(&(*c))!=0;c++) cmd_LCD(pgm_read_byte(&(*c)),1); } // fim void
//------------------------------------------------------------------------------------//Conversão de um número em seus digitos individuais – função auxiliar//-----------------------------------------------------------------------------------void ident_num(unsigned int valor, unsigned char *disp){ unsigned char n; for(n=0; n<tam_vetor; n++) disp[n] = 0 + conv_ascii; //limpa vetor para armazenagem dos digitos do{ *disp = (valor%10) + conv_ascii; //pega o resto da divisão por 10 valor /=10; //pega o inteiro da divisão por 10 disp++;
}while (valor!=0); }//-----------------------------------------------------------------------------------

Arquivo secundário 3/3 (LCD.h)

#ifndef _LCD_H#define _LCD_H#include "def_principais.h"#define DADOS_LCD PORTD//4 bits de dados do LCD no PORTD#define nibble_dados 1 /*0 para via de dados do LCD nos 4 LSBs do PORT empregado (Px0-D4, Px1-D5, Px2-D6, Px3-D7), 1 para via de dados do LCD nos 4 MSBs do PORT empregado (Px4-D4, Px5-D5, Px6-D6, Px7-D7) */
#define CONTR_LCD PORTD//PORT com os pinos de controle do LCD (pino R/W em 0).#define E PD3 //pino de habilitação do LCD (enable)#define RS PD2 //pino para informar se o dado é uma instrução ou caractere#define tam_vetor 5 //número de digitos individuais para a conversão por ident_num()#define conv_ascii 48 /*48 se ident_num() deve retornar um número no formato ASCII (0 paraformato normal)*/
//sinal de habilitação para o LCD#define pulso_enable() _delay_us(1); set_bit(CONTR_LCD,E); _delay_us(1); clr_bit(CONTR_LCD,E); _delay_us(45);
//protótipo das funçõesvoid cmd_LCD(unsigned char c, char cd);void inic_LCD_4bits();void escreve_LCD(char *c);void escreve_LCD_Flash(const char *c);
void ident_num(unsigned int valor, unsigned char *disp);
#endif