instrukcja - Politechnika Warszawska
Transkrypt
instrukcja - Politechnika Warszawska
Politechnika Warszawska Wydział Elektryczny Laboratorium Podstaw Techniki Mikroprocesorowej Skrypt do ćwiczenia M.42 Zbieranie pomiarów w czasie rzeczywistym - język C 1.Wstęp W ćwiczeniach od M.42 do M.48 opisane zostały programy, wykonane w języku C, korzystające z prostych algorytmów obliczających wartości wielkości kryterialnych. Zadaniem tych programów jest obliczanie parametrów sygnałów podawanych na wejście analogowe mikrokontrolera. Następnie opisanych zostało sześć programów napisanych w języku C, które wykonują następujące czynności: • obliczenie wartości średniej oraz amplitudy, • obliczenie mocy czynnej oraz biernej (metoda 1), • obliczenie części rzeczywistej oraz urojonej sygnałów, • obliczenie mocy czynnej oraz biernej na podstawie części rzeczywistej oraz urojonej sygnałów, • program obliczający rezystancję oraz reaktancję, • program obliczający przesunięcie fazowe pomiędzy sygnałami. KaŜdy z programów składa się z części wspólnej dotyczącej zbierania próbek sygnałów podawanych na wejście analogowe mikrokontrolera (nastawienie timerów, deklaracja obsługi przerwań, sterowanie przetwornikiem A/C oraz zapis próbek) oraz części obliczeniowej. Dotyczy to programów napisanych w asemblerze oraz w języku C. Opisany poniŜej kod programu jest częścią wspólną programów opisanych w kolejnych ćwiczeniach. Kod ten odpowiada za przetwarzanie analogowo-cyfrowe, nastawienie timerów, deklaracja obsługi przerwań, sterowanie przetwornikiem A/C, zbierania oraz zapis próbek sygnałów podawanych na wejście analogowe mikrokontrolera DSM-51. 1.1. Część wspólna dla programów napisanych w języku C Opisany w tym rozdziale kod znajduje się w katalogu „c\pr - podstawowy\”. Wszystkie poniŜsze programy napisane w języku C funkcjonują zgodnie ze schematem przedstawionym na Rys. 1.1. Deklaracja zmiennych, ustawienie trybu pracy timerów oraz zezwolenia na przerwania Ustawienie liczników timerów oraz start Timera 0 Obsługa przerwań od Timera0: - ustawienie Timera0 - wybór wejścia 0 na multiplekserze - start przetwornika A/C - nastawienia Timera 1 - start Timera 1 Pętla nieskończona Instrukcje obliczeniowe Obsługa przerwań od Timera1: - zapis wartości z przetwornika A/C - wybór wejścia 1 na multiplekserze - start przetwornika A/C - start Timera 1 Obsługa przerwań od Timera1: - zapis wartości z przetwornika A/C Skok do początku bloku Rys. 1.1. Schemat blokowy działania programu Programy rozpoczynają się od deklaracji zmiennych, ustawienia trybu pracy timerów oraz zezwolenia na przerwania, po czym następuje ustawienie liczników timerów oraz start Timera 1. Timer ten odlicza czas pomiędzy pobieraniem kolejnych próbek. Dalsza część programu działa w pętli nieskończonej, w której wykonywane są obliczenia. Działania pętli przerywane są jedynie przez instrukcje obsługi przerwań od Timerów, które odpowiadają za zbieranie oraz zapis próbek sygnałów. Częścią wspólną wszystkich programów napisanych w języku C jest obsługa timerów, obsługa przerwań oraz zapis próbek. Zostało to opisane poniŜej. Na początku programu dołączone zostały pliki nagłówkowe. Odbyło się to w następujący sposób: #include <reg51.h> #include <stdio.h> #include <math.h> #include "lcd.c" #include "delay.c" Jako pierwszy dołączony został plik reg51.h zawierający definicje rejestrów specjalnych mikrokontrolera. Plik stdio.h jest standardową biblioteką wejść-wyjść. Kolejny plik (lcd.c) odpowiada za obsługę wyświetlacza LCD, natomiast plik delay.c zawiera podprogram delay, wykorzystany do wprowadzania opóźnienia podczas wyświetlania wyników na ekranie LCD. Przed programem głównym zadeklarowane zostały poniŜsze zmienne, które wykorzystywane są w obsłudze przerwań: unsigned char a = 0; unsigned char licznik = 0; unsigned char *pamiec0,*pamiec1; unsigned char *CSAD,*CSMX; unsigned char licznik2; unsigned char pozwolenie = 0; /*Deklaracja przelacznika kanalow*/ /*Deklaracaja licznika dla obslugi przerwan*/ /*Deklaracja wskaznikow pamieci*/ /*Deklaracja wskaznika przetwornika A/C oraz multipleksera*/ /*Deklaracja licznika dla petli kopiujacej probki*/ /*Pozwolenie na wykonywanie obliczen oraz zapisu probek*/ Zmienna a wykorzystana została jako “przełącznik” kanałów. Jej stan (0 lub 1) decyduje o tym dla którego sygnału wykonane zostanie przetwarzanie A/C w obsłudze przerwań. Zmienna licznik, działa jako licznik w pętlach, pilnujący, aby zebrana została odpowiednia ilość próbek. Zmienne *pamiec0 oraz *pamiec1 są wskaźnikami komórek pamięci, do których zapisywane są próbki. Zmienna *CSAD wykorzystana została jako wskaźnik zawierający adres, pod którym znajduje się przetwornik A/C. Zmienna *CSMX pełni analogiczną funkcję co poprzednia zmienna, lecz zawiera informację o adresie, pod którym znajduje się multiplekser. Zmienna licznik2 posłuŜyła jako licznik w pętli kopiującej próbki do pamięci, z której pobierane będą wartości próbek do obliczeń. Zmienna pozwolenie pilnuje, aby nie nastąpił zapis próbek w trakcie obliczeń. Jej zastosowanie zostało dokładniej wyjaśnione w dalszej części opisu. 1.1.1. Podprogram obsługi przerwania od Timera 0 Następnie zdefiniowany został podprogram obsługi przerwania od timera 0. Kod tego podprogramu przedstawiono poniŜej: void Przerw_t0(void) interrupt 1 { TH0 = 0xFB; TL0 = 0x80; CSAD = 0x2ff10; CSMX = 0x2ff18; *CSMX = 0; *CSAD = 0x01; TH1 = 0x00; TL1 = 0x00; TR1 = 1; } /*Program obslugi przerwania od timera T0*/ /*Nastawienie licznika T0*/ /*Nastawienie licznika T0*/ /*Adres przetwornika A/C */ /*Adres multipleksera*/ /*Wybór wejscia 0 na multiplekserze*/ /*Start przetwarzania A/C*/ /*Nastawienie licznika T1*/ /*Nastawienie licznika T1*/ /*Start licznika T1*/ Na początku obsługi przerwania nastawiony został licznik timera 0, aby kolejny raz mógł on odliczyć właściwy czas. Następnie wskaźnikom przypisane zostały adresy przetwornika A/C oraz multipleksera, po czym wybrane zostało wejście 0 na multiplekserze i zainicjowane zostało przetwarzanie A/C. Przed końcem obsługi przerwania nastawiony został licznik timera 1 oraz zainicjowany został jego start. 1.1.2. Podprogram obsługi przerwania od Timera 1 Tak jak w poprzednim podprogramie obsługi przerwań, tak i w tym wskaźnikom przypisane zostały adresy przetwornika A/C oraz multipleksera oraz nastawiony został licznik Timera 1, aby kolejny raz mógł on odliczyć właściwy czas. Aby wskaźniki komórek pamięci, w których zapisywane są próbki, nie przekroczyły dopuszczalnych wartości sprawdzona została wartość licznika. Zrealizowane zostało to za pomocą instrukcji warunkowej if. JeŜeli wartość licznika wynosi zero, to wartości wskaźników zostają ustawione na wartości początkowe, czyli takie, od których zaczyna się zapis próbek. Pozostała część podprogramu wykonywana jest w instrukcji warunkowej if, którą moŜna podzielić na dwie części. Pierwsza wykonywana jest dla zmiennej a równej 0, natomiast druga dla zmiennej a równej 1. void Przerw_t1(void) interrupt 3 { CSAD = 0x2ff10; CSMX = 0x2ff18; TH1 = 0x00; TL1 = 0x00; if (licznik == 0) /*Program obslugi przerwania od timera T1*/ /*Adres przetwornika A/C */ /*Adres multipleksera*/ /*Nastawienie licznika T1*/ /*Nastawienie licznika T1*/ { pamiec0 = 0x022000; pamiec1 = 0x022010; /*Zresetowanie wskaznika pamieci*/ /*Zresetowanie wskaznika pamieci*/ } if (a == 0) { *pamiec0 = *CSAD; *CSMX = 1; *CSAD = 0x01; pamiec0++; a = 1; licznik++; } /*Zapis wyniku przetwarzania A/C dla kanalu 0*/ /*Wybór wejscia 1 na multiplekserze*/ /*Start przetwarzania A/C*/ /*Inkrementacja wskaznika pamieci*/ /*Przelaczenie na kanal 1*/ /*Inkrementacja licznika*/ W pierwszej kolejności zapisany został wynik przetwarzania dla kanału 0 do komórki pamięci, którą wskazuje wskaźnik *pamiec0. Następnie wybrane zostało wejście 1 na multiplekserze oraz zainicjowane zostało przetwarzanie A/C dla tego kanału. Na koniec inkrementowany został licznik oraz wskaźnik *pamiec0. Aby przy następnym wywołaniu podprogramu obsługi przerwania od Timera 1, wykonana została druga część instrukcji warunkowej, wartość zmiennej a została zmieniona na jedynkę. Dla zmiennej a równej jeden wykonywany jest poniŜszy kod: else { a = 0; TR1 = 0; *pamiec1 = *CSAD; pamiec1++; /*Przelaczenie na kanal 0*/ /*Zatrzymanie licznika T1*/ /*Zapis wyniku przetwarzania A/C dla kanalu 1*/ /*Inkrementacja wskaznika pamieci*/ if (licznik == 16) /*Sprawdzenie, czy licznik osiagnal maksimum*/ { licznik = 0; /*Resetowanie licznika*/ if (pozwolenie == 0) /*Sprawdzenie zezwolenia na zapis probek*/ { pamiec0 = 0x022020; /*Wstepne nastawienie wskaznikow*/ pamiec1 = 0x022000; /*Wstepne nastawienie wskaznikow*/ for (licznik2 = 0; licznik2 < 32; licznik2++) /*Kopiowanie probek*/ { *pamiec0 = *pamiec1; pamiec0++; pamiec1++; } pozwolenie = 1; /*Zezwolenie na wykonywanie obliczen*/ } } } } W tej części instrukcji nastąpił zapis wyniku przetwarzania A/C dla kanału 1, zatrzymanie Timera 1, inkrementacja wskaźnika komórek pamięci do których zapisywane mają być próbki z pierwszego kanału oraz wyzerowanie zmiennej a. Dodatkowo, jeŜeli licznik osiągnie wartość równą szesnaście, zostanie wyzerowany oraz przekopiowane zostaną wszystkie wartości próbek do pamięci od adresu 2030H. Osiągnięcie przez licznik wartości równej szesnaście jest równowaŜne z zapisaniem próbek dla całego okresu sygnałów wejściowych. Operacja kopiowania odbywa się w pętli for, przy wykorzystaniu dwóch wskaźników komórek pamięci, z których jeden wskazuje pierwszą próbkę dla sygnału 0, natomiast drugi wskazuje pierwszy adres komórki od którego zapisywane mają być skopiowane wartości. Pętla wykonywana jest 32 razy, dzięki czemu kopiowane są próbki dwóch sygnałów. Kopiowanie próbek odbędzie się tylko dla zmiennej pozwolenie równej 0. Pilnuje tego funkcja if, w której odbywa się kopiowanie. Dla zmiennej pozwolenie równej 0 moŜe nastąpić kopiowanie próbek, natomiast nie mogą zostać wykonane obliczenia. Po kopiowaniu próbek zmiennej pozwolenie nadawana jest wartość 1, dla której mogą zostać wykonane obliczenia, natomiast nie moŜe nastąpić kopiowanie próbek. Po wykonaniu obliczeń zmiennej pozwolenie nadawana jest wartość 0. Początkowa wartość zmiennej pozwolenie wynosi 0, aby w pierwszej kolejności odbył się zapis próbek, który rozpoczyna cykl naprzemiennego wykonywania zapisu próbek oraz obliczeń. Takie rozwiązanie powoduje, Ŝe dane, na których wykonywane są obliczenia nie zmienią się w trakcie wykonywania obliczeń. Dodatkową zaletą takiego rozwiązania jest fakt, Ŝe obliczenia mogą trwać dowolnie długo.