Sari la conținut
ELFORUM - Forumul electronistilor

Cum sa programez un PIC


sofian

Postări Recomandate

Buna ziua, cum pot seta la pic16f876a portul A astfel incat A0,A1,A2 sa fie intrari analogice si restul sa fie iesiri digitale? nu pricep mare lucru din datashet la chestia cu registrii. folosesc compilatorul mikroC. Multumesc!

Incearca asa:
ADCON1 = 0b00000011;        // configure RA2 pin as analog  TRISA  = 0x07;              // PORTA.0-2 is input
Link spre comentariu
  • Răspunsuri 602
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • Liviu M

    54

  • Vlad Mihai

    28

  • bbogdanmircea

    27

  • seichter

    24

Top autori în acest subiect

Imagini postate

@Vlad: Nu poti.Combinatiile analog/digital sunt configurate cu bitii PCFG3:PCFG0 din registrul ADCON1.La pagina 128 in data-sheet ai combinatiile posibile. Cea mai apropiata de ce-ti trebuie pare PCFG3:PCFG0 = 0100, caz in care RA0, RA1 & RA3 sunt intrari analogice, ceilalti pini fiind digitali.

Link spre comentariu

multumesc Liviu, m-am uitat si eu in datasheet si am observat alea. O sa modific cablajul si pun in loc de A2, A3, acum ramane cum le declar in cod, poate imi dai o idee.@nico_2010 multumesc de sfat dar din pacate nu functioneaza.

Link spre comentariu

Si totusi, incearca acest cod si simuleaza-l (este facut in graba, fara pretentii):

MCU:             PIC16F876A                      http://ww1.microchip.com/downloads/en/DeviceDoc/39762d.pdf      Oscillator:      HS, 10.0000 MHz     Ext. Modules:    -     SW:              mikroC PRO for PIC                      http://www.mikroe.com/eng/products/view/7/mikroc-pro-for-pic/  */// LCD module connectionssbit 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;unsigned int temp_res[3];unsigned int i;char txt3[] = "Test ADC";char txt4[7];char txt5[7];char txt6[7];void main() {  ADCON1 = 0b00000011;        // configure RA2 pin as analog  TRISA  = 0x07;              // PORTA is input  TRISC  = 0;                 // PORTC is output  Lcd_Init();  Lcd_Cmd(_LCD_CLEAR);               // Clear display  Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off  Lcd_Out(1,6,txt3);                 // Write text in first row  Delay_ms(500);    Lcd_Cmd(_LCD_CLEAR);               // Clear display  do {  for(i=0;i<3;i++) temp_res[i] = ADC_Read(i);  // Get results of AD conversion  IntToStr(temp_res[0], txt4);  IntToStr(temp_res[1], txt5);  IntToStr(temp_res[2], txt6);  Lcd_Out(1,1,txt4);  Lcd_Out(1,5,txt5);  Lcd_Out(1,9,txt6);  } while(1);                 // endless loop}
Link spre comentariu

@nico am testat practic acum, am pus secventa ta de cod in codul meu. si nu merge. pe RA0 citest o tensiune de 12v cu divizor de tensiune de 10X, problema e ca mie in loc de 12v cat trebuie sa imi arate imi indica 55.55V. atasez codul.

