Sari la conținut
ELFORUM - Forumul electronistilor

probleme programare pic


Myhayxx

Postări Recomandate

Uite de-aia prefer eu un compiler cat mai "neutru" si functii scrise de mana.Cu toate ca sunt destul de sigur ca si in mikroc se pot accesa registrii direct si seta toti cei 10 biti dupa nevoi.Referitor la ceas, se poate face si fara chip RTC extra. Eu am rezultate destul de bune cu un quarz de 32768 khz montat la timer1 parca. Ce-i drept, n-am backup (direct, ca am un modul dcf77 in caz de pana ora se regleaza automat).

Link spre comentariu
  • Răspunsuri 25
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • Myhayxx

    9

  • Mircea

    7

  • Liviu M

    6

  • costi002

    1

Top autori în acest subiect

Imagini postate

Am facut o afirmatie care lasa loc la interpretari.Ca sa reformulez: modulul PWM din MikroC ne da voie numai la 255 valori pentru duty_cycle.Evident ca poti incarca in registrii PWM ce vrei tu in MikroC (si alte compilatoare Mikroe). De altfel, modulul PWM de la Mikroe e foarte simplut. Nu stie half or full bridge. Eu pentru ESC-urile (full bridge P+N channel) mele imi setez registrii dupa nevoi fara functia PWM a compilatorului.

Link spre comentariu

