Programiranje EASY PIC 6.

Vlado

Legenda
Banovan
Poruka
53.345
U školi smo nedavno počeli da radimo programiranje dotičnog razvojnog sistema.. U utorak imam kontrolni, a nemam blage veze, ama baš ništa.. Nemamo ni knjigu ni svesku iz ovog predmeta, a profesor kada ga pitamo gde smo pogrešili u unošenju u računar gleda na tablu, on sam ne zna program, a traži da ga mi znamo napamet... Treba da prođem 5.00 i da dobijem 5 iz ovog dela. Tako da bih bio zahvalan da mi se javi neko ko zna programiranje ovog razvojnog sistema, pa da mu postavim neka pitanja. :)
 
Aha, može.. :)
Ne moram vam govoriti, da je ono pod kosom crtom komentar.. :)
// Program: A/D konverzija
// MIKROKONTROLLER PIC 16F887
// Program vrsi A/D konverziju i rezultat ispisuje na LCD
// Koristimo ADC biblioteke

// INICIJALIZACIJA LCD-a
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
//DEFINISANJE PROMENLJIVIH
unsigned int temp;
char txt[7];
//GLAVNI PROGRAM
void main() {
ANSEL = 0x04; // Konfigurisanje AN2 pina kao analognog
ANSELH = 0; // Ostali analogni ulazi su standardni UI
C1ON_bit = 0; // Uskljucivanje komparatora
C2ON_bit = 0;
Lcd_Init(); // Inicijalizacija LCD-a
Lcd_Cmd(_LCD_CLEAR); // Obrisi LCD
Lcd_Cmd(_LCD_CURSOR_OFF); // Iskljucu cursor
TRISA = 0xFF; // PORTA je ulaz
TRISC=0;
PORTC=0;

do {
temp = ADC_Read(2); // Ucitaj vrednost 10-bitne A/D konverzije sa 2. kanala
IntToStr(temp, txt); // Konverzija brojaca u string
Lcd_Out(1, 5, txt); // Ispis brojaca na LCD
} while(1);
}
 
Okej, prvo, na ploči postoji ležište za LCD ekran. On je povezan na port B, i to kao na ovoj šemi:

capturebtl.jpg


Ljudi iz mikroelektronike su razvili biblioteku pomoću koje se može upravljati LCD Displejom bez nekog posebnog predznanja o tome kako to funkcioniše ispod haube. Potrebno je samo da navedeš u svom programu gde je šta prikopčano, pa se to i radi na početku. Kad to uradiš, dalje možeš da pozivaš funkcije koje su definisane.

Na primer:

Lcd_Init();
Nju pozoveš na početku programa da bi mikrokontrolor poslao LCD dipleju set instrukcija koji će ga inicijalizovati u četvorobinom režimu rada. Ja sam pisao svoje funkcije za ovo, ima možda 20ak redova ali je ti imaš gotovu pa te baš briga. Uglavnom moraš je pozvati ili displej neće proraditi. E sad sve dalje je stvar llične želje:

Lcd_Cmd(_LCD_CLEAR);

Ovom funkcijom šalješ komandu LCD displeju. U ovom slučaju argument je _LCD_CLEAR što će reći "obriši sadržaj ekrana". Može i svašta nešto drugo, kao ova druga "isključi kursor"

Lcd_Cmd(_LCD_CURSOR_OFF);

Kad to obaviš možeš da ispišeš bilo koji niz karaktera na LCD pomoću funkcije:

Lcd_Out(int x, int y,string s);

x i y određuju poziciju gde se nešto ispisuje. Displej ima 2 reda po 16 znakova pa x može biti 1 ili 2, a y od 1 do 16. znači, ako hoćeš da ti ispiše "Ovlad" kucaš komadu:

Lcd_Out(1, 1,"Ovlad");

posle možeš da obrišeš sadržaj komandom za brisanje...

Znači neki glup program koji bi smao inicijalizovao LCD i napisao Ovlad na njemu bi izgledao ovako:


Kod:
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;

void main() {
  
  Lcd_Init();                        // Inicijalizacija LCD-a
  Lcd_Cmd(_LCD_CLEAR);               // Obrisi LCD
    Lcd_Out(1, 1, "OVLAD");              
while(1);
  }

Program inicijalizuje LCD i onda napiše OVLAD na njemu. A onda uđe u beskonačnu petlju pa ga moraš resetovati.

Jel to sad jasno?
 