sbit LCD_RS at RB2_bit;sbit LCD_EN at RB3_bit;sbit LCD_D4 at RB4_bit;sbit LCD_D5 at RB5_bit;sbit LCD_D6 at RB6_bit;sbit LCD_D7 at RB7_bit;sbit LCD_RS_Direction at TRISB2_bit;sbit LCD_EN_Direction at TRISB3_bit;sbit LCD_D4_Direction at TRISB4_bit;sbit LCD_D5_Direction at TRISB5_bit;sbit LCD_D6_Direction at TRISB6_bit;sbit LCD_D7_Direction at TRISB7_bit; //initiere conexiuni pic cu LCD  unsigned char txt1[] = "    Dc motor    ";  unsigned char txt2[] = "    Control     ";  unsigned char txt3[] = "     David      ";   unsigned char txt4[] ="    Valentin    ";  unsigned char ch;  unsigned short current_duty1,current_duty2;  unsigned int Tensiune,valoare_adc1,valoare_adc2,curent1,curent2;  unsigned long u,i;void main() {  TRISB = 0xC0;  PORTB = 0x00;  CMCON=7;  ADCON1 = 0b00000011;        // configure RA2 pin as analog  TRISA  = 0x07;              // PORTA.0-2 is input  TRISC.F7 = 1;                   //   butonul de oprire  TRISC.F6 = 1;                   //   butonul pentru dreapta motor1  TRISC.F5 = 1;                   //   butonul pentru stanga motor1  TRISB.F1 = 1;                   //   butonul pentru stanga motor2  TRISB.F0 = 1;                   //   butonul pentru dreapta motor2        TRISC.F0 = 0;                          //comanda motor1  TRISC.F3 = 0;                          //comanda motor1  TRISC.F4 = 0;                          //comanda motor2  TRISA.F4 = 0;                          //comanda motor2    PORTC.F0 = 0;                           //blocare motor1  PORTC.F3 = 0;                          //blocare motor1  PORTC.F4 = 0;                          //blocare motor2  PORTA.F4 = 0;                          //blocare motor2  PWM1_Init(10000);               //setare frecventa pwm1  10Khz  PWM2_Init(10000);                 //setare frecventa pwm2    10Khz  Lcd_Init();                        // Initialize LCD  Lcd_Cmd(_LCD_CLEAR);               // Clear display  Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off  Lcd_Out(1,1,txt1);                 // Write text in first row  Lcd_Out(2,1,txt2);                 // Write text in second row  Delay_ms(300);  Lcd_Cmd(_LCD_CLEAR);               // Clear display  Lcd_Out(1,1,txt3);                 // Write text in first row  Lcd_Out(2,1,txt4);                 // Write text in second row  Delay_ms(300);  Lcd_Cmd(_LCD_CLEAR);               // Clear display    LCD_Out(1, 1,"Va:");  LCD_Out(2, 1,"Sens:");  current_duty1  = 0;  current_duty2 = 0;                 // valori initiale   PWM1_Start();                       // start PWM1   PWM2_Start();                       // start PWM2  PWM1_Set_Duty(current_duty1);        // setare   factor de umplere  PWM2_Set_Duty(current_duty2);while (1) { //control sens motor1      if(PORTB.F1 == 0)                      //If the switch is pressed    {       Delay_ms(100);                             //Switch Debounce       if(PORTB.F1 == 0)                       //If the switch is still pressed       {          Delay_ms(100);        PORTC.F4 = 1;                          //1 logic        PORTA.F4 = 0;                          //0 logic        LCD_Out(2, 6,"St       ");       }    }  if(PORTB.F0 == 0)                      //If the switch is pressed    {       Delay_ms(100);                             //Switch Debounce       if(PORTB.F0 == 0)                       //If the switch is still pressed       {          Delay_ms(100);         PORTC.F4 = 0;                          //0 logic         PORTA.F4 = 1;                          //1 logic        LCD_Out(2, 6,"Dr       ");       }    }            //control sens motor2      if(PORTC.F6 == 0)                      //If the switch is pressed    {       Delay_ms(100);                             //Switch Debounce       if(PORTC.F6 == 0)                       //If the switch is still pressed       {          Delay_ms(100);         PORTC.F0 = 1;                           //1 logic         PORTC.F3 = 0;                          // 0 logic        LCD_Out(2, 9,"      Dr");       }    }  if(PORTC.F5 == 0)                      //If the switch is pressed    {       Delay_ms(100);                             //Switch Debounce       if(PORTC.F5 == 0)                       //If the switch is still pressed       {          Delay_ms(100);         PORTC.F0 = 0;                           //0 logic         PORTC.F3 = 1;                          // 1 logic        LCD_Out(2, 9,"      St");       }    }                 if(PORTC.F7 == 0)                          //If the switch is pressed    {       Delay_ms(100);                           //Switch Debounce       if(PORTC.F7 == 0)                        //If the switch is still pressed       {                         PORTC.F0 = 0;                        //blocare motor1           PORTC.F3 = 0;                        //blocare motor1           PORTC.F4 = 0;                        //blocare motor2           PORTA.F4 = 0;                        //blocare motor2          Delay_ms(100);        LCD_Out(2, 6,"   STOP     ");       }    }    //    /* end */         valoare_adc1 = ADC_Read(1); current_duty1= valoare_adc1>> 2;  // conversie citire de pe ADC din 10 Biti in 8 Biti    si setare pwm in fucntie de    ce citeste pe ADC PWM1_Set_Duty(current_duty1); valoare_adc2 = ADC_Read(2); current_duty2= valoare_adc2>> 2; // conversie citire de pe ADC din 10 Biti in 8 Biti    si setare pwm in fucntie de    ce citeste pe ADC PWM2_Set_Duty(current_duty2);            // Tensiune alimentare motoare            Tensiune=ADC_read(0);                // get ADC value for U from channel 1      u=(long)Tensiune*5555;         // covert adc reading to milivolts -valoare calculata in  functie de divizor rezistiv      u=u/1023;                            // 0..1023 -> 0-3500mV      ch=u/1000;                           // extract 10.00 U digit      if (ch==0)        {          LCD_Chr(1,4, 32);                // write empty space if digit is 0        }      else        {          LCD_Chr(1,4,48+ch);              // write ASCII digit at 1st row, 2nd column        }      ch=(u/100) %10;                      // extract 01.00 U digit      LCD_Chr_CP(48+ch);                   // write ASCII digit at cursor point        LCD_Chr_CP('.');                     // write '.' at cursor point      ch=(u/10) %10;                       // extract 00.10 U digit      LCD_Chr_CP(48+ch);                   // write ASCII digit at cursor point      ch=u %10;                            // extract 00.01 U digit      LCD_Chr_CP(48+ch);                  // write ASCII digit at cursor point      LCD_Chr_CP('V');                     // write 'V' at cursor point        }  }

