Pomiar napięcia i szeregowa transmisja danych z użyciem

advertisement
Instrukcja do ćwiczenia:
Pomiar napięcia i szeregowa transmisja danych z uŜyciem
mikrokontrolera
Materiał do samodzielnego opracowania: elementy języka C: typy danych i ich deklarowanie,
operatory, instrukcje, pętle, funkcje – definiowanie, deklarowanie i wywoływanie, tablice i
wskaźniki, pliki nagłówkowe, dyrektywy kompilatora: include, define.
1. Przetwornik analogowo-cyfrowy
Przetwornik analogowo – cyfrowy zamienia sygnał analogowy (ciągły) na sygnał cyfrowy
[1]. Proces przetwarzania analogowo-cyfrowego obejmuje próbkowanie, kwantyzację i kodowanie.
Poprzez próbkowanie sygnału wejściowego określa i zapamiętuje się jego wartość chwilową w
ustalonych odstępach czasu. Wartość ta w wyniku kwantyzacji zostaje przyporządkowywana jednej
ze zbioru wartości dyskretnych. Kodowanie oznacza zapis wartości dyskretnej za pomocą ciągu ser
i jedynek (niskich i wysokich stanów logicznych).
Mikrokontroler ATMega32 został wyposaŜony w przetwornik A/C o rozdzielczości 10 bitów
(wartość chwilowa sygnału ciągłego moŜe być przyporządkowana do jednej z 210 = 1024 wartości
dyskretnych). Wejście przetwornika jest dołączone do ośmiokanałowego multipleksera,
pozwalającego na pomiar sygnałów dołączonych do wyprowadzeń portu PA (rys.1).
Rys. 1. Schemat wyprowadzeń procesora ATMega 32 [2]
Czas przetwarzania wbudowanego przetwornika moŜe wynosić do 13 do 260 µs [2]. Z tego
względu przetwornik ten nie nadaje się do pomiaru sygnałów szybkozmiennych.
2. Uniwersalny układ transmisji szeregowej (USART)
Uniwersalny, synchroniczno - asynchroniczny układ nadajnik - odbiornik (ang. USART Universal Synchronous and Asynchronous Receiver and Transmitter [2]) pozwala na wymianę
2
danych mikrokontroler – otoczenie. Wymiana danych odbywa się w trybie szeregowym. Transmisja
rozpoczyna się bitem startowym, a kończy bitem stopu (rys. 2). Kontrola bitu parzystości pozwala
na detekcję błędów transmisji. Bit parzystości przyjmuje wartość 1 jeśli suma bitów danych jest
liczbą parzystą.
Rys. 2. Schemat pakietu (ramki) danych w transmisji szeregowej [2]:
St – bit startowy, Sp – bit stopu, 1 … 8 – bity danych,
P – bit kontroli parzystości (opcjonalny), IDLE – stan oczekiwania
USART komunikuje się z otoczeniem za pomocą dwóch wyprowadzeń: RXD – odbiornik i TXD –
nadajnik.
Dołączenie mikrokontrolera do komputera PC odbywa się za pomocą portu szeregowego
(tzw. kabel null – modem zakończony wtykami dziewięciostykowymi DB 9). Ze względu na
obowiązujące standardy, port szeregowy PC uŜywa poziomów napięć ± 15 V, natomiast
mikrokontroler 0, 5 V. Konieczne jest dopasowanie poziomów napięć pomiędzy mikrokontrolerem,
a PC. Te rolę spełnia układ scalony MAX232 (rys.3).
Rys. 3. Schemat ideowy konwertera poziomów napięć
z układem MAX232
Przed nawiązaniem połączenia poprzez port szeregowy oba urządzenia powinny mieć
skonfigurowane takie same parametry transmisji, tj. prędkość transmisji (300 – 115200 bit/s), ilość
bitów danych (4…8), kontrola parzystości (lub brak), ilość bitów stopu (1 … 2), rodzaj sterowania
przepływem danych.
3. Konfiguracja przetwornika A/C
W celu uruchomienia wbudowanego w mikrokontroler przetwornika A/C naleŜy wykonać
szereg czynności konfiguracyjnych w odpowiedniej kolejności. Oznacza to zapisanie w pewnych
rejestrach mikrokontrolera odpowiednich stanów logicznych [2]. Pierwszą czynnością jest wybór
wyprowadzenia portu A, które będzie pełniło rolę wejścia przetwornika. Do określonego bitu
3
rejestru DDRA naleŜy wpisać wartość 0. Na rys. 4 pokazano przykładowo składniki (poszczególne
bity) rejestru DDRA.
Rys. 4. Składniki (bity) rejestru DDRA[2].
Następnie naleŜy wybrać częstotliwość pracy przetwornika za pomocą bitów ADPSx (gdzie
x={0… 7}) w rejestrze ADCSRA (rys. 5). Częstotliwość pracy powinna znajdować się w przedziale
50 … 200 kHz.
Rys. 5. Składniki rejestru ADCSRA [2].
Uzyskuje się ją przez podział częstotliwości zegara mikrokontrolera (16 MHz) przez 2 … 128 i
przez 13 (średnio 13 cykli zegarowych trwa przetwarzanie A/C). Ustawienia bitów ADPSx naleŜy
wykonać zgodnie z tab. 1.
Tab. 1 Wybór częstotliwości taktowania przetwornika A/C [2]
W automatycznym trybie pracy naleŜy ustalić automatyczne wyzwalanie pomiaru za
pomocą zapisania wartości 1 do bitu ADATE rejestru ADCSRA (rys. 5), oraz wyzerowanie bitów
ADTSx rejestru SFIOR (rys. 6), wybierając tryb free running (tab. 2.).
Rys. 6. Składniki rejestru SFIOR
Kolejną czynnością jest wybranie aktywnego wejścia multipleksera, poprzez zapis bitów
MUXx (tab. 3) w rejestrze ADMUX (rys. 7). Wybór powinien dotyczyć tego samego wejścia, które
zostało ustawione w rejestrze DDRA. Zapis bitów REFSx w tym samym rejestrze pozwala wybrać
napięcie odniesienia dla przetwornika: REFS1;REFS0 = 01 – napięcie zasilania mikrokontrolera
4
(+5 V), REFS1;REFS0 = 11 – źródło napięcia odniesienia wbudowane w mikrokontroler (+ 2,56
V).
Tab. 2. Ustawienia bitów ADTSx dla wyzwalania automatycznego przetwornika A/C [2]
Tab. 2. Ustawienia bitów MUXx multipleksera przetwornika A/C [2]
Rys. 7. Składniki rejestru ADMUX.
Następnie naleŜy włączyć przetwornik A/C poprzez wpisanie logicznej 1 do bitu ADEN w
rejestrze ADCSRA (rys. 5) i rozpocząć pracę automatyczną poprzez nadanie wartości 1 bitowi
ADSC w tym samym rejestrze. Wynik przetwarzania odczytuje się bezpośrednio z rejestru ADC, po
zakończeniu przetwarzania danej próbki sygnału wejściowego. Zakończenie przetwarzania jest
sygnalizowane ustawieniem wartości 1 bitu ADIF w rejestrze ADCSRA. Jeśli wspomniany bit ma
wartość 0, oznacza to, Ŝe przetwarzanie A/C jest w toku. Odczytanie w takim przypadku rejestru
ADC daje błędny wynik.
Wartość zmierzonego napięcia moŜna uzyskać ze wzoru [2]:
wynik_przetwarzania = ADC/1024.0*VREF
gdzie: VREF – wartość napięcia odniesienia, ustawiona za pomocą bitów REFS1, REFS0 (2,56 lub
5,0 V).
W manualnym trybie pracy zbędne jest ustawianie bitów ADATE i ADTSx, Nadanie
wartości 1 bitowi ADSC powoduje jednokrotne zadziałanie przetwornika A/C. Zakończenie
5
przetwarzania jest sygnalizowane wyzerowaniem tego bitu. Ponadto po zakończeniu przetwarzania
naleŜy zapisać do ADSC wartość 0. Odczyt wyniku przetwarzania moŜe nastąpić po sprawdzeniu
wartości ADSC (musi być 0).
Do konfiguracji i uruchomienia przetwornika A/C naleŜy uŜyć funkcji języka C opisanych w
p. 4 a.
4. UŜyteczne funkcje języka C
a) Wiadomości podstawowe
W celu poprawienia przejrzystości programu za pomocą dyrektywy kompilatora „define”
moŜna nadać dowolnemu elementowi programu własną nazwę:
#define zastępujący_ciąg_znaków zastępowany_ciąg_znaków
np.:
#define WEJSCIE_0 PB0
Zamiast odwoływać się w programie do małointuicyjnej nazwy PA0 oznaczającej 0 wyprowadzenie
portu B, moŜna stosować nazwę WEJSCIE_PA0 jednoznacznie określającej jaka jest rola tego
wyprowadzenia.
Przy stosowaniu w programie funkcji generujących opóźnienie czasowe wymaga się
podania kompilatorowi częstotliwości taktowania procesora. SłuŜy do tego makro:
#define F_CPU 16000000
Liczba występująca powyŜej to częstotliwość rezonatora kwarcowego w [Hz].
Z praktyki programowania mikrokontrolerów wynika, Ŝe wszelkie konfiguracje części
sprzętowej mikrokontrolera (wejścia, wyjścia, przetwornika A/C, itd.) powinny być umieszczone w
oddzielnym pliku (tzw. nagłówkowym np.: config.h) i dołączane w momencie kompilacji do
właściwego pliku z tekstem programu. Owo dołączanie uzyskuje się stosując dyrektywę
kompilatora:
#include ”nazwa.pliku”
Nazwa pliku obejmuje jego rozszerzenie (*.h).
Do zapisywania w rejestrze zera lub jedynki logicznej słuŜy makro _BV(...) [3]. Aby z niego
skorzystać naleŜy na początku programu dołączyć plik nagłówkowy io.h znajdujący się w katalogu
z bibliotekami /avr:
#include <avr/io.h>
Ustawienie jedynki logicznej na wyprowadzeniu x portu X uzyskuje się za pomocą:
PORTX |= _BV(PXx)
Dla kilku wyprowadzeń jednocześnie instrukcja powinna wyglądać:
DDRX |= _BV(PXx1)|_BV(PXx2)|_BV(PXx3)
gdzie: X = {A, B, C, D}, x = {0 … 7}, np.
PORTB |= _BV(PB0)
6
ustawia stan 1 na wyjściu 0 portu B.
Stan niski ustawia się za pomocą instrukcji
PORTX &= ~(_BV(PXx))
dla kilku wyprowadzeń jednocześnie:
PORTX &= ~(_BV(PXx1)) & ~(_BV(PXx2)) & ~(_BV(PXx3))
Konfigurację wyprowadzenia x portu X jako wejścia uzyskuje się instrukcją:
DDRX &= ~(_BV(PXx))
jako wyjścia:
DDRX |= _BV(PXx)
Odczyt stanu logicznego wejścia wykonuje się za pomocą makr:
bit_is_clear(PINX,PXx)
zwracającego wartość 1 jeŜeli stan logiczny rejestru PINX, w polu x jest równy 0, oraz:
bit_is_set(PINX,PXx)
zwracającego wartość 1 jeŜeli stan logiczny rejestru PINX, w polu x jest równy 1. PowyŜsze makra
będą dostępne w programie po dołączeniu biblioteki io.h:
#include <avr/io.h>
Do odmierzania czasu i uzyskiwania opóźnienia czasowego przydatna jest funkcja:
void _delay_ms(float liczba_ms)
Aby z niej skorzystać naleŜy dołączyć plik delay.h dyrektywą:
#include <avr/delay.h>
b) Konfiguracja i obsługa USART
Do konfiguracji i obsługi transmisji danych moŜna wykorzystać funkcje z biblioteki
RKlibAVR autorstwa Roberta Krzysztofa [4]. Do projektu naleŜy dołączyć plik kbd.h dyrektywą:
#include "uart.h"
Do projektu naleŜy dołączyć konfigurację części sprzętowej umieszczonej w pliku config.h:
#define F_CPU
16000000
#define UART_BAUD
19200
#define UART_MAX_GETSTR
8
//częstotliwość zegara w Hz
// prędkość transmisji danych
//bufor dla odbieranego łańcucha znaków
Ponadto w pliku makefile naleŜy umieścić następujący kod (zastępując istniejący tekst):
7
# Nazwa pliku z funkcją main() - BEZ ROZSZERZENIA!
TARGET = nazwa_pliku_bez_rozszerzenia
# Lista plików, których zmiana powoduje przebudowanie projektu
CONFIG = config.h
# Lista plików źródłowych w języku C
SRC = $(TARGET).c
# Lista plików źródłowych w asemblerze (rozszerzenie S - DUśE S !)
ASRC =
# typ mikrokontrolera
MCU = atmega32
# Format pliku wyjściowego (srec, ihex)
FORMAT = ihex
# Poziom optymalizacji (0, 1, 2, 3, s)
# (Uwaga: 3 nie zawsze jest najlepszym wyborem)
OPT = s
# Katalog z bibliotekami uŜytkownika
USRLIB
= C:/WinAVR-20100110/lib
# Lista plików źródłowych bibliotek w języku C
SRCLIB =
include $(USRLIB)/uart/sources
# Dodatkowe biblioteki
#
# Minimalna wersja printf
#LDFLAGS += -Wl,-u,vfprintf -lprintf_min
#
# Zmiennoprzecinkowa wersja printf (wymaga biblioteki matematycznej)
#LDFLAGS += -Wl,-u,vfprintf -lprintf_flt
#
# Biblioteka matematyczna
#LDFLAGS += -lm
include $(USRLIB)/avr_make
W celu kasowania danych wysyłanych przez port szeregowy i drukowania nowych danych w
następnej linii terminala w programie naleŜy umieścić następujące definicje:
// tablica zawierająca znaki nowej linii
prog_char ANSI_NEWLINE[] = {'\n','\r',0};
// j.w. ale czyszcząca ekran terminala
prog_char ANSI_CLEAR[] = {27,'[','H',27,'[','2','J',0};
// makra przejscia do nowej linii
8
//i kasowania linii w teminalu
#define CLEAR()
UART_putstr_P(ANSI_CLEAR)
#define NEWLINE() UART_putstr_P(ANSI_NEWLINE)
Dzięki temu kasowanie linii uzyskuje się komendą CLEAR(), a przejście do nowej linii komendą
NEWLINE().
Do inicjowania USART słuŜy funkcja:
void UART_init (void)
Odczyt pojedynczych znaków lub łańcucha znaków z portu szeregowego umoŜliwiają funkcje:
int UART_getchar ( void )
void UART_getstr ( char * s )
Wysyłanie pojedynczych znaków lub łańcucha znaków z portu szeregowego umoŜliwiają funkcje:
int UART_putchar ( char c )
void UART_putstr ( char * s )
Funkcja:
void UART_putU08 ( u08 value )
wysyła przez port szeregowy dziesiętną reprezentację liczby całkowitej.
c) Sterowanie wyświetlacza LCD
Wizualizacja wyników pomiarów przetwornika A/C moŜe być przeprowadzona z uŜyciem
wyświetlacza LCD. Do sterowania wyświetlacza LCD zostaną wykorzystane funkcje z biblioteki
tAvrLib autorstwa Tomasza Wasilczyka [5]. Biblioteka objęta jest licencją GNU LGPL v3. W
folderze z zadaniem muszą być dostępne pliki hd44780.c, hd44780.h i macros.h – naleŜy je
skopiować z katalogu tAvrLib. Drugi z plików naleŜy dołączyć do programu dyrektywą:
#include "hd44780.h"
W pliku zawierającym konfigurację części sprzętowej config.h naleŜy umieścić następujący kod:
// pod którym portem jest szyna danych
#define HD44780_DATA_GPIO X
//port wyświetlacza X = {A, B,C, D}
// jaką część portu zajmuje szyna danych:
// jeŜeli wyświetlacz dołączono do wyprowadzeń portu 4 … 7 to Y = 1
// jeŜeli wyświetlacz dołączono do wyprowadzeń portu 0 … 3 to Y = 0
#define HD44780_DATA_HIGHHALFBYTE Y
//Do jakiego portu X i nr wyprowadzenia x podłączono linię RS wyświetlacza:
#define HD44780_RS_GPIO X
#define HD44780_RS_BIT x
//j. w. ale llinia E wyświetlacza:
9
#define HD44780_E1_GPIO X
#define HD44780_E1_BIT x
//parametry wyświetlacza w znakach
#define HD44780_WIDTH 16
#define HD44780_HEIGHT 2
Plik konfiguracyjny config.h powinien być dołączony w programie (#include...) wcześniej niŜ plik
hd44780.h.
Inicjalizacji wyświetlacza dokonuje się na początku programu za pomocą funkcji:
void hd44780_init(void)
Kasowanie znaków z wyświetlacza umoŜliwia funkcja:
void hd44780_clear (void)
Wyświetlenie znaków na konkretnym polu wyświetlacza umoŜliwia funkcja:
void hd44780_goto (uint8_t x, uint8_t y)
gdzie: x - Ŝądana kolumna, y - Ŝądany wiersz, uint8_t – liczba całkowita bez znaku (typ danej).
Wyświetlenie ciągu znaków (łańcucha znaków zdefiniowanego jako tablica znaków) uzyskuje się
dzięki funkcji:
void hd44780_putStr (char *str, uint8_t length)
gdzie: *str – wskaźnik do tablicy znaków, lenght – ilość znaków do wyświetlenia.
lenght = -1 funkcja wyświetla wszystkie znaki z tablicy.
JeŜeli
d) Przetwarzanie wartości liczbowej na łańcuch znaków
Wynik przetwarzania przetwornika A/C obliczony wg wzoru podanego w p. 3 jest liczbą
zmiennoprzecinkową (w formacie float lub double). Wspomniana w p. 4 lit. C funkcja biblioteczna:
void hd44780_putStr (char *str, uint8_t length)
słuŜąca do wyświetlania danych na wyświetlaczu LCD wymaga jako pierwszego argumentu
wskaźnika do tablicy znaków: char *str. W związku z tym istnieje konieczność zamiany liczby
zmiennoprzecinkowej na łańcuch znaków. Do tego celu moŜna uŜyć funkcji:
char* dtostrf (double _val, signed char _width, unsigned char _prec, char _s)
gdzie: char* – wskaźnik do tablicy znaków, _val – liczba do konwersji, _width – ilość znaków w
wynikowej tablicy znaków _s, _prec – ilość miejsc po przecinku. Podając parametr _width naleŜy
przewidzieć w razie konieczności dwa dodatkowe miejsca na punkt dziesiętny „ , ” i znak minus.
Funkcja zwraca wskaźnik do tablicy znaków _s. UŜycie funkcji dtostrf wymaga obecności w pliku
makefile dyrektywy: MATH_LIB = -lm.
5. Przebieg ćwiczenia
W celu uruchomienia przetwornika A/C do gniazda CINCH J4 (Line IN (DC)) naleŜy
połączyć z wyprowadzeniem VCC złącza JP9 (Zasilanie). Następnie wyprowadzenie „Tlum.”
10
złącza JP7 (ADC) naleŜy dołączyć do wybranego w programie wejścia przetwornika (PA0 … PA7).
Potencjometr PR4 umoŜliwia zmianę wartości napięcia podawanego na wejście przetwornika A/C
w zakresie 0 … 5 V.
Przykładowe zadania do wykonania:
a) Napisać i uruchomić program, na wyświetlaczu LCD będzie prezentowana wartość rejestru
ADC przetwornika A/C (dwa warianty: tryb manualny i automatyczny pracy przetwornika).
b) Napisać i uruchomić program, na wyświetlaczu LCD będzie prezentowana wartość napięcia
zmierzonego przez przetwornik A/C (dwa warianty: tryb manualny i automatyczny pracy
przetwornika).
NaleŜy wykorzystać wyświetlacz LCD znajdujący się w prawej, górnej części zestawu ZL3AVR.
Jego wyprowadzenia są dostępne na złączu JP29 (LCD4bit). Wyprowadzenia złącza JP29 naleŜy
podłączyć do wyprowadzeń wybranego portu mikrokontrolera. Następnie naleŜy poinformować
kompilator o dokonanym wyborze wpisując odpowiednie ustawienia w pliku z konfiguracją
sprzętową (patrz p. 3 c)). Potencjometr PR1 słuŜy do regulacji kontrastu wyświetlacza.
Uruchomienie transmisji szeregowej musi być poprzedzone połączeniem zworką obu
wyprowadzeń złącza JP4 (RxD Enable) i podłączeniem kabla null – modem do portu szeregowego
komputera PC i złącza J6 (COM) zestawu ZL3AVR. Nastepnie na komputerze PC naleŜy
uruchomić program Termite lub HyperTerminal (Menu Start\ Programy\ Akcesoria\ Komunikacja\
HyperTerminal) i ustawić te same parametry transmisji danych, które zostały uŜyte w programie dla
mikrokontrolera (typowe ustawienia rys. 8 – program Termite). Po uruchomieniu prawidłowo
skonstruowanego programu na mikrokontrolerze na ekranie monitora komputera PC powinny się
pojawić znaki odbierane z portu szeregowego.
Przykładowe zadania do wykonania:
c) Napisać i uruchomić program, w wyniku którego na ekranie monitora komputera PC będzie
wyświetlany łańcuch znaków wysyłany przez mikrokontroler.
d) Napisać i uruchomić program, w wyniku którego na ekranie monitora komputera PC będzie
wyświetlany wynik pomiaru napięcia przez przetwornik A/C.
e) Napisać i uruchomić program, w wyniku którego na ekranie monitora komputera PC i
jednocześnie na wyświetlaczu LCD zestawu ZL3AVR będzie wyświetlany wynik pomiaru
napięcia przez przetwornik A/C.
Rys. 8. Ustawienia parametrów transmisji szeregowej
6. Literatura
[1]
M. Rusek, J. Pasierbiński, „Elementy i układy elektroniczne w pytaniach i odpowiedziach”,
WNT 1999,
[2]
„8-bit Microcontroller with 32K Bytes In-System Programmable Flash Atmega32
Atmega32L”, 2503O–AVR–07/09, www.atmel.com,
[3]
„avr-libc 1.6.7”, Generated by Doxygen 1.5.6 Wed Jan 6 12:08:48 2010,
c:\Winavr-20100110\doc\avr-libc\,
11
[4]
[5]
R. Krzysztof, Dokumentacja biblioteki RKlibAVR,
http://www.isaa.pl/download/doc_details/89-rklibavr-uniwersalna-biblioteka-dla-avr-gcc,
T. Wasilczyk, Dokumentacja biblioteki tAvrLib, http://tAvrLib.wasilczyk.pl.
Wersja z dn. 21.01.2012 r.
Download