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   462 / 840
(#) sikolymester válasza blackdog hozzászólására (») Júl 26, 2012 /
 
Létezik AC optócsatoló is.
Lehet, hogy te is belebotlottál, csak gondolom linkelek egyet: TCMT4600
(#) blackdog válasza sikolymester hozzászólására (») Júl 26, 2012 /
 
Tudom, hogy létezid, de csak ezt rendelni nem éri meg.
Egyébként 16db ilyen bemenet lesz egymás mellett.
Csak "nagyon" brummos volt a kimenet egyutas egyenirányítás nélkül. Hiába volt ott a kondi. (Első kapcsolás szerint.)
(#) Moci.net hozzászólása Júl 26, 2012 /
 
Hello
Olvastam az ide tartozó avr asm-et és tennék is fel kérdést. Nagyon kezdő vagyok ASM-be meg elektroba is, szal lehet láma kérdés lesz:
LDI és a MOV az miben különbözik?
A MOV-al is lehet közvetlen operandust megadni nem?

Kösz a válaszokat!

u.i.: ha kell akkor C#-ban tudok segíteni...
(#) norbigal válasza Moci.net hozzászólására (») Júl 26, 2012 / 1
 
Én speciel rühellem az AVR assembly-jét, de suliban belénk erőszakolták és úgy rémllik, hogy az LDI egy konstans értéket ad az operandusodnak: LDI op1, konstans
ahol az op1 valamilyen SFR regiszter, vagy általános munkaregiszter (R0, R1, R2,.....)

A MOV viszont csak adatmozgatás két regiszter között: MOV op1, op2 ahol op1 és op2 is valamely tetszőleges regiszter lehet

A lényeg, hogy az LDI-vel nem töltheted bele egyik regiszter tartalmát egy másikba, a MOV-val pedig nem tölthetsz fel tetszőleges konstans értékkel semmit.
(#) Moci.net válasza norbigal hozzászólására (») Júl 26, 2012 /
 
aha értem kösz. Közbe az IDE-vel próbálkozok és felmerült még valami. Az hogy a kimenetet és a bemenetet ugy lehet érteni, hogy pl.:
ldi r11, 0xCC;
in r11, DDRB; (r11 |= DDRB) lesz egy bemenet? A többi bit meg marad ami volt (kimenet/bemenet)?
Ugye jól tudom hogy egy regiszter lehet bemenet is és kimenet is és ez csak a bitjeitől függ.? És akkor mely regiszterek vagy melyek nem használhatók I/O-ra? r0-r31-ig és a PORT-ok ok?

Bocs de még sokat tudok kérdezni a regiszterek hol hogyanjáról. De folyamatosan írom az asm-et és figyelem a biteket.
(#) mzozo95 válasza sgt hozzászólására (») Júl 26, 2012 /
 
Elkészült az uartos software pwm, az interruptban a signal os név kell az ISR-nél is, mert ha nem lefagy az avr, és resetel állandóan, de így jól működik.
Mellékelem a kódot, hátha segít majd valakinek...


  1. //hardware: atmega48, 1db servo, portb1en , 1db led port B-0on; adat fogadása: betű- space- 4jegyű szám(esetenként elején 0-val)  + '=', példa:'a 0587=', parancsok: echo, eoff, info, alma
  2. #define F_CPU 8000000
  3. #include <avr/io.h>
  4. #include <util/delay.h>
  5. #include <avr/interrupt.h>
  6. #include <inttypes.h>
  7.  
  8. #include <stdbool.h> //bool típushoz
  9.  
  10.  
  11. ////////////////////////////////
  12. #define BAUD 38400///38400bps
  13. #define UBRR ((F_CPU / (BAUD * 16L)) - 1)
  14. ////////////////////////////////
  15. //változók
  16. volatile unsigned char rec[15];//string buffeer
  17. volatile unsigned char buffer; //byte buffet
  18.  
  19. volatile unsigned char stat=0;//string karakter száma
  20.  
  21. volatile int servo[3]; ///szervo pozíció
  22.  
  23. volatile bool echo=0; //visszhang(0-1)
  24.  
  25. volatile bool inter=0;//(0-1) szemafor
  26. //////////////////
  27. /////
  28. void uart_init(void)
  29. {
  30. UCSR0B = (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
  31. // baud rate
  32. UBRR0H = (unsigned char) (UBRR>>8);
  33. UBRR0L = (unsigned char) UBRR;
  34. //  format: 8data, 2stop bit
  35. UCSR0C = (1<<UMSEL01)| (1<<USBS0) | (3<<UCSZ00);
  36. }
  37.  
  38. ///////UartKüld
  39.   void UARTKuld(unsigned char c){
  40.                 while((UCSR0A & (1<<UDRE0)) == 0) {}
  41.        
  42.             UDR0 = c;
  43. }
  44. ///////szövegküld
  45.    void UARTSzovegKuld( char *p)
  46. {
  47.         while(*p)
  48.         {
  49.           UARTKuld( *p++);
  50.         }
  51. }//szövegküld vége
  52.  
  53. void delrec(void){
  54.  for(int i=0; i<50;i++){
  55.   rec[i]=' ';
  56. stat=0;};
  57.  }
  58.  
  59. void kuldrec(void){
  60. for(int i=0; i<stat ;i++){
  61.  UARTKuld(rec[i]);}
  62.  }
  63.  
  64. //decimális szám küldése:
  65. void outdec(long data, unsigned int ndigits) { //integer to dec=>string, és érték kiírása
  66.     static char sign, s[12];
  67.     _delay_us(10);
  68.     unsigned int i;
  69.             i=0; sign=' ';  //alapvetően nincs előtte semmi
  70.             if(data<0) { sign='-'; data = -data;} //ha minusz, akk elé: -
  71.             do {
  72.                     s[i]=data%10 + '0'; //integer átírása ASCII ba
  73.                     data=data/10;
  74.                     i++;
  75.                     if(i==ndigits) {s[i]='.'; i++;}
  76.             } while(data>0);
  77.             UARTKuld(sign);
  78.             do{
  79.                       UARTKuld(s[--i]); //összes karakteren végigmenni
  80.             } while(i);
  81. }
  82.  
  83. uint8_t comm( char *p){
  84. char azonos=1;
  85. int szam=0;
  86. for(szam=0; szam < 15; szam++)
  87. {
  88.     if (rec[szam]!=( *p++))
  89.     {
  90.        azonos = 0;
  91.        break;
  92.     }
  93.     if(!*p) break;
  94.  }
  95. return (azonos);}
  96.  
  97.  
  98. uint16_t strtoint(int szam){
  99. int ertek=0;
  100.  
  101. if (rec[szam]>='0' && rec[szam]<='9') {ertek += (rec[szam] - '0')*1000;};
  102. szam+=1;
  103. if (rec[szam]>='0' && rec[szam]<='9') {ertek += (rec[szam] - '0')*100;};
  104. szam+=1;
  105. if (rec[szam]>='0' && rec[szam]<='9') {ertek += (rec[szam] - '0')*10;};
  106. szam+=1;
  107. if (rec[szam]>='0' && rec[szam]<='9') {ertek += (rec[szam] - '0');};
  108. return (ertek);}
  109.  
  110.  
  111. void init_servo(void){//servo init
  112. //16bit pwm
  113. DDRB|= _BV(DDB1)|_BV(DDB2)|_BV(DDB1);   //pwm portd1 2 3
  114.  
  115. TCCR1A = (1<<COM1A1)| (1<<COM1B1);
  116. TCCR1B = (1<<WGM13) | (1<<CS11) ;//Posztás 8al
  117. ICR1 = 10000;//periódus: 20ms
  118. OCR1A = 750;//servo1 1500us
  119. OCR1B = 750;//servo2 1500us
  120. }
  121.  
  122. void delay_1us(uint16_t delay_data) {//5us es késleltetés(így kevés memóriát foglal)
  123.          while(delay_data--) _delay_us(1); }
  124.  
  125. void s_pwm(void){
  126. ///////////////software pwm
  127. PORTB=2;
  128. delay_1us(servo[0]);
  129. PORTB=0;
  130. }
  131.  
  132. int main(void){
  133.  
  134. //init_servo();
  135.  
  136. DDRB=255;
  137. PORTB=0;
  138.  
  139. delrec();
  140.  
  141. uart_init();
  142. UARTSzovegKuld("Uart Online! Ready To Serial communication!");
  143.  
  144. sei();
  145.  
  146. servo[0]=1000;
  147. ///////
  148. while(1){
  149. s_pwm();
  150. _delay_ms(18);
  151.  
  152.  
  153. //uart kiértékelése
  154.  if (inter==1){
  155.  
  156. if (echo){UARTKuld(buffer);};
  157.  
  158. if (buffer==8){
  159.  delrec();
  160.    }
  161.   if (buffer=='?'){
  162.     kuldrec();
  163.    }
  164.  
  165. if (buffer=='!'){
  166.   if (comm("alma")) {UARTSzovegKuld("alma fogadva!");delrec();}else
  167.   if (comm("echo")) {UARTSzovegKuld("Echo ON!"); echo=1;delrec();}else
  168.   if (comm("eoff")) {UARTSzovegKuld("Echo Off!"); echo=0;delrec();} else
  169.   if (comm("info")) {UARTSzovegKuld("Uart Online! "); UARTSzovegKuld("| 38400bps | atmega48 | string.c");delrec();}
  170.   else {
  171.   UARTSzovegKuld("ERROR");
  172.   delrec();}
  173.   }
  174.  
  175.     if (buffer=='='){
  176. if (rec[0]=='a'){servo[0]=strtoint(2);
  177. UARTSzovegKuld("Servo modified!");
  178. UARTSzovegKuld("a=");
  179. outdec(servo[0],0);
  180. delrec();
  181. buffer=0;};
  182. }
  183.  
  184. if (buffer=='%'){
  185. int number=strtoint(1);
  186. outdec(number,0);
  187. delrec();}
  188. //led jelzés
  189. PORTB=1;
  190. _delay_ms(1);
  191. PORTB=0;
  192. inter=0;
  193. };
  194. }
  195. }
  196.  
  197. ISR(SIG_USART_RECV)
  198. {  
  199.    if(UCSR0A & (1 << RXC0)) {buffer = UDR0;}
  200.  
  201. rec[stat]=buffer;
  202. stat+=1;
  203.  
  204. inter=1;
  205. }


Üdv.: Zoltán
(#) sgt válasza Moci.net hozzászólására (») Júl 26, 2012 / 2
 
Hehe. Objektum orientáltról asm-re váltani elég meredek dolog. Itt nincs semmi sem a kezedben. Ha valamit csinálni akarsz, akkor azért vért kell izzadni.

Első szabály: olvasd végig legalább kétszer az adatlapot. AVR CPU core-tól legalább a Timerekig.

Második szabály: mindig jobbról balra történik az értékadás. Az in-nel speciális regiszter tartalmát olvasod be, out-al adsz értéket. Ennek megfelelően a rövidke kódod így fog alakulni:
  1. ldi r11, 0xCC
  2. out DDRB, r11
  3. ldi r12, 0xCC
  4. out PORTB, r12 ; 0xCC-t kitesszük a kimenetre
  5. in r13, PINB ; beolvassuk a bemeneteket, de ugye a porton van már egy 0xCC, amit kiszeretnénk maszkolni
  6. com r12 ; ezért a 0xCC-t negáljuk
  7. and r13, r12 ; és maszkolunk

A DDRx - Data Direction Register x-porton. Ha a DDRx 0-ba van állítva, akkor a PINx register segítségével tudsz beolvasni. Ha a DDRx 1-be van állítva, akkor a PORTx segítségével tudsz kitenni értéket a pin(ek)re.
(#) sgt válasza mzozo95 hozzászólására (») Júl 26, 2012 /
 
Fogok reagálni, csak ez egy kicsit nagyobb lélegzet lesz, és mert netezni sincs időm.
(#) zolee1209 válasza sgt hozzászólására (») Júl 27, 2012 / 1
 
Azért az 'ldi r11' nem éppen valós... R16 és fölötte használható.
(#) attycsek hozzászólása Júl 27, 2012 /
 
Sziasztok!
Egy nagyon érdekes problémával találkoztam, amikor UART kommunikációt próbáltam megvalósítani két ATmega128-as között.

A kódok:
  1. void uart_INIT(void)
  2. {
  3.  
  4. //Calcuate the baudrate register content  
  5.  
  6. //RS232(UART0)
  7. UBRR0H = (uint8_t) (UART_BAUD_CALC(UART_BAUD_RATE,F_CPU) >> 8);
  8. UBRR0L = (uint8_t) UART_BAUD_CALC(UART_BAUD_RATE, F_CPU);
  9.  
  10. //Display(UART2)
  11.  
  12. UBRR1H = (uint8_t) (UART_BAUD_CALC1(UART_BAUD_RATE1,F_CPU) >> 8);
  13. UBRR1L = (uint8_t) UART_BAUD_CALC1(UART_BAUD_RATE1, F_CPU);
  14.  
  15. UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0) | (1 << TXCIE0) | (0 << UDRIE0); //Enable the receiver and transmitter and receiver interrupts on UART0 //USART0_-RX_vect
  16. UCSR1B = (1 << RXEN1) | (1 << TXEN1) | (0 << RXCIE1) | (0 << RXCIE0) | (0 << UDRIE1); //Enable the receiver and transmitter on UART2
  17.  
  18.  
  19. UCSR0C = (3 << UCSZ00) | (0 << UPM00) | (0 << USBS0) | (0 << UMSEL0) | (0 << UCPOL0) ; //Set the UART0 to 8 bit, no parity, 1 stop bit asynchronous receiver-transmitter
  20. UCSR1C = (3 << UCSZ10) | (0 << UPM10) | (0 << USBS1) | (0 << UMSEL1) | (0 << UCPOL1) ; //Set the UART2 to 8 bit, no parity, 1 stop bit asynchronous receiver-transmitter
  21.  
  22.  
  23. DIRECTION_RECEIVER
  24.  
  25. //Enable global interrupts
  26. sei();
  27.  
  28. }


  1. ISR(USART0_RX_vect)
  2. {
  3. receiver_Buffer[receiver_Buffer_counter] = UDR0;
  4. receiver_Buffer_counter++;
  5.  
  6. if((receiver_Buffer_counter > 2) && (receiver_Buffer_counter == receiver_Buffer[1] ))
  7. {
  8.  
  9. receiver_Buffer_counter = 0;
  10. if( ( receiver_Buffer[0] ==  MASTER_ADDRESS) || (receiver_Buffer[0] == GENERAL_CALL) )
  11. {
  12. New_Value_Com = 1;
  13. }
  14. }
  15. }
  16.  
  17. ISR(USART0_TX_vect)
  18. {
  19. transmitter_Buffer_counter++;
  20. if(transmitter_Buffer_counter != transmitter_Buffer[1])
  21. {
  22. UDR0 = transmitter_Buffer[transmitter_Buffer_counter];
  23. }
  24. else
  25. {
  26. DIRECTION_RECEIVER;
  27. }
  28. }

A kód nagyon egyszerű, inicializálom először az UART perifériát, majd ha valamit szeretnék küldeni, beleteszem az UDR0 regiszterbe. Minden adatcsomag második bájtja tartalmazza az adatcsomag hosszát, az első byte a cím, a többi adat. A DIRECTION_RECEIVER vezérli az RS485-ös átalakító adatirányát. Ha a számláló ugyanannyi, mint a fogadott csomag második bájtja, akkor megérkezett a csomag, és egy a New_Value_Com változó értéke.

Az a problémám, hogy egyik irányba tökéletesen működik a kommunikáció, a másik irányba pedig az MSB mindig 1, és nem tudok rájönni, hogy miért, kipróbáltam terminallal, és egyértelmű, hogy az adó oldalon van a hiba, próbáltam hexában direkten adni az UDR0 regiszterbe, az se segített, és mind a 2 vezérlőn ez a kód fut. Próbáltam más vezérlővel is, úgy se volt jó, ha csak magát ezt a kódot használom, akkor működik, csak ha hozzáteszem a többi programot, ami működteti a berendezést, akkor jelentkezik a baj. Már egy hete küzdök vele, és nem tudom rájönni a hibára, szerintetek mi lehet a baj?
(#) san398 hozzászólása Júl 28, 2012 /
 
Ebben a forrás file-ban Bővebben: Link lévő delay.h, lcd.h és uart.h file-okra lenne szükségem.Akinek megvan kérem segítsen.Köszönöm.
(#) Moci.net válasza sgt hozzászólására (») Júl 28, 2012 /
 
Hát van benne valami, nem lesz könnyű. De azért a html layout se volt könnyű abba se vannak változók. Csak hozzá kell szokni. De igaz ez a legnehezebb eddig, de elvagyok vele mert jó érzés, hogy végre nem vagyok rabja egy keretrendszernek se .
A szabályokat vettem és zoli is jól mondta r11 az nem éppen valós. Mindegyik hszolásbol tanultam. Köszöntem .
Majd még biztos kérdezek.
(#) Moci.net hozzászólása Júl 28, 2012 /
 
Már kérdezek is . Ez mondjuk elvi kérdés lesz, de azért megkérdezem. Hogyan van az hogy ennél az avr-nél van memória. A "sima" intel meg amd mikrochip -eknél külön van a RAM (meg a HDD). Itt meg a uC-be van benne a flash meg az sram (meg persze az regiszterek, de ez ok). Most ezek az integrált memóriák nem feleslegesek? Azért mondom, mert így nem érzem az egységek függetlenségét. Vagy ezek a memóriák cache-ként foghatóak fel?
(#) sgt válasza Moci.net hozzászólására (») Júl 28, 2012 /
 
Ezt is olvasd el. Haza fele a vonaton utána kerestem ennek, hogy az r11 miért nem jó. A lényeg az, hogy vannak bizonyos műveletek (jó részt konstanssal való művelet), amik csak az r16-tól r31-ig működnek. A többi utasításnál szabadon használhatók r0-r31-ig a regiszterek.

HTML igazából nem is programozási nyelv, csak egy szimpla leíró nyelv, mint a latex, vagy az xml.

Am tényleg jó néha asm-ben programozni, mert jobban megmozgatja az agyat mint a C vagy éppen a .net.
(#) sgt válasza Moci.net hozzászólására (») Júl 28, 2012 /
 
Számítógép architektúrákat nem tanultál még?

Mikrokontrollerek jellemzően Harvard architektúrára épülnek. Lényeg, hogy a programmemória és az adatmemória külön vannak, így egyszerre történhet írás/olvasás. PC-nél más a helyzet, mert ott a HDD-ről nem tudsz real-time beolvasni programot, emiatt a program futása előtt ezt betölti a memóriába, és majd onnan fogja kiolvasni azt a CPU. Ugyanebbe a memóriába fogja majd az adatokat is rakni, mert még egy nagy sávszélességű memóriát kiszolgálni pazarlás lenne, ha már van egy ilyen.
(#) sgt válasza sgt hozzászólására (») Júl 28, 2012 / 1
 
Kifutottam az időből.

Az adatlapban bővebben is olvashatsz a memóriákról . Az AVR-ekben háromféle memória van: egy flash (programnak, és a megszakítási táblának), egy SRAM ( általános felhasználású regisztereknek, speciális felhasználású regisztereknek, és az adatoknak), és egy EEPROM.
(#) sgt válasza mzozo95 hozzászólására (») Júl 28, 2012 /
 
Ezt próbáld meg: USART_RX_vect Bővebben: Link

Amit írtál kód az úgy egészen biztosan nem maradhat, mert tényleg átláthatatlan az egész. Használj pointereket, mert sokkal átláthatóbb lesz. Még akkor is ha 10-15 változót/tömböt adsz át!!!

Pointernek az a lényege, hogy az adott változó címét / tömbnek a kezdő címét használod nem pedig magát az objektumot. Így ha több visszatérési értéket kellene megvalósítani a függvényben (amit PERL-ben simán meg lehet), akkor ott ezeket a változóknak a pointerét tedd bele a függvény argumentumába, és így hiába nem lesz benne a return operandausába, meg fog változni, mert a címén keresztül éred el. A tömbökre ugyanez vonatkozik.

Alább betettem egy példa kódot, igaz ez PC-re van, de a helyzeten nem változtat.
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int i = 10;
  5.  
  6. void array_write(int *i, int *pointer)
  7. {
  8.      int j = 0;
  9.      for(; j <= *i; j++)
  10.      {
  11.            *pointer++ = j;
  12.      }
  13. }
  14.  
  15. void array_print(int *i, int *pointer)
  16. {
  17.      int j = 0;
  18.      for(; j <= *i; j++)
  19.      {
  20.            printf("%i\n", *pointer++);
  21.      }
  22. }
  23.  
  24. int main(int argc, char *argv[])
  25. {
  26.   int array[10];
  27.   int *a_p = &array[10];
  28.   int *i_p = &i;
  29.  
  30.   array_write(i_p, a_p);
  31.   array_print(i_p, a_p);  
  32.  
  33.   system("PAUSE");
  34.   return 0;
  35. }

Azok a tömbök/változók, amiket a megszakításban is használsz azok maradjanak meg globális változóként, míg a többit tedd bele a mainbe. Sőt azt amit kint hagysz globálisként arra nyugodtan mutathatsz a mainen belül egy pointerrel és használhatod a függvény argumentumokban.

Azt amit beteszel a main-en belül, arra példa az array tömb, amit pedig kint hagysz a megszakítás miatt, arra példa az i változó.

Ha bool-t használsz akkor bátran írj true-t, és false-t. Utána néztem a C99-ben már tényleg benne van a bool változó. Csak én anno egy régebbi szabványon tanultam meg, ami még nem ismerte, emiatt volt kavarodás részemről.
(#) Moci.net válasza sgt hozzászólására (») Júl 28, 2012 /
 
De tanultam szgép architektúrát, csak az olyan is volt hogy semmilyen. De amiket írtál azokat vágom. Inkább megkérdezem máshogy, mert rosszul tettem fel a kérdést. A mikrokontrollerekhez lehet csatolni külső memóri(át/ákat)? (Ugy mint pl a PC AMD-jéhez a RAM. És akkor ebből a RAM-ból betölteni/beleírni a cuccokat.) Persze ha Harvard akkor min 2 külön külső memóriát lehet-e csatolni?
(#) sgt válasza Moci.net hozzászólására (») Júl 28, 2012 / 1
 
Flash-t tudtommal nem lehet bőveítni, de cáfoljatok meg ha nem így van. Am két lehetőség van. Egyikkel a már meg lévő SRAM-ot lehet kibővíteni, viszont ehhez olyan uC kell, de ekkor az SRAM kiterjesztéseként tudod kezelni, ami nagy előny, mert gyors, és egyszerű használni. Másik lehetőség amikor egy különálló ramot kapcsolsz rá, ami vagy parallel, vagy SPI interfésze van, de ez lassabb, és nehézkesebb kezelni.
(#) mzozo95 válasza sgt hozzászólására (») Júl 28, 2012 /
 
Szia!
Köszönöm, így a megszakítás már tökéletes.

Amit lehetett, mindent bepakoltam lokális változónak, de sajnos a main sok másik függvényt meghív, amiknek globális változó kell(+ az interruptos változók)

A pointert ahol lehetett alkalmaztam(kivéve az interruptban, így láttam ésszerűbbnek), de engem igazából a globális pointerek jobban összezavarnak, mint ahogy most írtam...

AZ átláthatatlanságot a sok kis függvény okozhatja, ami a mainban van, a program így tökéletesen működik, 12ch software pwm + 2ch hardware pwm...

  1. #define F_CPU 8000000
  2. #include <avr/io.h>
  3. #include <util/delay.h>
  4. #include <avr/interrupt.h>
  5. #include <inttypes.h>
  6.  
  7. #include <stdbool.h> //bool típushoz
  8.  
  9. ////////////////////////////////
  10. #define BAUD 38400///38400bps
  11. #define UBRR ((F_CPU / (BAUD * 16L)) - 1)
  12. ////////////////////////////////
  13. //változók
  14. volatile unsigned char rec[15];//string buffeer
  15. volatile unsigned char buffer; //byte buffet
  16.  
  17. volatile unsigned char stat=0;//string karakter száma
  18.  
  19. volatile int se[12]; //bejövő adat
  20.  
  21. volatile int servo[12]; ///szervo pozíció
  22. volatile bool inter=0;//(0-1) szemafor
  23. //////////////////
  24. /////
  25. void uart_init(void)
  26. {
  27. UCSR0B = (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
  28. // baud rate
  29. UBRR0H = (unsigned char) (UBRR>>8);
  30. UBRR0L = (unsigned char) UBRR;
  31. //  format: 8data, 2stop bit
  32. UCSR0C = (1<<UMSEL01)| (1<<USBS0) | (3<<UCSZ00);
  33. }
  34.  
  35. ///////UartKüld
  36.   void UARTKuld(unsigned char c){
  37.                 while((UCSR0A & (1<<UDRE0)) == 0) {}
  38.        
  39.             UDR0 = c;
  40. }
  41. ///////szövegküld
  42.    void UARTSzovegKuld( char *p)
  43. {
  44.         while(*p)
  45.         {
  46.           UARTKuld( *p++);
  47.         }
  48. }//szövegküld vége
  49.  
  50. void delrec(void){
  51.  for(int i=0; i<15;i++){
  52.   rec[i]=' ';
  53. stat=0;};
  54.  }
  55.  
  56. void kuldrec(void){
  57. for(int i=0; i<stat ;i++){
  58.  UARTKuld(rec[i]);}
  59.  }
  60.  
  61. //decimális szám küldése:
  62. void outdec(long data, unsigned int ndigits) { //integer to dec=>string, és érték kiírása
  63.     static char sign, s[12];
  64.     _delay_us(10);
  65.     unsigned int i;
  66.             i=0; sign=' ';  //alapvetően nincs előtte semmi
  67.             if(data<0) { sign='-'; data = -data;} //ha minusz, akk elé: -
  68.             do {
  69.                     s[i]=data%10 + '0'; //integer átírása ASCII ba
  70.                     data=data/10;
  71.                     i++;
  72.                     if(i==ndigits) {s[i]='.'; i++;}
  73.             } while(data>0);
  74.             UARTKuld(sign);
  75.             do{
  76.                       UARTKuld(s[--i]); //összes karakteren végigmenni
  77.             } while(i);
  78. }
  79.  
  80. uint8_t comm( char *p){
  81. char azonos=1;
  82. int szam=0;
  83. for(szam=0; szam < 15; szam++)
  84. {
  85.     if (rec[szam]!=( *p++))
  86.     {
  87.        azonos = 0;
  88.        break;
  89.     }
  90.     if(!*p) break;
  91.  }
  92. return (azonos);}
  93.  
  94.  
  95. uint16_t strtoint(int szam){
  96. int ertek=0;
  97.  
  98. if (rec[szam]>='0' && rec[szam]<='9') {ertek += (rec[szam] - '0')*1000;};
  99. szam+=1;
  100. if (rec[szam]>='0' && rec[szam]<='9') {ertek += (rec[szam] - '0')*100;};
  101. szam+=1;
  102. if (rec[szam]>='0' && rec[szam]<='9') {ertek += (rec[szam] - '0')*10;};
  103. szam+=1;
  104. if (rec[szam]>='0' && rec[szam]<='9') {ertek += (rec[szam] - '0');};
  105. return (ertek);}
  106.  
  107. void ready(void){
  108. for(int i=0; i<14;i++)
  109. {servo[i]=se[i];}
  110. }
  111.  
  112. void init_servo(void){//servo init
  113. //16bit pwm
  114. DDRB|= _BV(DDB1)|_BV(DDB2)|_BV(DDB1);   //pwm portd1 2 3
  115.  
  116. TCCR1A = (1<<COM1A1)| (1<<COM1B1);
  117. TCCR1B = (1<<WGM13) | (1<<CS11) ;//Posztás 8al
  118. ICR1 = 10000;//periódus: 20ms
  119. OCR1A = 750;//servo1 1500us
  120. OCR1B = 750;//servo2 1500us
  121. }
  122.  
  123. uint16_t afterdelay(void){
  124. int ertek=0;
  125. ertek+=se[0]+se[1]+se[2]+se[3]+se[4]+se[5]+se[6]+se[7]+se[8]+se[9]+se[10]+se[11];
  126. return(20000-ertek);}
  127.  
  128. void delay_1us(uint16_t delay_data) {//5us es késleltetés(így kevés memóriát foglal)
  129.          while(delay_data--) _delay_us(1); }
  130.  
  131. void s_pwm(void){
  132. ///////////////software pwm
  133. PORTD=4;
  134. delay_1us(servo[0]);
  135.  
  136. PORTD=8;
  137. delay_1us(servo[1]);
  138.  
  139. PORTD=16;
  140. delay_1us(servo[2]);
  141.  
  142. PORTD=32;
  143. delay_1us(servo[3]);
  144.  
  145. PORTD=64;
  146. delay_1us(servo[4]);
  147.  
  148. PORTD=128;
  149. delay_1us(servo[5]);
  150.  
  151. PORTD=0;
  152. PORTB=1;
  153. delay_1us(servo[6]);
  154.  
  155. PORTB=8;
  156. delay_1us(servo[7]);
  157.  
  158. PORTB=16;
  159. delay_1us(servo[8]);
  160.  
  161. PORTB=32;
  162. delay_1us(servo[9]);
  163.  
  164. PORTB=0;
  165. PORTC=1;
  166. delay_1us(servo[10]);
  167.  
  168. PORTC=2;
  169. delay_1us(servo[11]);
  170. PORTC=0;
  171. }
  172.  
  173. int main(void){
  174.  
  175. bool echo=0; //(0-1)visszhang szemafor
  176.  
  177. DDRB=255;
  178. PORTB=0;
  179. DDRD=255;
  180. PORTB=0;
  181. DDRC=3;
  182. PORTB=0;
  183.  
  184. delrec();
  185.  
  186. uart_init();
  187.  
  188. UARTSzovegKuld("Uart Online! Ready To Serial communication!");
  189.  
  190. init_servo();
  191.  
  192. sei();
  193.  
  194. se[0]=1000;
  195. se[1]=1000;
  196. se[2]=1000;
  197. se[3]=1000;
  198. se[4]=1000;
  199. se[5]=1000;
  200. se[6]=1000;
  201. se[7]=1000;
  202. se[8]=1000;
  203. se[9]=1000;
  204. se[10]=1000;
  205. se[11]=1000;
  206. ready();
  207.  
  208. ///////
  209. while(1){
  210. s_pwm();
  211. if (afterdelay()>0){delay_1us(afterdelay()/3);}
  212. //uart kiértékelése
  213.  if (inter==1){
  214.  
  215. if (echo){UARTKuld(buffer);};
  216.  
  217. if (buffer==8){
  218.  delrec();
  219.    }
  220.   if (buffer=='?'){
  221.     kuldrec();
  222. delrec();
  223.    }
  224.  
  225. if (buffer=='!'){
  226.   if (comm(">online")) {UARTSzovegKuld("System online!");}else
  227.   if (comm(">echo")) {UARTSzovegKuld("Echo ON!"); echo=1;}else
  228.   if (comm(">eoff")) {UARTSzovegKuld("Echo Off!"); echo=0;} else
  229.   if (comm(">info")) {UARTSzovegKuld("Uart Online! "); UARTSzovegKuld("| 38400bps | atmega48 | Majlath.tech 2012");}
  230.   else {
  231.   UARTSzovegKuld("ERROR");
  232.   }
  233.   delrec();
  234.   }
  235.  
  236.     if (buffer=='='){ //servo pos módisítás
  237.  
  238. UARTSzovegKuld("Servo modified!");
  239. UARTKuld(' ');
  240. UARTKuld(rec[0]);
  241. UARTKuld(':');
  242.  
  243.  
  244. if (rec[0]>='a' && rec[0] <='z'){ //angol abc szerinti abc sorrendbeli betűk elhelyezkedésének sorszáma-1 számú szervó pozíciójának módosítása
  245. se[rec[0]-'a']=strtoint(1);
  246. outdec(se[0],0);} else {UARTSzovegKuld("ERROR IN SERVO TITLE!");
  247. };
  248.  
  249.  
  250. if (rec[0]>='A' && rec[0] <='Z'){ //angol abc szerinti abc sorrendbeli betűk elhelyezkedésének sorszáma-1 számú szervó pozíciójának módosítása
  251. if (rec[0]=='A'){OCR1A=strtoint(1); outdec(OCR1A,0);} else
  252. if (rec[0]=='B'){OCR1A=strtoint(1); outdec(OCR1B,0);}
  253.  else {UARTSzovegKuld("ERROR IN SERVO TITLE!");};
  254.  };
  255.  
  256. delrec();
  257. buffer=0;
  258. }
  259.  
  260. if (buffer=='%'){
  261. int number=strtoint(1);
  262. outdec(number,0);
  263. delrec();}
  264.  
  265. if (buffer=='<'){
  266. ready();
  267. delrec();
  268. }
  269.  
  270. //led jelzés
  271. PORTB=1;
  272. _delay_ms(1);
  273. PORTB=0;
  274. inter=0;
  275. };
  276. }
  277. }
  278.  
  279. ISR(USART_RX_vect)
  280. {  
  281.    if(UCSR0A & (1 << RXC0)) {buffer = UDR0;}
  282.  
  283. rec[stat]=buffer;
  284. stat+=1;
  285.  
  286. inter=1;
  287. }

Mit gondolsz?
(#) karika200 hozzászólása Júl 29, 2012 /
 
Sziasztok!

Korábban itt a fórumon már írtam, hogy egy dallas IC-s hőmérőt szeretnék ethernetre illeszteni AVR-el. Ehhez kerestem Ethernetes Arduino panelt, amit egyszerűen, akár I2C-n, akár más egyszerű protokollon keresztül tudok hajtani. Ezt találtam a Conradnál: http://www.conrad.de/ce/de/product/191803/Arduino-Ethernet-Platine-...il=005

Ezzel ha jól gondolom megoldható a mutatvány, hogy fogok egy ATmega MCU-t amiben lefejlesztem a hőmérők lekérdezését és a HTTP-n keresztüli küldést, és a TCP/IP dolgokat pedig intézi az Arduino. Csak a biztonság kedvéért, nem szeretnék beruházni egy olyan HW-be ami végülis nem megoldás a problémámra..
(#) Robi98 hozzászólása Júl 29, 2012 /
 
Sziasztok!
Írtam egy programot, ami azt csinálná, hogy egy ATtiny 45-ös ic PB4-es lábát ha földre húzzuk, akkor elkezd felváltva villogtatni két led-et, majd ha mégegyszer a földre húzzuk, akkor már párossával villogtatja a ledekt, harmadjára pedig felcseréli a ledek állapotát. A végeredmény abszolút nem az lett amire számítottam: Amikor a lehúzó nyomógombot a földre megnyomom, a ledek nem világítnak. Ha rengetegszer megnyomom, csak akkor kezdenek villogni a ledek, de nem jól.
1. Ha nincs a földre húzva, akkor háromszor párossával, majd kétszer felválta villognak a végtelenségig.
2. Ha folyamatosan lehúzom, akkor felváltva villog, ha még egyszer, akkor párossával. De ha már felengedem a gombot, akkor újra úgy, ahogy az 1-es pontban írtam.
  1. #include <avr/io.h>
  2. #include <util/delay.h>
  3.  
  4. int main(void)
  5. {
  6. DDRB=(1<<PB0)|(1<<PB1);//a két led kimenet
  7. DDRB&=~(1<<PB4);//a gomb bemenet
  8. PORTB|=(1<<PB4);//a gomb felhúzóellenállásának bekapcsolása
  9. uint8_t x=0;
  10.  
  11. while(1)
  12. {
  13. while(PINB&(1<<PB4))
  14. {
  15. DDRB|=(1<<PB4);//a lábat letiltom...
  16. _delay_ms(25);//várok...
  17. DDRB&=~(1<<PB4);//majd újra engedélyezem. (ezzel szűröm ki a pergést)
  18. x++;
  19. }
  20. if(x==1)
  21. {
  22. PORTB|=(1<<PB0);
  23. _delay_ms(500);
  24. PORTB&=~(1<<PB0);
  25. PORTB|=(1<<PB1);
  26. _delay_ms(500);
  27. PORTB&=~(1<<PB1);
  28. }
  29. if(x==2)
  30. {
  31. PORTB=(1<<PB0)|(1<<PB1);
  32. _delay_ms(500);
  33. PORTB&=~(1<<PB0);
  34. PORTB&=~(1<<PB1);
  35. _delay_ms(500);
  36. }
  37. if(x==3)
  38. {
  39. PORTB=(1<<PB0)^(1<<PB1);
  40. }
  41. if(x==4) x=0;
  42. }
  43. }
(#) TavIR-AVR válasza karika200 hozzászólására (») Júl 29, 2012 /
 
Ebben ott a chip. Nézd meg az Arduino ethernet projektet... Abban ez készen is van...
Tanulni sosem késő...
(#) karika200 válasza TavIR-AVR hozzászólására (») Júl 29, 2012 /
 
Mire gondolsz, hogy ez készen van? A TCP/IP vagy maga a hőmérős dolog http-vel? Nekem a fenti linkelt panellal a következő az elgondolásom: kézhez kapom és csak egy programot kell írjak a saját MCU-mra ami lekérdezi a hőmérőket és HTTP GET-el megadott URL-re. Tehát IP szinten nem szeretnék belefolyni, csak "socket" szinten: küld el az x bájtos csomagot y címre ezzel a tartalommal. Aztán olvasom a választ.
(#) TavIR-AVR válasza karika200 hozzászólására (») Júl 29, 2012 /
 
Igen, ez.
Arduino ethernet alkalmazáscsomagja.
(#) karika200 válasza TavIR-AVR hozzászólására (») Júl 29, 2012 /
 
Tehát akkor ez tökéletes lesz az elvárásaimra, köszönöm! ...és a linket is.
(#) mario1111 válasza mario1111 hozzászólására (») Júl 30, 2012 /
 
Megvan, hogy nagyjából mi a gond, de a megoldást nem tudom még :S A GCC-vel van gond. A 128K bájt feletti kódmemória megcímzése nem megy neki. Azért ez eléggé dühítő, így első körben...
(#) blackdog hozzászólása Júl 30, 2012 /
 
Sziasztok!

Nagyobb AVR-ek nem csak egy-egy VCC/GND lábbal rendelkeznek. TQFP tokban ATMEGA128 2db ATMEGA32 3db.
Van annak értelme vagy jelentőssége, ha minden VCC láb közelébe teszek egy 100 nF kondit? Vagy felesleges?
(#) Massawa válasza blackdog hozzászólására (») Júl 30, 2012 /
 
Rendszerint nincs értelme, untig elég egy, de a lehetö legközelebb a lábakhoz.
(#) blackdog válasza Massawa hozzászólására (») Júl 30, 2012 /
 
Akkor viszont felmerül bennem a kérdés: Mindenhova el kell vezetni a VCC/GND-t vagy elegendő egy helyere?
Következő: »»   462 / 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