codul presupune controlul independent a 2 motoare de cc cu o punte H L298N si turatie reglabila cu pwm(cu ajutorul unui potentiometru).

daca pun asta

ADCON1 = 0x80; TRISA = 0xFF; // PORTA is input
imi functioneaza ADC corect, dar nu merge RA4 ca iesire digitala.
Link spre comentariu

Verifica-l si acum:

sbit LCD_RS at RB2_bit;sbit LCD_EN at RB3_bit;sbit LCD_D4 at RB4_bit;sbit LCD_D5 at RB5_bit;sbit LCD_D6 at RB6_bit;sbit LCD_D7 at RB7_bit;sbit LCD_RS_Direction at TRISB2_bit;sbit LCD_EN_Direction at TRISB3_bit;sbit LCD_D4_Direction at TRISB4_bit;sbit LCD_D5_Direction at TRISB5_bit;sbit LCD_D6_Direction at TRISB6_bit;sbit LCD_D7_Direction at TRISB7_bit; //initiere conexiuni pic cu LCD  unsigned char txt1[] = "    Dc motor    ";  unsigned char txt2[] = "    Control     ";  unsigned char txt3[] = "     David      ";   unsigned char txt4[] ="    Valentin    ";   unsigned char txt5[7];    unsigned char txt6[7];  unsigned char ch;  unsigned short current_duty1,current_duty2;  unsigned int Tensiune,valoare_adc1,valoare_adc2,curent1,curent2;  //  Variabile  unsigned int temp_res1,temp_res2;  // adaugate de nico_2010  unsigned long u,i;void main() {  TRISB = 0xC0;  PORTB = 0x00;  CMCON=7;  ADCON1 = 0b00000011;        // configure RA2 pin as analog  TRISA  = 0x07;              // PORTA.0-2 is input  TRISC.F7 = 1;                   //   butonul de oprire  TRISC.F6 = 1;                   //   butonul pentru dreapta motor1  TRISC.F5 = 1;                   //   butonul pentru stanga motor1  TRISB.F1 = 1;                   //   butonul pentru stanga motor2  TRISB.F0 = 1;                   //   butonul pentru dreapta motor2  TRISC.F0 = 0;                          //comanda motor1  TRISC.F3 = 0;                          //comanda motor1  TRISC.F4 = 0;                          //comanda motor2  TRISA.F4 = 0;                          //comanda motor2  PORTC.F0 = 0;                           //blocare motor1  PORTC.F3 = 0;                          //blocare motor1  PORTC.F4 = 0;                          //blocare motor2  PORTA.F4 = 0;                          //blocare motor2  PWM1_Init(10000);               //setare frecventa pwm1  10Khz  PWM2_Init(10000);                 //setare frecventa pwm2    10Khz  Lcd_Init();                        // Initialize LCD  Lcd_Cmd(_LCD_CLEAR);               // Clear display  Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off  Lcd_Out(1,1,txt1);                 // Write text in first row  Lcd_Out(2,1,txt2);                 // Write text in second row  Delay_ms(300);  Lcd_Cmd(_LCD_CLEAR);               // Clear display  Lcd_Out(1,1,txt3);                 // Write text in first row  Lcd_Out(2,1,txt4);                 // Write text in second row  Delay_ms(300);  Lcd_Cmd(_LCD_CLEAR);               // Clear display  LCD_Out(1, 1,"Va:");  LCD_Out(2, 1,"Sens:");  current_duty1  = 0;  current_duty2 = 0;                 // valori initiale   PWM1_Start();                       // start PWM1   PWM2_Start();                       // start PWM2  PWM1_Set_Duty(current_duty1);        // setare   factor de umplere  PWM2_Set_Duty(current_duty2);while (1) { //control sens motor1      if(PORTB.F1 == 0)                      //If the switch is pressed    {       Delay_ms(100);                             //Switch Debounce       if(PORTB.F1 == 0)                       //If the switch is still pressed       {          Delay_ms(100);        PORTC.F4 = 1;                          //1 logic        PORTA.F4 = 0;                          //0 logic        LCD_Out(2, 6,"St       ");       }    }  if(PORTB.F0 == 0)                      //If the switch is pressed    {       Delay_ms(100);                             //Switch Debounce       if(PORTB.F0 == 0)                       //If the switch is still pressed       {          Delay_ms(100);         PORTC.F4 = 0;                          //0 logic         PORTA.F4 = 1;                          //1 logic        LCD_Out(2, 6,"Dr       ");       }    }    //control sens motor2      if(PORTC.F6 == 0)                      //If the switch is pressed    {       Delay_ms(100);                             //Switch Debounce       if(PORTC.F6 == 0)                       //If the switch is still pressed       {          Delay_ms(100);         PORTC.F0 = 1;                           //1 logic         PORTC.F3 = 0;                          // 0 logic        LCD_Out(2, 9,"      Dr");       }    }  if(PORTC.F5 == 0)                      //If the switch is pressed    {       Delay_ms(100);                             //Switch Debounce       if(PORTC.F5 == 0)                       //If the switch is still pressed       {          Delay_ms(100);         PORTC.F0 = 0;                           //0 logic         PORTC.F3 = 1;                          // 1 logic        LCD_Out(2, 9,"      St");       }    }     if(PORTC.F7 == 0)                          //If the switch is pressed    {       Delay_ms(100);                           //Switch Debounce       if(PORTC.F7 == 0)                        //If the switch is still pressed       {           PORTC.F0 = 0;                        //blocare motor1           PORTC.F3 = 0;                        //blocare motor1           PORTC.F4 = 0;                        //blocare motor2           PORTA.F4 = 0;                        //blocare motor2          Delay_ms(100);        LCD_Out(2, 6,"   STOP     ");       }    }    //    /* end */ valoare_adc1 = ADC_Read(1); current_duty1= valoare_adc1>> 2;  // conversie citire de pe ADC din 10 Biti in 8 Biti    si setare pwm in fucntie de    ce citeste pe ADC  //conversie int to string  IntToStr(current_duty1, txt5);  //pentru teste doar. nico_2010 PWM1_Set_Duty(current_duty1); valoare_adc2 = ADC_Read(2); current_duty2= valoare_adc2>> 2; // conversie citire de pe ADC din 10 Biti in 8 Biti    si setare pwm in fucntie de    ce citeste pe ADC //conversie int to string IntToStr(current_duty2, txt6); //pentru teste doar. nico_2010 PWM2_Set_Duty(current_duty2);      // Tensiune alimentare motoare      Tensiune=ADC_read(0);                // get ADC value for U from channel 1      u=(long)Tensiune*5555;         // covert adc reading to milivolts -valoare calculata in  functie de divizor rezistiv      u=u/1023;                            // 0..1023 -> 0-3500mV      ch=u/1000;                           // extract 10.00 U digit      if (ch==0)        {          LCD_Chr(1,1, 32);                // write empty space if digit is 0        }      else        {          LCD_Chr(1,1,48+ch);              // write ASCII digit at 1st row, 2nd column        }      ch=(u/100) %10;                      // extract 01.00 U digit      LCD_Chr_CP(48+ch);                   // write ASCII digit at cursor point        LCD_Chr(1,2,'.');                     // write '.' at cursor point      ch=(u/10) %10;                       // extract 00.10 U digit      LCD_Chr(1,3,(48+ch));                   // write ASCII digit at cursor point      ch=u %10;                            // extract 00.01 U digit      LCD_Chr(1,4,(48+ch));                  // write ASCII digit at cursor point      LCD_Chr_CP('V');                     // write 'V' at cursor point//afisare continut ADC 1 si 2 pentru testarea functionarii setarilor de utilizare a ADC. nico_2010  LCD_Out(1, 10,txt5);  LCD_Out(2, 10,txt6);  delay_ms(2500);   Lcd_Cmd(_LCD_CLEAR); } }
In coltul din dreapta, pe cele doua linii, incepand cu poz.10 vei regasi valoarea ADC 1, respectiv ADC 2, iar pe prima linie, poz.1 ai valoarea convertita a ADC 0
Link spre comentariu

