Fórum témák

» Több friss téma
Fórum » AVR - Miértek hogyanok
 
Témaindító: pakibec, idő: Márc 11, 2006
Témakörök:
WinAVR / GCC alapszabályok:
1. Ha ISR-ben használsz globális változót, az legyen "volatile"
2. Soha ne érjen véget a main() függvény
3. UART/USART hibák 99,9% a rossz órajel miatt van
4. Kerüld el a -O0 optimalizációs beállítást minden áron
5. Ha nem jó a _delay időzítése, akkor túllépted a 65ms-et, vagy rossz az optimalizációs beállítás
6. Ha a PORTC-n nem működik valami, kapcsold ki a JTAG-et
Bővebben: AVR-libc FAQ
Lapozás: OK   166 / 840
(#) kendre256 válasza frankopeter hozzászólására (») Nov 17, 2009 /
 
Ebben a témában én is kezdő vagyok, de azok a gombok csak akkor aktívak, ha fut a szimuláció (Build and Run CTRL+F7 után).
(#) trudnai válasza mathe hozzászólására (») Nov 18, 2009 /
 
Idézet:
„Tehát, ha C-ben így írom if((x & y)), tehát nem &&-t írok közéjük, akkor azt bites logikai műveletnek veszi?”


Igen, erdemes lenne valami C konyvet elovenned, vagy valami ehhez hasonlo tutorialt olvasgatnod

Idézet:
„Tehát tömbként akarom azt kezelni. És a tömb minden elemét a for-ban rávagyolom a portra.
PxOUT = ~PxOUT | maszk[i];”

(az [i] -t mar en tettem oda)

Szerintem egyszerubb lenne elobb ossze rakni azt amit ki szeretnel rakn a portra, azutan azt egyszeruen kimasolni. Amugy amit jelenleg csinal, hogy negalod a PxOUT-ot es ahhoz rakod a maszkot, majd megint negalod (tehat 2. lepesben vissza kaptad az eredeti erteket... nem tudom pontosan mi volt a cel, ezert nem tudom hogy ezt akartad-e).

LED kijelzon amugy (met ebbol indultunk ki) ugy szokas csinalni, hogy veszed a digitet, tombbol kiolvasod a karakter kepet es kiteszed a portra.

Masik lehetoseg, hogy elagazol a program futasban a megjelenitendo karakternek megfeleloen es a megfelelo rutin kirajzolja a megjelenitendo karaktert, mint ahogy ez a tutorial is teszi:

7-SEGMENT DISPLAY INTERFACING WITH AVR
(#) trudnai válasza trudnai hozzászólására (») Nov 18, 2009 /
 
hmm, tenyleg kiszedi a [ i ] -t -- remelem igy egymastol szetvalasztva mar megeszi?
(#) mathe válasza trudnai hozzászólására (») Nov 18, 2009 /
 
Idézet:
„LED kijelzon amugy (met ebbol indultunk ki) ugy szokas csinalni, hogy veszed a digitet, tombbol kiolvasod a karakter kepet es kiteszed a portra.”


Igen, ez nekem is eszembe jutott, egy jegyű számnál nincs is vele probléma, de mi van akkor ha több számjegy van? Esetleg sztingként kéne kezelni és karakterenként megfeleltetni a tömb adott elemének? Mert két digitnél se lenne igazából probléma mert a port 8 bitjére pont kiférne a két bcd kód, de én legalább 3mat szeretnék.

PxOUT = ~PxOUT | maszk i; végiggondolva ez tényleg hülyeség, igazad van.

Köszi a linkeket, megnézegetem majd mindenképp.
(#) trudnai válasza mathe hozzászólására (») Nov 18, 2009 /
 
Idézet:
„két digitnél se lenne igazából probléma mert a port 8 bitjére pont kiférne a két bcd kód, de én legalább 3mat szeretnék.”


Ha sima BCD atalakitot hasznalsz, akkor ugye mindegyik digit kulon byte-ra tarolodik. Ha pakolt BCD-vel dolgozol, akkor az also ket digit az elso byte-on van (also es felso nibble-eken), a 3. pedig a masodik byte also nibble-jen...

Sima BCD jobb lenne most neked, de a pakolt sem akadaly:

1. Kimaszkolod az also nibble-t, es kirakod a portodra
2. leshifteled a felso nibblye-t az alsora es kirakod a porta...
3. kimaszkolod a kovetkezo byte also nibble-jet.. es igy tovabb...
(#) poznamokus válasza mathe hozzászólására (») Nov 18, 2009 /
 
Mondjuk úgy nem lehetne, hogy a kijelzőn megjelenő számok kódját értékek sorrendjében letárolod egy char tömbben, és ha van a kétjegyű számod (praktikusan tároljuk unsigned char-ban, mert belefér), akkor a tízes helyiértékre a számod / 10 (div, gyk egészosztás) kerül, míg az egyesekre a számod modulo 10 (10-el való osztás maradéka) kerül. És az így kapott két értékkel választjuk ki a kijelzettek kódok közül az éppen aktuálisat. Pl vmi unsigned char seg[10], amiben a seg[0] a nullát adja ki a kijelzőn, míg a seg[9] a 9-est. És ebből válogatunk az egészosztással meg a maradékképzéssel.
(#) mathe hozzászólása Nov 18, 2009 /
 
Mindkét megoldás tetszik, kár, hogy ilyen trükköket nem tanítanak nekünk... Habár végül is, ha már lesz egy kis gyakorlatom, biztos jönni fognak magától is az ilyen ötletek.
Köszi a segítséget!
(#) pako válasza Sir-Nyeteg hozzászólására (») Nov 19, 2009 /
 
Üdv!

Felesleges mégegy AVR. 74HC245: Tiltható kimenet, állítható irány ("A" port "B"-re, vagy "B" port "A"-ra), A és B port egymással szemben van.
(#) niches hozzászólása Nov 21, 2009 /
 
Sziasztok!
A segítségeteket szeretném kérni. Most ismerkedek az ATmega164P mikrovezérlővel, építettem hozzá panelt, programozót, minden okés. Most az AD konverterét próbálgatom, ismerkedés gyanánt gondoltam csinálok egy olyat, hogy potméter az egyik ADC be lábra (ez a PORTA0 lett), LED sor a D portra, tekergetem a potit és nő a led világító oszlop...
Már egy napja szenvedek vele, kutatgatok neten, de nem tudok rájönni mit rontok el. Kérném tehát a segítségeteket, hogyan lehetne kijavítani a kódot?

ADC beállításai:
ADMUX: 0100 0000 azaz Vcc referencia feszültség, 0-ás csatorna
ADCSRA: engedélyezem az ADC-t a 7-es bittel, frekiosztás 64-gyel, így az eredeti 11,059 MHz-ből ~172 kHz-es AD órajel freki lesz.
ADCSRB: csupa nulla, free running mode...

Jelenleg a programmal egyik problémám, hogy nem folyamatosan fut. Ha a resetet nyomogatom akkor rááll újabb értékekre, de csak a poti egy kis szakaszán van változás. Tartomány felén 4 led világít, majd gyorsan tovább ugrik 8 ledre. Vajon mi okozza azt, hogy nem konvertál újra és újra, azaz változik valós időben a világító ledek száma?
Illetve gondolom rosszul kezelem a konvertált értéket a main részben. Hogyan vizsgáljam az U értékét, hogy attól helyesen változzanak a ledek? Én úgy gondolom, hogy az U-ban 0 és 1024 közötti érték lehet decimálisan a 10bit felbontás miatt. Avagy mégsem?

Használt fejlesztőprogram: AVR Studio

Előre is köszi a segítséget!
A program:
  1. #include <avr/io.h>
  2. #include <util/delay.h>
  3. #include "ADC_routines.h"
  4. /*******************
  5. ***********ADC_routines.h fájl:*********
  6. #ifndef ADC_ROUTINES_H
  7.  
  8. #define ADC_ENABLE ADCSRA |= (1<<ADEN)
  9. #define ADC_DISABLE ADCSRA &= 0x7F
  10. #define ADC_START_CONVERSION ADCSRA |= (1<<ADSC)
  11.  
  12. void ADC_init(void);
  13. int ADC_read(void);
  14. float ADC_calculateTemp(int);
  15. unsigned char* updateTempDisplay(float);
  16. unsigned char* temporary(void);
  17. void ADC_displayValue(void);
  18.  
  19. #endif
  20. **************************/
  21.  
  22. //ADC inicializálása
  23. void ADC_init(void)
  24.         {
  25.         ADCSRA = 0x00//disable adc
  26.         ADMUX = 0x40;   //4: VCC=5V ref. fesz, 0: PORTA0 csatorna kivalasztasa
  27.         ADCSRA = 0x86;  //64-es osztó, start conversion bit 0-ás, ezért nem 0xC6
  28.         ADCSRB = 0x00;  //free runing mode
  29.         }
  30.  
  31. //ADC beolvasás indítása függvény
  32. int ADC_read(void)
  33. {
  34. int i;
  35. int ADC_temp, ADCH_temp;
  36. int ADC_var = 0;
  37.  
  38. ADC_ENABLE; //ADC_routines.h-ból veszi
  39. ADC_START_CONVERSION; //elso nem hasznalt konverzio
  40. while(!(ADCSRA & 0x10)); // wait for conversion done, ADIF flag active
  41. ADCSRA|=(1<<ADIF); //eredeti programban benne volt, de nem tudom miért kellen a flaget nekem 1re állitani mkor pont arra várok...
  42.  
  43. for(i=0;i<8;i++) // do the ADC conversion 8 times for better accuracy
  44. {
  45. ADC_START_CONVERSION;
  46. while(!(ADCSRA & 0x10)); // wait for conversion done, ADIF flag set
  47. ADCSRA|=(1<<ADIF);
  48.  
  49. ADC_temp = ADCL; // read out ADCL register
  50. ADCH_temp = ADCH; // read out ADCH register
  51. ADC_temp +=(ADCH_temp << 8); //elshifteli 8 bittel, így egymás mögé kerülnek
  52. ADC_var += ADC_temp; // accumulate result (8 samples)
  53.  
  54. }
  55.  
  56. ADC_var = ADC_var >> 3; // average the 8 samples
  57. ADC_DISABLE;
  58. return ADC_var; //ebbe került a konverzió eredménye
  59. }
  60.  
  61. int main(void)
  62. {
  63. DDRD=0xFF; //PortD kimenetre allitasa
  64. PORTD=0xFF;
  65. unsigned int U=0; //Feszültség konvertált értéke
  66.  
  67. while(1)
  68. {
  69. U=ADC_read();
  70. if(U<128) PORTD=0x01;
  71.                 else if(U<256) PORTD=0x03;
  72.                         else if(U<384) PORTD=0x07;
  73.                                 else if(U<512) PORTD=0x0F;
  74.                                         else if(U<640) PORTD=0x1F;
  75.                                                 else if(U<768) PORTD=0x3F;
  76.                                                         else if(U<896) PORTD=0x7F;
  77.                                                                 else if(U<1024) PORTD=0xFF;
  78.                                                                         else {
  79.                                                                                         PORTD=0xAA; //hibajelzés 10101010 a ledek
  80.                                                                                         _delay_ms(500);
  81.                                                                                         PORTD=0x55; //01010101 a ledek állapota
  82.                                                                                         _delay_ms(500);
  83.                                                                                         }
  84. }
  85. }
(#) Ricsi89 hozzászólása Nov 21, 2009 /
 
Helló!
Ezzel tudom kezelni a DS1972-es ibuttont? Ha megy, akkor az eepromba hogy kell beírni az ID-t? Ugyanúgy sorrendben kell, mint az ibutton-on van felírva, esetleg fordított sorrendben? Ez nem derült ki számomra. Mert megcsináltam a kapcsolást attiny45-el, beírtam már többféle képpen az ID-t, de semmi reakció nincs. A programban a device ID-t átírtam az én ibuttom-éra, de semmi. Szóval a kérdésem, hogy a két eszköz kezelése megegyezik, vagy van eltérés az ID kiolvasásban és ezért nem megy? az ibutttonom azonosítója egyébként 000000532286. A device ID pedig 2D, amit át is írtam a programban.
(#) ATtiny válasza niches hozzászólására (») Nov 21, 2009 /
 
Látok pár dolgot így ránézésre ami nekem nem tetszik. Bár egyik sem okozhatja a leírt jelenségeket, de azért jó lenne kijavítani. Tehát az első, hogy felesleges a varázslás az ADC alsó és felső eredmény byte -jával. Van ADCW is a WinAVR-ben. Ami ezt a 2 byte -ot egy 16bites szónak mutatja. A másik, hogy az ADC_read(void) fügvényed int -et ad vissza. Pedig a logikus az lenne ha unsigned lenne. Fölleg, hogy a main kódban már egy unsigned U váltózónak ad értéket ez a fügvény. Ez persze magával hozza, hogy az ADC_read(void) belső változóit is át kéne írni mind unsigned -re. Illetve azt sem értem minek leállítani az AD konvertert az ADC_DISABLE -el. Mikor a freerunning mode -nak pont az lenne a lényege, hogy nyugodtan pöröghet folyamatosan. Így az ADC_ENABLE is csak 1x kéne nyilván. Valamikor a main kód elején. Na meg az a sok else if sem szerencsés. Másképp jobb lenne megoldani. Mondjuk pl. az U változót kéne maszkolni.
(#) poznamokus válasza niches hozzászólására (») Nov 22, 2009 /
 
1. Nem ártana némi várakozás a főciklusba
2. A számkonverzió eléggé veszélyes megoldás, vagy művelet értelmesebb lenne a += helyett.
3. 10 bites felbontás mellett bőven elég lenne egy unsigned short változó is (ami ugye 16 bites). 8 AD-zás után sem fog túlcsordulni, és optimálisabb is. (Mellesleg bőven elég lenne a 8 bites felbontás is...)
(#) trudnai válasza poznamokus hozzászólására (») Nov 22, 2009 /
 
int szinten 16 bites...
(#) niches válasza ATtiny hozzászólására (») Nov 22, 2009 /
 
Sziasztok!

Köszi a segítséget. Ma tiszta fejjel inkább újrakezdtem saját kútfőből és nem egy kész progit írtam át, így kicsit egyszerűbb lett
És már működik is
A kérdésem annyi lenne még, hogy miért kell a while(1) ciklusomon belül az ADSC bitet mindig 1-re állítanom, hogy folyamatos legyen a konverzió? Úgy értem a free runban nem folyamatosan konvertál magától? Bár most olvastam utána az adatlapban, azt írja, ez a konvverzió végeztével mindig nullára áll...tehát akkor a kérdésem érvényét veszti

@ATtiny: U változó maszkolására tudnál példát mondani nekem? A későbbi felhasználásban elég sok feltételnek kell majd alávetnem ezt a konvertált jelet, bizonyos tartományain kell kimeneteken 1-re vagy 0-ra állítgatni. És ép ezért a sebesség is kulcskérdés lesz. De gondolom maszkolással sem fog gyorsabban futni a program, mint az else if-ek tömkelegével. Vagy valakinek vmi jobb ötlet az ifeknél?
Még egyszer kösz mindenkinek. a kód:

Idézet:

#include
#include

int main(void)
{

//ADC inicializalasa
ADMUX=0x40; //VCC=5V referenciafesz, 0: PORTA0 csatorna kivalasztasa
ADCSRA=0xC6; //enable, start konverzió, 64-es osztó
ADCSRB=0x00; //free running mód

DDRD=0xFF; //PortD kimenetre allitasa
unsigned int U; //Feszültség konvertált értéke

while(1)
{
ADCSRA|=(1< while(!(ADCSRA & 0x10));

U=ADCW; //konverzió eredménye. 10 bit

if (U>=0 && U<128) PORTD=0x01;
else if (U>=128 && U<256) PORTD=0x02;
else if (U>=256 && U<384) PORTD=0x04;
else if (U>=384 && U<512) PORTD=0x08;
else if (U>=512 && U<640) PORTD=0x10;
else if (U>=640 && U<768) PORTD=0x20;
else if (U>=768 && U<896) PORTD=0x40;
else if (U>=896 && U<1024) PORTD=0x80;
else
{
PORTD=0xAA; //hibajelzés 10101010 a ledek
_delay_ms(500);
PORTD=0x55; //01010101 a ledek állapota
_delay_ms(500);
}
_delay_ms(2);
}
}
(#) Rakloo hozzászólása Nov 22, 2009 /
 
Hello,először írok ide.
Keresek egy egyszerű soros porti programozót ,amivel tudnék égetni Attiny13-ba.
Tudnátok ajánlani valami olcsót lehetőleg?
(#) mammut válasza Rakloo hozzászólására (») Nov 22, 2009 /
 
Miért pont soros? Párhuzamos avagy LPT port nincs a gépen?
Az STK200 a legegyszerűbb szerintem és AVRISP programmal nagyon egyszerű a használata..

Van EZEN az oldalon egy, de nincs tapasztalatom a soros égetők terén! (...szerencsére...)
(#) Rakloo válasza mammut hozzászólására (») Nov 22, 2009 /
 
Sajnos nincs LPT portom,de ha jobban belegondolok akkor ott a húgom gépe,csak hát mégsem azt kéne ilyen dolgokra használni

Ezt a programot kellesz beleégetni majd.
Igazából mikrovezérlők terén még nagyon kezdő vagyok.
(#) ATtiny válasza niches hozzászólására (») Nov 22, 2009 /
 
Én így oldanám meg:
  1. switch(U>>7)
  2.  {
  3.   case 0: PORTD=0x01; break;
  4.   case 1: PORTD=0x02; break;
  5.   case 2: PORTD=0x04; break;
  6.   case 3: PORTD=0x08; break;
  7.   case 4: PORTD=0x10; break;
  8.   case 5: PORTD=0x20; break;
  9.   case 6: PORTD=0x40; break;
  10.   case 7: PORTD=0x80; break;
  11.  }
(#) niches válasza ATtiny hozzászólására (») Nov 22, 2009 /
 
Igen, ez így elég tetszetős
Csak az a problémám, hogy ezt nem tudom alkalmazni majd tartományokra, csak bizonyos értékekre, szóval ahhoz maradni fog azt hiszem az if-es szisztéma.
(#) ATtiny válasza niches hozzászólására (») Nov 22, 2009 /
 
Ez a megoldás is tartományokra működik. Mivel kishiftelem az alsó 7 bitet így pontosan 128 -as (decimális) a tartomány amit kezel. Pont ahogy a példádban van. Nyilván ha nem egyforma tartományokat kell kezelni majd a végleges kódban, akkor ez a megoldás nem jó.
(#) niches válasza ATtiny hozzászólására (») Nov 22, 2009 /
 
igen, ezt nem írtam... tehát nem egyformákat, és szám szerint sem nyolcat mint itt, hanem mintegy 32-40-et
(#) trudnai válasza niches hozzászólására (») Nov 23, 2009 /
 
Idézet:
„igen, ezt nem írtam... tehát nem egyformákat, és szám szerint sem nyolcat mint itt, hanem mintegy 32-40-et”


Az rendben van, de par dolgot erdemes eszre venni:
ugye ez volt az eredeti kodod:
  1. if (U>=0 && U<128) PORTD=0x01;
  2. else if (U>=128 && U<256) PORTD=0x02;
  3. else if (U>=256 && U<384) PORTD=0x04;
  4. else if (U>=384 && U<512) PORTD=0x08;
  5. else if (U>=512 && U<640) PORTD=0x10;
  6. else if (U>=640 && U<768) PORTD=0x20;
  7. else if (U>=768 && U<896) PORTD=0x40;
  8. else if (U>=896 && U<1024) PORTD=0x80;
  9. else
  10. {.....

1. Nos, mivel az U unsiged, ezert a 0-nal nagyobb vizsgalat teljesen felesleges (valoszinuleg a compiler ki is szedi azt, vagy talan meg warningot is ad erre)

2. Mivel mindig if..else reszben van a vizsgalat, teljesen felesleges masodszor is vizsgalni, hogy a port nagyobb-e, hiszen elozoleg ezt mar megallapitottad. Tehat le lehet egyszerusiteni a kodot:
  1. if (U<128) PORTD=0x01;
  2. else if (U<256) PORTD=0x02;
  3. else if (U<384) PORTD=0x04;
  4. else if (U<512) PORTD=0x08;
  5. else if (U<640) PORTD=0x10;
  6. else if (U<768) PORTD=0x20;
  7. else if (U<896) PORTD=0x40;
  8. else if (U<1024) PORTD=0x80;
  9. else
  10. {.....

Azonkivul ha ilyen speci szamokkal dolgozol, akkor jogos az eszrevetel, hogy erdemesebb lenne shiftelgetni es csak az ertekes biteket vizsgalni. Ha mas nem azert erdemes leshiftelni, hogy byte-ba bele ferjen a vizsgalt ertek, igy a compilernek van eselye, hogy kisebb kodot varazsoljon az egeszbol, tehat:
  1. unsigned char U2 = (unsigned char)(U >> 7);
  2. if (U2<0x01) PORTD=0x01;
  3. else if (U2<0x02) PORTD=0x02;
  4. else if (U2<0x03) PORTD=0x04;
  5. else if (U2<0x04) PORTD=0x08;
  6. else if (U2<0x05) PORTD=0x10;
  7. else if (U2<0x06) PORTD=0x20;
  8. else if (U2<0x07) PORTD=0x40;
  9. else if (U2<0x08) PORTD=0x80;
  10. else
  11. {.....

...es akkor mar rogton latszik is, hogy hoppa, a szamok elegge specialisak, egymast kovetik, tehat siman lehetne switch...case-be berakni, tehat:
  1. unsigned char U2 = (unsigned char)(U >> 7);
  2. switch (U2) {
  3.     case 0x02:
  4.         PORTD=0x02;
  5.         break;
  6.     case 0x03:
  7.         PORTD=0x04;
  8.         break;
  9.     case 0x04:
  10.         PORTD=0x08;
  11.         break;
  12.     case 0x05:
  13.         PORTD=0x10;
  14.         break;
  15.     case 0x06:
  16.         PORTD=0x20;
  17.         break;
  18.     case 0x07:
  19.         PORTD=0x40;
  20.         break;
  21.     case 0x08:
  22.         PORTD=0x80;
  23.         break;
  24.     default:
  25.         ...hiba...
  26.         break;
  27. {.....

Namost ez forrasban talan hoszabbnak tuni, de nem az, sot a compiler ha minden igaz egy ugro tablat csinal ebbol osszehasonlitasok helyett, tehat a kod kisebb es gyorsabb lesz...
(#) niches válasza trudnai hozzászólására (») Nov 23, 2009 /
 
Értem Arról a bizonyos dupla vizsgálatról én is tudom, hogy felesleges, először én is olyan összehasonlítást csináltam, mint amit te hoztál ki belőle, csak én az íráskor már a későbbi tartományokat tartottam szem előtt, nyilvánvalóan feleslegesen ehhez a programhoz

Egyébként egy abszolút szöghelyzet jeladó analóg jelét kell digitalizálnom, és adott tartományain megfelelő elektromágneses működtetésű pneumatikus szelepeket húzgálni - csak hogy ne legyek már ennyire titokzatos

Viszont örülök, hogy egy ilyen hozzáértővel akadtam össze, mint Te, mivel nekem csak halvány elképzeléseim vannak arról, a fordító hogyan dolgozik, és mi az optimális a számára...így tehát ki fogom próbálni a későbbiekben a te módszeredet a gyorsabb futás érdekében.

Köszöntem a segítséged!
Gyanítom, még visszatérek
(#) poznamokus hozzászólása Nov 25, 2009 /
 
Sziasztok!

Légyszi segítsetek, AVRDude-t kellene frissíteni 5.8-ra (AT90USB1287-es vezérlő miatt, mert azt a pony már nem ismeri, és be kéne állítani a kristály frekijét, arra meg a FLIP nem képes, így 2 Mhz-ről ketyeg 16 helyett), de a cygwin alatt nem megy a dolog. A leírás szerint meg kell adni az install elérési útvonalat, de nem sikerül:

$ set PREFIX=

esetén szintaktikai hibát ír ki, ha

( set PREFIX= ) formájában írtam be, ahogy javasolja az útmutató. 5let?
(#) Ricsi89 hozzászólása Nov 26, 2009 /
 
Sikerült összeraknom egy akkufesz őrt attiny45-el és egy kétszínű leddel. Ez az első dolog, amit csináltam. Ez most 6V-os rendszerű motorokhoz készült. A kétszinű led jelzi, hogy milyen feszültség van az aksiban. 6V alatt pirosan világít, 6v és 6,8v között narancs színű, ami az aksi normál állapotát jelzi, 6,8v és 7,4v között zölden világít jelezve a megfelelő töltést. Efölött pirosan villog, figyelmeztetve a túltöltésre. A mérendő feszt egy ellenállásosztóval osztom a felére, így tökéletesen mérhető a fesz. Próbapanelon, trimmerrel változtatva a feszt szépen működik. Az alapot Topi akkutöltős cikkéből vettem. Mit szóltok hozzá?
  1. #include <avr/io.h>
  2. #include <util/delay.h>
  3. #define PIN_RED          PB1
  4. #define PIN_GRN          PB0
  5.  
  6. #define RED_ON()         PORTB |=  (1<<PIN_RED)
  7. #define RED_OFF()        PORTB &= ~(1<<PIN_RED)
  8. #define GRN_ON()         PORTB |=  (1<<PIN_GRN)
  9. #define GRN_OFF()        PORTB &= ~(1<<PIN_GRN)
  10. #define ORANGE_ON()      PORTB |=  (1<<PIN_RED & 1<<PIN_GREEN)
  11. #define ORANGE_OFF()     PORTB &=  ~(1<<PIN_RED & 1<<PIN_GREEN)
  12. #define BATT_MAX         7.4
  13. #define BATT_MIN         6.8
  14. #define BATT_LOW         6
  15.  
  16.  
  17. const unsigned short BATT_MAX_ADC     = 1024*BATT_MAX/5/2;
  18. const unsigned short BATT_MIN_ADC     = 1024*BATT_MIN/5/2;
  19. const unsigned short BATT_LOW_ADC     = 1024*BATT_LOW/5/2;
  20. //-------------------------------------
  21. void m_delay_10ms(unsigned short val) {
  22. //-------------------------------------
  23.            while(val--) _delay_ms(10);
  24. }
  25. //-------------------------------------
  26. void init() {
  27. //-------------------------------------
  28.            DDRB = (1<<PIN_RED)|(1<<PIN_GRN);    //kimenetek
  29.            //Init ADC
  30.            ADMUX = 0x00;
  31.            ADCSRA =  (1<<ADEN)
  32.                   |  (0<<ADATE)
  33.                   |  (0<<ADSC)
  34.                   |  (1<<ADPS2)
  35.                   |  (1<<ADPS1)
  36.                   |  (1<<ADPS0)
  37.                   ;
  38. }
  39. //-------------------------------------
  40. unsigned short ADConvert(unsigned char channel) {
  41. //-------------------------------------
  42.            ADMUX &= ~(1<<MUX1|1<<MUX0);
  43.            ADMUX |= channel;
  44.            ADCSRA |= (1<<ADSC);
  45.            while(ADCSRA & (1<<ADSC));
  46.            return ADC;
  47. }
  48. //-------------------------------------
  49. int main(void) {
  50. //-------------------------------------
  51. unsigned short adc;
  52.            init();
  53.            for(;;)  {
  54.                adc = ADConvert(2);    //mérés
  55.                if(adc<BATT_LOW_ADC) {
  56.                    //Piros, akku alacsony fesz
  57.                      RED_ON();
  58.                      GRN_OFF();
  59.                      adc = ADConvert(2);    //mérés
  60.                 }
  61.             if(adc>=BATT_LOW_ADC && adc<BATT_MIN_ADC){
  62.                   //Narancs, akku normál fesz
  63.                      RED_ON();
  64.                      GRN_ON();
  65.                      adc = ADConvert(2);    //mérés
  66.                 }
  67.                if(adc>=BATT_MIN_ADC && adc<BATT_MAX_ADC){
  68.                   //Zöld, van töltés
  69.                     RED_OFF();
  70.                     GRN_ON();
  71.                     adc = ADConvert(2);    //mérés
  72.               }
  73.               if(adc>BATT_MAX_ADC){
  74.                 //Piros villog, akku túltöltődik
  75.                 GRN_OFF();
  76.                 _delay_ms(500);
  77.                 RED_ON();
  78.                 _delay_ms(500);
  79.                 RED_OFF();
  80.                 adc = ADConvert(2);    //mérés
  81.               }
  82.         }
  83. }
(#) toto hozzászólása Nov 27, 2009 /
 
Sziasztok!
Most ismerkedem az AVR-ekkel, és már az első programommal adódott egy gond, amit nem értek. Egy Nokia3310-es LCD-t izzítottam be. Ez itt a program-kezdeményem..

  1. #include <avr/io.h>
  2. #include <util/delay.h>
  3. #include <avr/pgmspace.h>
  4. #include <stdlib.h>
  5. //#include <stdio.h>
  6. #include "pcd8544.h"  //ez itt az LCD kezelő modul a netről
  7. #define LED_ON()    PORTD |=  (1<<PD4)
  8. #define LED_OFF()   PORTD &= ~(1<<PD4)
  9.  
  10. char str;
  11. char *strp;
  12. int value;
  13.  
  14. int main(void) {
  15.  strp=&str;
  16.  DDRC=0;
  17.  DDRD=0;                                //all input
  18.  DDRB=0;                                //all input
  19.  DDRD |=(1<<PD4);               //PD4: output ->LED
  20.  LED_ON();
  21.  
  22.  LcdInit();
  23.  LcdContrast(0x49);             //00-7F
  24.  LcdClear();
  25.  LcdGotoXYFont(1,1);
  26.  LcdFStr(FONT_1X,(unsigned char*)PSTR("FLabs"));
  27.  LcdGotoXYFont(1,2);
  28.  LcdFStr(FONT_1X,(unsigned char*)PSTR("Radio     0.1."));
  29.  LcdGotoXYFont(1,3);
  30.  LcdUpdate();
  31.  value=1234;
  32.  dtostrf(value,5,1,strp);               //convert int -> string
  33.  LcdStr(FONT_1X,(unsigned char*)&str);
  34.  LcdFStr(FONT_1X,(unsigned char*)PSTR(" MHz"));
  35.  LcdUpdate();
  36.  strp="123.4";
  37.  LcdStr(FONT_1X,(unsigned char*)strp);
  38.  LcdUpdate(); */
  39.  
  40.  value=1;
  41.  while(1){
  42.         dtostrf(value,5,1,strp);                //convert int -> string
  43.     LcdStr(FONT_1X,(unsigned char*)&str);       //str -> display
  44.         LcdUpdate();
  45.         value++;
  46.         LED_ON();
  47.         _delay_ms(100);
  48.         LED_OFF();
  49.     _delay_ms(100);
  50.         LED_OFF();
  51.     _delay_ms(100);
  52.  }
  53.  return 0;
  54. }


Amikor csak az LCD modult izzítottam be, kb. 33% volt a programmemória foglaltsága. Ez korrektnek tűnt, mert ebben vannak a karakterek megrajzolva, ami sok memóriát eszik. Utána jött a dtostrf fv., ami egészet konvertál sztinggé. Ekkor felugrott 55%-ra a prgmem. foglaltság. Utána a második dtostrf használatakor már 66%-ra emelkedett ez az érték, miközben a regiszterek használata 75 %.
Még igazából nem csináltam semmit, és lassan tele van az ATMega8-as 8K-ja. AVRStudio+WinAVR-t használok, az optimalizáció -Os, ami azt hiszem, a legkisebb kódot generálja. PIC-kel ez lényegesen kisebb kóddal volt megoldható emlékeim szerint. Azt sem értem, ha egy függvényt kétszer hívok meg, a második hívásnál miért növekszik jelentősen a prog.mem. foglaltsága.
Azt hittem, hogy 8K elég mindenre (Bill után szabadon ), de most már nem tudom.
Mit csinálok rosszul?
(#) Ricsi89 válasza (») Nov 27, 2009 /
 
C kódot úgy kell berakni, hogy a code után beírsz egyenlőségjel után egy c betűt. Így kell kinéznie, persze szóközök nélkül. [ code = c ] Lezárás marad a régi.
(#) toto válasza Ricsi89 hozzászólására (») Nov 27, 2009 /
 
Köszi.
Biztos nem először írtátok már le, csak hát vannak lusta emberek...
(#) levi18 válasza toto hozzászólására (») Nov 27, 2009 /
 
Szia!
Remélem tudok neked segíteni. Amikre felfigyeltem:

Ez szerintem itt nem teljesen tökéletes:
#define LED_ON() PORTD |= (1<

Ez pedig nem ennyi lesz, mert 65 ms-nél nagyobbat nem tud késlelteni. :
_delay_ms(100);

Órajeldefiniálás megvolt?

Üdv!>
(#) toto válasza levi18 hozzászólására (») Nov 27, 2009 /
 
A sornak nem látszik a vége mert rosszul szúrtam be először. Ez a rész jól működik, a led villog. Így néz ki igazából:
  1. #define LED_ON()    PORTD |=  (1<<PD4)
  2. #define LED_OFF()   PORTD &= ~(1<<PD4)

A késleltetés rész nem kritikus, de kösz hogy szóltál, észben tartom.
A freki beállítás a Project/Configuration Options/Frequency helyen megvolt.
A program warning nélkül rendesen fut, a bajom, hogy zabálja a programmemóriát.
Még egy dolog van, ami zavar. Fordításkor ha valami baja van, kiír két-három warningot. Eddig rendben. Utána néha ha változtatás nélkül újrafordítom, előfordul néha, hogy eltűnnek a figyelmeztetések, 0 warninggal fordul. Utána változtatok valamit, erre újra előtűnnek az előbbi warningok. Miért tűnik el néha újrafordításkor egy-két figyelmeztetés anélkül, hogy javítottam volna?
(AVRStudio 4.17 + WinAVR 20090313)
Ja, és sikerült a kódbeszúrás. Csodálatos!
Következő: »»   166 / 840
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