Fórum témák

» Több friss téma
Fórum » PIC programozása C nyelven, C-Compiler
Lapozás: OK   105 / 153
(#) Hp41C válasza AZoli hozzászólására (») Szept 14, 2014 /
 
  1. unsigned long ProgMemoryAddress = 0x40000 + (0x4000 * (long)WhitchMap);

helyett írd így:
  1. unsigned long ProgMemoryAddress = 0x40000UL + (0x4000UL * (unsigned long)WhitchMap);
(#) gacserus hozzászólása Szept 15, 2014 /
 
Sziasztok,

PIC12F1840/MPLAB/XC8 - UART kapcsán a következő rutinom van:
A rutin egy stringgel hívható aminek a végét a NULL terminátor ellenőrzésével ellenőrzi.

void Write2Serial (const char *DataOut)
{
while ((DataOut!="\0"))
{
EUSART_Write(*DataOut++);
//__delay_ms(50);
}
}

A rutint az alábbi módon hívom meg de nem érzékeli a végét:

const char str1[] ="OK";
Write2Serial(str1);

Próbáűltam így is:
const char str2[] ={'O','K','\0'};
Write2Serial(str2);

Mi lehet az oka?

Egyetlen mód ahogy megy az a következő:
Write2Serial("OK");

De én egy változóval szeretném meghívni.

Előre is kösz,

Gacserus
(#) Hp41C válasza gacserus hozzászólására (») Szept 15, 2014 /
 
A const char* az XC8 -ban egy ROM -ban tárolt karakterlánc mutató, ezért fogadja el csak a "OK" parametert. Javítsd ki a deklarációt:
  1. void Write2Serial (char *DataOut)

Ezt az eljárást már hívhítod így is:
  1. const char str1[] ="OK";
  2. Write2Serial(str1);
(#) gacserus hozzászólása Szept 15, 2014 /
 
Köszi a tippet,

kijavítottam:
void Write2Serial ( char *DataOut)
{
while ((DataOut!="\0"))
{
EUSART_Write(*DataOut++);
//__delay_ms(50);
}
}

Hibaüzenetet kaptam:
can't generate code for this expression

Így hívom meg:

char str1[] ="OK";
Write2Serial(str1);
(#) icserny válasza gacserus hozzászólására (») Szept 16, 2014 /
 
Idézet:
„while ((DataOut!="\0"))”

A fenti sor nem jó, mert a macskaköröm használata stringet eredményez, amit egy mutatóval akarsz összehasonlítani. Én inkább így próbálnám:

  1. void Write2Serial ( char *DataOut)
  2. {
  3.     while (*DataOut)
  4.     {
  5.         EUSART_Write(*DataOut++);
  6.     }
  7. }
(#) watt válasza gacserus hozzászólására (») Szept 16, 2014 /
 
Tudom, hogy a fórum azért van, hogy kérdezz, de még is megpróbálhatnád leszimulálni a programodat és rögtön kiderülne minden kérdésedre a válasz...
(#) AZoli válasza Hp41C hozzászólására (») Szept 16, 2014 /
 
Köszi, ez végül megoldódott annyival hogy a WhitchMap az unsigned int lett.

Viszont most nem tudok double -t csinálni két unsigned int -ből.
Az a problémám, hogy PID szabályzó egy hatalmas unsigned int tömb 2 eleméből kéne hogy kapja a "P" értékét, ami double.
A double 0.1 az a memóriában 0x3DCCCCCD azaz elvileg össze kéne hogy tudjam rakni 2 int-ből:
  1. long valami = ((long)(0x3DCC) << 16) | 0xCCCD;
  2. double P = valami;

valami-be szépen bekerül a 0x3DCCCCCD, de a P -ben 0x4E773333 lesz...
(#) watt válasza AZoli hozzászólására (») Szept 16, 2014 /
 
Miért akarod lebegőpontos számításokkal megfojtani szegény PIC-et!? Egészekkel nem lehetne megoldani? (dehogynem ).
(#) AZoli válasza watt hozzászólására (») Szept 16, 2014 /
 
24EP512... családból való. Meg se kottyan neki . Régen a 18F -eken asm-ban én is úgy csináltam, de azért váltottam C-re hogy lehessen így. Lemértem szimulátorban, gyorsabb a C-s lebegőpontos PID rutinom optimalizáció nélkül ezen (120MHz), mint a 18F -eken volt asm-ben egész számokkal. Csak az ilyenek miatt haragszom a C -re... évek óta barátkozom vele, de valamiért nagyon nem tudom befogadni néhány hülyeségét.
(#) watt válasza AZoli hozzászólására (») Szept 16, 2014 /
 
Akkor ez a megoldás(lásd a képet).
Javaslom neked is a szimulációt!!!
Ja igen, a bal felső és a középső alsó számot nézd! Titok a lebegőpontos szám ábrázolás...
A hozzászólás módosítva: Szept 16, 2014
(#) AZoli válasza watt hozzászólására (») Szept 16, 2014 /
 
Én is szimulátorban (vagyis debug alatt) nézem.
Ezt az összefüggést én nem vettem észre, de nem tudom ez hogyan segít nekem.
P-ben 0.1 -et, azaz 0x3DCCCCCD kéne hogy lássak, ehelyett 1.03683194E9 azaz 0x4E773333 van. Mint nálad.
Értem én hogy a fordító helyettem próbál gondolkodni, és a hex- ből decimálist csinál, majd azt tárolja el hatvány alakban, de ezzel (hogy okos próbál lenni) az őrületbe kerget. Muszáj lesz asm betétekkel arra a memória címre másolnom azt a 2 word-öt.
(#) watt válasza AZoli hozzászólására (») Szept 16, 2014 /
 
Dehogy okoskodik! A lebegőpontos számábrázolás ilyen formában tárolja a long értékét. Igaz kerekíti, mert nem fér bele. 0x3DCCCCCD=1036831949, ami 1.036832E+9, azaz 1036820000.
(#) AZoli válasza watt hozzászólására (») Szept 16, 2014 /
 
Na jó, de nekem ne foglalkozzon a long "értékével", hanem a nullákat és egyeseket pakolja át egyik memória címről a másikra. Az hogy az egyik long, a másik double, azon ne gondolkodjon, mert megárt! Főleg nekem...
De érdekel más megoldás is.
Akkor hogy csinálnátok azt, hogy pl. soros porton PC-ről átküldeni egy 32biten tárolt double-t? Szét kell szednem 4 byte-á, majd a PIC-ben összerakni. Na ezzel az összerakással van bajom.

Persze a PC oldalt még nem néztem, remélem valamennyire szabványosak C -ben ezek a számábrázolások, és ott nem kell assembly, mert különben keresek valami más hobbit.
A hozzászólás módosítva: Szept 16, 2014
(#) watt válasza AZoli hozzászólására (») Szept 16, 2014 /
 
De hiszen te akarod double típusba pakolni a long-ot, ami nem fér bele!
Simán össze lehet rakni. De egyelőre azt nem értem minek rakod bele, miért nem a long-ot küldöd át azt csak össze kell állítani simán!

Közben módosítottál, úgy olvastam az előbb, hogy a PC-re akarod küldeni a double-t. Akkor mi a feladat?
A hozzászólás módosítva: Szept 16, 2014
(#) AZoli válasza watt hozzászólására (») Szept 16, 2014 /
 
PC-ről PIC-re. És a PIC-ben összerakni, majd double-ként felhasználni.
Idézet:
„De hiszen te akarod double típusba pakolni a long-ot, ami nem fér bele!”

De hát mind a kettő 32bites, nem?
(#) Hp41C válasza AZoli hozzászólására (») Szept 16, 2014 / 1
 
A megoldás az union: 4 byte, 2 word, 1 longword és egy float elfér 32 biten. A kérdés az, hogy a fordító hány biten ábrázolja e double -t.
(#) AZoli válasza AZoli hozzászólására (») Szept 16, 2014 /
 
Lehet hogy az lesz a megoldás hogy csinálok egy union-t... így ugyan azt a memóriaterületet elérem long-ként a (és char -ként) a soros port kezelő függvényből, majd a PID függvény eléri ugyan ezt a memória területet double-ként.
(#) AZoli válasza Hp41C hozzászólására (») Szept 16, 2014 /
 
Uhhh.. gyors vagy, köszi!
(#) watt válasza Hp41C hozzászólására (») Szept 16, 2014 /
 
Szia! A fordító 4 bájton ábrázolja a double-t és a float-ot is. Gyakorlatilag a kettő itt ugyanaz.
(#) AZoli válasza watt hozzászólására (») Szept 16, 2014 /
 
Köszi mindkettőtöknek! Így már működik.
Tehát e- helyett:
  1. long valami = ((long)(0x3DCC) << 16) | 0xCCCD;
  2. double P = valami;

Ez:
  1. union
  2.         {
  3.            struct
  4.            {
  5.                uInt L;
  6.                uInt H;
  7.            }st;
  8.            double Dbl;
  9.         }U;
  10.  
  11.         U.st.H = 0x3DCC;  //persze ezek a konstasok helyett változók
  12.         U.st.L = 0xCCCD;
  13.         double P = U.Dbl;
(#) Hp41C válasza AZoli hozzászólására (») Szept 16, 2014 /
 
... és még azt a sok léptetést is megúszod...
(#) watt válasza AZoli hozzászólására (») Szept 16, 2014 /
 
Ja, hogy a 0x3DCCCCCD egy törtszám lebegőpontosan (0.1)? Ezt eddig nem értettem meg...
A hozzászólás módosítva: Szept 16, 2014
(#) potyo válasza AZoli hozzászólására (») Szept 16, 2014 /
 
Amúgy lehet ám C-ben cast-olni is, nem muszáj uniont használni. Csinálsz float/double változót, majd castolod az adott helyen long-ra vagy akár char-ra, és ugyanúgy ugyanazt a memóriaterületet éred el. Néha célszerűbb az union, néha a castolás, helyzettől függ.
Pl.
  1. float valtozo;
  2. long valami = *(long*)&valtozo;
  3. Vagy soros átküldéshez a bájtok
  4. unsigned char bajt2=((unsigned char *)&valtozo)[2];
A hozzászólás módosítva: Szept 16, 2014
(#) AZoli válasza potyo hozzászólására (») Szept 17, 2014 /
 
watt:
Idézet:
„Ja, hogy a 0x3DCCCCCD egy törtszám lebegőpontosan (0.1)?”

Pontosan így van, bocs ha félrevezető voltam.
Két uInt -ből (0x3DCC és 0xCCCD) kéne összeraknom a double 0.1 -et. Persze a konkrét számok csak egy példa.

Tökéletesen működik a fenti union-os megoldással, de potyo verzióját is szeretném megérteni. Bár az pont az ellenkező irány mint ami nekem kell, nem is értem teljesen, de az alapján ezt csináltam:
  1. double P = 0;
  2. unsigned int* P_Addr = &P;
  3.  
  4. *P_Addr = 0xCCCD;
  5. P_Addr++;
  6. *P_Addr = 0x3DCC;
  7. // Itt már P= 0.1

Szerk: De ez még mindig nem castolás...
A hozzászólás módosítva: Szept 17, 2014
(#) potyo válasza AZoli hozzászólására (») Szept 17, 2014 / 1
 
Nem castolás, de pointer aritmetika. Az is egy jó dolog a C-ben

  1. double P = 0;
  2.  
  3. ((unsigned *)&P)[0]=0xCCCD;
  4. ((unsigned *)&P)[1]=0x3DCC;


Ez azt csinálja, hogy kiszedi a P változó címét (ami ugye egy double-re mutató pointer), a címet castolja unsigned-re mutató pointerré, és utána azt a pointert indexeli 0-val és 1-el. Azért lehet indexelni, mert a pointer és egy tömb neve a C-ben majdnem ugyanazt jelenti. Ha egy adott típusra mutató pointert indexelsz, akkor az ugyanaz, mintha az adott típusból lenne egy tömböd, és azt indexelnéd.
A hozzászólás módosítva: Szept 17, 2014
(#) AZoli válasza potyo hozzászólására (») Szept 17, 2014 /
 
Köszi, Értem! Lett néhány megoldás a végére!
(#) watt válasza potyo hozzászólására (») Szept 17, 2014 /
 
Ezt nem ismertem, köszi! Nem is foglal nagy helyet, talán 21 parancs.
Eddig uniont használtam...

Az unsigned önmagában gondolom int-et jelent. Megcsináltam char-okkal, úgy is működik bájtonként, tetszik...
A hozzászólás módosítva: Szept 17, 2014
(#) potyo válasza watt hozzászólására (») Szept 17, 2014 /
 
Elvileg ez csak C-ben néz ki ilyen rosszul, lefordítva nem kellene, hogy vészes legyen a dolog. Ugyanaz kellene, hogy legyen, mintha a P már eleve egy unsigned típusú tömb lenne. Esetleg próbáld ki, hogy ugyanazt kapod-e, ha ezt csinálod
  1. unsigned P[2];
  2. P[0]=0xCCCD;
  3. P[1]=0x3DCC;


Na meg szintén elvileg ugyanaz, mintha az ember csinálna uniont és azzal végezne műveleteket egyszer double-ként, máskor másképp.

És még lehetne úgy is írni, hogy
  1. 0[((unsigned *)&P)]=0xCCCD;
  2. 1[((unsigned *)&P)]=0x3DCC;



int-et nem kötelező kiírni, mert az az alapértelmezett. Mint ahogy azt sem szokás írni, hogy signed int, hanem csak az int-et, mert a signed az alapértelmezett. Persze mindkettő egyszerre nem hagyható el, de ha már az unsigned ott van, akkor az int elhagyható.
A hozzászólás módosítva: Szept 17, 2014
(#) watt válasza potyo hozzászólására (») Szept 17, 2014 /
 
Igen, a művelet végzés unionnal szinte azonos méretet igényel. Valójában a fordító mindkét esetben előre elkészíti a kódot, csak a leírás formája más.
A hozzászólás módosítva: Szept 17, 2014
(#) Poostmaster hozzászólása Szept 29, 2014 /
 
Sziasztok!
Van egy 5*5-ös led mátrixom. Mindenféle képeket rajzolnák ki vele, amit aztán körbeforgatok. Azért, hogy ne legyen olyan nagy fogyasztása, multiplexelve rajzolnám a képeket.
most az a bajom, hogy így sokkal halványabban világítanak a ledek. Meg lehet úgy oldani, hogy ne veszítsenek sokat a fényerejükből?
Ez a program:
  1. #include <xc.h>
  2.  
  3. // CONFIG1
  4. #pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
  5. #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
  6. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  7. #pragma config MCLRE = ON       // RE3/MCLR pin function select bit (RE3/MCLR pin function is MCLR)
  8. #pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
  9. #pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
  10. #pragma config BOREN = ON       // Brown Out Reset Selection bits (BOR enabled)
  11. #pragma config IESO = ON        // Internal External Switchover bit (Internal/External Switchover mode is enabled)
  12. #pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)
  13. #pragma config LVP = OFF        // Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming)
  14.  
  15. // CONFIG2
  16. #pragma config BOR4V = BOR40V   // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
  17. #pragma config WRT = OFF        // Flash Program Memory Self Write Enable bits (Write protection off)
  18.  
  19. #define _output 0x00
  20. #define _input  0xFF
  21. #define _XTAL_FREQ 20000000
  22. #define Be 1
  23. #define Ki 0
  24.  
  25. char ForgoB;
  26. char ForgoC;
  27. char ForgoD;
  28.  
  29. void s_delay(unsigned int iPiheno){
  30.             for (unsigned int y = 0; y < iPiheno; y++){
  31.         __delay_ms(1);
  32.         };
  33.     };
  34.  
  35. void _RotateLeft_D(char cFDTemp, char cStep){
  36.     char DMagas;
  37.     for (char Lep = 1; Lep <= cStep; Lep++){
  38.     DMagas = (cFDTemp&128)>>7;
  39.     cFDTemp = (cFDTemp<<1)|DMagas;
  40.     }
  41.     ForgoD = cFDTemp;
  42. }
  43.  
  44. void _RotateRight_D(char cFDTemp, char cStep){
  45.     char DAlacsony;
  46.     for (char Lep = 1; Lep <= cStep; Lep++){
  47.     DAlacsony = (cFDTemp&1)<<7;
  48.     cFDTemp = (cFDTemp>>1)|DAlacsony;
  49.     }
  50.     ForgoD = cFDTemp;
  51. }
  52.  
  53. void _RotateLeft_2(char cFBTemp, char cFCTemp, char cStep){
  54.     char CMagas, BMagas;
  55.     for (char Lep = 1; Lep <= cStep; Lep++){
  56.     CMagas = (cFCTemp&128)>>7;
  57.     BMagas = (cFBTemp&128)>>7;
  58.     cFBTemp = (cFBTemp<<1)|CMagas;
  59.     cFCTemp = (cFCTemp<<1)|BMagas;
  60.     }
  61.     ForgoB = cFBTemp;
  62.     ForgoC = cFCTemp;
  63. }
  64.  
  65. void _RotateRight_2(char cFBTemp, char cFCTemp, char cStep){
  66.     char CAlacsony, BAlacsony;
  67.     for (char Lep = 1; Lep <= cStep; Lep++){
  68.     CAlacsony = (cFCTemp&1)<<7;
  69.     BAlacsony = (cFBTemp&1)<<7;
  70.     cFBTemp = (cFBTemp>>1)|CAlacsony;
  71.     cFCTemp = (cFCTemp>>1)|BAlacsony;
  72.     }
  73.     ForgoB = cFBTemp;
  74.     ForgoC = cFCTemp;
  75. }
  76. main(void) {
  77.     ANSEL = 0;
  78.     ANSELH = 0;
  79.     TRISA = _output;
  80.     TRISB = _output;
  81.     TRISC = _output;
  82.     TRISD = _output;
  83.     PORTB = 0;
  84.     PORTA = 0;
  85.     PORTC = 0;
  86.     PORTD = 0;
  87. /**/
  88.     ForgoB = 55;
  89.     ForgoC = 25;
  90.     ForgoD = 0;
  91.     PORTC = ForgoC;
  92.     PORTB = ForgoB;
  93.     PORTD = ForgoD;
  94.     for (int iter = 1; iter < 15000; iter++){
  95.     _RotateLeft_2(ForgoB,ForgoC,2);
  96.     _RotateRight_D(ForgoD,1);
  97.     PORTC = ForgoC;
  98.     PORTB = ForgoB;
  99.     PORTD = ForgoD;
  100.     }
  101.    while (1){
  102.        
  103.     }
  104. }
Következő: »»   105 / 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