Cu

ADCON1 = 0b00000011;        // configure RA2 pin as analog
foloseste referinta externa. Ce tensiune ai pe Vref+ (cum e legat pinul RA3)?

acum ramane cum le declar in cod, poate imi dai o idee.

N-am inteles intrebarea. RA0, RA1 & RA2 nu ajunge?ADCON1 = 0xY4?
Link spre comentariu

Cu

ADCON1 = 0b00000011;        // configure RA2 pin as analog
foloseste referinta externa. Ce tensiune ai pe Vref+ (cum e legat pinul RA3)?
Am pornit de la premisa ca Vref=tensiunea de alimentare de 5V, sper ca nu este gresita.
Link spre comentariu

@nico_2010 multumesc de ajutor dar nu afiseaza corect valoarea adc convertita adc0 imi afiseaza 5.55v desi trebuia sa afiseze 12v. celelalte 2 se comporta ciudat. invart un pic de potentiometre si imi arata maxim 255, potentiometrele sunt de 50k.@Liviu Ra3 este in aer.ziceai ca nu pot configura conform datasheet ra0,ra1,ra2 si restul sa fie digitali, ci trebuie sa fac cu ra0,ra1 si ra3 restul sa fie digitali nu? valoarea aia cu ADCON1=0xY4; nu e corecta imi da eroare.