Shvatio sam taj program gore..
Ali ovaj nikako ne mogu, ama baš ništa..
//Program: PWM
//MIKROKONTROLLER PIC 16F887
//Demonstracija rada PWM modula
//Impulsno sirinska modulacija
//Frekvencija je stalna, npr.5kHz, a menjamo odnos impuls/pauza, tj. faktora ispunjenosti
//Ima siroku primenu kada se digitalnim signalima upravlja analognim uredjajima
//Ako je 8 bitna: Duty=0 -> 0V Duty=255 -> 5V
//Primeri primene: regulacija osvetljenja, regulacija grejanja, regulacija
//broja obrtaja motora. Mozemo prikljuciti i piezo zvucnike i koristiti za
//generisanje jednostavnijih zvukova

//DEKLARISANJE PROMENLJIVIH**************************************************
char i;
//POCETAK PROGRAMA********************************************************
void main() {
//*************INICIJALIZACIJA*****************************************
Delay_ms(500); // Pauza 0.5s
ANSEL = 0; ANSELH = 0; // Iskljucenje analognih ulaza. Svi su I/O
C1ON_bit = 0; C2ON_bit = 0; // Iskljucenje komparatora
TRISD=0; PORTD = 0; // PORTD izlaz. nulovanje
// Inicijalizacija PWM (5kHz) i startovanje
PWM1_Init(5000); PWM1_Start();
PWM2_Init(5000); PWM2_Start();
// Pocetne vrednosti PWM-a - Faktora ispune 0-255
PWM1_Set_Duty(0); PWM1_Set_Duty(0);
i = 0;
//*****BESKONACNA PETLJA**********************************************
while (1) {
if (PORTE.B0 == 1) i++; // Ako je pritisnut taster RE0, inkrementacija
if (PORTE.B1== 1) i--; // AKo je pritisnut RE1, dekrementacija
PWM1_Set_Duty(i); // Faktor ispune, impuls i=0-255
PWM2_Set_Duty(255-i); //Faktor ispune, pauza
PORTD = i; // Na portu D pratimo vrednost binarno
Delay_ms(100); // Pauza 0,1s
}
}
 
Okej... Evo jedan sličan primer. Prvo, imamo šemu pločee, pa da znamo šta je gde povezano:

http://www.mikroe.com/eng/downloads/get/312/easypic6_schematic_v101.pdf
Drugo, opet se koriste ugrađene biblioteke koje pravi mikroelektronika, a ja sam lično dokoni protivnik korišćenja istih jer ne možeš dobro ukapirati šta se događa u kontroleru ako ćeš koristi već gotove funkcije. No, nebitno. Pretostavljama da znaš šta je PWM signal, ali ako ne znaš, evo kratkog objašnjenja: PWM je fazno modulisan pravougaoni signal kod kojeg se menja faktor ispune (duty cycle) dok frekvencija i amplituda ostaju iste.

Evo primera:

dadc74b4230.jpg


Dakle, poenta je da tvoj mikrokontroler generiše PWM signal. Gde i kako se to radi videćemo u nastavku. Ovde u primeru sam odabrao ovaj mikrokontroler: PIC16F887. PA da vidimo šta se tu događa.... Jedan način da se generiše PWM je putem digitalnog IO sistema, dakel setuje neki bit na 1 određeno vreme, pa resetuješ na 0 određeno vreme i tako u krug pri tome pazeži da zbir vremena setovanja i vreme resetovanja budu konstantni inače bi menjao frekvenciju. Ovo znači koliko povećaš jedno vreme, za toliko moraš smanjiti drugo. Drugi način, i to mnogo bolji je putem tajmera koji postoje ugrađeni u mikrokontrloler. Obično se oni fabrički izvedu tako da mogu vrlo jednostavno da generišu PWM signal, a to je slučaj i sa ovim mikrokontrolerom. Kad ne bi imao ove ugrađene funkcije za inicijalizaciju, mogao bi opet sam da ih napišeš i to bez puno muke. (možda ti jednom pokažem detaljno kako se to radi, ali ima vremena)

Prvo da vidimo kako izgleda mikrokontroler:

PIC16F887-pinout.jpg


Primetićeš izlaze CCP1 i CCP2 na pinovima 16 i 17. Ti izlazi su u stvari izlazi unutrašnjeg PWM generatora i na njima se javlja PWM kad ga uključiš. To je dakle na portu C, pa ja ne znam šta je tvoj profa zamislio sa porotm D... Valjda da prati veličinu faktora ispune?! :dash: Elem, na pinove 16 i 17 se prikače osciloskopa i posmatra signal koji treba da izgleda kao na slici gore. Idemo dalje. Funkcije

PWM1_Init(5000); // Initialize PWM1 module at 5KHz
PWM2_Init(5000); // Initialize PWM2 module at 5KHz

