SlideShare a Scribd company logo
ELEKTROTEHNIČKI FAKULTET U BEOGRADU
Katedra za elektroniku
Predmet: Sistemi u realnom vremenu
Projekat br.9
Student: Predmetni profesor :
Jovan Vlajić 321/2008 Dr. Ivan Popović
Predmetni asistent :
Strahinja Janković
Beograd, Februar 2016
2
Sadržaj
1. Uvod .......................................................................................................................3
2. Postavka zadatka ....................................................................................................4
2.1. Objašnjenje zadatka ..................................................................................4
3. Blok šema sistema..................................................................................................5
4. Koncept realizacije zadatka....................................................................................6
5. Realizacija projekta .............................................................................................13
6. Simulacija.............................................................................................................25
7. Zaključak..............................................................................................................26
Literatura ..................................................................................................................27
3
1. Uvod
U ovom dokumentu dato je potpuno rešenje projektnog zadatka koji se radi u okviru predmeta
“Sistemi u realnom vremenu”, predmeta sa četvrte godine osnovnih studija Elektrotehničkog
Fakulteta Univerziteta u Beogradu.
Implementacija datog projekta radi se na razvojnom okruženju koje sadrži
mikrokontroler proizvođača Texas Instruments, serije MSP430. Tačna oznaka čipa jeste
MSP430F449. U daljem tekstu podrazumevaće se da se koristi dati čip, kao i odgovarajuće,
gore spomenuto, razvojno okruženje.
4
2. Postavka zadatka
Napisati program kojim se na izlazima TB0.3-TB0.6 generišu PWM signali osnovne
učestanosti 1kHz, čiji se duty-cycle-ovi kontrolišu preko četiri kanala AD konvertora (ADC14,
ADC15, ADC8 i ADC9). Vrednost duty-cycle-a se ispisuje na LCD displeju ( jedna cifra za
svaki kanal ).
2.1. Objašnjenje zadatka
Za realizaciju projekta, na razvojnoj ploči se koriste sledeće periferije : četiri LED diode
( LD1-LD4) i četiri potenciometara ( P1 POT - P4 POT ). Izlazi TB0.3-TB0.6 su direktno
povezani na date diode,kao što su i pomenuti potenciometri povezani na odgovarajuće kanale AD
konvertora (ADC14,ADC15,ADC8,ADC9).
Zadatak je sledeći : Potrebno je napraviti da se menjanjem vrednosti potenciometara ( P1
POT-P4 POT menja osvetljaj na odgovarajućim LED diodama ( LD1-LD4 ) i da se vrednost
duty cycle-a ispisuje na LCD displeju ( jedna cifra za svaki kanal ). Ukratko, menjanjem
vrednosti na potenciometru P1, menja se osvetljaj na diodi LD1, menja se vrednost duty cycle-a i
simultano se ispisuje vrednost na LCD ekranu.
U narednoj glavi data je blok šema koja prikazuje prethodno spomenute komponente,dok
je u glavi 4 dato kompletno objašnjenje na koji način je realizovan projekat.
5
3. Blok šema sistema
Na sledećoj slici prikazan je deo šeme koji se koristi za potrebe izrade projektnog zadatka.
Vcc
Vcc
Vcc
Vcc
P1
POT
P2
POT
P3
POT
P4
POT
LD1
LD2
LD3
LD4
M
S
P
4
3
0
Ch1: Ch2:
Ch3: Ch4:
LCD displej
µc
Slika 1. Deo blok šeme koji se koristi za projekat
6
4. Koncept realizacije zadatka
U glavi 2.1 je rečeno šta se koristi od periferija na samoj razvojnoj ploči, dok su u glavi 3
date periferije simbolički prikazane. Takođe za efikasnu realizaciju potrebno je iskoristiti i
određene periferije koje se nalaze unutar samog mikrokontrolera. Od datih periferija, koriste se
TimerB i dvanaestobitan AD konvertor, ADC12. Kako su date periferije dosta“inteligentne”,
ceo projekat se može jednostavno realizovati pravilnom upotrebom i sa minimalno dodatnog
koda. Naime, TimerB može automatski generisati PWM signal, dok dvanaestobitan konvertor,
ADC12 može samostalno konvertovati naponske nivoe sa kanala i rezultate dostavljati preko
prekidnih rutina.
Osnovni koncept rada koji je primenjen u ovom projektu je sledeći :
TimerB automatski generiše PWM na osnovu vrednosti Duty Ratio-a koji se dobija
iz 5 viših bita digitalne vrednosti,koja se dobija sa AD konvertora, putem prekidnih rutina
a zatim se vrednost ispisuje na LCD ekran.
U nastavku sledi detaljnije objašnjenje načina na koji su inicijalizovane periferije
mikrokontrolera ( detalji inicijalizacije se mogu videti u izvornom kodu koji je dat u glavi 5 ),
kao i konceptualno objašnjenje projektnog rešenja.
Takt kojim se taktuje TimerB jeste ACLK ( 32768 Hz ). Kako je potrebno generisati
PWM signal sa osnovnom učestanošću od 1 kHz, izabran je režim Up Mode i u odgovarajući
registar ( TBCCR0 ) je upisan broj pomoću koga brojač broji sa zadatom učestanošću. Sada se na
jednostavan način može generisati PWM na izlazima TB3-TB6, tako što se u odgovarajućim
upravljačkim registrima ( TBCCTL3-TBCCTL6 ) podesi izlazni mod Set/Reset i u compare
registre ( TBCCR3-TBCCR6 ) se upiše željeni Duty Ratio. Na ovaj način je inicijalizovan
TimerB koji automatski generiše PWM sa zadatim Duty Ratio-m.
Naime,osnovna ideja i jeste da se dobijene vrednosti sa AD konvertora pretvore u
odgovarajući Duty Ratio i da se onda taj Duty Ratio upiše u odgovarajući compare registar
a zatim ispiše na LCD ekran.
Što se tiče inicijalizacije AD konvertora, on je podešen da na zahtev može da izvrši
konverziju sa sva četiri kanala,što je brže moguće i da odgovarajuće rezultate dostavlja glavnom
programu preko prekidnih rutina. Ova funkcionalnost je podešena tako što je izabran režim rada
Sequence-of-Channels Mode ( pomoću kojeg se sekvencijalno vrši konverzija sa sva četiri
kanala), bit MSC u registru ADC12CTL0 je postavljen na logičku jedinicu 1 ( što omogućava da
odmah nakon što je konvertovana vrednost sa jednog kanala počne konverzija sa drugog) i
ostavljeni su odgovarajući flegovi prekida. Takođe, izabrano je da se konverzija startuje
setovanjem bita ADC12SC u registru ADC12CTL0.
7
Inicijalizacija LCD-a je vršena iz podataka data sheet-a za konkretan LCD displej.
U okviru inicijalizacije LCD ekrana izvršen je ispis karaktera (ch1: ,ch2: ,ch3: ,ch4:) za sva 4
kanala na tačno definisanim pozicijama. Ispis je izvršen na ovaj način jer je to potrebno uraditi
samo jedanput.
Ono što je bitno napomenuti jeste to da je u odgovarajući registar koji generiše osnovnu
učestanost za PWM ( registar TBCCR0) upisan broj 31, iako frekvenciji od 1 kHz više odgovara
vrednost od 33 (32768/1000 = 32.678). To je urađeno da bi Duty Ratio mogao da se proračunava
na jednostavan način. Naime, broj 31 predstavlja maksimalnu vrednost koju je moguće
predstaviti sa 5 bita, što dalje znači da pomoću 5 bita možemo generisati pun opseg Duty Ratio-a,
od 0% do 100%. Zbog toga možemo od digitalizovanih vrednosti dobijenih sa potenciometara da
uzimamo viših 5 bita (konvertovane vrednosti imaju ukupno 12 značajnih bita) i one će direktno
predstavljati traženi Duty Ratio.
Sada, obzirom da je objašnjen koncept inicijalizacije, potrebno je osmisliti glavni
program. Pošto se za realizaciju ovog projekta koristi operativni sistem u realnom
vremenu,potrebno je osmisliti odgovarajuće objekte i servise kernela. Objekti i servisi kernela
koji se koriste u ovom projektu su dve task rutine ( ADTask,LCDTask ),dva reda sa porukama
( Red1,Red2 ).Pored navedenih objekata i servisa, koristi se i jedna prekidna rutina u kojoj AD
konvertor dostavlja odgovarajuće konvertovane podatke.
U nastavku sledi detaljno objašnjenje svakog objekta,pri čemu ćemo prvo objasniti redove
sa porukama,pa prekidnu rutinu i na kraju taskove.
Jedan red sa porukama ( Red1) služi da se u njega smeste vrednosti dobijene sa
odgovarajućih analognih kanala. Prekidna rutina AD konvertora šalje poruke u ovaj red kada se
završi konverzija, dok jedna od Task rutina preuzima date poruke i na osnovu njih generiše
odgovarajući DutyRatio. Jedna poruka u redu sadrži konvertovanu vrednost,dobijenu sa kanala i
oznaku kanala sa koga data vrednost dolazi. Kako se po završetku konverzija, nova konverzija
startuje tek kada su sve prethodne vrednosti očitane, dužina reda je 4 ( 4 kanala).
Drugi red sa porukama (Red2) služi za prihvatanje novih vrednosti, koje treba da se upišu
u odgovarajuće compare registre. ADTask šalje vrednosti Duty Ratio-a koji su prouzrokovani
promenom potenciometara, dok LCDTask čita date vrednosti i upisuje ih u odgovarajuće
compare registre i zatim posle izvršene komparacije vrši ispis sadržaja compare registra na
odgovarajući segment LCD ekrana. Činjenica da su LED diode direktno povezane sa compare
registrima, promena DutyRatio-a će se odraziti direktno na promenu osvetljaja odgovarajuće
LED diode ( i ovde je dužina reda 4,zbog 4 kanala).
AD konvertor generiše prekide čim se u odgovarajućem registru pojavi nova digitalna
vrednost. U prekidnoj rutini, kada se odredi sa kog kanala je vrednost konvertovana, u Red1 se
šalje poruka koja sadrži oznaku kanala, kao i samu digitalnu vrednost.
8
Sam AD konvertor vrši konverzije samo na zahtev. Kada se traže nove vrednosti,startuje
se ciklus AD konverzija, pošalju se sve konvertovane vrednosti u Red1 i onda se čeka na novi
zahtev.
ADTask je glavni task i njegova uloga je da prima i predaje poruke, da startuje AD
konverziju. Kada stigne nova poruka u Red1 ( box1 ), ADTask je preuzima i proverava da li je na
kanalu uopšte došlo do promene. Ako je došlo do promene,računa se novi DutyRatio. Zatim
pamti se stara vrednost DutyRatio-a a pošto se DutyRatio dobija iz viših 5 bita digitalne vrednosti
dobijene sa AD konvertora,može se desiti da je novodobijeni Duty Ratio kao prethodni. Iz tog
razloga,proverava se da li je došlo do promene u u DutyRatio-u. Ako je došlo do promene ,novi
DutyRatio se šalje u Red2 ( box2). U suprotnom ako nije došlo do promene DutyRatio-a,
ADTask čeka na novu poruku.
Ispituje se da li je obrađen i poslednji kanal AD konvertora ( u našem slučaju četvrti kanal
AD konvertora), ako jeste, startuje se nova konverzija. Sinhronizacija izmedju dva taska,
ADTask i LCDTask-a se vrši pomoću Delay-a.
Drugi task je LCDTask, on čeka na poruke iz Red2 (box2). Čim neka poruka stigne,čita
se iz box2 i upisuje u promenljivu DutyRat. DutyRat je struktura koja se sastoji iz vrednosti
(DutyRat.vrednost) i broja kanala (DutyRat.broj_kanala). Zatim se vrši konverzija u procente za
Duty cycle. Pomoću switch-case strukture, na osnovu DutyRat.broj_kanala pristupa se
odgovarajućem kanalu i vrši se upis vrednosti u odgovarajući compare registar kao i ispis cifara
na odgovarajuće pozicije za dati kanal na LCD ekranu.
Što se tiče prioriteta koji su dodeljeni task rutinama, ADTask je task sa većim prioritetom
od LCDTask-a, jer se u ADTask-u vrši startovanje AD konverzije i očitavanje vrednosti
potenicometara te je prioritetniji task.
U nastavku dati su flow dijagrami prekidne rutine (slika2), main programa (slika3),
ADTask-a (slika 4), LCDTask-a (slika 5) kao i dijagram sinhronizacije (slika6) .
9
Prekidna rutina
AD konvertora
Identifikacija kanala
( Potenciometra )
konvertovanog signala
Slanje poruke u Red1 ( box1 )
koja sadrži novu digitalnu
vrednost i oznaku kanala
Povratak u
glavni program
Slika 2. Flow dijagram prekidne rutine
START
Inicijalizacija OS-a
Inicijalizacija Portova
Inicijalizacija Tajmera
Kreiranje taskova
Prepuštanje kontrole OS-u
Slika 3. Flow dijagram main programa
10
START
ADTask
Startovanje AD konverzije
prviStart=1
prviStart=0?
DA
NE
Da li ima
poruke u box1?
NE
Nova vrednost
!=
stara vrednost?
DA
DA
Računaj novu vrednost
DutyRatio-a i upiši u tajmer
Pamti se stara vrednost
NE
DA
NE stariDuty
!=
DutyRatio
Pošalji trenutnu vrednost
DutyRatio-a i broj kanala u
box2
LCD Task
Broj kanala = 3 ?
DA
NE
Start konverzije
Delay = 20 ms
Slika 4. Flow dijagram ADTask-a
11
START LCD
TASK
Da li ima
poruke u box2?
NE
DA
Konverzija u procente za
duty cycle
SWITCH
(DutyRat.broj_kanala)
CASE 0 CASE 1 CASE 2 CASE 3
Upis u compare
registar
TB0CCR6
Upis u compare
registar
TB0CCR5
Upis u compare
registar
TB0CCR3
Upis u compare
registar
TB0CCR4
Ispis na
odgovarajući
segment LCD-a
Ispis na
odgovarajući
segment LCD-a
Ispis na
odgovarajući
segment LCD-a
Ispis na
odgovarajući
segment LCD-a
Delay = 20ms
Slika 5. Flow dijagram LCDTask-a
12
LCDTask
ADTask
Red1 ( box1 )
(Poruke koje šalje prekidna
rutina,a obrađuje ADTask.
Poruka sadrži broj kanala i
konvertovanu vrednost sa tog
kanala)
Prekidna rutina AD konvertora
Upisuje digitalizovane vrednosti
dobijene sa kanala AD
konvertora u Red1 (box1)
Red2 ( box2 )
Poruka koju šalje ADTask,
sadrži broj kanala i novu
konvertovanu vrednost sa tog
kanala
Čita informaciju iz Red1 (box1) i
vrši poređenje sa starom vrednošću.
Ako je različita,priprema novu
poruku i šalje u Red2 (box2)
Čita poruku iz Red2 (box2),vrši
upis dobijene vrednosti u
compare registar,zatim vrši
konverziju u procente i ispisuje
vrednosti kanala na LCD ekran
Slika 6. Dijagram sinhronizacije
13
5. Realizacija projekta
U tabeli jedan, predstavljeni su simbolički nazivi i nazivi koji se koriste u izvornom kodu.
Tabela1. Simbolički nazivi i nazivi koji se koriste u izvornom kodu
Simbolički naziv Naziv u izvornom kodu
ADTask ADTask
LCDTask LCDTask
Red1 box1
Red2 box2
U nastavku je dat izvorni kod programa.
#include "msp430.h"
#include "RTOS.h"
typedef struct Mail1_struct {
int broj_kanala;
int vrednost;
} Poruka;
Poruka DutyRat; // Za mejlove primljene od box2
Poruka Vrednost; // Za mejlove primljene od box1
Poruka ADval; // Za nove mejlove pripremljene od strane prekidne rutine
Poruka newMail;
int staraVrednost[4];
int stariDuty[4];
unsigned char prviStart = 0;
OS_STACKPTR int StackAD[200], StackLCD[200];
OS_TASK TCBad, TCBlcd;
14
OS_MAILBOX box1, box2;
int Mails1[sizeof(Poruka)*4];
int Mails2[sizeof(Poruka)*4];
int data;
int cifra1, cifra2, cifra3;
void port_init(void);
void TimerB_init(void);
void ADC_init(void);
void LCD_init(void);
int DutyRatio(int);
void Delay(int time) // Potreban zarad sinhronizacije taskova
{
int i;
for(i=0;i<time;i++)
{
asm("nop");
}
}
void write_character(char position, char c){ // Funkcija koja ispisuje karakter na određenu poziciju
char address=0x80+position;
P8OUT=(address & 0xF0)+ 0x08; // Setovanje adresa
P8OUT=0x00;
Delay(1000);
15
P8OUT=((address & 0x0F)<<4)+0x08; // Četvorobitan pristup LCD,da bi se smanjio potreban
broj pinova,radi se šiftovanje
P8OUT=0x00;
Delay(1000);
P8OUT=(c & 0xF0)+ 0x0C; // Slanje podatka
P8OUT=0x00;
Delay(1000);
P8OUT=((c & 0x0F)<<4)+0x0C; // Slanje podatka
P8OUT=0x00;
Delay(1000);
}
static void LCDTask(void){
while(1){
if (!OS_GetMailCond(&box2, &DutyRat)) { // GetMailCond čita iz mailbox2 i to što pročita upisuje u
promenjlivu DutyRat (ne blokirajuće čitanje)
data = DutyRat.vrednost;
int duty = (data*100)/31; // Konverzija u procente za duty cycle
cifra1 = duty/100 + 48;
cifra2 = (duty%100)/10 + 48;
cifra3 = duty%10 + 48;
switch(DutyRat.broj_kanala){ // , Ispis na tačno određene pozicije na LCD-u
u zavisnosti od DutyRat.broj_kanala
case 0:
TB0CCR5 = data;
write_character(44, cifra1);
write_character(45, cifra2);
16
write_character(46, cifra3);
break;
case 1:
TB0CCR6 = data;
write_character(52, cifra1);
write_character(53, cifra2);
write_character(54, cifra3);
break;
case 2:
TB0CCR3 = data;
write_character(4, cifra1);
write_character(5, cifra2);
write_character(6, cifra3);
break;
case 3:
TB0CCR4 = data;
write_character(12, cifra1);
write_character(13, cifra2);
write_character(14, cifra3);
break;
default:
break;
}
}
OS_Delay(20);
}
}
17
static void ADTask(void){
while(1){
if (!prviStart){
ADC12CTL0 |= ADC12SC; // Startovanje AD konverzije
prviStart = 1;
}
if (!OS_GetMailCond(&box1, &Vrednost)) { // Ako nešto ima u box1, idemo dalje, ako ne – ništa
if (staraVrednost[Vrednost.broj_kanala]!=Vrednost.vrednost) { // Ispitujemo da li je vrednost AD
konvertora različita? Ako jeste , računaj,ako nije izadji
newMail.vrednost=DutyRatio(Vrednost.vrednost); // Računanje nove vrednosti Dutyratio, koja
se upisuje u tajmer
staraVrednost[Vrednost.broj_kanala]=Vrednost.vrednost; // Pamti se stara vrednost
if (stariDuty[Vrednost.broj_kanala]!=newMail.vrednost) { // Proveravamo vrednost koja treba da
se upiše u tajmer,ako je različita šalji LCD tasku, ako nije izađi iz taska
newMail.broj_kanala=Vrednost.broj_kanala; // Pripremi novi mejl
stariDuty[Vrednost.broj_kanala]=newMail.vrednost; // Sačuvaj staru vrednost za upis u tajmer
OS_PutMail(&box2, &newMail); // Šalje obe vrednosti mailboxa ( podatak se sastoji iz dva
dela-broja kanala i vrednosti od 0-31 za tajmer)
}
}
if (Vrednost.broj_kanala == 3) // Pitamo da li je Task obradio sve kanale konvertora
ADC12CTL0 |= ADC12SC; // Ako je obradio sve kanale konvertora startuj konverziju
}
OS_Delay(20); // Suspenduj ADTask, kako bi LCD task mogao da se izvrši
}
}
18
#pragma vector=ADC12_VECTOR // Prekidna rutina AD konvertora
__interrupt void ADC12_ISR(void)
{
OS_EnterInterrupt();
switch(ADC12IV)
{
case 0: break; // Vector 0: No interrupt
case 2: break; // Vector 2: ADC overflow
case 4: break; // Vector 4: ADC timing overflow
case 6: // Vector 6: ADC12IFG0
ADval.broj_kanala=0;
ADval.vrednost=ADC12MEM0;
OS_PutMailCond(&box1, &ADval);
break;
case 8:
ADval.broj_kanala=1;
ADval.vrednost=ADC12MEM1;
OS_PutMailCond(&box1, &ADval);
break;
case 10:
ADval.broj_kanala=2;
ADval.vrednost=ADC12MEM2;
OS_PutMailCond(&box1, &ADval);
break; // Vector 10: ADC12IFG2
case 12:
ADval.broj_kanala=3;
19
ADval.vrednost=ADC12MEM3; // ADC12MEM3 sadrži rezultat AD konverzije (0-4095 jer je
12 bitan konvertor)
OS_PutMailCond(&box1, &ADval);
break; // Vector 12: ADC12IFG3
case 14: break; // Vector 14: ADC12IFG4
case 16: break; // Vector 16: ADC12IFG5
case 18: break; // Vector 18: ADC12IFG6
case 20: break; // Vector 20: ADC12IFG7
case 22: break; // Vector 22: ADC12IFG8
case 24: break; // Vector 24: ADC12IFG9
case 26: break; // Vector 26: ADC12IFG10
case 28: break; // Vector 28: ADC12IFG11
case 30: break; // Vector 30: ADC12IFG12
case 32: break; // Vector 32: ADC12IFG13
case 34: break; // Vector 34: ADC12IFG14
default: break;
}
OS_LeaveInterrupt();
}
void port_init(){ // Inicijalizacija portova
P7SEL |= 0xC0; // Potenciometri
P5SEL |= 0x03; // Potenciometri
P4SEL |= 0x78; // LED
P4DIR |= 0x78; // LED
P8OUT=0x00; // LCD
P8DIR=0xFC // LCD
20
}
void TimerB_init(){ // Inicijalizacija Tajmera
TB0CCR0 = 31; // Definišemo period tajmera
TB0CCTL3 = OUTMOD_7; // Mod rada tajmera
TB0CCTL4 = OUTMOD_7;
TB0CCTL5 = OUTMOD_7;
TB0CCTL6 = OUTMOD_7;
TB0CCR3 = 6;
TB0CCR4 = 17;
TB0CCR5 = 17;
TB0CCR6 = 17;
TB0CTL = TBSSEL_1 + MC_1; // Koji takt dolazi do tajmera i da broji nagore ( ACLK)
}
void ADC12_init(){ // Inicijalizacija AD konvertora
ADC12CTL0 = ADC12ON+ADC12MSC; // ADC12MSC startuje višestruku AD konverziju
ADC12CTL1 = ADC12SHS_0 + ADC12CONSEQ_1 + ADC12SHP; // startovanje bitom ADC12SC,
ADC12CONSEQ_1 znači da se sekvenca kanala vrši jedanput
ADC12MCTL0 = ADC12INCH_8;
ADC12MCTL1 = ADC12INCH_9;
ADC12MCTL2 = ADC12INCH_14;
ADC12MCTL3 = ADC12INCH_15 + ADC12EOS;
ADC12IE |= ADC12IE0 + ADC12IE1 + ADC12IE2 + ADC12IE3; // Omogućava prekidnu rutinu AD
konvertora
ADC12CTL0 |= ADC12ENC; // Omogućava konverziju AD konvertora
}
21
void LCD_init() // Inicijalizacija LCD-a
{
Delay(10000);
P8OUT=0x38;
P8OUT=0x30;
Delay(5000);
P8OUT=0x38;
P8OUT=0x30;
Delay(100);
P8OUT=0x38;
P8OUT=0x30;
Delay(1000);
P8OUT=0x28; // Function set (4-bit interface)
P8OUT=0x20;
Delay(1000);
P8OUT=0x28; // Function set (4-bit interface)
P8OUT=0x20;
Delay(1000);
P8OUT=0x88;
P8OUT=0x80;
Delay(1000);
22
P8OUT=0x08; // Display off
P8OUT=0x00;
Delay(1000);
P8OUT=0x88;
P8OUT=0x80;
Delay(1000);
P8OUT=0x08; // Display clear
P8OUT=0x00;
Delay(1000);
P8OUT=0x18;
P8OUT=0x10;
Delay(1000);
P8OUT=0x08; // Entry mode set
P8OUT=0x00;
Delay(1000);
P8OUT=0x68;
P8OUT=0x60;
Delay(1000);
P8OUT=0x08; // Display on
P8OUT=0x00;
23
Delay(1000);
P8OUT=0xE8;
P8OUT=0xE0;
Delay(1000);
P8OUT=0x08; // Display clear
P8OUT=0x00;
Delay(1000);
P8OUT=0x18;
P8OUT=0x10;
Delay(1000);
write_character(0, 'C'); // U okviru inicijalizacije LCD-a vršimo ispis na LCD ekran za
kanale ( to radimo samo jedanput )
write_character(1, 'h');
write_character(2, '1');
write_character(3, ':');
write_character(8, 'C');
write_character(9, 'h');
write_character(10, '2');
write_character(11, ':');
write_character(40, 'C');
write_character(41, 'h');
write_character(42, '3');
write_character(43, ':');
write_character(48, 'C');
24
write_character(49, 'h');
write_character(50, '4');
write_character(51, ':');
}
int DutyRatio(int result){
return result >> 7; // Samo viših 5 bita konverzije koristimo za računanje Duty cycle-a zbog
našeg podešenog tajmeraB (0-31,tj 5 bita)
}
int main(void) { // Glavni program sa standardnim funkcijama
OS_IncDI(); // Initially disable interrupts
OS_InitKern(); // Initialize OS
OS_InitHW(); // Initialize Hardware for OS
port_init(); // Inicijalizacija portova
TimerB_init(); // Inicijalizacija tajmeraB
ADC12_init(); // Inicijalizacija AD konvertora
LCD_init(); // Inicijalizacija LCD-a
__bis_SR_register(GIE);
OS_CREATETASK(&TCBad, "AD", ADTask, 150, StackAD);
OS_CREATETASK(&TCBlcd, "LCD", LCDTask, 100, StackLCD);
OS_CREATEMB(&box1, sizeof(Poruka), 4, &Mails1);
OS_CREATEMB(&box2, sizeof(Poruka), 4, &Mails2);
OS_DecRI(); //Enable interupts to send string
OS_SendString("embOS will start ...");
OS_Start(); //Start multitasking
return 0;
}
25
6. Simulacija
Zbog složenosti korišćenih periferija, ovu aplikaciju je dosta nezahvalno simulirati u
simulatoru. Iz tog razloga je ovaj program testiran isključivo u realnom radu na ploči i
debagovan je na licu mesta.Većih problema pri izradi aplikacije nije bilo osim par grešaka u
pretpostavci studenta koje su bile nađene i otklonjene. Program je testiran na primeru
promene jednog i više potenciometara istovremeno dok su ispis na LCD ekran i osvetljaj
diode pravilno reagovali na promene potenciometara. Program je takođe testiran za svaki
potenciometar posebno od nulte vrednosti do maksimalne gde su takođe ispis odgovarajućeg
kanala i osvetljaj odgovarajuće diode bili tačni što je predmeni asistent potvrdio.
26
7. Zaključak
Iz prethodno izloženog može se videti jedan klasičan primer rada sa taskovima.
Očigledne su prednosti koje operativni sistem pruža sa svojim API funkcijama, koje se
ispoljavaju u jednostavnosti pisanja koda, dobroj preglednosti, a samim tim i boljoj kontroli nad celim
sistemom. Takođe, može se primetiti i jedna očigledna mana vezana za korišćenje gotovih API funkcija,
koja se odnosi na vreme izvršavanja koje može biti dosta dugo.
Na osnovu rezultata simulacije mogu se uočiti neki specifični detalji koji bi možda mogli
drugačije da se realizuju.
Na primer, spomenuto je da se poruke u Red1 smeštaju onim redosledom kojim se dobijaju
konvertovane vrednosti sa kanala. Znači, prvo se smešta konvertovana vrednost sa kanala 1, pa onda sa
kanala 2, itd. Imavši to u vidu moguće je pojednostaviti poruke reda Red1, tako da ne sadrže
oznaku kanala. Međutim, iako na prvi pogled to zaista izgleda logično, ovde prikazan način realizacije
je dosta sigurniji jer ne ostavlja mogućnost greške. Takođe, nije potrebno pisati dodatni kod koji bi
morao da pamti koja je poruka prethodno primljenja i sl.
27
Literatura
[1] IAR Systems, http://www.iar.com/
[2] SEGGER http://www.segger.com/
[3] Texas Instruments, MSP430F449
http://focus.ti.com/docs/prod/folders/print/msp430f449.html
[4] Razvojno okruženje koje se koristi za implementaciju projekta
http://tnt.etf.rs/~oe4srv

