Fórum témák

» Több friss téma
Fórum » PIC programozása C nyelven, C-Compiler
Lapozás: OK   149 / 153
(#) Hp41C válasza Laja1 hozzászólására (») Ápr 21, 2021 /
 
Az lehet a gond, hogy a tmr1 tovább számol a TMR1IF beállítása után, de a program megint csak a 3035=65536-62500 -at tölti bele, azaz néhány számlálás elveszik másodpercenként.

A jó módszer a TMR1 aktuális értékéhez való hozzáadás lenne, ami nem egyszerű a 16 bites érték és a módosítás közbeni alsó byte átfordulás miatt. (ld.Timer1 Errata).

Jobb lett volna a TMR2 -t használni. Vele nem lehet 1s időt előállítani, de ha hozzáteszünk egy szoftver számlálót, akkor meg lehet csinálni.

16F716.c
    
(#) Laja1 válasza Hp41C hozzászólására (») Ápr 21, 2021 /
 
Igazad van, ez lehet az oka, erre nem is gondoltam. De ha a frekvenciát úgy vesszük fel az elején, hogy a timer nulláról épp 1 sec alatt csorduljon túl, akkor végülis megoldottuk!
(#) ktamas66 válasza Laja1 hozzászólására (») Ápr 21, 2021 /
 
Vagy használhatod a CCP modul special event triggert, az automatikusan nullázza a TMR1-et.
(#) Laja1 hozzászólása Ápr 26, 2021 /
 
Azt meg tudjátok mondani, hogy hogy lehet azt programozni, hogy a PIC egyik bemenetére érkező jel (Volt) a nagyobb, vagy a másik bemenetelére érkező? Nem kell tudni, hogy melyik mennyi, csak a relációt. 0-5 V-os jelek érkeznek. Természetesen a bemeneteknél az analóg bemeneteket választom, de aztán megállt a tudomány. Csináltam már ADC-t használó programot, de az csak egy bemenetet használt. Köszönöm!
(#) Bakman válasza Laja1 hozzászólására (») Ápr 26, 2021 / 1
 
Erre való a komparátor modul.
(#) Laja1 válasza Bakman hozzászólására (») Ápr 26, 2021 /
 
Igen tudom, de ez annyival volna bonyolultabb, hogy ha a két érték viszonylag közel van egymáshoz (pl. 10 %-on belül), akkor azt még egyenlőnek tekintse. Szerintem a komparátor ezt nem tudja.
(#) benjami válasza Laja1 hozzászólására (») Ápr 26, 2021 / 1
 
A komparátor csak 2 értéket tud eredményül adni (kisebb/nagyobb). Ha 3 részre szeretnéd bontani az összehasonlítást, ahhoz 2db komparátor kell, vagy AD átalakító.
(#) Bakman válasza Laja1 hozzászólására (») Ápr 26, 2021 / 1
 
Akkor ADC. A mérés eredménye alapján döntöd el, hogy melyik a nagyobb, illetve ha a tűrésen belül van, akkor egyenlő.

Éppen úgy működik a dolog mintha egy csatornát használnál, de jelen esetben kettőt fogsz és két mérési eredményed lesz. PIC függő a dolog pontos menete de valószínűleg az ADCON0 regiszterrel lehet csatornát váltani.

Csatonaváltás, mérés, eredmény kiolvasása, csatornaváltás, mérés, eredmény kiolvasása egy második változóba. Ezután pl. egyiket kivonod a másikból. Ha az eredmény kevesebb mint -10, akkor kevesebb, ha nagyobb mint 10, akkor nagyobb és ha a kettő között van, akkor pedig egyenlő. Hasraütéses számok, a pontos értékeket számolni kell.
(#) Laja1 válasza Bakman hozzászólására (») Ápr 26, 2021 /
 
Én így gondoltam, de nem működik (a főprogram még nincs kidolgozva, az már egyszerűbb lesz)
  1. #include <xc.h>
  2.  
  3. #define _XTAL_FREQ 20000000 //define crystal frequency to 20MHz
  4.  
  5. // CONFIG
  6. #pragma config FOSC = XT     // Oscillator ion bits (RC oscillator)
  7. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  8. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  9. #pragma config BOREN = OFF       // Brown-out Reset Enable bit (BOR disabled)
  10. #pragma config CP = OFF      // Flash Program Memory Code Protection bit (Code protection off)
  11.  
  12. unsigned int counter = 0;
  13. int adc_valuek;
  14. int adc_valueb;//store output value  Analog Read functoion
  15. unsigned int number;
  16. long tlong;
  17. unsigned int voltage;
  18.  
  19.  
  20. void Analog_setting(){
  21.     ADCON0 = 0x81;
  22.     ADCON1 = 0x02;}
  23.    
  24.     unsigned int Analog_read(unsigned char channel){
  25.     int aadc,bbdc, ccdc;
  26.     if(channel>7)return 0;
  27.     ADCON0 = ADCON0 & 0xC5;
  28.     ADCON0 = ADCON0 | (channel << 3);
  29.     __delay_ms(2);
  30.     ADCON0bits.GO_DONE = 1;
  31.     while(ADCON0bits.GO_DONE);
  32.     {
  33.     aadc = ADRES;
  34.    // aadc = aadc<<2;
  35.     bbdc = ADRES;
  36.     //bbdc = bbdc >>6;
  37.     ccdc = aadc|bbdc;
  38.     return ccdc;}
  39.  
  40. }
  41. void main(void) {
  42.      Analog_setting();
  43.     TRISB = 0x00; //define PORTD as a output pin
  44.     PORTB=0X00;   // initialize PORTD pins to active low
  45.     TRISB=0X00;
  46.  
  47.     while(1)
  48.       {
  49.           adc_valuek = Analog_read(0);  // read data  channel 0
  50.           adc_valueb = Analog_read(1);
  51.            
  52.            
  53.         if (adc_valuek<<adc_valueb)
  54.            {PORTB.bitsRB0=1;
  55.                  
  56.             __delay_ms(3000);
  57.             PORTB.bitsRB1=0;
  58.            
  59.         }
  60. }
  61. }
(#) Bakman válasza Laja1 hozzászólására (») Ápr 26, 2021 /
 
Pontosan melyik PIC-ről van szó?
(#) Laja1 válasza Bakman hozzászólására (») Ápr 26, 2021 /
 
(#) Hp41C válasza Laja1 hozzászólására (») Ápr 26, 2021 /
 
Idézet:
„Én így gondoltam, de nem működik”

Hiszen le sem fordul...
A PORT.bitsRB0 nem értelmezett azonosító, a PORTBbits.RB0 lenne a jó.

Felhívnám a figyelmet arra, hogy a 16F716 -ban csak 8 bites A/D van.


unsigned char adc_valuek;
unsigned char adc_valueb;//store output value Analog Read functoion


void Analog_setting(){
ADCON0 = 0x81;
ADCON1 = 0x02;
}

unsigned char Analog_read(unsigned char channel){

if(channel>7)return 0;
ADCON0 = ADCON0 & 0xC5;
ADCON0 = ADCON0 | (channel << 3);
__delay_ms(2);

ADCON0bits.GO_DONE = 1;
while(ADCON0bits.GO_DONE);

return ADRES;
}
A hozzászólás módosítva: Ápr 26, 2021
(#) Laja1 válasza Hp41C hozzászólására (») Ápr 28, 2021 /
 
Szia!

Köszönöm! Elmagyaráznád ennek a logikáját, mert nem értem?
ADCON0 = 0x81;ADCON1 = 0x02; Ezeket értem, itt állítjuk be a paramétereket.
Az alábbiakat nem értem:
if(channel>7)return 0;
ADCON0 = ADCON0 & 0xC5;
ADCON0 = ADCON0 | (channel << 3); Ebben a 3 sorban mit csinálunk?
__delay_ms(2); Itt megvárjuk, hogy az átalakítás megtörténjen.
ADCON0bits.GO_DONE = 1;Itt indítjuk az ADC-t
return ADRES = itt visszatérünk oda, ahol tároljuk az elmentett értéket. Ez már digitális adat?
(#) icserny válasza Laja1 hozzászólására (») Ápr 28, 2021 /
 
  1. if(channel>7)return 0;  //Érvénytelen csatornaszámnál visszatérés 0-val
  2. ADCON0 = ADCON0 & 0xC5;  // Töröljük ADCON0 1., 3., 4. és 5. bitjeit
  3. ADCON0 = ADCON0 | (channel << 3); // 1-be állítjuk a 3., 4. és 5. bit közül azokat,
  4. //amelyek értéke chan-ban is 1, azaz bemásojuk a helyére a csatornaválsztó biteket
(#) Hp41C válasza Laja1 hozzászólására (») Ápr 28, 2021 /
 
Idézet:
„if(channel>7)return 0;”

A 16F716 -on 8 analóg csatornát lehet választani (0 .. 7), ha valaki nagyobb csatorna számot adna meg, a mért érték 0.
Idézet:
„ADCON0 = ADCON0 & 0xC5;”

A mérni kívánt csatorna számát az ADCON0 5..3 bitjeivel lehet kiválasztani. Ez az utasítás törli az 5..3 és a 1. bitet (ami nem használt).
Idézet:
„ADCON0 = ADCON0 | (channel << 3);”

A mérni kívánt csatorna számát az ADCON0 5..3 bitjeivel lehet kiválasztani, ezeket a biteket a kapott csatorna száma alapján állítja be. Az értéket 3 bittel balra lépteti és az előzőleg 0 állított bitek helyére "írja" (logikai vagy kapcsolattal).
Idézet:
„__delay_ms(2);”

Itt megvárjuk, hogy belső kondenzátorok felvegyék a bemeneten levő feszültséget.
Idézet:
„ADCON0bits.GO_DONE = 1;Itt indítjuk az ADC-t”

Idézet:
„while(ADCON0bits.GO_DONE);”

Megvárjuk az átalakítás végét.
Idézet:
„return ADRES;”

Egy eljárásban vagyunk, amit több helyről is meg lehet hívni. Az eljárás egy visszatérési értékkel deklaráltuk: unsigned char Analog_read(unsigned char channel)
Ez az utasítás kiolvassa az ADRES (8 bites resiszter) értékét és visszatér oda, ahonnan hívták az eljárást. Az ADRES a kiválasztott csatornán történt mérés digitális formáját tartalmazza.
(#) Laja1 válasza Hp41C hozzászólására (») Ápr 28, 2021 /
 
Köszönöm, értem!!
Korábban azért figyelmeztettél, hogy 8 bit-es az ADC ebben a PIC-ben, mert így a felbontás nem 1024, hanem csak 256? Így ez pontatlanabb?
Ha 10 bit-eset választok, akkor a 10 bit 8 bitjét az ADRESL és a maradék 2 bitjét az ADRESH-ba kell rakni?
Így?
if(channel>7)return 0;
ADCON0 = ADCON0 & 0xC5;
ADCON0 = ADCON0 | (channel << 3);
__delay_ms(2);
ADCON0bits.GO_DONE = 1;
while(ADCON0bits.GO_DONE);
aadc = ADRESH;
aadc = aadc<<2;
bbdc = ADRESL;
bbdc = bbdc >>6;
ccdc = aadc|bbdc;
return ccdc;
(#) Hp41C válasza Laja1 hozzászólására (») Ápr 28, 2021 /
 
Idézet:
„Ha 10 bit-eset választok, akkor a 10 bit 8 bitjét az ADRESL és a maradék 2 bitjét az ADRESH-ba kell rakni?”

Az átalakítás végén 12 bites értéket ad az A/D. Hogy miként kell értelmezni az ADRESH és ADRESL regisztereket, beállítható az ADCON1 regiszterben.
A 16F818 adatlapjából:
Idézet:
„bit 7 ADFM: A/D Result Format Select bit
1 = Right justified, 6 Most Significant bits of ADRESH are read as ‘0’
0 = Left justified, 6 Least Significant bits of ADRESL are read as ‘0’”


  1. void Analog_setting(){
  2. ADCON1 = 0x80;  // PCFG3..0: AN4..AN0 analog, ADFM: 1
  3. ADCON0 = 0x81;  // ADCS: Fosc/64, ADON: 1
  4. }
  5. unsigned int Analog_read(unsigned char channel){
  6. unsigned int value;
  7.  if(channel>7)return 0;
  8. ADCON0 = ADCON0 & 0xC5;
  9. ADCON0 = ADCON0 | (channel << 3);
  10. __delay_ms(2);
  11.  
  12. ADCON0bits.GO_DONE = 1;
  13. while(ADCON0bits.GO_DONE);
  14.  
  15. value = ADRESH;
  16. value <<=8;
  17. value |= ADRESL;
  18.  
  19. return value;
  20. }



Érdemes egy típust csinálni:
  1. typedef u_n_i_o_n _BYTE_VAL
  2. {
  3.     int Val;
  4.     unsigned char bytes[2];
  5.     struct
  6.     {
  7.         unsigned char b0:1;
  8.         unsigned char b1:1;
  9.         unsigned char b2:1;
  10.         unsigned char b3:1;
  11.         unsigned char b4:1;
  12.         unsigned char b5:1;
  13.         unsigned char b6:1;
  14.         unsigned char b7:1;
  15.         unsigned char b8:1;
  16.         unsigned char b9:1;
  17.         unsigned char b10:1;
  18.         unsigned char b11:1;
  19.         unsigned char b12:1;
  20.         unsigned char b13:1;
  21.         unsigned char b14:1;
  22.         unsigned char b15:1;
  23.     } bits;
  24. } INT_VAL, INT_BITS;


Ekkor a
  1. unsigned int value;
  2. ...
  3. value = ADRESH;
  4. value <<=8;
  5. value |= ADRESL;
  6. return value;

helyett
  1. INT_VAL value;
  2. ...
  3. value.bytes[1] = ADRESH;
  4. value.bytes[0]= ADRESL;
  5. return value.Val;

lesz.
A hozzászólás módosítva: Ápr 28, 2021
(#) Laja1 válasza Hp41C hozzászólására (») Ápr 30, 2021 /
 
Azt nem értem, hogy ha ez egy 12 bit-es érték, akkor az ADFM-nél miért kell megadnunk, hogy a bitek hogy helyezkedjenek el? Azt gondolnám, hogy az ADRESL-be kerülne az alsó 8 bit, az ADRESH-ba a maradék 4 bit, a többi hely pedig automatikusan kinullázódna. Pontosan mit adunk meg az ADFM 0/1 értékével?
(#) benjami válasza Laja1 hozzászólására (») Ápr 30, 2021 /
 
Pedig van értelme. Mégpedig akkor, ha csak 8 bitet használunk fel belőle. Ekkor ADRESH-ban megkapjuk a felső 8 bitet, és nem kell a biteket tologatni.
(#) Hp41C válasza Laja1 hozzászólására (») Ápr 30, 2021 /
 
Kétféle módon kezelhető a mért érték:
0...1023: egész szám
0, 1/2024 .. , 1023/1024 helyett 0, 64/65536, ... 65471/65536 tört érték.
Az utóbbival egyes számítások egyszerűbbek.
(#) Laja1 válasza Hp41C hozzászólására (») Ápr 30, 2021 /
 
Pillanatnyilag a tört értékes megoldás nekem bonyolultabbnak tűnik, de biztos, hogy vannak olyan esetek, amikor az a jobb. Az egész számos megoldásnál az ADFM értéke 1 legyen?
(#) Hp41C válasza Laja1 hozzászólására (») Ápr 30, 2021 /
 
Idézet:
„Az egész számos megoldásnál az ADFM értéke 1 legyen?”

A 16F818 adatlapjából idéztem itt, 1 kell az egész szám formátum szerinti értelmezéshez. A kérdéses típus adatlapjában kell megnézni.
Idézet:
„Pillanatnyilag a tört értékes megoldás nekem bonyolultabbnak tűnik, de biztos, hogy vannak olyan esetek, amikor az a jobb.”

Vannak olyan típusok, is, amelyekben 12 bites az A/D. Tört ábrázolásnál nem változik a program, csak pontosabb lehet a kiszámított érték.
A hozzászólás módosítva: Ápr 30, 2021
(#) Zsora válasza Laja1 hozzászólására (») Ápr 30, 2021 /
 
Arra állítod be, ami neked (az adott feladatra) kényelmesebb, praktikusabb.
A hozzászólás módosítva: Ápr 30, 2021
(#) Laja1 válasza Hp41C hozzászólására (») Máj 1, 2021 /
 
Idézet:
„unsigned int value;
...
value = ADRESH;
value <<=8;
value |= ADRESL;
return value;”

Az én esetemben két analóg értéket kell összehasonlítani. Amikor már digitális értéke van (value), akkor is két értéknek kell lennie: valueb és valuek. A fenti idézett részbe ezt hogyan kell megkülönböztetnem?
(#) Hp41C válasza Laja1 hozzászólására (») Máj 1, 2021 /
 
Ahogy itt csináltad.
  1. adc_valuek = Analog_read(0);  // read data  channel 0
  2.           adc_valueb = Analog_read(1);  // read data  channel 1

Analog_read(unsigned char channel) egy eljárás. Minden hívása egy mérést végez a paraméterként átadott számú csatornán. A visszatérési értéke a mért érték (digitálisan).
Ha a típuson az A/D 8 bites, akkor célszerű unsigned char, ha 10 vagy 12 bites, akkor unsigned int típusú.

Ha a két mérés (a Analog_read() visszatérési értékét) eltárolod egy-egy (átmeneti) változóban, később műveleteket végezhetsz velük. Pl:
  1. if (adc_valuek < adc_valueb) PORTCbits.RC0 = 0;
  2.   if (adc_valuek > adc_valueb) PORTCbits.RC0 = 1;
(#) Laja1 válasza Hp41C hozzászólására (») Máj 2, 2021 /
 
Azt gondolnam, hogy az ADFM=1 meghatározza, hogy a bitek hova kerüljenek. Az ADRESL be 8 bit, az ADRESH ba pedig a felső kettő. De akkor mit csinálunk itt :
value = ADRESH;
value <<=8;
value |= ADRESL;
return value;”
És ez mennyire PIC függő?
(#) pipi válasza Laja1 hozzászólására (») Máj 3, 2021 /
 
Legyen ADRESH=0000 00xx, ADRESL=yyyy yyyy (4 bites bontásban az áttekinthetőségért)
A value-nek 16 bit hosszúnak kell lennie, mondjuk unsigned int...

value = ADRESH; value=0000 0000 0000 00xx
value <<=8; value=0000 00xx 0000 0000
value |= ADRESL; value=0000 00xx yyyy yyyy vagyis itt a 10 bit AD érték
A hozzászólás módosítva: Máj 3, 2021
(#) Hp41C válasza Laja1 hozzászólására (») Máj 4, 2021 /
 
Idézet:
„És ez mennyire PIC függő?”

8 biteseken általános. 16 és 32 bitesen nem kell, egyben beolvasható a 10 / 12 bites érték.
(#) sdrlab hozzászólása Máj 4, 2021 /
 
Xc16 fordító alatt el lehet érni valahogy a konkrét PIC flash méretét? Létezik rá valamilyen konstans?
(#) Zsora válasza sdrlab hozzászólására (») Máj 4, 2021 /
 
A header állományban vannak ilyen definíciók:
  1. #define __PROGRAM_BASE 0x200
  2. #define __PROGRAM_LENGTH 0xa9f8
  3. ...
  4. #define __DATA_BASE 0x800
  5. #define __DATA_LENGTH 0x2000
Következő: »»   149 / 153
Bejelentkezés

Belépés

Hirdetés
XDT.hu
Az oldalon sütiket használunk a helyes működéshez. Bővebb információt az adatvédelmi szabályzatban olvashatsz. Megértettem