Liviu M Postat Aprilie 11, 2014 Partajează Postat Aprilie 11, 2014 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
Mircea Postat Aprilie 11, 2014 Partajează Postat Aprilie 11, 2014 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
Myhayxx Postat Aprilie 12, 2014 Autor Partajează Postat Aprilie 12, 2014 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 }} Link spre comentariu
Liviu M Postat Aprilie 12, 2014 Partajează Postat Aprilie 12, 2014 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
Myhayxx Postat Aprilie 12, 2014 Autor Partajează Postat Aprilie 12, 2014 PS Foloseste, te rog, tagurile code pentru cod.nu stiu cum 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
Liviu M Postat Aprilie 12, 2014 Partajează Postat Aprilie 12, 2014 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
Mircea Postat Aprilie 13, 2014 Partajează Postat Aprilie 13, 2014 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. 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 . Link spre comentariu
Myhayxx Postat Aprilie 13, 2014 Autor Partajează Postat Aprilie 13, 2014 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 inca odata mii de multumiri celor care m-au ajutat! o sa va mai bat la cap sper sa nu va deranjeze prea tare Link spre comentariu
Liviu M Postat Aprilie 13, 2014 Partajează Postat Aprilie 13, 2014 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). 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
Myhayxx Postat Aprilie 13, 2014 Autor Partajează Postat Aprilie 13, 2014 *) Quarz de 32768 Hz + TMR1ce 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 } Link spre comentariu
Liviu M Postat Aprilie 13, 2014 Partajează Postat Aprilie 13, 2014 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
Postări Recomandate
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 contAutentificare
Ai deja un cont? Autentifică-te aici.
Autentifică-te acum