More Related Content

Similar to PWM control of LED-diodes on the MSP430x series development board

sinhroni i asinhroni prenos podataka.pdf
sinhroni i asinhroni prenos podataka.pdfsinhroni i asinhroni prenos podataka.pdf
sinhroni i asinhroni prenos podataka.pdf
StanisaJankovic1
 
Simulacija digitalnih modulacionih postupaka (Diplomski rad)
Simulacija digitalnih modulacionih postupaka (Diplomski rad)Simulacija digitalnih modulacionih postupaka (Diplomski rad)
Simulacija digitalnih modulacionih postupaka (Diplomski rad)Nenad Milo?evi?
 
Pitanja Maturski Fe
Pitanja Maturski FePitanja Maturski Fe
Pitanja Maturski Feguest199a1d0
 
Embedded systems : D/A converters
Embedded systems : D/A convertersEmbedded systems : D/A converters
Embedded systems : D/A converters
Jovan Vlajic
 
zavrsni
zavrsnizavrsni
zavrsnixenosb
 
IT9-L3.pptx
IT9-L3.pptxIT9-L3.pptx
IT9-L3.pptx
AleksandarSpasic5
 
OIR9-L2.pptx
OIR9-L2.pptxOIR9-L2.pptx
OIR9-L2.pptx
AleksandarSpasic5
 
