Wydział Informatyki
Katedra Systemów Czasu Rzeczywistego
Laboratorium Architektury Komputerów
Data
1.12.2009
Ćwiczenie nr 5
Temat: Clock
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 napis zawierający:
•
dzień,
•
miesiąc,
•
rok,
•
godzinę,
•
minuty.
Teoria:
Podstawowe zegary w układzie:
•
LFXT1CLK – może być używany z niskoczęstotliwościowym kwarcem 32678 Hz,
bądź z rezonatorami z zakresu 450 kHz – 8 MHz (tryb pracy
wysokoczęstotliwościowej),
•
XT2CLK – 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.
Zegary sterujące komponentami mikrokontrolera:
•
ACLK – zegar pomocniczy, jego źródłem jest LFXT1CLK,
•
MCLK – zegar używany przez CPU oraz system, jego źródłem może być
LFXT1CLK, XT2CLK, oraz DCO,
•
SMCLK – jest przeznaczony do współpracy z urządzeniami peryferyjnymi, jego
źródłem może być LFXT1CLK, XT2CLK, oraz DCO.
Ustawienie zegara początkowego:
1. Włączenie oscylatora
2. Wyczyszczenie flagi OFIFG
3. Odczekanie około 50 ns
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
Schemat blokowy zegara:
Podstawowe rejestry zegara:
Rejestr
Krótka forma
Typ rejestru
Adres
Initial State
DCO control
register
DCOCTL
Read / write
056h
060h with PUC
Basic clock
system control 1
BCSCTL1
Read / write
057h
084h with PUC
Basic clock
system control 2
BCSCTL2
Read / write
058h
Reset with POR
SFR Interrupt
enable register 1
IE1
Read / write
000h
Reset with PUC
SFR interrupt
flag register 1
IFG1
Read / write
002h
Reset with PUC
Zdjęcie wykonania programu:
Kod programu:
#include<msp430x14x.h>
#include "lcd.h"
#include "portyLcd.h"
#define PRZYCISK BIT4&P4IN
unsigned int i=0;
unsigned int dziesiatkidni=3;
unsigned int dni=0;
unsigned int dziesiatkigodz=2;
unsigned int godz=3;
unsigned int dziesiatkiminut=5;
unsigned int minuty=9;
unsigned int dziesiatkisekund=3;
unsigned int sekundy=5;
unsigned int licznik=0;
unsigned int miesiac=8;
unsigned int dziesiatkimiesiecy=0;
unsigned int tysiaceroku=2;
unsigned int setkiroku=0;
unsigned int dziesiatkiroku=0;
unsigned int rok=9;
unsigned char znak;
unsigned char literar;
char sty[12]={" sty "};
char lut[12]={" lut "};
char mar[12]={" mar "};
char kwi[12]={" kwi "};
char maj[12]={" maj "};
char cze[12]={" cze "};
char lip[12]={" lip "};
char sie[12]={" sie "};
char wrz[12]={" wrz "};
char paz[12]={" paz "};
char lis[12]={" lis "};
char gru[12]={" gru "};
void Clock(void);
void main( void )
{
znak=':';
literar='r';
P2DIR |= BIT1;
// STATUS LED
WDTCTL=WDTPW + WDTHOLD; // Wyłączenie WDT
InitPortsLcd();
// inicjalizacja portów LCD
InitLCD();
// inicjalizacja LCD
clearDisplay();
// czyszczenie wyświetlacza
// Basic Clock Module ustawiamy na ACLK(zegar 8 MHz ) i dzielimy częstotliwość przez 2 (4 MHz)
BCSCTL1 |= XTS;
// ACLK = LFXT1 = HF XTAL 8MHz
do
{
IFG1 &= ~OFIFG;
// Czyszczenie flgi OSCFault
for (i = 0xFF; i > 0; i--);
// odczekanie
}
while ((IFG1 & OFIFG) == OFIFG);
// dopóki OSCFault jest ciągle ustawiona
BCSCTL1 |= DIVA_1;
// ACLK=8 MHz/2=4 MHz
BCSCTL2 |= SELM0 | SELM1;
// MCLK= LFTX1 =ACLK
// Timer_A ustawiamy na 500 kHz
// a przerwanie generujemy co 100 ms
TACTL = TASSEL_1 + MC_1 +ID_3;
// Wybieram ACLK, ACLK/8=500kHz,tryb Up
CCTL0 = CCIE;
// włączenie przerwań od CCR0
CCR0=50000;
// podzielnik 50000: przerwanie co 100 ms
_EINT();
// włączenie przerwań
for (;;)
{
_BIS_SR(LPM3_bits);
// przejscie do trybu LPM3
Clock();
}
}
void Clock(void)
{
if (licznik %10 ==0)
// gdy mineła sekunda (10 * 100 milisekund)
{
licznik=0;
P2OUT ^=BIT1;
//zapal diodę
++sekundy;
// licz sekundy
sekundy = sekundy%10;
dziesiatkisekund = dziesiatkisekund%6;
SEND_CMD(DD_RAM_ADDR);
// gorna linia wyswietlacza
SEND_CHAR(dziesiatkidni+48); // wyswietla dziesiatki dni
SEND_CHAR(dni+48);
// wyswietla jednosci dni
SEND_CHAR(' ');
// wyswietla pustny znak (odstęp)
SEND_CHAR(' ');
// wyswietla pustny znak (odstęp)
if (dziesiatkimiesiecy==0 && miesiac==1)
for (i=0;i<=11;i++) SEND_CHAR(sty[i]); // wyswietla styczen, jesli spelnione
if (dziesiatkimiesiecy==0 && miesiac==2)
for (i=0;i<=11;i++) SEND_CHAR(lut[i]); // wyswietla luty, jesli spelnione
if (miesiac==3)
for (i=0;i<=11;i++) SEND_CHAR(mar[i]);// wyswietla marzec, jesli spelnione
if (miesiac==4)
for (i=0;i<=11;i++) SEND_CHAR(kwi[i]);// wyswietla kwiecien, jesli spelnione
if (miesiac==5)
for (i=0;i<=11;i++) SEND_CHAR(maj[i]);// wyswietla maj, jesli spelnione
if (miesiac==6)
for (i=0;i<=11;i++) SEND_CHAR(cze[i]); // wyswietla czerwiec, jeśli spelnione
if (miesiac==7)
for (i=0;i<=11;i++) SEND_CHAR(lip[i]); // wyswietla lipiec, jesli spelnione
if (miesiac==8)
for (i=0;i<=11;i++) SEND_CHAR(sie[i]); // wyswietla sierpien, jesli spelnione
if (miesiac==9)
for (i=0;i<=11;i++) SEND_CHAR(wrz[i]);// wyswietla wrzesien, jesli spelnione
if (dziesiatkimiesiecy==1 && miesiac==0)
for (i=0;i<=11;i++) SEND_CHAR(paz[i]);// wyswietla pazdziernik, jeśli spelnione
if (dziesiatkimiesiecy==1 && miesiac==1)
for (i=0;i<=11;i++) SEND_CHAR(lis[i]); // wyswietla listopad, jesli spelnione
if (dziesiatkimiesiecy==1 && miesiac==2)
for (i=0;i<=11;i++) SEND_CHAR(gru[i]);// wyswietla grudzien, jeśli spelnione
SEND_CMD(DD_RAM_ADDR2);
// dolna linia wyswietlacza
SEND_CHAR(dziesiatkigodz+48); // wyswietla dziesiatki godzin
SEND_CHAR(godz+48);
// wyswietla jednosci godzin
SEND_CHAR(znak);
// wyswietla dwukropek
SEND_CHAR(dziesiatkiminut+48); // wyswietla dziesiatki minut
SEND_CHAR(minuty+48); // wyswietla jednosci minut
SEND_CHAR(' ');
// wyswietla pustny znak (odstęp)
SEND_CHAR(' ');
// wyswietla pustny znak (odstęp)
SEND_CHAR(' ');
// wyswietla pustny znak (odstęp)
SEND_CHAR(' ');
// wyswietla pustny znak (odstęp)
SEND_CHAR(' ');
// wyswietla pustny znak (odstęp)
SEND_CHAR(' ');
// wyswietla pustny znak (odstęp)
SEND_CHAR(tysiaceroku+48); // wyswietla tysiace lat
SEND_CHAR(setkiroku+48); // wyswietla setki lat
SEND_CHAR(dziesiatkiroku+48); // wyswietla dziesiatki lat
SEND_CHAR(rok+48);
// wyswietla jednosci lat
SEND_CHAR(literar);
// wyswietla literke "r"
SEND_CMD(CUR_SHIFT_LEFT ); // wróć kursorem na początek
if(sekundy==9)
// przeskok z X9 sekund na (X+1)0 sekund
dziesiatkisekund++;
if(dziesiatkisekund==6)
// przeskok z 59 sekund na X minut 00 sekund
{
dziesiatkisekund=0;
minuty++;
}
if(minuty==10)
// przeskok z X9 minut na (X+1)0 minut
{
minuty=0;
dziesiatkiminut++;
}
if(dziesiatkiminut==6)
// przeskok z 59 minut na X godzin 00 minut
{
dziesiatkiminut=0;
godz++;
}
if(godz==10)
// przeskok z X9 godzin na (X+1)0 godzin
{
godz=0;
dziesiatkigodz++;
}
if(dziesiatkigodz==2 && godz==4 )
// przeskok z 23:59:59 na 00:00:00
{
dziesiatkigodz=0;
godz=0;
dni++;
}
if(dni==9)
// przeskok z X9 dni na (X+1)0 dni
{
dni=1;
dziesiatkidni++;
}
// przeskok z 31 dnia na dzień 1 kolejnego miesiąca (dla miesięcy: 1,3,5,7,8,10,12)
if(dziesiatkidni==3 && dni==2 && (miesiac==1 || miesiac==3 || miesiac==5 ||miesiac==7
||miesiac==8 ||(miesiac==0 && dziesiatkimiesiecy==1) ||(miesiac==2 && dziesiatkimiesiecy==1)))
{
dziesiatkidni=0;
dni=1;
miesiac++;
}
// przeskok z 30 dnia na dzień 1 kolejnego miesiąca (dla miesięcy: 4,6,9,11)
if(dziesiatkidni==3 && dni==1 && (miesiac==4 || miesiac==6 ||miesiac==7 ||miesiac==9
||(miesiac==1 && dziesiatkimiesiecy==1)))
{
dziesiatkidni=0;
dni=1;
miesiac++;
}
// przeskok z 28 dnia na dzień 1 kolejnego miesiąca (dla miesięca: 2)
if(dziesiatkidni==2 && dni==9 && miesiac==2)
{
dziesiatkidni=0;
dni=1;
miesiac++;
}
if(dziesiatkimiesiecy==0 && miesiac==10)// przeskok z 9 miesiaca na 10
{
miesiac=0;
dziesiatkimiesiecy=1;
}
if(dziesiatkimiesiecy==1 && miesiac==3) // przeskok z 12 miesiaca na 1
{
dziesiatkimiesiecy=0;
miesiac=1;
rok++;
}
if(rok==10)
// przeskok z XXX9 lat na XX(X+1)0 lat
{
rok=0;
dziesiatkiroku++;
}
if(dziesiatkiroku==10)
// przeskok z XX99 lat na X(X+1)00 lat
{
dziesiatkiroku=0;
setkiroku++;
}
if(setkiroku==10)
// przeskok z X999 lat na (X+1)000 lat
{
setkiroku=0;
tysiaceroku++;
}
}
}
// procedura obsługi przerwania od TimerA
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
++licznik;
_BIC_SR_IRQ(LPM3_bits);
// wyjście z trybu LPM3
}