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
}