PROGRAMIRANJE-C-IIRAZRED.pdf
PROGRAMIRANJE-C-IIRAZRED.pdfPROGRAMIRANJE-C-IIRAZRED.pdf
PROGRAMIRANJE-C-IIRAZRED.pdf
MilicaJovanovi14
 
Računarske mreže - Miodrag Mijajlović - Žaklina Eftimovski
Računarske mreže - Miodrag Mijajlović - Žaklina EftimovskiRačunarske mreže - Miodrag Mijajlović - Žaklina Eftimovski
Računarske mreže - Miodrag Mijajlović - Žaklina Eftimovski
NašaŠkola.Net
 
Advantages of Practical Application of TeleCAD-GIS in Calculating Influence o...
Advantages of Practical Application of TeleCAD-GIS in Calculating Influence o...Advantages of Practical Application of TeleCAD-GIS in Calculating Influence o...
Advantages of Practical Application of TeleCAD-GIS in Calculating Influence o...
Maksim Sestic
 
CCNA - Predavanje
CCNA - PredavanjeCCNA - Predavanje
CCNA - Predavanje
Nikola Damjanović
 
Revenge
RevengeRevenge
RevengeBole98
 

Similar to PWM control of LED-diodes on the MSP430x series development board (15)

sinhroni i asinhroni prenos podataka.pdf
sinhroni i asinhroni prenos podataka.pdfsinhroni i asinhroni prenos podataka.pdf
sinhroni i asinhroni prenos podataka.pdf
 
