Fórum témák

» Több friss téma
Fórum » MSP430 mikrovezérlők
 
Témaindító: gomzito, idő: Ápr 21, 2006
Témakörök:
Lapozás: OK   102 / 139
(#) szitko hozzászólása Ápr 20, 2013 /
 
Sziasztok.

Két problémával fordulok hozzátok.
Első.: Segítséget szeretnék kérni a mutatók megértésében. Egyszerűen nem megy a fejembe, hogy hogy működik. Már több könyvet (PIC prog. C ny., A C prog nyelv...) és weboldalt (pl. Icserny oldala) átnéztem, de még mindig nem értem. Pl. egy mutató, honnan tudja, hogy egy több dimenziós tömbből melyik értéket szeretném kiolvasni.........
Ha esetleg valaki szánna rám egy kis időt, és konyhanyelven leírná pár sorba a mutatók működését, nagyon megköszönném.

Második.: Kaptam egy jó csomó, mindenféle IC-t (CMOS, TTL stb..) Találtam az egyik "sínben" 2db ENC28j60-as Ethernet vezérlőt, és ezért elkezdtem foglalkozni ezzel az IC-vel. Első körben megpróbáltam egy MSP430f5510-el meghajtani, de mivel még nem foglalkoztam az 5510-el inkább félreraktam.
Most egy g2553-al próbálkozom, kisebb-nagyobb sikerrel, Duncan Frost blogjában leírtak alapján. Közben láttam, hogy Icserny fórumtársunk is foglalkozott már ezzel az Ethernet vezérlővel.
A ledek villogtatása nekem is sikerült, az ARP nem, igaz azt se tudom, hogy mi az az ARP, és meg is tudtam pingelni. De ha beírom az IP címet, a böngésző nem éri el a vezérlőt. Mivel még ilyesmivel nem foglalkoztam, nem tudom, hogy az említett programmal ez egyáltalán lehetséges? Vagy egyáltalán, hogy működik ez az Ethernet vezérlő + MCU?
(#) mechanika válasza szitko hozzászólására (») Ápr 20, 2013 /
 
Háát igen!
(#) szitko válasza mechanika hozzászólására (») Ápr 20, 2013 /
 
Nem írtam kommentet, de nézd át, és kérdezz, ha valami nem tiszta. Ez egy energia pazarló megoldás, de mindjárt csökkentünk a fogyasztáson.
  1. #include "io430.h"
  2.  
  3. long ADC_value=0;
  4. long ADC_fesz=0;
  5. char egyesek=0;
  6. char tizedes=0;
  7. // ---- Led villogtatása -------
  8. void led_vill(char egyesek, char tizedes){
  9.      
  10.      while(egyesek){
  11.           P1OUT |= BIT6;    // led be
  12.           __delay_cycles(500000); //  másodpercig világít a led
  13.           P1OUT &= ~BIT6;    // led ki
  14.           __delay_cycles(500000);  //  várakozás
  15.           egyesek--;
  16.      } // while
  17.      __delay_cycles(100000);  //  várakozás
  18.      while(tizedes){
  19.           P1OUT |= BIT6;    // led be
  20.           __delay_cycles(200000);//  másodpercig világít a led
  21.           P1OUT &= ~BIT6;    // led ki
  22.           __delay_cycles(200000);  //  várakozás
  23.           tizedes--;
  24.      } // while/2
  25. } // led_vill
  26. // ---- Fő progi ------------------------
  27. void main( void ){
  28.      
  29.      // Stop watchdog timer to prevent time out reset
  30.      WDTCTL = WDTPW + WDTHOLD;
  31.      BCSCTL1 = CALBC1_1MHZ;
  32.      DCOCTL = CALDCO_1MHZ;
  33.      
  34.      ADC10CTL0 = ADC10SHT_3              // mintavétel: 64 óraütés
  35.           | ADC10ON                      // Az ADC bekapcsolása
  36.                | SREF_0                  // VR+ = AVCC és VR- = AVSS
  37.                     | ADC10IE;           // ADC10 megszakítás engedélyezése
  38.      ADC10CTL1 = ADC10SSEL_0 | INCH_5;   // ADC10OSC az órajel, A1 a bemenet
  39.      ADC10AE0 |= BIT5;                   // P1.1 analóg funkció engedélyezése
  40.      
  41.      P1DIR |= BIT6;           //P1.6 kimenet
  42.      P1OUT &= ~BIT6;
  43.      P1DIR &= ~BIT3 ;         //P1.3 bemenet
  44.      P1REN |= BIT3 ;          // fehúzó be
  45.      P1OUT |= BIT3 ;          // felhúzás Vcc-re
  46.      
  47.      while(1){
  48.           if (!(P1IN & BIT3)){
  49.                ADC10CTL0 |= ENC + ADC10SC;    // Mintavétel és átalakítás ind
  50.                __low_power_mode_0();          // LPM0 mód bekapcsolás
  51.                ADC_value = ADC10MEM;          // Ad konverzió érték másolása
  52.                
  53.                ADC_fesz = ADC_value * 322;
  54.                ADC_fesz /= 10000;
  55.                egyesek = ADC_fesz/10;
  56.                tizedes = ADC_fesz%10;
  57.                led_vill(egyesek, tizedes);
  58.           } // if
  59.      } // while
  60.      
  61. }  // main
  62.  
  63. // ----- ADC10 megszakítás -----------
  64. #pragma vector=ADC10_VECTOR
  65. __interrupt void ADC10_ISR (void)
  66. {
  67.    __low_power_mode_off_on_exit();        // Ébresztő
  68. }
(#) mechanika válasza szitko hozzászólására (») Ápr 20, 2013 /
 
Köszönöm!
Kérdés az lesz, csak elaltatom a gyereket!
(#) szitko válasza mechanika hozzászólására (») Ápr 20, 2013 /
 
Én most küzdök vele, hogy menjen fürdeni

Egy potit tettem az ADC bemenetre, és így, az alábbi kiegészítéssel 0,3mA az áramkör áramfelvétele. Ez már jobb, mert a módosítás nélkül 2,1mA-t mértem.
  1. P1DIR &= ~BIT3 ;         //P1.3 bemenet
  2.      P1REN |= BIT3 ;          // fehúzó be
  3.      P1OUT |= BIT3 ;          // felhúzás Vcc-re
  4.      P1IES |= BIT3;     // Felfutó él
  5.      P1IFG &= ~BIT3;    // flag törlés
  6.      
  7.      while(1){
  8.                ADC10CTL0 |= ENC + ADC10SC + ADC10ON;    // Mintavétel és átalakítás ind
  9.                __low_power_mode_0();          // LPM0 mód bekapcsolás
  10.                ADC_value = ADC10MEM;          // Ad konverzió érték másolása
  11.                
  12.                ADC10CTL0 &= ~(ENC + ADC10ON); // ADC ki ???
  13.                
  14.                ADC_fesz = ADC_value * 322;
  15.                ADC_fesz /= 10000;
  16.                egyesek = ADC_fesz/10;
  17.                tizedes = ADC_fesz%10;
  18.                led_vill(egyesek, tizedes);
  19.                
  20.                P1IE |= BIT3;     // P1.3 interrupt
  21.                __low_power_mode_4();    // mély alvás
  22.      } // while
  23.      
  24. }  // main
  25. // ----- Port_1 megszakítás ----------
  26. #pragma vector=PORT1_VECTOR
  27. __interrupt void Port1_int(void){
  28.      
  29.      P1IFG &= ~BIT3;    // flag törlés
  30.      __low_power_mode_off_on_exit();       // ébresztő a mély álomból
  31.      
  32. }

Az ADC kikapcsolásában nem voltam biztos, de úgy nézem működik.
(#) kissi válasza szitko hozzászólására (») Ápr 20, 2013 /
 
A mutató az indirekt címzéshez kell, ha használtál assemblyt, akkor talán így könnyebb !? Az a lényeg, hogy az adatokat a memóriában egymás után tárolod le és ha tudod a típusát ( byte, int ), akkor tudod, hogy egy-egy adatod hány cellában van. Ha a mutatót ráállítod a kezdő memóriacímre, akkor indirekt címzéssel abban a cellában ( vagy az ahhoz tartozókban ! ) fogsz "matatni" ! A C a típus alapján tudja, hogy növelés vagy csökkentés esetén mennyit kell változtatni a mutatón, hogy a következő adatra mutasson!
Idézet:
„egy mutató, honnan tudja, hogy egy több dimenziós tömbből melyik értéket szeretném kiolvasni”
A mutató ezt nem fogja tudni, Neked kell a megfelelő adatra pozicionálnod !!
Remélem segítettem egy kicsit ?!
A hozzászólás módosítva: Ápr 20, 2013
(#) szitko válasza kissi hozzászólására (») Ápr 20, 2013 /
 
Igen programoztam/ok assembly-ben (PIC-et).
Azt már megértettem, hogy indirekt címzéshez kell, csak egyenlőre felfogni nem tudom a menetét. Igaz a statikus változókat is, vagy 5x el kellett olvasnom, hogy megértsem, és ott írtam egy példát magamnak a teljes megértéshez. A mutatóknál, viszont a példaprogramjaim mind-mind hibába futnak, vagy nem azt csinálják amit kéne, ill. amit elképzelek.
Köszönöm!
(#) kissi válasza szitko hozzászólására (») Ápr 20, 2013 /
 
int tomb[3]={0,1,2); // def. tömb
int temp; // változó
int *pointer; // def. mutató

pointer=&tomb; // ráállítom a mutatót a tömb kezdőcímére

temp= *pointer; // temp = tomb [0]
pointer+=2; // a tömb második elemére pozícionál

temp= *pointer; // temp = tomb[2]
(#) mechanika válasza szitko hozzászólására (») Ápr 20, 2013 /
 
Na elaludt!

A
  1. led_vill(egyesek, tizedes);
sor egy kicsit kimaradt az enyémből...
A többi elsőre világosnak tűnik, mindjárt tesztelem!
(#) szitko válasza kissi hozzászólására (») Ápr 20, 2013 /
 
Majdnem jó, de erre is hiba jött. De ha innen "pointer=&tomb;" kiveszem a "&" akkor jó. Így, hogy van egy működő mutatóm, a disasm-ben már látom, hogy mi is történik. Így már lassssan megértem.
Köszönöm szépen!
(#) kissi válasza szitko hozzászólására (») Ápr 20, 2013 /
 
Igen, mert "elbambultam" ! A "tomb" már maga is egy mutató és ezért jó, ha nem rakod oda az '&' jelet! Én azt akartam írni, hogy pointer= & tomb[0] !
Ha PIC-et programoztál, akkor FSR és INDF a kulcsszavak !
(#) idlob válasza szitko hozzászólására (») Ápr 20, 2013 /
 
A tömb igazából bűvészkedés a mutatókkal, így ha a tömböt érted, akkor igazából a mutatókat is, csak még nem tudsz róla.
Amikor azt mondod, hogy a tömb 0. eleme, akkor valamitől 0 távolságra lévő értékről beszélsz. Amikor azt mondod, hogy a tömb 2. eleme, akkor valamitől 2 távolságra lévő értékről beszélsz.
Ez a valami a tömb elejére mutató mutató.
Sőt, a tömb neve, az önmagában egy mutató.
  1. tomb[0] == *(tomb + 0) == *tomb
  2. tomb[2] == *(tomb + 2)

azaz
  1. tomb[j] == *(tomb + j)

A két (vagy több) dimenziós tömb mutatóra fordítása sem fekete mágia, egyszerűen a fordító csal:
  1. int tomb[][3] = {{1,2,3},{4,5,6},{7,8,9}};
  2. tomb[i][j] == *(tomb + i*3 + j);

Azaz a fordító minden lekérdezésnél visszanyúl a deklarációhoz, megnézi, hogy egy "sor" milyen hosszú, ugrik annyit ahányadik sorban van (+i*3) és még lép annyit ahányadik oszlopban (+j).
A valóságban a tömbben tárolt változók típusa miatt nem ilyen egyszerű a dolog, hanem bele kell számolni a változó szélességét is.
  1. tomb[i][j] == *(tomb + i * sizeof(*tomb) * egy_sorban_levo_elemek_szama + j * sizeof(*tomb))

Ha ezt végiggondolod, megérted, miért is 0. indexelődik a tömb, miért kell deklarációnál legalább a tömb szélességét megadni és miért lehet egy több dimenziós tömböt bármikor úgy kezelni, mintha csak egydimenziós lenne, illetve miért lehet könnyen "túlcímezni" egy tömböt.
A hozzászólás módosítva: Ápr 20, 2013
(#) szitko válasza idlob hozzászólására (») Ápr 21, 2013 /
 
Nagyon köszönöm mindkettőtöknek. Így már minden világos.
Egy programot írok, ahol 4db PCF8574-es portbővítőt használok, amik 11db külső eszközt kezelnek. Egy 4x4-es bill. mátrixtól kapott érték alapján kell állítani a portbővítők kimenetét, és ezt most a mutatók ismeretével sokkal könnyebben meg tudom valósítani, arról nem is beszélve, hogy a program fele annyi memóriát foglal.
Tehát még egyszer köszi a segítséget!
Már csak az Ethernet kérdésemre keresem a választ.
(#) icserny válasza szitko hozzászólására (») Ápr 21, 2013 /
 
Idézet:
„Már csak az Ethernet kérdésemre keresem a választ.”
Az E-mail címedre tegnap küldtem választ, nem kaptad meg?
(#) szitko válasza icserny hozzászólására (») Ápr 21, 2013 /
 
De........, köszönöm.
Berakta a Spam-ek közé, és az Outlook a spam-ket nem tölti le, és még értesítést sem kapok róluk. A google html felületén, meg nem szoktam nézni az emaileket.
(#) SBahadurD hozzászólása Ápr 24, 2013 /
 
Sziasztok!

Az lenne a kérdésem, hogy hogyan tudok az információs memóriába írni?
Szeretnék csinálni egy számkódolós zárat, és azt akarom, hogy a beállított jelszót megőrizze a tápfeszültség elvétele után is.

Köszönöm!
(#) Grebi válasza SBahadurD hozzászólására (») Ápr 24, 2013 /
 
Konstans értékként írd be, vagy statikusan adj egy értéket a kódban. Így ha újra indul a program valami oknál fogva, akkor is ismét elérhető lesz az adott érték.
(#) szitko válasza SBahadurD hozzászólására (») Ápr 24, 2013 / 1
 
Parancsolj.:
  1. // ------- Flash memoria setup ------------
  2.      FCTL2 = FWKEY + FSSEL0 + FN1;             // Flash kulcs, órajel beállítása
  3. ...
  4. // -- FLash művelet XY változó mentése --
  5.      flash_clear(0x1000);                  // flash törlése, írás előtt kell!
  6.      flash_write(0x1000, XY, 0);    //  írás a flash-be
  7. // -- Flash olvasás --
  8.      XY = flash_read(0x1000,0);     // beolvassuk a flash-ből az adatot
  9.  
  10. // --- Flash függvények ----
  11.  
  12. int *Flash_ptr;        // flash mutató
  13. uint16_t ftemp;
  14. //------------------------------- Flash törlés ---------------------------
  15. void flash_clear(int cim){
  16.      Flash_ptr = (int *) cim;   // flash mutató cim=0x
  17.      FCTL1 = FWKEY + ERASE;     // erase bit 1-be, kulcs
  18.      FCTL3 = FWKEY;             // lezárás kikapcsolása
  19.      *Flash_ptr = 0;            // segmens törlése
  20.      while (FCTL3 & BUSY);      // írás kikapcsolása
  21.      FCTL3 = FWKEY + LOCK;      // lezárás
  22. }  // void
  23. //------------------------------- Flash írás ------------------------------
  24. void flash_write(int cim, int val, char cim_1){
  25.      Flash_ptr = (int *) cim + cim_1;     // flash mutató
  26.      FCTL3 = FWKEY;                       // lezárás kikapcsolása
  27.      FCTL1 = FWKEY + WRT;                 // írás engedélyezése
  28.      *Flash_ptr = val;                    // érték beírása
  29.      while (FCTL3 & BUSY);
  30.      FCTL1 = FWKEY;                       // írás kikapcsolása
  31.      FCTL3 = FWKEY + LOCK;                // lezárás
  32. } // void
  33. //------------------------------- Flash olvasása -----------
  34. uint16_t flash_read(int cim, char cim_1){
  35.      Flash_ptr = (int *) cim + cim_1;   // olvasás
  36.      ftemp = *Flash_ptr;                // mutató másolása
  37.      return ftemp;
  38. }

Írás előtt mindenképp törölni kell azt a szegmenst, amibe írni akarsz.
(#) SBahadurD válasza szitko hozzászólására (») Ápr 25, 2013 /
 
Köszi szépen!

Jól látom, hogy a memória itt nem byte, hanem szószervezésű lesz (int-re mutató mutató)?
És ha én csak egyetlen szó tartalmát akarom változtatni, akkor is ki kell törölnöm a teljes szegmenst (64 byte)?
Ez azt jelenti, hogy ha egyet is módosítani akarok, akkor előtte ki kell mentenem a RAM-ba az adatokat, a szegmensből, majd a törlés után után visszaírni?
Csak mert így fölöslegesen használódik a többi cella is.
Hány írást bírnak elviselni ezek?

Köszönöm szépen!
(#) SBahadurD válasza Grebi hozzászólására (») Ápr 25, 2013 /
 
Sajnos ennyire egyszerűen a kontroller nem engedi meg, hogy a flash-ben nyúlkáljon az ember.
(#) Grebi válasza SBahadurD hozzászólására (») Ápr 25, 2013 /
 
Lehet hogy félre értettem a kérdés lényegiségét,félrevezető nem akrtam lenni. Bocsánat érte
A hozzászólás módosítva: Ápr 25, 2013
(#) szitko válasza SBahadurD hozzászólására (») Ápr 25, 2013 / 1
 
Idézet:
„Jól látom, hogy a memória itt nem byte, hanem szószervezésű”

Igen, de egy bájtot is tudsz írni bele. (Az más kérdés, hogy van-e értelme.)
Ha jól emlékszem, csak akkor kell törölni a szegmens tartalmát, ha egy, már beírt adatot akarsz felülírni/módosítani.
Tehát, pl: 0x1000h (D szegmens) címtől berakod a 0x1234h-t,
(pl:flash_write(0x1000, 0x1234, 0)
és ezt meg akarod változtatni, akkor előtte törölni kell, de ha folytatod az írást,
(pl:flash_write(0x1000, 0x1234, 1)
akkor nem kell törölni.
Szerintem nem feltétlenül kell kiírni a módosítani kívánt adatot egy változóba, hisz a módosított adat is "valahol" szerepel.
Azt, hogy hány írást visel el az info.mem, az adatlap megmondja (kb. 1 1/2 év írtam egy programot amiben heti használatban van a flash mem. Még nem szólt, hogy baj lenne.).
Azt még hozzá kell tegyem, hogy a függvényeket én eddig csak a g2553-al használtam, de több infót találsz a FUG-ban ahol minden részletesen le van írva.
A hozzászólás módosítva: Ápr 25, 2013
(#) SBahadurD válasza szitko hozzászólására (») Ápr 25, 2013 /
 
Köszönöm szépen.
Ha jól látom, valóban csak a módosításnál kell a blokkot törölni. Üres rekesz írásánál nem.
Akkor lehet, hogy érdemes úgy megírnom a programot, hogy minden módosításnál új címbe mentsen, és mindig csak a legújabb adatot használom. És ha betelt, akkor törlöm a használt szegmenseket. (Tudom, az A szegmensre vigyázni kell. )
A kimentést arra értettem, hogy ha az adott szegmensben más adatot is tárolok, de az egyiket módosítani akarom, akkor előtte ki kell mentenem a többi adatot is, mert az egész szegmenst ki kell törölnöm, majd az összes adatot visszaírni.

Amúgy én is g2553-at használok.
(#) szitko válasza SBahadurD hozzászólására (») Ápr 25, 2013 /
 
Idézet:
„akkor előtte ki kell mentenem a többi adatot is”

Ha nem sok adat van, pl. egy szegmensnyi, akkor nem biztos. Ha jól emlékszem, (nekem kéne egy kis memória...) akkor a példaprogramok között van példa a szegmensek közötti másolásra. Ha ki lehet hagyni a módosítani kívánt adatot a másolásból, akkor csak át kell másolni másik szegmensbe, így nem kell külső változó. De ennek utána kell nézni!!
(#) uli hozzászólása Ápr 25, 2013 /
 
Sziasztok!
Egy kicsit elakadtam programozás terén, és szeretnék segítséget kérni.
Egy befecskendező rendszert tervezek, amit a gyári rendszer mellé lehet telepíteni. Beolvassa a motor szenzorainak adatait és az alapján kiszámolja a befecskendezési időt. Minden fordulat alatt egyszer fecskendez, a megfelelő jelet az injektoroktól vagy gyújtásjeladótól kapja. Ez a beérkező jel a programban generál egy interruptot, lenullázza a timert, és az egyik kimenetet a kiszámított időre bekapcsolja, ezzel nyitva az injektort. Ez szép és jó, de mi van, ha leállítom az autót, de a gyújtás rajta marad. Ekkor ugye nem érkezik interrupt, azaz nem is kellene befecskendezni. De a számláló egy idő után túlcsordul és kezdi előről a számolást, ezzel újra bekapcsolva a kimenetet. Ezt a problémát nem tudom hogy oldjam meg. Most ugye Set/reset módban használom a timert. Nincs valami olyan mód, ami set, aztán kikapcsol a következő resetig? Vagy esetleg programozás ügyileg nincs valakinek erre valami ötlete? Köszönöm
(#) szitko válasza uli hozzászólására (») Ápr 25, 2013 /
 
Csak egy ötlet. Ha nincs beérkező jel, gondolok itt a "injektoroktól vagy gyújtásjeladótól" érkező jelre, akkor tiltsd le a Timer-t. Ha észleli a beérkező jelet, elindítod a Timert, és a megszakításban törlöd.
(#) röntgen válasza SBahadurD hozzászólására (») Ápr 25, 2013 /
 
Szia,

Egy filléres külső eeprom nem lenne egyszerűbb?
Csak egy ötlet........
(#) SBahadurD válasza röntgen hozzászólására (») Ápr 25, 2013 /
 
Nincs több szabad lába a kontrollernek. Meg plussz hely lenne a NYÁK-on. Meg úgy simán minek, ha van beépítve?
(#) röntgen válasza SBahadurD hozzászólására (») Ápr 25, 2013 /
 
Így érthető......
(#) szitko hozzászólása Ápr 29, 2013 /
 
Sziasztok.

Két kérdésem lenne.
Összeállítottam egy billentyű mátrix kezelő programocskát (csatolva). Az első kérdésem, hogy lehet megoldani szoftveresen a prellt? A "Key_Scan" rutinba beraktam egy várakozó ciklust, mely megvárja a billentyű felengedését, de ez a tesztek alapján kevésnek bizonyult.
A második kérdésem, hogy tudnám ezt az egész rutint megszakításban kezelni? Igazából nem sok dolga lenne a mikrovezérlőnek, ezért az ideje döntő többségét mély alvással (LPM4 módban) töltené, ezért szeretném megszakításban lekezelni a rutin.

main.c
    
Következő: »»   102 / 139
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