Wydział Informatyki Katedra Systemów Czasu Rzeczywistego Laboratorium Architektury Komputerów |
Data 22.12.2009 |
Ćwiczenie nr 7 Temat: ADC Zespół nr 2 1. Robert Jarocki Grupa nr 6 2. Jarosław Jastrzębski |
Prowadzący …...................... Ocena …...................... |
Zadanie:
Napisać program wyświetlający na wyświetlaczu msp430 temperaturę otoczenia.
Teoria:
Moduł konwersji analogowo-cyfrowej ADC12, przetwarza napięcie na odpowiadającą mu miarę liczbową w oparciu o metodę sukcesywnej aproksymacji SAR (ang. Successive approximation). 12-bitowy rdzeń ma monotoniczną charakterystykę, pozbawiony jest efektu „brakujących kodów” i umożliwia konwersję z szybkością do 200 ksps. Konwersji mogą podlegać sygnały z ośmiu wejść analogowych (A0-A7) multipleksowanych z portem P6 lub z czterech wewnętrznych kanałów dedykowanych: przetwornikowi temperatury, napięciu zasilającemu przetwornik (AVcc/2), zewnętrznym napięciom odniesienia (VeREF+ i VeREF-). Kanał do próbkowania wybierany jest programowo za pośrednictwem analogowego multipleksera redukującego zakłócenia powstałe we wyniku przełączania kanałów. Źródło napięcia odniesienia dla przetwarzanej próbki również wybierane jest programowo i mogą nim być następujące napięcia: zasilania, zewnętrzne lub wewnętrzne (1,5 lub 2,5V). Algorytm przetwarzania taktowany jest sygnałem ADC12CLK, otrzymanym po ewentualnym podzieleniu z jednego z podstawowych zegarów mikrokontrolera (ACLK, MCLK, SMCLK) lub przebiegiem o częstotliwości ok. 5 MHz wytworzonym we wewnętrznym oscylatorze.
Okres próbkowania ustalany jest na podstawie wspomnianego sygnału ADC12CLK lub bezpośrednio przez sygnał SHI, który inicjalizuje proces próbkowania a następnie konwersji. Przebieg SHI wytwarzany jest przez jeden z modułów czasowych lub programowo za pośrednictwem bitu ADC12SC.
Przetwornik ADC12 może pracować w jednym z czterech trybów:
Jednokrotna konwersja w pojedynczym kanale.
Wielokrotna konwersja w pojedynczym kanale.
Jednokrotna konwersja w sekwencji kanałów.
Wielokrotna konwersja w powtarzającej się sekwencji kanałów.
Schemat blokowy przetwornika analogowo-cyfrowego ADC12.
Wyniki konwersji zapisywane są w buforze utworzonym z szesnastu rejestrów 16-bitowych, przy czym cztery najstarsze bity są tylko do odczytu. Każdy z rejestrów ma odpowiadający mu rejestr sterujący, który określa kanał przetwarzania, napięcie odniesienia i ewentualnie koniec sekwencji.
Przetwornik ADC12 ma przydzielony jeden wektor przerwania wspólny dla osiemnastu źródeł, które mogą je wywołać. Żądanie przerwania może być generowane przez:
Dowolną z flag ADC12IFG0-ADC12IFG15 ustawianą ze wpisem rezultatu konwersji do korespondującego z nią rejestru w buforze wyników.
Zdarzenie polegającego na nadpisaniu któregokolwiek z rejestrów w pamięci wyników.
Zdarzenie polegające na przekroczeniu czasu konwersji.
Zdjęcie przedstawiające działanie programu:
Kod programu:
#include <msp430x14x.h>
#include "lcd.h"
#include "portyLcd.h"
#define INTERVAL 50000
unsigned int cntr;
int celsiusToFarenheit(int t)
{
int u = t % 100;
float f = 32 + 9*((t - u)/100.f + u/100.f)/5.f; // obliczanie temp.
float x = (f - (int)f)*100;
if(x - (int)x >= 0.5)
f += 0.01f;
return (int)(f * 100);
}
void show(int t)
{
int cyfra, waga=10;
Delayx100us(2);
if(t < 0) // wypisanie „-” przed wartością ujemna
{
SEND_CHAR('-');
t *= -1;
}
if(t < 10)
SEND_CHAR('0');
if(t >= 10000) // wypisanie „?” jeżeli temperatura przekroczy dopuszczalny poziom
{
SEND_CHAR('?');
return;
}
while(waga <= t)
waga *= 10;
while((waga /= 10) > 10)
{
cyfra = t / waga; // liczba która zostanie wyświetlona jako temperatura
SEND_CHAR((int)('0' + cyfra));
t -= cyfra * waga;
}
SEND_CHAR('.');
cyfra = t / waga; // pierwsza cyfra po przecinku
SEND_CHAR((int)('0' + cyfra));
t -= cyfra * waga; // druga cyfra po przecinku
SEND_CHAR((int)('0' + t));
}
void main()
{
WDTCTL = WDTPW + WDTHOLD;
InitPortsLcd();
InitLCD(); // inicjalizacja wyswietlacza
clearDisplay();
int temp;
unsigned int k;
ADC12CTL0 = ADC12ON | REFON | SHT0_15; // włączenie rdzenia i generatora napięcia odniesienia oraz wybór napięcia odniesienia
ADC12CTL1 = SHP | CSTARTADD_0; // próbkowanie impulsowe, wynik składany w ADC12MEM0
ADC12MCTL0 = INCH_10 | SREF_1; // kanał 10, źródło napięcia odniesienia - wewnętrzny generator 1,5 V
for(k = 0; k < 0x3600; k++); // czas na ustabilizowanie generatora napięcia odniesienia
CCR0 = INTERVAL; // ustala nowy okres licznika
TACTL = TASSEL_2 | ID_3 | MC_1; // źródło taktowania SMCLK dzielone przez 8, tryb UP
CCTL0 = CCIE; // uaktywnienie przerwania od TACCR0
_BIS_SR(GIE); // włączenie przerwań
ADC12CTL0 |= ENC; // uaktywnienie konwersji
while(1)
{
clearDisplay();
P2OUT ^= BIT1;
ADC12CTL0 |= ADC12SC; // start konwersji
while((ADC12CTL1 & ADC12BUSY) == ADC12BUSY); // czekanie na koniec konwersji
temp = (int)((0.366*ADC12MEM0-986)/0.0355); // wartość temperatury z dokładnością do 2 miejsc po przecinku
show(temp); // wyświetla na wyświetlaczu
SEND_CHAR(' ');
SEND_CHAR('C');
SEND_CMD(DD_RAM_ADDR2);
show(celsiusToFarenheit(temp));
SEND_CHAR(' ');
SEND_CHAR('F');
_BIS_SR(LPM0_bits); // wejście w tryb oszczędny
}
}
#pragma vector = TIMERA0_VECTOR
__interrupt void Timer_A()
{
if(++cntr == 10)
{
_BIC_SR_IRQ(LPM0_bits);
cntr = 0;
}
}