Simulacija digitalnih modulacionih postupaka (Diplomski rad)
Simulacija digitalnih modulacionih postupaka (Diplomski rad)Simulacija digitalnih modulacionih postupaka (Diplomski rad)
Simulacija digitalnih modulacionih postupaka (Diplomski rad)
 
Pitanja Maturski Fe
Pitanja Maturski FePitanja Maturski Fe
Pitanja Maturski Fe
 
Embedded systems : D/A converters
Embedded systems : D/A convertersEmbedded systems : D/A converters
Embedded systems : D/A converters
 
zavrsni
zavrsnizavrsni
zavrsni
 
IT9-L3.pptx
IT9-L3.pptxIT9-L3.pptx
IT9-L3.pptx
 
Uor pitanja
Uor pitanjaUor pitanja
Uor pitanja
 
OIR9-L2.pptx
OIR9-L2.pptxOIR9-L2.pptx
OIR9-L2.pptx
 
PROGRAMIRANJE-C-IIRAZRED.pdf
PROGRAMIRANJE-C-IIRAZRED.pdfPROGRAMIRANJE-C-IIRAZRED.pdf
PROGRAMIRANJE-C-IIRAZRED.pdf
 
Računarske mreže - Miodrag Mijajlović - Žaklina Eftimovski
Računarske mreže - Miodrag Mijajlović - Žaklina EftimovskiRačunarske mreže - Miodrag Mijajlović - Žaklina Eftimovski
Računarske mreže - Miodrag Mijajlović - Žaklina Eftimovski
 