inicijalizuju tajmere u mikrokontroleru da rade kao PWM generatori i to na 5000 herca u ovom konkretnom slučaju. Posle toga se podesi i faktor ispune:

PWM1_Set_Duty(0); // Set current duty for PWM1
PWM2_Set_Duty(0); // Set current duty for PWM2

Ovako se praktično isključi PWM, jer je vreme setovanja 0% a vreme resetovanja 100%. Posle toga neka petlja podešava faktor ispune, a kako će to da radi je stvar programera. Možeš ga menjati preko nekih dugmića, možeš ga menjati preko analognog ulaza, slati ga serijskom vezom preko RS232 ulaza... Još da napomenem faktor ispune od 100% odgovara vrednosti 255....

U nastavku evo programa koji je ponudila Mikroelektronika, a ja ću ga komentarisati

Kod:
unsigned short current_duty, current_duty1;

//Ovde su deklarisane dve promenjive koje će kasnije trebati, dakle ništa posebno

void InitMain() {
  ANSEL  = 0;                         // Ovde se analogni pinovi kofigurišu kao digitalni jer nema potrebe za njihovim korišćejem. DA zadajemo PWM preko nekog potenciometra, onda bi trebalo...
  ANSELH = 0;
  C1ON_bit = 0;                       // Komparatori su takođe nepotrebni pa su isključeni
  C2ON_bit = 0;
  
  PORTA = 255;
  TRISA = 255;                        // Port A je ulazni jer su dugmići preko kojih povećavamo i smanjujemo faktor ispune na portu A. Ovo znači da u njega treba  upisati 255. 
  PORTB = 0;                          // Set PORTB to 0
  TRISB = 0;                          //Port B je izlazni ali ga ne koristimo, ne treba  nam,
  PORTC = 0;                          // Set PORTC to 0
  TRISC = 0;                          // Port C je izlazni takođe. Mislim da mora biti ovako jer su CCP1 i CCP2 povezani na iste pinove ali možda i ne mora, treba pogleradi u user manual za mikrokontroler...
  PWM1_Init(5000);                    
  PWM2_Init(5000);                   // Inicijalizujemo  generatore na 5kHz
}

void main() {
  InitMain();
  current_duty  = 16;                 
  current_duty1 = 16;                //Podesimo neki mali faktor ispune svejedno koji
  PWM1_Start();                      
  PWM2_Start();                      
  PWM1_Set_Duty(current_duty);        
  PWM2_Set_Duty(current_duty1);       // Potom startujemo generatore sa tim nekim malim početnim faktorom ispune

  while (1) {                         // Sad pravimo beskonačnu petlju u kojoj preko dugmića na RA0 i RA1 za prvi i RA2 i RA3 za drugi PWM generator povećavamo i smanjujemo faktor ispune 
    if (RA0_bit) {                    // Button on RA0 pressed
      Delay_ms(40);
      current_duty++;                 // Increment current_duty
      PWM1_Set_Duty(current_duty);
     }

    if (RA1_bit) {                    // Button on RA1 pressed
      Delay_ms(40);
      current_duty--;                 // Decrement current_duty
      PWM1_Set_Duty(current_duty);
     }

    if (RA2_bit) {                    // Button on RA2 pressed
      Delay_ms(40);
      current_duty1++;                // Increment current_duty1
      PWM2_Set_Duty(current_duty1);
     }

    if (RA3_bit) {                    // Button on RA3 pressed
      Delay_ms(40);
      current_duty1--;                // Decrement current_duty1
      PWM2_Set_Duty(current_duty1);
     }

    Delay_ms(5);                      // Ovde malo usporimo izvršavanje toka petlje, mada je nebitno....
  }
}

E pa slično radi i ovaj primer tvog profe uz neke nebitne stvari tipa ona besmislena pauza na početku. Sad pravo kažem, mislim da ovde ni port B ne mora posebno da se podešava, jer je i on nebitan, a verovatno čak ni port C. Samo analogni ulazi i komparatori i port A na koji su nakačeni dugmići... Ja bih ovde izmenio neke sitnice:

Prvo, port a bih vezao na +5V preko pull-up otpornika a dugmiće RA0 do RA3 na masu. Tako bi u stvari imao obrnutu situaciju, da ti pritisnuto dugme zapravo obara nivo ulaza porta na 0, što je generalno bolja praksa. Kod bi bio neznatno izmenjen, samo bi se pitao da li je RAx_bit == 0. ali to zavsi od konkretnih veza na ploči i onoga što hoćeš da uradiš...
 

Back
Top