Przerobiłem trochę program z książki "Mikrokontrolery Avr W Praktyce" (Doliński) w taki sposób, by napięcie mierzone było wyświetlane na wyświetlaczu LCD. Używałem modułu uruchomieniowego ZL3AVR wyposażonego m.in. w mikrokontroler Atmel ATMEGA32 16PU, wyświetlacz LCD HD444780 2x16 oraz 16-sto przyciskową klawiaturę. Układ podłączyłem jak na rysunku:
Do obsługi wyświetlacza użyto uniwersalnej biblioteki tAvrLib.
Cykl pomiarowy rozpoczyna się od ustawienia stanu wysokiego na wyjściu PD4, w wyniku czego kondensator C zaczyna się ładować przez opornik R na do napięcia zasilającego Vcc. W tym samym czasie mikrokontroler uruchamia pomiar czasu. W momencie, gdy napięcie na kondensatorze osiągnie wartość mierzonego napięcia wejściowego, na wyjściu komparatora nastąpi zmiana stanu, co powoduje zatrzymanie pomiaru czasu (zatrzaśnięcie wyniku w rejestrach ICR1H i ICR1L), który jest proporcjonalny do napięcia wejściowego (błąd jest niewielki). Cykl pomiarowy kończy się podaniem stanu niskiego na wyjściu PD4,
w wyniku czego kondensator jest rozładowywany przez rezystor R i niewielką oporność wyjściową portu PD4 w tym stanie.
Napięcie wejściowe woltomierza będące jednocześnie napięciem w stanie ustalonym na kondensatorze wylicza się z zależności:
$$U_{c}=\frac{I*t}{C}=\frac{V{cc}-U_{BEP}}{R_{1}}*\frac{t}{C}$$
Założono spadek napięcia na złączu baza-emiter w stanie przewodzenia 0,7 V.
Otrzymany wynik jest przysłany na wyświetlacz LCD.
Na początku programu deklaruje się wartości pojemności C oraz rezystancji rezystora R1.
Do wyliczenia napięcia referencyjnego zastosowano procedurę kalibracyjną. Jest ona uruchamiana gdy zaraz po restarcie mikrokontrolera zostanie wykryte wciśnięcie klawisza S5 (bit_is_clear(PIND,1)). W pętli do...while jest realizowany cykliczny pomiar napięcia wejściowego. Wyjście z pętli jest możliwe po naciśnięciu klawisza S1. Powoduje to wyliczenie współczynnika kalibracyjnego i zapisanie go w pamięci EEPROM mikrokontrolera.
Do pisania i kompilowania programu użyto środowiska AVR Studio 4.18 połączone z WinAVR-20090313 natomiast do przesyłania skompilowanego programu (pliku HEX) używano ISP Programmer 1.2.0.52.
Czy mógłby ktoś sprawdzić czy to w ogóle ruszy? Płytkę miałem pożyczoną więc teraz już nie mam jak samemu? W załączniku biblioteka tAvrLib oraz program wraz z HEXem
Do obsługi wyświetlacza użyto uniwersalnej biblioteki tAvrLib.
Cykl pomiarowy rozpoczyna się od ustawienia stanu wysokiego na wyjściu PD4, w wyniku czego kondensator C zaczyna się ładować przez opornik R na do napięcia zasilającego Vcc. W tym samym czasie mikrokontroler uruchamia pomiar czasu. W momencie, gdy napięcie na kondensatorze osiągnie wartość mierzonego napięcia wejściowego, na wyjściu komparatora nastąpi zmiana stanu, co powoduje zatrzymanie pomiaru czasu (zatrzaśnięcie wyniku w rejestrach ICR1H i ICR1L), który jest proporcjonalny do napięcia wejściowego (błąd jest niewielki). Cykl pomiarowy kończy się podaniem stanu niskiego na wyjściu PD4,
w wyniku czego kondensator jest rozładowywany przez rezystor R i niewielką oporność wyjściową portu PD4 w tym stanie.
Napięcie wejściowe woltomierza będące jednocześnie napięciem w stanie ustalonym na kondensatorze wylicza się z zależności:
$$U_{c}=\frac{I*t}{C}=\frac{V{cc}-U_{BEP}}{R_{1}}*\frac{t}{C}$$
Założono spadek napięcia na złączu baza-emiter w stanie przewodzenia 0,7 V.
Otrzymany wynik jest przysłany na wyświetlacz LCD.
Na początku programu deklaruje się wartości pojemności C oraz rezystancji rezystora R1.
Do wyliczenia napięcia referencyjnego zastosowano procedurę kalibracyjną. Jest ona uruchamiana gdy zaraz po restarcie mikrokontrolera zostanie wykryte wciśnięcie klawisza S5 (bit_is_clear(PIND,1)). W pętli do...while jest realizowany cykliczny pomiar napięcia wejściowego. Wyjście z pętli jest możliwe po naciśnięciu klawisza S1. Powoduje to wyliczenie współczynnika kalibracyjnego i zapisanie go w pamięci EEPROM mikrokontrolera.
Do pisania i kompilowania programu użyto środowiska AVR Studio 4.18 połączone z WinAVR-20090313 natomiast do przesyłania skompilowanego programu (pliku HEX) używano ISP Programmer 1.2.0.52.
Konfiguracja połączeń:
- PORTA4-PORTA7 - piny DATA4-DATA7 kontrolera HD44780
- PORTA1 - pin RS
- PORTA2 - pin E
- PORTB2 - wejście nieodwracające komparatora +
- PORTB3 - wejście odwracające komparatora -
- PORTD4 - wejście służące do rozładowywania kondensatora
- PORTD0 - wejście z podciąganiem z klawiatury
- PORTD1 - wejście z podciąganiem z klawiatury
Należy zadać wartości:
- pojemności C
- rezystora R1
- napięcie zasilania Vcc
*/
float rezystorR1=1; //1 Ohm
float kondensatorC=0.001; //1 mF
float napieciezasilania = 5; //5 V
double prad;
#define F_CPU 16000000 //częstotliwość taktowania
#define HD44780_DATA_GPIO A // pod którym portem jest szyna danych
#define HD44780_DATA_HIGHHALFBYTE 1
#define HD44780_RS_GPIO A
#define HD44780_RS_BIT 1
#define HD44780_E1_GPIO A
#define HD44780_E1_BIT 2
#define HD44780_WIDTH 16 //liczba kolumn wyświetlacza
#define HD44780_HEIGHT 2 //liczba wierszy wyświetlacza
#define HD44780_CHARSET HD44780_CHARSET_PL
#define HD44780_CODEPAGE HD44780_CODEPAGE_UTF8
#include <tAvrLib/hd44780.h> //biblioteka do obsługi wyświetlacza
#include <avr/io.h> //biblioteka plikowych operacji wejścia - wyjścia
#include <avr/signal.h> //biblioteka umożliwiająca obsługę sygnałów
#include <avr/eeprom.h> //biblioteka umożliwiająca korzystanie z pamięci EEPROM
#include <compat/deprecated.h> //biblioteka umożliwiająca kompatybilność z starszymi wersjami kompilatora
unsigned char liczt0;
volatile unsigned char pomiar; //flaga dokonania pomiaru
union{
unsigned int wspkal; //współczynnik kalibracji
unsigned char wspkalb[2];
} uwspkal;
void czekaj(unsigned long zt) //procedura wytracania czasu
{
#define tau 10.38
unsigned char zt1;
for(;zt>0;zt--)
{
for(zt1=255;zt1!=0;zt1--);
}
}
SIGNAL (SIG_INPUT_CAPTURE1) //obsługa przerwania od przechwycenia
{
union {
unsigned int czas;
unsigned char czasb[2];
} uczas;
uczas.czasb[0]=ICR1L; //zatrzaśnij rejestry przechwytywania
uczas.czasb[1]=ICR1H;
float WYNIK=(uczas.czas/uwspkal.wspkal)*(prad/kondensatorC);
int cyf0 = WYNIK; // wyznacz cyfrę przy pozycji 1V
int cyf1 = (WYNIK-cyf0)*100; // pozycja po przecinku
// początek kodu odpowiedzialnego za wyświetlenie dolnego napisu
hd44780_goto(1, 1);
HD44780_PUTPSTR(" ");
hd44780_putInt(cyf0, 10, 0);
hd44780_putChar('.');
hd44780_putInt(cyf1, 10, 0);
HD44780_PUTPSTR(" V");;
// koniec kodu odpowiedzialnego za wyświetlenie dolnego napisu
pomiar=1; //pomiar dokonany (zapal flagę)
sbi(PORTD,4); //zacznij rozładowywać kondensator pomiarowy
}
int main(void)
{
hd44780_init(); //inicjacja wyświetlacza
HD44780_BIND_STREAM(stdout); //powiązanie wyświetlacza ze standardowym wyjściem
hd44780_goto(0, 0); //przejście do początku górnej linii wyświetlacza
HD44780_PUTPSTR("Napiecie wynosi:"); //wyświetlenie górnego napisu
DDRD=0x13; //PORTD we oprócz PD4, PD1 i PD0 - wy
PORTD=0xff; //z podciąganiem
PORTB=0x04; //PB2 z podciąganiem
DDRB=0xF3; //PORT B0,B1,B4-B7 - wy, PORTB2 i PORTB3-0 - we
TCCR1A=0; //funkcje porównania i PWM wyłączone
TCCR1B=0x41; //preskaler XTAL/1 dla TC1, przechwytywanie na narastającym zboczu
TIMSK=0x08; //zezwolenie na przerwania od przechwytywania
ACSR=1<<ACIC; //zezwolenie na wyzwalanie przechwytywania komparatorem
czekaj(10*tau);
TIFR=0xff; //kasuj przerwania od timerów
if(bit_is_clear(PIND,1)) //wciśnięty S5 - kalibracja
{
hd44780_goto(1, 1);
HD44780_PUTPSTR(" KALIBRACJA"); //wyświetl napis „KALIBARCJA”
do
{
prad=((napieciezasilania-(0.7))/(rezystorR1));
cbi(PORTD,4); //ładuj kondensator pomiarowy (stan wysokiej impedancji na PD4
TCNT1H=0; //zeruj licznik 1 pomiar czasu ładowania
TCNT1L=0;
sbi(TIFR,ICF1); //ustawienie bitu ICF1 w rejestrze TIFR
while(bit_is_clear(TIFR,ICF1)); //czekaj aż napięcie mierzone zrówna się
//z napięciem wejściowym
uwspkal.wspkalb[0] = ICR1H; //zapisanie do zmiennej 16 bitowej wspkal wartość 16 bitowego rejestru przechwytywania (ICR1H do starszej części 16 bitowej danej)
uwspkal.wspkalb[1] = ICR1L; // ICR1L do młodszej części 16 bitowej danej
//uwspkal.wspkal=(ICR1L+256*ICR1H); // inny sposób zapisania powyższych operacji
sbi(PORTD,4); //zacznij rozładowywać kondensator pomiarowy
czekaj(1*tau); //opóźnienie związane z częstotliwością odświeżania
} while(bit_is_set(PIND,0));
uwspkal.wspkal = uwspkal.wspkal / 64;
eeprom_write_byte(1,uwspkal.wspkalb[0]); //zapisz współczynnik kalibracji
eeprom_write_byte(2,uwspkal.wspkalb[1]); //do pamięci EEPROM
sbi(TIFR,ICF1); //ustawienie bitu ICF1 w rejestrze TIFR
}
else
{
uwspkal.wspkal=eeprom_read_byte(1); //odczytaj współczynnik kalibracji z EEPROM-u
}
sei(); //odblokuj globalne przerwania
while(1) //główna pętla pomiarowa
{
cbi(PORTD,4); //ładuj kondensator pomiarowy
TCNT1H=0; //zeruj licznik 1 - pomiar czasu ładowania
TCNT1L=0;
pomiar=0;
while(pomiar==0); //czekaj aż napięcie mierzone zrówna się z napięciem
//na kondensatorze pomiarowym
czekaj(23*tau); //opóźnienie związane z częstotliwością odświeżania LCD
}
}
Czy mógłby ktoś sprawdzić czy to w ogóle ruszy? Płytkę miałem pożyczoną więc teraz już nie mam jak samemu? W załączniku biblioteka tAvrLib oraz program wraz z HEXem