Algoritmi
AlgoritmiAlgoritmi
Algoritmi
 
Advantages of Practical Application of TeleCAD-GIS in Calculating Influence o...
Advantages of Practical Application of TeleCAD-GIS in Calculating Influence o...Advantages of Practical Application of TeleCAD-GIS in Calculating Influence o...
Advantages of Practical Application of TeleCAD-GIS in Calculating Influence o...
 
CCNA - Predavanje
CCNA - PredavanjeCCNA - Predavanje
CCNA - Predavanje
 
Mq listener
Mq listenerMq listener
Mq listener
 
Revenge
RevengeRevenge
Revenge
 

PWM control of LED-diodes on the MSP430x series development board

  • 1. ELEKTROTEHNIČKI FAKULTET U BEOGRADU Katedra za elektroniku Predmet: Sistemi u realnom vremenu Projekat br.9 Student: Predmetni profesor : Jovan Vlajić 321/2008 Dr. Ivan Popović Predmetni asistent : Strahinja Janković Beograd, Februar 2016
  • 2. 2 Sadržaj 1. Uvod .......................................................................................................................3 2. Postavka zadatka ....................................................................................................4 2.1. Objašnjenje zadatka ..................................................................................4 3. Blok šema sistema..................................................................................................5 4. Koncept realizacije zadatka....................................................................................6 5. Realizacija projekta .............................................................................................13 6. Simulacija.............................................................................................................25 7. Zaključak..............................................................................................................26 Literatura ..................................................................................................................27
  • 3. 3 1. Uvod U ovom dokumentu dato je potpuno rešenje projektnog zadatka koji se radi u okviru predmeta “Sistemi u realnom vremenu”, predmeta sa četvrte godine osnovnih studija Elektrotehničkog Fakulteta Univerziteta u Beogradu. Implementacija datog projekta radi se na razvojnom okruženju koje sadrži mikrokontroler proizvođača Texas Instruments, serije MSP430. Tačna oznaka čipa jeste MSP430F449. U daljem tekstu podrazumevaće se da se koristi dati čip, kao i odgovarajuće, gore spomenuto, razvojno okruženje.
  • 4. 4 2. Postavka zadatka Napisati program kojim se na izlazima TB0.3-TB0.6 generišu PWM signali osnovne učestanosti 1kHz, čiji se duty-cycle-ovi kontrolišu preko četiri kanala AD konvertora (ADC14, ADC15, ADC8 i ADC9). Vrednost duty-cycle-a se ispisuje na LCD displeju ( jedna cifra za svaki kanal ). 2.1. Objašnjenje zadatka Za realizaciju projekta, na razvojnoj ploči se koriste sledeće periferije : četiri LED diode ( LD1-LD4) i četiri potenciometara ( P1 POT - P4 POT ). Izlazi TB0.3-TB0.6 su direktno povezani na date diode,kao što su i pomenuti potenciometri povezani na odgovarajuće kanale AD konvertora (ADC14,ADC15,ADC8,ADC9). Zadatak je sledeći : Potrebno je napraviti da se menjanjem vrednosti potenciometara ( P1 POT-P4 POT menja osvetljaj na odgovarajućim LED diodama ( LD1-LD4 ) i da se vrednost duty cycle-a ispisuje na LCD displeju ( jedna cifra za svaki kanal ). Ukratko, menjanjem vrednosti na potenciometru P1, menja se osvetljaj na diodi LD1, menja se vrednost duty cycle-a i simultano se ispisuje vrednost na LCD ekranu. U narednoj glavi data je blok šema koja prikazuje prethodno spomenute komponente,dok je u glavi 4 dato kompletno objašnjenje na koji način je realizovan projekat.
  • 5. 5 3. Blok šema sistema Na sledećoj slici prikazan je deo šeme koji se koristi za potrebe izrade projektnog zadatka. Vcc Vcc Vcc Vcc P1 POT P2 POT P3 POT P4 POT LD1 LD2 LD3 LD4 M S P 4 3 0 Ch1: Ch2: Ch3: Ch4: LCD displej µc Slika 1. Deo blok šeme koji se koristi za projekat
  • 6. 6 4. Koncept realizacije zadatka U glavi 2.1 je rečeno šta se koristi od periferija na samoj razvojnoj ploči, dok su u glavi 3 date periferije simbolički prikazane. Takođe za efikasnu realizaciju potrebno je iskoristiti i određene periferije koje se nalaze unutar samog mikrokontrolera. Od datih periferija, koriste se TimerB i dvanaestobitan AD konvertor, ADC12. Kako su date periferije dosta“inteligentne”, ceo projekat se može jednostavno realizovati pravilnom upotrebom i sa minimalno dodatnog koda. Naime, TimerB može automatski generisati PWM signal, dok dvanaestobitan konvertor, ADC12 može samostalno konvertovati naponske nivoe sa kanala i rezultate dostavljati preko prekidnih rutina. Osnovni koncept rada koji je primenjen u ovom projektu je sledeći : TimerB automatski generiše PWM na osnovu vrednosti Duty Ratio-a koji se dobija iz 5 viših bita digitalne vrednosti,koja se dobija sa AD konvertora, putem prekidnih rutina a zatim se vrednost ispisuje na LCD ekran. U nastavku sledi detaljnije objašnjenje načina na koji su inicijalizovane periferije mikrokontrolera ( detalji inicijalizacije se mogu videti u izvornom kodu koji je dat u glavi 5 ), kao i konceptualno objašnjenje projektnog rešenja. Takt kojim se taktuje TimerB jeste ACLK ( 32768 Hz ). Kako je potrebno generisati PWM signal sa osnovnom učestanošću od 1 kHz, izabran je režim Up Mode i u odgovarajući registar ( TBCCR0 ) je upisan broj pomoću koga brojač broji sa zadatom učestanošću. Sada se na jednostavan način može generisati PWM na izlazima TB3-TB6, tako što se u odgovarajućim upravljačkim registrima ( TBCCTL3-TBCCTL6 ) podesi izlazni mod Set/Reset i u compare registre ( TBCCR3-TBCCR6 ) se upiše željeni Duty Ratio. Na ovaj način je inicijalizovan TimerB koji automatski generiše PWM sa zadatim Duty Ratio-m. Naime,osnovna ideja i jeste da se dobijene vrednosti sa AD konvertora pretvore u odgovarajući Duty Ratio i da se onda taj Duty Ratio upiše u odgovarajući compare registar a zatim ispiše na LCD ekran. Što se tiče inicijalizacije AD konvertora, on je podešen da na zahtev može da izvrši konverziju sa sva četiri kanala,što je brže moguće i da odgovarajuće rezultate dostavlja glavnom programu preko prekidnih rutina. Ova funkcionalnost je podešena tako što je izabran režim rada Sequence-of-Channels Mode ( pomoću kojeg se sekvencijalno vrši konverzija sa sva četiri kanala), bit MSC u registru ADC12CTL0 je postavljen na logičku jedinicu 1 ( što omogućava da odmah nakon što je konvertovana vrednost sa jednog kanala počne konverzija sa drugog) i ostavljeni su odgovarajući flegovi prekida. Takođe, izabrano je da se konverzija startuje setovanjem bita ADC12SC u registru ADC12CTL0.
  • 7. 7 Inicijalizacija LCD-a je vršena iz podataka data sheet-a za konkretan LCD displej. U okviru inicijalizacije LCD ekrana izvršen je ispis karaktera (ch1: ,ch2: ,ch3: ,ch4:) za sva 4 kanala na tačno definisanim pozicijama. Ispis je izvršen na ovaj način jer je to potrebno uraditi samo jedanput. Ono što je bitno napomenuti jeste to da je u odgovarajući registar koji generiše osnovnu učestanost za PWM ( registar TBCCR0) upisan broj 31, iako frekvenciji od 1 kHz više odgovara vrednost od 33 (32768/1000 = 32.678). To je urađeno da bi Duty Ratio mogao da se proračunava na jednostavan način. Naime, broj 31 predstavlja maksimalnu vrednost koju je moguće predstaviti sa 5 bita, što dalje znači da pomoću 5 bita možemo generisati pun opseg Duty Ratio-a, od 0% do 100%. Zbog toga možemo od digitalizovanih vrednosti dobijenih sa potenciometara da uzimamo viših 5 bita (konvertovane vrednosti imaju ukupno 12 značajnih bita) i one će direktno predstavljati traženi Duty Ratio. Sada, obzirom da je objašnjen koncept inicijalizacije, potrebno je osmisliti glavni program. Pošto se za realizaciju ovog projekta koristi operativni sistem u realnom vremenu,potrebno je osmisliti odgovarajuće objekte i servise kernela. Objekti i servisi kernela koji se koriste u ovom projektu su dve task rutine ( ADTask,LCDTask ),dva reda sa porukama ( Red1,Red2 ).Pored navedenih objekata i servisa, koristi se i jedna prekidna rutina u kojoj AD konvertor dostavlja odgovarajuće konvertovane podatke. U nastavku sledi detaljno objašnjenje svakog objekta,pri čemu ćemo prvo objasniti redove sa porukama,pa prekidnu rutinu i na kraju taskove. Jedan red sa porukama ( Red1) služi da se u njega smeste vrednosti dobijene sa odgovarajućih analognih kanala. Prekidna rutina AD konvertora šalje poruke u ovaj red kada se završi konverzija, dok jedna od Task rutina preuzima date poruke i na osnovu njih generiše odgovarajući DutyRatio. Jedna poruka u redu sadrži konvertovanu vrednost,dobijenu sa kanala i oznaku kanala sa koga data vrednost dolazi. Kako se po završetku konverzija, nova konverzija startuje tek kada su sve prethodne vrednosti očitane, dužina reda je 4 ( 4 kanala). Drugi red sa porukama (Red2) služi za prihvatanje novih vrednosti, koje treba da se upišu u odgovarajuće compare registre. ADTask šalje vrednosti Duty Ratio-a koji su prouzrokovani promenom potenciometara, dok LCDTask čita date vrednosti i upisuje ih u odgovarajuće compare registre i zatim posle izvršene komparacije vrši ispis sadržaja compare registra na odgovarajući segment LCD ekrana. Činjenica da su LED diode direktno povezane sa compare registrima, promena DutyRatio-a će se odraziti direktno na promenu osvetljaja odgovarajuće LED diode ( i ovde je dužina reda 4,zbog 4 kanala). AD konvertor generiše prekide čim se u odgovarajućem registru pojavi nova digitalna vrednost. U prekidnoj rutini, kada se odredi sa kog kanala je vrednost konvertovana, u Red1 se šalje poruka koja sadrži oznaku kanala, kao i samu digitalnu vrednost.
  • 8. 8 Sam AD konvertor vrši konverzije samo na zahtev. Kada se traže nove vrednosti,startuje se ciklus AD konverzija, pošalju se sve konvertovane vrednosti u Red1 i onda se čeka na novi zahtev. ADTask je glavni task i njegova uloga je da prima i predaje poruke, da startuje AD konverziju. Kada stigne nova poruka u Red1 ( box1 ), ADTask je preuzima i proverava da li je na kanalu uopšte došlo do promene. Ako je došlo do promene,računa se novi DutyRatio. Zatim pamti se stara vrednost DutyRatio-a a pošto se DutyRatio dobija iz viših 5 bita digitalne vrednosti dobijene sa AD konvertora,može se desiti da je novodobijeni Duty Ratio kao prethodni. Iz tog razloga,proverava se da li je došlo do promene u u DutyRatio-u. Ako je došlo do promene ,novi DutyRatio se šalje u Red2 ( box2). U suprotnom ako nije došlo do promene DutyRatio-a, ADTask čeka na novu poruku. Ispituje se da li je obrađen i poslednji kanal AD konvertora ( u našem slučaju četvrti kanal AD konvertora), ako jeste, startuje se nova konverzija. Sinhronizacija izmedju dva taska, ADTask i LCDTask-a se vrši pomoću Delay-a. Drugi task je LCDTask, on čeka na poruke iz Red2 (box2). Čim neka poruka stigne,čita se iz box2 i upisuje u promenljivu DutyRat. DutyRat je struktura koja se sastoji iz vrednosti (DutyRat.vrednost) i broja kanala (DutyRat.broj_kanala). Zatim se vrši konverzija u procente za Duty cycle. Pomoću switch-case strukture, na osnovu DutyRat.broj_kanala pristupa se odgovarajućem kanalu i vrši se upis vrednosti u odgovarajući compare registar kao i ispis cifara na odgovarajuće pozicije za dati kanal na LCD ekranu. Što se tiče prioriteta koji su dodeljeni task rutinama, ADTask je task sa većim prioritetom od LCDTask-a, jer se u ADTask-u vrši startovanje AD konverzije i očitavanje vrednosti potenicometara te je prioritetniji task. U nastavku dati su flow dijagrami prekidne rutine (slika2), main programa (slika3), ADTask-a (slika 4), LCDTask-a (slika 5) kao i dijagram sinhronizacije (slika6) .
  • 9. 9 Prekidna rutina AD konvertora Identifikacija kanala ( Potenciometra ) konvertovanog signala Slanje poruke u Red1 ( box1 ) koja sadrži novu digitalnu vrednost i oznaku kanala Povratak u glavni program Slika 2. Flow dijagram prekidne rutine START Inicijalizacija OS-a Inicijalizacija Portova Inicijalizacija Tajmera Kreiranje taskova Prepuštanje kontrole OS-u Slika 3. Flow dijagram main programa
  • 10. 10 START ADTask Startovanje AD konverzije prviStart=1 prviStart=0? DA NE Da li ima poruke u box1? NE Nova vrednost != stara vrednost? DA DA Računaj novu vrednost DutyRatio-a i upiši u tajmer Pamti se stara vrednost NE DA NE stariDuty != DutyRatio Pošalji trenutnu vrednost DutyRatio-a i broj kanala u box2 LCD Task Broj kanala = 3 ? DA NE Start konverzije Delay = 20 ms Slika 4. Flow dijagram ADTask-a
  • 11. 11 START LCD TASK Da li ima poruke u box2? NE DA Konverzija u procente za duty cycle SWITCH (DutyRat.broj_kanala) CASE 0 CASE 1 CASE 2 CASE 3 Upis u compare registar TB0CCR6 Upis u compare registar TB0CCR5 Upis u compare registar TB0CCR3 Upis u compare registar TB0CCR4 Ispis na odgovarajući segment LCD-a Ispis na odgovarajući segment LCD-a Ispis na odgovarajući segment LCD-a Ispis na odgovarajući segment LCD-a Delay = 20ms Slika 5. Flow dijagram LCDTask-a
  • 12. 12 LCDTask ADTask Red1 ( box1 ) (Poruke koje šalje prekidna rutina,a obrađuje ADTask. Poruka sadrži broj kanala i konvertovanu vrednost sa tog kanala) Prekidna rutina AD konvertora Upisuje digitalizovane vrednosti dobijene sa kanala AD konvertora u Red1 (box1) Red2 ( box2 ) Poruka koju šalje ADTask, sadrži broj kanala i novu konvertovanu vrednost sa tog kanala Čita informaciju iz Red1 (box1) i vrši poređenje sa starom vrednošću. Ako je različita,priprema novu poruku i šalje u Red2 (box2) Čita poruku iz Red2 (box2),vrši upis dobijene vrednosti u compare registar,zatim vrši konverziju u procente i ispisuje vrednosti kanala na LCD ekran Slika 6. Dijagram sinhronizacije
  • 13. 13 5. Realizacija projekta U tabeli jedan, predstavljeni su simbolički nazivi i nazivi koji se koriste u izvornom kodu. Tabela1. Simbolički nazivi i nazivi koji se koriste u izvornom kodu Simbolički naziv Naziv u izvornom kodu ADTask ADTask LCDTask LCDTask Red1 box1 Red2 box2 U nastavku je dat izvorni kod programa. #include "msp430.h" #include "RTOS.h" typedef struct Mail1_struct { int broj_kanala; int vrednost; } Poruka; Poruka DutyRat; // Za mejlove primljene od box2 Poruka Vrednost; // Za mejlove primljene od box1 Poruka ADval; // Za nove mejlove pripremljene od strane prekidne rutine Poruka newMail; int staraVrednost[4]; int stariDuty[4]; unsigned char prviStart = 0; OS_STACKPTR int StackAD[200], StackLCD[200]; OS_TASK TCBad, TCBlcd;
  • 14. 14 OS_MAILBOX box1, box2; int Mails1[sizeof(Poruka)*4]; int Mails2[sizeof(Poruka)*4]; int data; int cifra1, cifra2, cifra3; void port_init(void); void TimerB_init(void); void ADC_init(void); void LCD_init(void); int DutyRatio(int); void Delay(int time) // Potreban zarad sinhronizacije taskova { int i; for(i=0;i<time;i++) { asm("nop"); } } void write_character(char position, char c){ // Funkcija koja ispisuje karakter na određenu poziciju char address=0x80+position; P8OUT=(address & 0xF0)+ 0x08; // Setovanje adresa P8OUT=0x00; Delay(1000);
  • 15. 15 P8OUT=((address & 0x0F)<<4)+0x08; // Četvorobitan pristup LCD,da bi se smanjio potreban broj pinova,radi se šiftovanje P8OUT=0x00; Delay(1000); P8OUT=(c & 0xF0)+ 0x0C; // Slanje podatka P8OUT=0x00; Delay(1000); P8OUT=((c & 0x0F)<<4)+0x0C; // Slanje podatka P8OUT=0x00; Delay(1000); } static void LCDTask(void){ while(1){ if (!OS_GetMailCond(&box2, &DutyRat)) { // GetMailCond čita iz mailbox2 i to što pročita upisuje u promenjlivu DutyRat (ne blokirajuće čitanje) data = DutyRat.vrednost; int duty = (data*100)/31; // Konverzija u procente za duty cycle cifra1 = duty/100 + 48; cifra2 = (duty%100)/10 + 48; cifra3 = duty%10 + 48; switch(DutyRat.broj_kanala){ // , Ispis na tačno određene pozicije na LCD-u u zavisnosti od DutyRat.broj_kanala case 0: TB0CCR5 = data; write_character(44, cifra1); write_character(45, cifra2);
  • 16. 16 write_character(46, cifra3); break; case 1: TB0CCR6 = data; write_character(52, cifra1); write_character(53, cifra2); write_character(54, cifra3); break; case 2: TB0CCR3 = data; write_character(4, cifra1); write_character(5, cifra2); write_character(6, cifra3); break; case 3: TB0CCR4 = data; write_character(12, cifra1); write_character(13, cifra2); write_character(14, cifra3); break; default: break; } } OS_Delay(20); } }
  • 17. 17 static void ADTask(void){ while(1){ if (!prviStart){ ADC12CTL0 |= ADC12SC; // Startovanje AD konverzije prviStart = 1; } if (!OS_GetMailCond(&box1, &Vrednost)) { // Ako nešto ima u box1, idemo dalje, ako ne – ništa if (staraVrednost[Vrednost.broj_kanala]!=Vrednost.vrednost) { // Ispitujemo da li je vrednost AD konvertora različita? Ako jeste , računaj,ako nije izadji newMail.vrednost=DutyRatio(Vrednost.vrednost); // Računanje nove vrednosti Dutyratio, koja se upisuje u tajmer staraVrednost[Vrednost.broj_kanala]=Vrednost.vrednost; // Pamti se stara vrednost if (stariDuty[Vrednost.broj_kanala]!=newMail.vrednost) { // Proveravamo vrednost koja treba da se upiše u tajmer,ako je različita šalji LCD tasku, ako nije izađi iz taska newMail.broj_kanala=Vrednost.broj_kanala; // Pripremi novi mejl stariDuty[Vrednost.broj_kanala]=newMail.vrednost; // Sačuvaj staru vrednost za upis u tajmer OS_PutMail(&box2, &newMail); // Šalje obe vrednosti mailboxa ( podatak se sastoji iz dva dela-broja kanala i vrednosti od 0-31 za tajmer) } } if (Vrednost.broj_kanala == 3) // Pitamo da li je Task obradio sve kanale konvertora ADC12CTL0 |= ADC12SC; // Ako je obradio sve kanale konvertora startuj konverziju } OS_Delay(20); // Suspenduj ADTask, kako bi LCD task mogao da se izvrši } }
  • 18. 18 #pragma vector=ADC12_VECTOR // Prekidna rutina AD konvertora __interrupt void ADC12_ISR(void) { OS_EnterInterrupt(); switch(ADC12IV) { case 0: break; // Vector 0: No interrupt case 2: break; // Vector 2: ADC overflow case 4: break; // Vector 4: ADC timing overflow case 6: // Vector 6: ADC12IFG0 ADval.broj_kanala=0; ADval.vrednost=ADC12MEM0; OS_PutMailCond(&box1, &ADval); break; case 8: ADval.broj_kanala=1; ADval.vrednost=ADC12MEM1; OS_PutMailCond(&box1, &ADval); break; case 10: ADval.broj_kanala=2; ADval.vrednost=ADC12MEM2; OS_PutMailCond(&box1, &ADval); break; // Vector 10: ADC12IFG2 case 12: ADval.broj_kanala=3;
  • 19. 19 ADval.vrednost=ADC12MEM3; // ADC12MEM3 sadrži rezultat AD konverzije (0-4095 jer je 12 bitan konvertor) OS_PutMailCond(&box1, &ADval); break; // Vector 12: ADC12IFG3 case 14: break; // Vector 14: ADC12IFG4 case 16: break; // Vector 16: ADC12IFG5 case 18: break; // Vector 18: ADC12IFG6 case 20: break; // Vector 20: ADC12IFG7 case 22: break; // Vector 22: ADC12IFG8 case 24: break; // Vector 24: ADC12IFG9 case 26: break; // Vector 26: ADC12IFG10 case 28: break; // Vector 28: ADC12IFG11 case 30: break; // Vector 30: ADC12IFG12 case 32: break; // Vector 32: ADC12IFG13 case 34: break; // Vector 34: ADC12IFG14 default: break; } OS_LeaveInterrupt(); } void port_init(){ // Inicijalizacija portova P7SEL |= 0xC0; // Potenciometri P5SEL |= 0x03; // Potenciometri P4SEL |= 0x78; // LED P4DIR |= 0x78; // LED P8OUT=0x00; // LCD P8DIR=0xFC // LCD
  • 20. 20 } void TimerB_init(){ // Inicijalizacija Tajmera TB0CCR0 = 31; // Definišemo period tajmera TB0CCTL3 = OUTMOD_7; // Mod rada tajmera TB0CCTL4 = OUTMOD_7; TB0CCTL5 = OUTMOD_7; TB0CCTL6 = OUTMOD_7; TB0CCR3 = 6; TB0CCR4 = 17; TB0CCR5 = 17; TB0CCR6 = 17; TB0CTL = TBSSEL_1 + MC_1; // Koji takt dolazi do tajmera i da broji nagore ( ACLK) } void ADC12_init(){ // Inicijalizacija AD konvertora ADC12CTL0 = ADC12ON+ADC12MSC; // ADC12MSC startuje višestruku AD konverziju ADC12CTL1 = ADC12SHS_0 + ADC12CONSEQ_1 + ADC12SHP; // startovanje bitom ADC12SC, ADC12CONSEQ_1 znači da se sekvenca kanala vrši jedanput ADC12MCTL0 = ADC12INCH_8; ADC12MCTL1 = ADC12INCH_9; ADC12MCTL2 = ADC12INCH_14; ADC12MCTL3 = ADC12INCH_15 + ADC12EOS; ADC12IE |= ADC12IE0 + ADC12IE1 + ADC12IE2 + ADC12IE3; // Omogućava prekidnu rutinu AD konvertora ADC12CTL0 |= ADC12ENC; // Omogućava konverziju AD konvertora }
  • 21. 21 void LCD_init() // Inicijalizacija LCD-a { Delay(10000); P8OUT=0x38; P8OUT=0x30; Delay(5000); P8OUT=0x38; P8OUT=0x30; Delay(100); P8OUT=0x38; P8OUT=0x30; Delay(1000); P8OUT=0x28; // Function set (4-bit interface) P8OUT=0x20; Delay(1000); P8OUT=0x28; // Function set (4-bit interface) P8OUT=0x20; Delay(1000); P8OUT=0x88; P8OUT=0x80; Delay(1000);
  • 22. 22 P8OUT=0x08; // Display off P8OUT=0x00; Delay(1000); P8OUT=0x88; P8OUT=0x80; Delay(1000); P8OUT=0x08; // Display clear P8OUT=0x00; Delay(1000); P8OUT=0x18; P8OUT=0x10; Delay(1000); P8OUT=0x08; // Entry mode set P8OUT=0x00; Delay(1000); P8OUT=0x68; P8OUT=0x60; Delay(1000); P8OUT=0x08; // Display on P8OUT=0x00;
  • 23. 23 Delay(1000); P8OUT=0xE8; P8OUT=0xE0; Delay(1000); P8OUT=0x08; // Display clear P8OUT=0x00; Delay(1000); P8OUT=0x18; P8OUT=0x10; Delay(1000); write_character(0, 'C'); // U okviru inicijalizacije LCD-a vršimo ispis na LCD ekran za kanale ( to radimo samo jedanput ) write_character(1, 'h'); write_character(2, '1'); write_character(3, ':'); write_character(8, 'C'); write_character(9, 'h'); write_character(10, '2'); write_character(11, ':'); write_character(40, 'C'); write_character(41, 'h'); write_character(42, '3'); write_character(43, ':'); write_character(48, 'C');
  • 24. 24 write_character(49, 'h'); write_character(50, '4'); write_character(51, ':'); } int DutyRatio(int result){ return result >> 7; // Samo viših 5 bita konverzije koristimo za računanje Duty cycle-a zbog našeg podešenog tajmeraB (0-31,tj 5 bita) } int main(void) { // Glavni program sa standardnim funkcijama OS_IncDI(); // Initially disable interrupts OS_InitKern(); // Initialize OS OS_InitHW(); // Initialize Hardware for OS port_init(); // Inicijalizacija portova TimerB_init(); // Inicijalizacija tajmeraB ADC12_init(); // Inicijalizacija AD konvertora LCD_init(); // Inicijalizacija LCD-a __bis_SR_register(GIE); OS_CREATETASK(&TCBad, "AD", ADTask, 150, StackAD); OS_CREATETASK(&TCBlcd, "LCD", LCDTask, 100, StackLCD); OS_CREATEMB(&box1, sizeof(Poruka), 4, &Mails1); OS_CREATEMB(&box2, sizeof(Poruka), 4, &Mails2); OS_DecRI(); //Enable interupts to send string OS_SendString("embOS will start ..."); OS_Start(); //Start multitasking return 0; }
  • 25. 25 6. Simulacija Zbog složenosti korišćenih periferija, ovu aplikaciju je dosta nezahvalno simulirati u simulatoru. Iz tog razloga je ovaj program testiran isključivo u realnom radu na ploči i debagovan je na licu mesta.Većih problema pri izradi aplikacije nije bilo osim par grešaka u pretpostavci studenta koje su bile nađene i otklonjene. Program je testiran na primeru promene jednog i više potenciometara istovremeno dok su ispis na LCD ekran i osvetljaj diode pravilno reagovali na promene potenciometara. Program je takođe testiran za svaki potenciometar posebno od nulte vrednosti do maksimalne gde su takođe ispis odgovarajućeg kanala i osvetljaj odgovarajuće diode bili tačni što je predmeni asistent potvrdio.
  • 26. 26 7. Zaključak Iz prethodno izloženog može se videti jedan klasičan primer rada sa taskovima. Očigledne su prednosti koje operativni sistem pruža sa svojim API funkcijama, koje se ispoljavaju u jednostavnosti pisanja koda, dobroj preglednosti, a samim tim i boljoj kontroli nad celim sistemom. Takođe, može se primetiti i jedna očigledna mana vezana za korišćenje gotovih API funkcija, koja se odnosi na vreme izvršavanja koje može biti dosta dugo. Na osnovu rezultata simulacije mogu se uočiti neki specifični detalji koji bi možda mogli drugačije da se realizuju. Na primer, spomenuto je da se poruke u Red1 smeštaju onim redosledom kojim se dobijaju konvertovane vrednosti sa kanala. Znači, prvo se smešta konvertovana vrednost sa kanala 1, pa onda sa kanala 2, itd. Imavši to u vidu moguće je pojednostaviti poruke reda Red1, tako da ne sadrže oznaku kanala. Međutim, iako na prvi pogled to zaista izgleda logično, ovde prikazan način realizacije je dosta sigurniji jer ne ostavlja mogućnost greške. Takođe, nije potrebno pisati dodatni kod koji bi morao da pamti koja je poruka prethodno primljenja i sl.
  • 27. 27 Literatura [1] IAR Systems, http://www.iar.com/ [2] SEGGER http://www.segger.com/ [3] Texas Instruments, MSP430F449 http://focus.ti.com/docs/prod/folders/print/msp430f449.html [4] Razvojno okruženje koje se koristi za implementaciju projekta http://tnt.etf.rs/~oe4srv