Link spre comentariu

@nico_2010 multumesc de ajutor dar nu afiseaza corect valoarea adc convertita adc0 imi afiseaza 5.55v desi trebuia sa afiseze 12v. celelalte 2 se comporta ciudat. invart un pic de potentiometre si imi arata maxim 255, potentiometrele sunt de 50k.@Liviu Ra3 este in aer.

Conecteaza RA3 la +5V.Vezi in imaginea alaturata cum ar trebui sa iti apara pe LCD.

post-40487-139829668891_thumb.png

Link spre comentariu

da, acum functioneaza potentiomerele ok pe adc, la afisarea valorii adc0 convertite imi afiseaza 1.2 ma gandesc ca e o eroare undeva in soft nu? acum sa inteleg ca merge ra4 ca iesire digitala?

Link spre comentariu

da, acum functioneaza potentiomerele ok pe adc, la afisarea valorii adc0 convertite imi afiseaza 1.2 ma gandesc ca e o eroare undeva in soft nu? acum sa inteleg ca merge ra4 ca iesire digitala?

Testeaza-l pe RA4 punandu-l sa aprinda, de exemplu, un LED si apoi sa-l stinga.Edit: Nu-l vei putea folosi ca port digital I/O
Link spre comentariu

nu merge, am introdus noile date in codul meu, altfel nu am cum testa, pentru am deja cablajul facut, conform codului atunci cand apas un anumit buton RA4 se face 1 logic si impreuna cu alt pin care se face 0 logic roteste motorul intr-un sens. la mine e problema ca motorul se roteste doar cand ra4 e 0 adica intr-un singur sens. cand apas pe buton sa execute ra4 1 logic nu se intampla nimic. am masurat cu voltmetrul am 0V atunci cand ar trebuie sa fie 1 logic. codul e cel de mai sus. la care am pus modificarile din codul de la nico_2010 cu privire la adcon si portulA. e sa aiba? mentionez ca ma chinui cu acest pin ca nu mai am alt pin pe alt port, as mai avea liber RA5. multumescpai atunci nu ma ajuta cu nimic ceea ce am facut noi adineari, ca si mie imi mergeau toate porturile adc corect, doar ca vroiam ca un port adc sa fie digital si nu am reusit. in rest mi-a functionat corect intrarile analogice.

Link spre comentariu

Ra5 e si intrare analogica AN4, nu mai trebuie sa modific nimic acolo la ADCON1? pur si simplu il declar ca iesire si gata? ar trebuie sa mearga?

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