Wydział Informatyki
Katedra Systemów Czasu Rzeczywistego
Laboratorium Architektury Komputerów
Data: 27.03.2008
Sprawozdanie z projektu nr.2
Grupa III:
Cieśluk Krzysztof
Kiełpiński Krzysztof
Prowadzący:
dr inż. Krzysztof Bielawski
Ocena:
Teoria
System zegarowy jest podstawowym elementem każdego urządzenia
mikroprocesorowego. W przypadku mikrokontrolerów z rodziny MSP430 system zegarowy
został znacząco rozbudowany. Takie podejście konstruktorów firmy T.I. miało za zadanie
danie programistom swobodę w operowaniu zegarami. Umiejętne poruszanie się w systemie
zegarowym umożliwia tworzenie najefektywniejszych aplikacji energooszczędnych.
Zaimplementowany został zegar podstawowy (Basic Clock) oraz Timery( w zależności od
urządzenia TimerA, bądź też TimerB). Schemat zegara podstawowego możemy zobaczyć na
rysunku :
Jak można na nim zauważyć zegar podstawowy składa się z dwóch, bądź trzech
wewnętrznych źródeł zegarowych. Są to:
· LFXT1CLK (Low Frequency/High Frequency Oscillator ) – może on być użyty z
niskoczęstotliwościowym kwarcem 32678Hz, bądź z rezonatorami z zakresu 450kHz- 8MHz
(tryb pracy wysokoczęstotliwościowej)
· XT2CLK (High Frequency Oscillator) jest używany opcjonalnie może być zasilany
standardowym kwarcem, bądź rezonatorami z zakresu 450kHz-8MHz
· DCO- wewnętrzny zegar taktujący posiadający charakterystykę RC
Powyżej wymienione źródła zegarowe taktują trzy zegary, a mianowicie są to :
· ACLK (Auxilary Clock) –zegar pomocniczy jego źródłem jest LFXT1CLK
· MCLK (Main Clock) – zegar używany przez CPU oraz system, jego źródłem może być
:LFXT1CLK, bądź XT2CLK, bądź DCO.
· SMCLK (Sub-main Clock)- jest przeznaczony do współpracy z urządzeniami peryferyjnymi,
jego źródłem może być :LFXT1CLK, bądź XT2CLK, bądź DCO.
Po restarcie urządzenie MCLK=SMCLK=DCO. Mamy jednak możliwość przełączania
MCLK, oraz SMCLK z taktowania przez DCO na taktowanie przez LFXT1CLK, bądź jeśli w
urządzeniu istnieje na XT2CLK. Takie przełączenie odbywa się wedle określonego schematu:
1. Włączenie oscylatora
2. Wyczyszczenie flagi OFIFG
3. Odczekanie około 50µs
4. Sprawdzenie stanu flagi OFIFG jeśli jest nadal ustawiona to powtórzenie kroków 1-4
5. Zmiana taktowania zegarów w rejestrze BCSCTL2
MSP430f149; posiada dwa timery - TimerA oraz TimerB. TimerA jest 16bitowym
licznikiem/zegarem, który posiada trzy zliczające/porównujące rejestry. Natomiast TimerB
również jest 16 bitowym licznikiem/zegarem, który z kolei posiada, aż siedem takich
rejestrów.
TimerA oraz TimerB posiadają identyczną budowę.
TimerA może być inkrementowany bądź dekrementowany, ma to miejsce z każdym
narastającym zboczem zegara. Może być programowo czytany oraz zapisywany. Dodatkowo
w przypadku wystąpienia przepełnienia jest generowane przerwanie. Źródłem zegara
taktującego TimerA mogą być (TACLK,ACLK,SMCLK,INCLK), dodatkowo istnieje
możliwość podziału częstotliwości sygnału taktującego przez 1,2,4,8. TimerA ma możliwość
pracowania w czterech trybach pracy, za ich ustawienie odpowiada znacznik MCx w rejestrze
TACTL. Są to tryby pracy:
· Stop – MC=00 – Timer jest zatrzymany
· Up – MC=01 – Timer cyklicznie liczy od zera do wartości zapisanej w rejestrze TACCR0
· Continuous- MC-10- Timer cyklicznie liczy od zera do wartości 0xffff
· Up/Down – MC=11- Timer cyklicznie inkrementuje od zera do wartości zapisanej w
rejestrze TACCR0 , a dekrementuje od wartości w rejestrze TACCR0 do zera
Tryb Compare jest stosowany do generowania sygnałów wyjściowych PWM, oraz do
generowania przerwań w określonym odstępie czasowy. Przerwanie jest generowane w
przypadku gdy wartość w rejestrze TAR zostanie doliczona do wartości w rejestrze TACCRx.
Wówczas to:
· Flaga CCIFG zostaje ustawiona
· Wewnętrzny sygnał EQUx równa się jeden
· Przychodzący sygnał CCI jest zatrzaskiwany w SCCI
Tryb Capture jest używany do rejestrowania zdarzeń czasowych. Jako wejścia brane są
CCIxA oraz CCIxB. Mogą być do nich podłączone sygnały zewnętrze jak również
wewnętrzne. Znacznik CMx odpowiada za rodzaj zbocza na które mamy zareagować. W
przypadku zajścia zdarzenia:
· Wartość z TAR jest kopiowana do rejestru TACCRx
· CCIFG jest ustawiana
W każdej chwili jest możliwe odczytywanie wartości sygnału wejściowego, a możemy to
czynić przez znacznik CCI.
Zadanie
Zadanie polega na stworzeniu zegara czasu rzeczywistego z kurantem co 15 sec.
Specyfikacja.
•
zegar ma być wyświetlany na LCD płytki MSP430
•
zegar nie może się spóźniać
•
kuran ma być wyraźnie słyszalny
•
należy wykorzystać przerwania
Kod
#include <msp430x14x.h>
#include "lcd.h"
#include "portyLcd.h"
unsigned int s_licznik=0;
unsigned int sekundy = 0;
unsigned int minuty = 0;
unsigned int godziny = 0;
int brzeczyk = 0; //ile tickniec
int odwroc_bity = 0;
int tick=0;
char zegar[] = "00:00:00";
void clock(void) {
char *zegar_tmp = zegar;
if(!(s_licznik%10)) {
sekundy = (s_licznik/10) % 60;
minuty = (s_licznik/600) % 60;
godziny = (s_licznik/36000) % 24;
if((sekundy%15) == 0) {
brzeczyk = (sekundy / 15)*100 ;
if(sekundy == 0)
brzeczyk = 4*100;
}
else {
brzeczyk = 0;
}
zegar[0] = godziny/10 + '0';
zegar[1] = godziny%10 + '0';
zegar[3] = minuty/10 + '0';
zegar[4] = minuty%10 + '0';
zegar[6] = sekundy/10 + '0';
zegar[7] = sekundy%10 + '0';
clearDisplay();
while(*zegar_tmp)
SEND_CHAR(*(zegar_tmp++));
}
}
void main(void) {
int i;
WDTCTL = WDTPW + WDTHOLD; //zatrzymanie watchdoga
P2DIR |= BIT1;
P4DIR |= BIT2 | BIT3;
BCSCTL1 |= XTS; //*MHz rezonator LFXT1
do { //czyszczenie flagi ofifg
IFG1 &= ~OFIFG;
for(i = 0; i < 0xFF; i++)
;
} while((IFG1 & OFIFG) == OFIFG);
BCSCTL1 |= DIVA_3; //podzielnik do ACLK, ACLK = 1Mhz
BCSCTL2 |= SELM0 | SELM1; //zegar glowny = ACLK = rezonator LFTX1
TACTL = TASSEL_1 + MC_1 + ID_2; //co czwarte narastajace zbocze timer ma
"tykniecie", tryb up
TACCTL0 = CCIE; //bedziemy generowac przerwania
TACCR0 = 25000;
TBCTL = TBSSEL_1 + MC_1 + ID_2;
TBCCTL0 = CCIE;
TBCCR0 = 500;
_EINT(); //wlaczenie przerwań
InitPortsLcd();
InitLCD();
clearDisplay();
SEND_CMD(DD_RAM_ADDR);
while(1) {
clock();
}
}
#pragma vector=TIMERA0_VECTOR
__interrupt void timer_a(void) {
s_licznik++;
}
#pragma vector=TIMERB0_VECTOR
__interrupt void timer_b(void) {
if(brzeczyk) {
tick++;//ile tickniec
tick %= 100;
brzeczyk--;
} else {
tick = 0;
}
if(brzeczyk && (tick > 50)) {
if(odwroc_bity) {
P4OUT |= BIT2;
P4OUT &= ~BIT3;
odwroc_bity = 0;
} else {
P4OUT &= ~BIT2;
P4OUT |= BIT3;
odwroc_bity = 1;
}
}
}
Wyliczenia
Timer_A generuje przerwanie co 0.1 s czyli 10 przerwań na sekundę.
Timer_B generuje przerwanie co 0.002s czyli 500 przerwań na sekundę.
Z tego wynika, że między jednym przerwaniem Timera_A a drugim występuje 50 przerwań
Timera_B.
Zmienna brzeczyk wskazuje ile razy usłyszymy dźwięk z buzzera.
wartość zmiennej brzeczyk liczba sekund ile razy usłyszymy dźwięk
400
0 4
300
45
3
200
30
2
100
15
1
Jeden dźwięk składa się z dwóch części: przerwy i grania. Każda z nich składa się z 50
przerwań Timera_B.
Zmienna tick przyjmuję wartości modulo 100 i służy do sprawdzenia czy należy
grać(tick<50 to przerwa,tick>50 to granie).
Jeśli brzeczyk przyjmnie wartość 100 to wystąpi jeden dźwięk trwający 0.2s.
Jeśli brzeczyk przyjmnie wartość 200 to wystąpią dwa dźwięki trwające 0.4s.
Jeśli brzeczyk przyjmnie wartość 300 to wystąpią trzy dźwięki trwający 0.6s.
Jeśli brzeczyk przyjmnie wartość 400 to wystąpią cztery dźwięki trwający 0.8s.
Czyli kurant nie bedzie trwał więcej niż 1 s, co nie zakłóci pracy zegara.
Wnioski:
Program działa poprawnie spełniając wszystkie założenia.