m-am straduit zilele acestea sa fac programul sa lucreze cum vreau eu insa mai am mult de lucru. Am luat tutorialul din Mikroc de la PWM si am facut mici modificari insa nu am reusit cine stie ce. in simulator functioneaza atunci can apas unul din butoane pentru cresterea inensitatii si repectiv scaderea ei;functioneaza si in montaj doar ca se mai intampla ceva: creste intensitatea la maxim dupa care isi reia ciclul fara ca sa intervin eu cu unul din butoane..insa cand am unul din butoane apasat functioneaza cum trebuie.(oare trebuie sa pun condensatoare de 100 nF intre pinul de intrare si masa?) in program ar mai trebui adaugat ceva ca atunci cand tin unul din butoane apasat sa mearga pana la maxim si sa se opreasca acolo (acum daca tin apasat se duce pana la maxim si o ia din nou de la 1 si tot asa cat este butonul apasat) am incercat codul de la "thunderer" dar nu merge compilat. imi poate arata cineva pe ce rand al programului mai trebuie adaugat ceva si ce ar trebui sa scriu acolo sa se opreasca atunci cand ajunge la maxim?acesta e programul pe care l-am testat:unsigned short current_duty, old_duty, current_duty1, old_duty1;void InitMain() {PORTA = 0; TRISA = 0; // configure PORTA pins as input PORTB = 0; // set PORTB to 0 TRISB = 0; // designate PORTB pins as output PORTC = 0; // set PORTC to 0 TRISC = 0; // designate PORTC pins as output PWM1_Init(5000); // Initialize PWM1 module at 5KHz} void main() { InitMain(); current_duty = 1; // initial value for current_duty PWM1_Start(); // start PWM1 while (1) { // endless loop if (RD0_bit) { // button on RA0 pressed Delay_ms(1); current_duty++; // increment current_duty PWM1_Set_Duty(current_duty); } if (RD1_bit) { // button on RA1 pressed Delay_ms(1); current_duty--; // decrement current_duty PWM1_Set_Duty(current_duty); } Delay_ms(4); // slow down change pace a little }}

post-27344-139829794153_thumb.jpg

Link spre comentariu

   if (RD0_bit) {                    // button on RA0 pressed      //      Delay_ms(1);  //ce rol are intarzierea asta aici?      if(current_duty < 255) { //testezi daca mai "ai loc" intr-un unsigned char         current_duty++;                 // increment current_duty      }      PWM1_Set_Duty(current_duty);   }         if (RD1_bit) {                    // button on RA1 pressed//      Delay_ms(1);   //ce rol are intarzierea asta aici?      if(current_duty > 0) { //testezi daca mai "ai loc" intr-un unsigned char         current_duty--;                   // decrement current_duty      }      PWM1_Set_Duty(current_duty);   }}

PS Foloseste, te rog, tagurile code pentru cod.

Link spre comentariu

PS Foloseste, te rog, tagurile code pentru cod.

nu stiu cum :jytuiyu

 

iti multumesc de ajutor

 

intarzierea aceea am puso pentru timpul de crestere a intensitatii din momentul cand apesi pe buton.eu am nevoie sa ajung la intensitate maxima in aproximativ o jumatate de ora..

acum se opreste cand ajunge la maxim dar problema e ca atunci cand apas butonul creste brusc pana la maxim si se opreste acolo

Link spre comentariu

Cu butonul Code din meniul ferestrei din care raspunzi. Sau scrii [ code ] [ /code ] (fara pauze) la inceputul/sfarsitul codului.

 

Faptul ca intensitatea creste brusc e normal - bucla while se repeta foarte repede - si nu cred ca 1 ms intarziere face diferenta (cel mult in cazul in care functia e total aproximativa).

Ori pui intarzierea la loc (eventual mai lunga), ori modifici codul sa incrementeze/decrementeze intensitatea cu o unitate la fiecare apasare. Ceva in genul

   if (RD0_bit) {                    // button on RA0 pressed           if(current_duty < 255) { //testezi daca mai "ai loc" intr-un unsigned char         current_duty++;                 // increment current_duty      }      PWM1_Set_Duty(current_duty);      while(RD0_bit) { //cat timp butonul e apasat nu mai face nimic           ;      }     }
Chestia asta e foarte ineficienta, si poate fi folosita cand nu vrei si altceva de la pic.

Cand o sa ai si partea de ceas, o sa fie mai usor sa "temporizezi" modificarile (poti folosi secundele, de exemplu, pentru "sincronizare").

Link spre comentariu

Ideea din programelul din pagina precedenta era ca ai un semnal "1" pentru 30 minute si apoi este "0" pentru 23 de ore si 30 minute - de la acel timer de ziceai ca-l ai. D-asta merge cu butonul apasat continuu si nu cu apasari de butoane. Nu ca nu s-ar putea face cu apasari momentane.30minx60sec = 1.800.000 msec / 255 = approx 7100msec.In loc de valoarea eronata de 117ms (gresita in exemplul precedent - unde erau numai 30 secunde, nu 30 minute) pui Delay_ms(7100). N-are sa mai creasca brusc la 100%, ci in 30 minute. Are sa incrementeze factor_umplere la fiecare 7,1 secunde.Codul precedent nu avea "protectie" la overflow, si dupa 255 vine 0, si dupa 0 vine 255 dupa cum ai descoperit. :nas: In if se mai pune un alt if care testeza cand factor_umplere=255 sa ramana vesnic la 255 (idem pentru 0). Cu toate ca, daca intarzierile la incrementarea factor_umplere sunt puse cum trebuie (adica suficient de lungi) nu ajungi acolo. La 7100ms nu ar trebui ca factor_umplere sa ajunga vreodata la 255, ci doar la 254. Delay_ms() este sigur mai precis decat acel timer aditional. Eventual, din teste mai poti ajusta acest Delay_ms(7100) ca sa se comporte cum trebuie, in sensul ca maresti sau scazi. Liviu are dreptate, PIC nu va mai face altceva, ci doar modificarea PWM in aceste 30 minute. Dupa mine, as face cu intrerupere pe un timer (cu prescaler) cata vreme nu se vrea RTC, dar mai intai zic sa invatam sa mergem in 4 labe, apoi ne saltam pe 2 picioare :limb: .

Link spre comentariu

am facut aseara cateva teste si am reusit cu urmatorul cod si se aprinde la maxim in aproximativ 23 minute. delay-ul dupa cum se vede e destul de mic dar asa merge,daca pun mai mare trece o gramada de timp pana sa se aprinda ledurile dupa ca a fost actionat butonul.

unsigned short current_duty, old_duty, current_duty1, old_duty1;void InitMain() {PORTA = 0;  TRISA = 0;                        // configure PORTA pins as input  PORTB = 0;                          // set PORTB to 0  TRISB = 0;                          // designate PORTB pins as output  PORTC = 0;                          // set PORTC to 0  TRISC = 0;                          // designate PORTC pins as output  PWM1_Init(5000);                    // Initialize PWM1 module at 5KHz}  void main() { InitMain();     current_duty  = 1;                 // initial value for current_duty    PWM1_Start();                       // start PWM1     while (1) {                         // endless loop              if (RD0_bit) {                    // button on RA0 pressed        Delay_ms(1800);        if(current_duty < 255)        {        current_duty++;                 // increment current_duty      }      PWM1_Set_Duty(current_duty);      }             if (RD1_bit) {                    // button on RA1 pressed      Delay_ms(1800);      if(current_duty > 0)       {         current_duty--;                   // decrement current_duty      }      PWM1_Set_Duty(current_duty);   }  }}

sigur ca vreau acel RTC singura problema pentru care l-am ocolit a fost ca habar nu aveam si inca nu am cum se programeaza dar macar am inteles principiul de functionare si oricum nu ma las pana nu-l fac cum trebuie. ai dreptate cu ceea ce ziceai ca mai intai incepi de jos si treptat te ridici. o sa iau o pauza pana dupa sarbatori si apoi dau comanda de acel RTC si incep testele. dupa cum am fost sfatuit mai intai o sa incerc sa aprind un led la secunda/minutul dorit si apoi trec mai departe cu PWM si mai am in plan sa activez cateva iesiri la anuminte intervale de timp dar deja visez :freaza:

inca odata mii de multumiri celor care m-au ajutat! o sa va mai bat la cap sper sa nu va deranjeze prea tare :bataie

Link spre comentariu

La mine merg si "RTC-ul" *) si afisajul ceasului pe un LCD si PWM hard (de la stins la aprins total in 25 de minute). :da N-am butoane sa activez si tastatura de reglare a orei (meniul il am).Da' recunosc ca am trisat - am "scurtat" un proiect mai vechi **) (cele mai mari batai de cap le-am avut cu LCD-ul, ca am schimbat compilatorul si nu mai voia).*) Quarz de 32768 Hz + TMR1**) Tot pentru acvariu il folosesc si eu, dar nu pentru lumini ci pentru fertiulizare, CO2 si hranire in concedii. Pentru lumini, ca lampa mea tot nu e "dimabila", folosesc o priza programabila.

Link spre comentariu

*) Quarz de 32768 Hz + TMR1

ce insemna TMR1? quartzul acesta l-ai pus pe DS1307? am vazut ca pe acesta il recomanda in catalog.mai am o intrebare: trebuie un quartz pentru PIC si unul pentru RTC? am incercat codul acesta pentru ceas si am legat afisajul dupa indicatiilie de la inceputul codului dar imi apar aprinse toate ledurile afisajului si am incercat sa leg niste butoane pentru setarea ceasului dar n-am reusit;poate n-am nimerit corect intrarile. stiti cumva pe ce pini ar trebui sa leg butoanele pentru setarea ceasului?
/* Copyright:     (c) Mikroelektronika, 2011. * Revision History:     2013-12-24:       - initial release (; * Description:     This code demonstrates how to display a Real Clock Time number on 4     7-segment display( common cathode).     Display is connected to PORTD (RD0..RD7, segment A to RD0, segment B to RD1, etc)     ; common cathode is connected to the pin RA0 on  PORTA.     Number is incremented every 1s. * Test configuration:      EASYPIC4     MCU:             PIC16F877A  8MHz xstal     RTC DS1307 PORTC3 pin 6 SCL; PORTC4 pin 5 SDA         F U N Z I O N A  CON MULTIPLEX  & INTERRUPT         F U N Z I O N A  button set         FUNZIONA CON 6 DISLPAY */unsigned short shifter, portd_index;unsigned int   digit, number; // number1, number2unsigned short portd_array[6];unsigned short read_ds1307(unsigned short address);void write_ds1307(unsigned short address, unsigned short w_data);unsigned short sec, secL, secH;unsigned short minute, minuteL, minuteH;unsigned short hour, hourL, hourH;unsigned short day;unsigned short month;unsigned short year;unsigned short dataa;unsigned short BCD2UpperCh (unsigned short bcd);unsigned short BCD2LowerCh (unsigned short bcd);//unsigned int counter_sec;      // counter for Sec from RTC max 36.000sec = 10h// ENTER VALUESextern void StoreToRTC(void);unsigned short in_hour, in_minute;unsigned short in_hourL, in_hourH, in_minuteL, in_minuteH;  //new valuesbit oldstate;        // flag of button//   conversion BCD to binary for each digitunsigned short BCD2UpperCh (unsigned short bcd) {   return (bcd >> 4);// & 0xF0) + 48; // 48); } unsigned short BCD2LowerCh (unsigned short bcd) {   return (bcd & 0x0F);// + 48); }void StoreToRTC() {          // store into RTC with conversion  write_ds1307(0, 0x00);   // reset sec and start  //write_ds1307(0, 0x80);   // sec  minute = (in_minuteL & 0x0F) + ((in_minuteH << 4) & 0xF0);  write_ds1307(1, minute);   // minute 0 - 59  in_hour = (in_hourL & 0x0F) + ((in_hourH << 4)& 0xF0);  write_ds1307(2, in_hour);//0x24);   // hour  //write_ds1307(3, 0x07);   //  day  //write_ds1307(4, 0x22);   //  date  //write_ds1307(5, 0x05);   //  month  //write_ds1307(6, 0x10);   //  year  write_ds1307(7, 0x10);   // SQWE  delay_ms(2000);}unsigned short read_ds1307(unsigned short address){I2C1_Start();I2C1_Wr(0xd0);I2C1_Wr(address);I2C1_Repeated_Start();I2C1_Wr(0xD1);dataa=I2C1_Rd(0);I2C1_Stop();return(dataa);}void write_ds1307(unsigned short address, unsigned short w_data){I2C1_Start();I2C1_Wr(0xd0);I2C1_Wr(address);I2C1_Wr(w_data);I2C1_Stop();}void interrupt() {                  // timer sequence for scrolling display  PORTA = 0;                             // Turn off all 7seg displays  PORTD = portd_array[portd_index];      // bring appropriate value to PORTD  PORTA = shifter;                       // turn on appropriate 7seg. display  // move shifter to next digit         // 6 display  shifter <<= 1;  if (shifter > 32u)    shifter = 1;  // increment portd_index  portd_index++ ;  if (portd_index > 5u)           // 0,1,2,3,4,5    portd_index = 0;             // turn on 1st, turn off 2nd 7seg.    TMR0IF_bit = 0;    TMR0 = 5;                    //TMR0 a 5 o 0 funziona}// conversion binary to 7 segmunsigned short mask(unsigned short num) {  switch (num) {    case 0 : return 0x3F;    case 1 : return 0x06;    case 2 : return 0x5B;    case 3 : return 0x4F;    case 4 : return 0x66;    case 5 : return 0x6D;    case 6 : return 0x7D;    case 7 : return 0x07;    case 8 : return 0x7F;    case 9 : return 0x6F;  } //case end}extern void display7Seg(void){          // show clock time on display    sec = read_ds1307(0);    minute = read_ds1307(1);    hour = read_ds1307(2);    hourH = BCD2upperCh(hour);        // hourH    hourL = BCD2Lowerch(hour);        // HourL    portd_array[5] = mask(hourH);        // and store it to PORTD array    portd_array[4] = mask(hourL);        // and store it to PORTD array    minuteH = BCD2upperCh(minute);    // MinuteH    minuteL = BCD2Lowerch(minute);    // MinutesL    portd_array[3] = mask(minuteH);        // and store it to PORTD array    portd_array[2] = mask(minuteL);        // and store it to PORTD array    secH = BCD2upperCh(sec);         // SecH    secL = BCD2Lowerch(sec);         // SecL    portd_array[1] = mask(secH);        // and store it to PORTD array    portd_array[0] = mask(secL);        // and store it to PORTD array}void main() {  ADCON1 = 0;                          // Set AN pins to Digital I/O;  //ADCON0 = 0;  TRISA = 0;                     // Configure PORTA as output  PORTA  = 0;                     // Clear PORTA  TRISD = 0;                     // Configure PORTD as output  PORTD  = 0;                     // Clear PORTD  TRISB = 0b10000111;          //B7 input from SQWE from RTC,B0 INC Hour                               //B1 INCR Minute  PORTB = 0;  TRISE = 0;  PORTE = 0;  OPTION_REG         = 0x82;  TMR0         = 5;  INTCON         = 0xA0;  I2C1_Init(100000);  digit = 0;  portd_index = 0;  shifter = 1;  oldstate = 0;  // thess are the default values  write_ds1307(0, 0x80);   // sec  write_ds1307(1, 0x25);   // minute 0 - 59  write_ds1307(2, 0x12);   // hour  write_ds1307(3, 0x07);   //  day  write_ds1307(4, 0x22);   //  date  write_ds1307(5, 0x05);   //  month  write_ds1307(6, 0x10);   //  year  write_ds1307(7, 0x10);   // SQWE  write_ds1307(0, 0x00);   // reset sec and start  // up here  GIE_bit = 1;  TMR0IE_bit = 1;   in_hourL = 0;   in_hourH = 0;   in_minuteL = 0;   in_minuteH = 0;   do {        do {              if (Button(&PORTB, 1,0,1)){   // PORTB F1 INC Hour              oldstate = 1;              in_hourL++;                   if (in_hourL > 9){                   in_hourL = 0;                   in_hourH++;                   }                   if (in_hourH == 2 && in_hourL == 4){                   in_hourH = 0;                   in_hourL = 0;                   }                PORTB.F3 = 1;               //  PORTB F3 LED UNDER HOUR DSP ON                PORTB.F4 = 0;                portd_array[5] = mask(in_hourH);        // and store it to PORTD array                portd_array[4] = mask(in_hourL);        // and store it to PORTD array                                delay_ms(250);                }                if(Button(&PORTB, 2,0,1)){     // PORTB F2 INC Minute                oldstate = 1;                in_minuteL++;                   if(in_minuteL > 9) {                   in_minuteL = 0;                   in_minuteH++;                   }                   if (in_minuteH >5) {                   in_minuteH =0;                   }                PORTB.F3 = 0;                PORTB.F4 = 1;                 // PORTB F4 LED under Minute DSP ON                portd_array[3] = mask(in_minuteH);        // and store it to PORTD array                portd_array[2] = mask(in_minuteL);        // and store it to PORTD array                delay_ms(250);                }               if (Button(&PORTB,0,0,1)){   // Press SET to store new values                StoreToRTC();                PORTB.F3 = 0;                          // reset                PORTB.F4 = 0;                          // reset                oldstate = 0;                          // reset flag                delay_ms(250);                }            }  while (oldstate == 1);            display7Seg();      }while(1);                // endless loop }

post-27344-139829795469_thumb.jpg

Link spre comentariu

TMR1 e Timer1 - pagina 53 in data-sheet.Nu, quarzul nu l-am pus la DS, l-am pus in loc de DS.Daca conectezi un oscilator intre pinii T1OSI si T1OSO (RC1&RC0 la 16F877) si configurezi cum trebuie timer1 - T1CON bit 1 = 1:

TMR1CS: Timer1 Clock Source Select bit1 = External clock from pin RC0/T1OSO/T1CKI (on the rising edge)0 = Internal clock (FOSC/4)

timer1 va numara cu frecventa oscilatorului respectiv. Configurat cum trebuie si folosind un quarz potrivit (din 32768 se obtine usor 1 secunda prin divizari), se poate construi un ceas destul de bun.

mai am o intrebare: trebuie un quartz pentru PIC si unul pentru RTC?

La RTC quarz, la pic nu neaparat quarz, dar un oscilator da. Quarzul e mai precis, da' daca tot ai unul la RTC, poti incerca si un oscilator RC pentru pic (pagina 123). Sau alegi un alt pic, care sa aibe oscilator intern.La cod nu ma bag.LE Cam asa arata codul pentru ceas la mine:Initializare:
    // Timer1 - ceas    TMR1L = 0x00;    TMR1H = 0x80; // => aprox. 1 sec.    T1CON = 0b00001111; // activate the timer 1    //intreruperi generale (INTCON):    // Global Interrupt Enable = 1    // Periferal Interrupt Enabled (pentru TX)    // Timer 0 Interrupt Disable    // RB Port Change Interrupt disabled    // RB0/INT disabled, o activez cand am nevoie sa potrivesc ceasul    INTCON = 0b11000000;    //intreruperi periferice (PIE1)    // RXIE enabled, TMR1IE enabled    PIE1 = 0b00100001;
Intrerupere
   if(TMR1IF && TMR1IE)  /*ceas*/   {       T1CON = 0b00001110;    // stop the timer        TMR1L = 0x00;              TMR1H = 0x80;          // ~ 1 sec       T1CON = 0b00001111;    // start the timer              Flags.ClkInt = 1; //variabila folosita in program        TMR1IF = 0;   }
Program
        if (Flags.ClkInt) // daca vine o intrerupere de la ceas si nu sunt in programare (la fiecare secunda)        {            Flags.ClkInt = 0;            if (Flags.TrOk)....
Undeva in program mai trebuie activate intreruperile.
Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări