Prezentuję poniżej kod źródłowy sonaru (nie uwzględniam tu plików biblioteki Procyon AVRlib).
//#############################
//
// Sonar ultradźwiekowy
//
//#############################
#include <avr/io.h>
#include "deprecated.h"
#include "sonar.h"
#include "znaki.h"
#include <avr/interrupt.h>
#include <util/delay.h>
#include "i2c.h"
#define wait 0xffff
int distance=0;
int idx; //zmienna uzyta w petli w funkcji wynik
unsigned int TicksNo[42] = {10,20,50,85,120,150,170, //3...30cm
220,240,280,315,335,375, //35...60cm
400,440,460,500,530,560, //65...90cm
600,630,660,690,720,760, //95...120cm
790,820,850,885,910,945, //125...150cm
970,1010,1050,1080,1115, //155...175cm
1150,1180,1210,1240,1270, //180...200cm
1300}; //troche ponad 2m
unsigned short DisplayChars0[42] = {0,0,1,1,2,2,3,3, //03...35cm
4,4,5,5,6,6,7,7, //40...75cm
8,8,9,9,0,0,1,1, //80...115cm
2,2,3,3,4,4,5,5, //120...155cm
6,6,7,7,8,8,9,9, //160...195cm
0,10}; //200...troche ponad 200
unsigned char DisplayChars1[42] = {3,5,0,5,0,5,0,5, //03...35cm
0,5,0,5,0,5,0,5, //40...75cm
0,5,0,5,0,5,0,5, //80...115cm
0,5,0,5,0,5,0,5, //120...155cm
0,5,0,5,0,5,0,5, //160...195cm
0,10}; //200...troche ponad 200
unsigned char digits[11] = {
((1<<LEDA)|(1<<LEDB)|(1<<LEDC)|(1<<LEDD)|(1<<LEDE)|(1<<LEDF)),
((1<<LEDB)|(1<<LEDC)),
((1<<LEDA)|(1<<LEDB)|(1<<LEDD)|(1<<LEDE)|(1<<LEDG)),
((1<<LEDA)|(1<<LEDB)|(1<<LEDC)|(1<<LEDD)|(1<<LEDG)),
((1<<LEDB)|(1<<LEDC)|(1<<LEDF)|(1<<LEDG)),
((1<<LEDA)|(1<<LEDC)|(1<<LEDD)|(1<<LEDF)|(1<<LEDG)),
((1<<LEDA)|(1<<LEDC)|(1<<LEDD)|(1<<LEDE)|(1<<LEDF)|(1<<LEDG)),
((1<<LEDA)|(1<<LEDB)|(1<<LEDC)),
((1<<LEDA)|(1<<LEDB)|(1<<LEDC)|(1<<LEDD)|(1<<LEDE)|(1<<LEDF)|(1<<LEDG)),
((1<<LEDA)|(1<<LEDB)|(1<<LEDC)|(1<<LEDD)|(1<<LEDF)|(1<<LEDG)),
(1<<LEDG) //kreska pozioma
};
unsigned char DisplayedChar[2];
unsigned char Com[2] = {~(1<<COM1),~(1<<COM2)};
//
//############################################################
//
//-------------------------
//
// procedura wysyłania paczki ultradźwięków
//
//-------------------------
int sygnal(void)
{
int echos=0; // zmienna do bliczenia powrotu ultradźwięków
sinus_40_khz();
sinus_40_khz();
sinus_40_khz();
sinus_40_khz();
sinus_40_khz();
sinus_40_khz();
sinus_40_khz();
sinus_40_khz();
sinus_40_khz();
sinus_40_khz();
// teraz trzeba wytłumić drgania przetwornika zwierając go do masy
cbi(ultrasonic_pinA_port,ultrasonic_pinA_pin);
cbi(ultrasonic_pinB_port,ultrasonic_pinB_pin);
delay(8);
// przetwornik wejściowy też zwieramy do masy w celu wytłumienia
sbi(DDRD,PD6);
cbi(PORTD,PD6);
delay(8);
cbi(DDRD,PD6); // no i można go włączyć
for(echos=0;echos<2500;echos++) // i czekać na odbite dźwięki
{
if(bit_is_set(ACSR,ACO)) // jeżeli bit ACO rejestru ACSR ustawiony
{
break; // to przerwij
}
}
return echos; // zwróć wartość zmiennej
}
//-------------------------
//
// procedura sygnału 40kHz
//
//-------------------------
void sinus_40_khz(void)
{
sbi(ultrasonic_pinA_DDR,ultrasonic_pinA_pin);sbi(ultrasonic_pinA_port,ultrasonic_pinA_pin);
sbi(ultrasonic_pinB_DDR,ultrasonic_pinB_pin);cbi(ultrasonic_pinB_port,ultrasonic_pinB_pin);
asm volatile("WDR"::); //watchdog reset, czyli nic nie rób.
asm volatile("WDR"::);
asm volatile("WDR"::);
asm volatile("WDR"::);
cbi(ultrasonic_pinA_port,ultrasonic_pinA_pin);
sbi(ultrasonic_pinB_port,ultrasonic_pinB_pin);
asm volatile("WDR"::);
asm volatile("WDR"::);
}
//-----------------------------------------------------
//
// procedura wyswietlajaca wynik na wyswietlaczach LED
//
//-----------------------------------------------------
void result(void)
{
idx = 0;
while(distance > TicksNo[idx])
idx++;
if(idx>41) //wieksza odleglosc niz 2m z hakiem
{
DisplayedChar[0]=0;
DisplayedChar[1]=0;
_delay_loop_2(wait);
}
else //w mierzonym zakresie
{
DisplayedChar[0]=digits[DisplayChars0[idx]];
DisplayedChar[1]=digits[DisplayChars1[idx]];
if(idx>19 && idx<40) //miedzy 1m a 2m
DisplayedChar[0] = DisplayedChar[0] | mdp; //dodaj kropke
if(idx==40) // 2m
DisplayedChar[1] = DisplayedChar[1] | mdp; //dodaj kropke
_delay_loop_2(wait);
}
}
//-----------------------------------------------------
//
// MAIN
//
//-----------------------------------------------------
int main(void)
{
//inicjalizacja i2c - na razie nie uzywana...
i2cInit();
i2cSetBitrate(10);
sbi(DDRD,PD7);
cbi(PORTD,PD7);
LEDDDR=0xff;
COMDDR=((1<<COM1)|(1<<COM2));
TCCR0 = 1<<CS01|1<<CS00;//preskaler 64//
TIMSK = 1<<TOIE0;
sei();
for(;;)
{
distance = sygnal();
result();
}
return(0);
}
//-----------------------------------------------------
//
// PRZERWANIE
//
//-----------------------------------------------------
SIGNAL(SIG_OVERFLOW0)
{
static int ActiveDisplay = 0;
TCNT0=128;
COMPORT &= ~(1<<COM1 | 1<<COM2); ///zerowanie wyswietlacza
LEDPORT = DisplayedChar[ActiveDisplay]; ///wysylanie znaku
COMPORT |= (Com[ActiveDisplay]); ///wlaczenie wyswietlacza
++ActiveDisplay; /// wlaczanie kolejnego wyswietlacza
if(ActiveDisplay > 1)
{
ActiveDisplay = 0;
}
}