Fórum témák
- • Sprint-Layout NYÁK-tervező
- • Kaputelefon
- • Számítógép hiba, de mi a probléma?
- • Rádióamatőrök topikja
- • Boombox javítás
- • CNC építése házi alkatrészekből az alapoktól
- • USB 3.2 HUB modul
- • Klíma szervizelés, javítás
- • Kapcsolóüzemű tápegység
- • Autóriasztó és központi zár
- • Li-Ion saját akkucsomag készítése
- • Elektromos távirányítós kapunyitó
- • Erősítő mindig és mindig
- • Analóg oszcilloszkóp javítása
- • LED szalag
- • Hangszórójavítás (otthon)
- • Mosógép vezérlők és általános problémáik
- • Érdekességek
- • Transzformátor készítés, méretezés
- • Villanypásztor
- • Kondenzátor
- • Arduino
- • Videomagnó problémák
- • IMI villanymotor
- • Digitális adatátvitel
- • Mosogatógép hiba
- • Nagyfeszültségű tápegység
- • 3-fázisú Modbus-os teljesítményszabályzó (SCR power controller)
- • Elfogadnám, ha ingyen elvihető
- • Villanyszerelés
- • TDA7294 végerősítő
- • Klíma beszerelése, fűtés-hűtés házilag
- • Kombikazán működési hiba
- • Általános antennás kérdések, válaszok
- • Dobozolási technikák, műszerdobozok
- • Elektronikai témájú könyvek újságok
- • Elektromos vezérlésű pneumatika
- • Internetes rádióvevő
- • Alternativ HE találkozó(k)
- • 3D nyomtatás
- • Felajánlás, azaz ingyen elvihető
- • Akkumulátor töltő
- • Háromfázisú aggregátor
- • Szintetizátor javítás
- • Sütő javítás
- • Laptop javítás, tuning
- • Autós erősítős kérdések, problémák
- • Mikrohullámú sütő javítás, magnetron csere, stb.
- • Villanymotor
- • Vegyes barkácsfogások
- • Digitális óra
- • Hűtőgép probléma
- • TV hiba, mi a megoldás?
- • Szünetmentes táp javítása, élesztése
- • Erősítő építése elejétől a végéig
» Több friss téma
|
Fórum » AVR - Miértek hogyanok
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
Létezik AC optócsatoló is.
Lehet, hogy te is belebotlottál, csak gondolom linkelek egyet: TCMT4600
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.)
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...
É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.
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.
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...
//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
#define F_CPU 8000000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#include <stdbool.h> //bool típushoz
////////////////////////////////
#define BAUD 38400///38400bps
#define UBRR ((F_CPU / (BAUD * 16L)) - 1)
////////////////////////////////
//változók
volatile unsigned char rec[15];//string buffeer
volatile unsigned char buffer; //byte buffet
volatile unsigned char stat=0;//string karakter száma
volatile int servo[3]; ///szervo pozíció
volatile bool echo=0; //visszhang(0-1)
volatile bool inter=0;//(0-1) szemafor
//////////////////
/////
void uart_init(void)
{
UCSR0B = (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
// baud rate
UBRR0H = (unsigned char) (UBRR>>8);
UBRR0L = (unsigned char) UBRR;
// format: 8data, 2stop bit
UCSR0C = (1<<UMSEL01)| (1<<USBS0) | (3<<UCSZ00);
}
///////UartKüld
void UARTKuld(unsigned char c){
while((UCSR0A & (1<<UDRE0)) == 0) {}
UDR0 = c;
}
///////szövegküld
void UARTSzovegKuld( char *p)
{
while(*p)
{
UARTKuld( *p++);
}
}//szövegküld vége
void delrec(void){
for(int i=0; i<50;i++){
rec[i]=' ';
stat=0;};
}
void kuldrec(void){
for(int i=0; i<stat ;i++){
UARTKuld(rec[i]);}
}
//decimális szám küldése:
void outdec(long data, unsigned int ndigits) { //integer to dec=>string, és érték kiírása
static char sign, s[12];
_delay_us(10);
unsigned int i;
i=0; sign=' '; //alapvetően nincs előtte semmi
if(data<0) { sign='-'; data = -data;} //ha minusz, akk elé: -
do {
s[i]=data%10 + '0'; //integer átírása ASCII ba
data=data/10;
i++;
if(i==ndigits) {s[i]='.'; i++;}
} while(data>0);
UARTKuld(sign);
do{
UARTKuld(s[--i]); //összes karakteren végigmenni
} while(i);
}
uint8_t comm( char *p){
char azonos=1;
int szam=0;
for(szam=0; szam < 15; szam++)
{
if (rec[szam]!=( *p++))
{
azonos = 0;
break;
}
if(!*p) break;
}
return (azonos);}
uint16_t strtoint(int szam){
int ertek=0;
if (rec[szam]>='0' && rec[szam]<='9') {ertek += (rec[szam] - '0')*1000;};
szam+=1;
if (rec[szam]>='0' && rec[szam]<='9') {ertek += (rec[szam] - '0')*100;};
szam+=1;
if (rec[szam]>='0' && rec[szam]<='9') {ertek += (rec[szam] - '0')*10;};
szam+=1;
if (rec[szam]>='0' && rec[szam]<='9') {ertek += (rec[szam] - '0');};
return (ertek);}
void init_servo(void){//servo init
//16bit pwm
DDRB|= _BV(DDB1)|_BV(DDB2)|_BV(DDB1); //pwm portd1 2 3
TCCR1A = (1<<COM1A1)| (1<<COM1B1);
TCCR1B = (1<<WGM13) | (1<<CS11) ;//Posztás 8al
ICR1 = 10000; //periódus: 20ms
OCR1B = 750;//servo2 1500us
}
void delay_1us(uint16_t delay_data) {//5us es késleltetés(így kevés memóriát foglal)
while(delay_data--) _delay_us(1); }
void s_pwm(void){
///////////////software pwm
PORTB=2;
delay_1us(servo[0]);
PORTB=0;
}
int main(void){
//init_servo();
DDRB=255;
PORTB=0;
delrec();
uart_init();
UARTSzovegKuld("Uart Online! Ready To Serial communication!");
sei();
servo[0]=1000;
///////
while(1){
s_pwm();
_delay_ms(18);
//uart kiértékelése
if (inter==1){
if (echo){UARTKuld(buffer);};
if (buffer==8){
delrec();
}
if (buffer=='?'){
kuldrec();
}
if (buffer=='!'){
if (comm("alma")) {UARTSzovegKuld("alma fogadva!");delrec();}else
if (comm("echo")) {UARTSzovegKuld("Echo ON!"); echo=1;delrec();}else
if (comm("eoff")) {UARTSzovegKuld("Echo Off!"); echo=0;delrec();} else
if (comm ("info")) {UARTSzovegKuld ("Uart Online! "); UARTSzovegKuld ("| 38400bps | atmega48 | string.c");delrec (); }
else {
UARTSzovegKuld("ERROR");
delrec();}
}
if (buffer=='='){
if (rec[0]=='a'){servo[0]=strtoint(2);
UARTSzovegKuld("Servo modified!");
UARTSzovegKuld("a=");
outdec(servo[0],0);
delrec();
buffer=0;};
}
if (buffer=='%'){
int number=strtoint(1);
outdec(number,0);
delrec();}
//led jelzés
PORTB=1;
_delay_ms(1);
PORTB=0;
inter=0;
};
}
}
ISR(SIG_USART_RECV)
{
if(UCSR0A & (1 << RXC0)) {buffer = UDR0;}
rec[stat]=buffer;
stat+=1;
inter=1;
}
Üdv.: Zoltán
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:
ldi r11, 0xCC
out DDRB, r11
ldi r12, 0xCC
out PORTB, r12 ; 0xCC-t kitesszük a kimenetre
in r13, PINB ; beolvassuk a bemeneteket, de ugye a porton van már egy 0xCC, amit kiszeretnénk maszkolni
com r12 ; ezért a 0xCC-t negáljuk
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.
Fogok reagálni, csak ez egy kicsit nagyobb lélegzet lesz, és mert netezni sincs időm.
Azért az 'ldi r11' nem éppen valós... R16 és fölötte használható.
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: void uart_INIT(void)
{
//Calcuate the baudrate register content
UBRR0H = (uint8_t) (UART_BAUD_CALC(UART_BAUD_RATE,F_CPU) >> 8);
UBRR0L = (uint8_t) UART_BAUD_CALC(UART_BAUD_RATE, F_CPU);
//Display(UART2)
UBRR1H = (uint8_t) (UART_BAUD_CALC1(UART_BAUD_RATE1,F_CPU) >> 8);
UBRR1L = (uint8_t) UART_BAUD_CALC1(UART_BAUD_RATE1, F_CPU);
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0) | (1 << TXCIE0) | (0 << UDRIE0); //Enable the receiver and transmitter and receiver interrupts on UART0 //USART0_-RX_vect
UCSR1B = (1 << RXEN1) | (1 << TXEN1) | (0 << RXCIE1) | (0 << RXCIE0) | (0 << UDRIE1); //Enable the receiver and transmitter on UART2
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
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
DIRECTION_RECEIVER
//Enable global interrupts
sei();
}
ISR(USART0_RX_vect)
{
receiver_Buffer[receiver_Buffer_counter] = UDR0;
receiver_Buffer_counter++;
if((receiver_Buffer_counter > 2) && (receiver_Buffer_counter == receiver_Buffer[1] ))
{
receiver_Buffer_counter = 0;
if( ( receiver_Buffer[0] == MASTER_ADDRESS) || (receiver_Buffer[0] == GENERAL_CALL) )
{
New_Value_Com = 1;
}
}
}
ISR(USART0_TX_vect)
{
transmitter_Buffer_counter++;
if(transmitter_Buffer_counter != transmitter_Buffer[1])
{
UDR0 = transmitter_Buffer[transmitter_Buffer_counter];
}
else
{
DIRECTION_RECEIVER;
}
}
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?
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.
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.
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?
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.
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.
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.
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.
#include <stdio.h>
#include <stdlib.h>
int i = 10;
void array_write(int *i, int *pointer)
{
int j = 0;
for(; j <= *i; j++)
{
*pointer++ = j;
}
}
void array_print(int *i, int *pointer)
{
int j = 0;
for(; j <= *i; j++)
{
printf("%i\n", *pointer++);
}
}
int main(int argc, char *argv[])
{
int array[10];
int *a_p = &array[10];
int *i_p = &i;
array_write(i_p, a_p);
array_print(i_p, a_p);
system("PAUSE");
return 0;
}
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.
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?
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.
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...
#define F_CPU 8000000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#include <stdbool.h> //bool típushoz
////////////////////////////////
#define BAUD 38400///38400bps
#define UBRR ((F_CPU / (BAUD * 16L)) - 1)
////////////////////////////////
//változók
volatile unsigned char rec[15];//string buffeer
volatile unsigned char buffer; //byte buffet
volatile unsigned char stat=0;//string karakter száma
volatile int se[12]; //bejövő adat
volatile int servo[12]; ///szervo pozíció
volatile bool inter=0;//(0-1) szemafor
//////////////////
/////
void uart_init(void)
{
UCSR0B = (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
// baud rate
UBRR0H = (unsigned char) (UBRR>>8);
UBRR0L = (unsigned char) UBRR;
// format: 8data, 2stop bit
UCSR0C = (1<<UMSEL01)| (1<<USBS0) | (3<<UCSZ00);
}
///////UartKüld
void UARTKuld(unsigned char c){
while((UCSR0A & (1<<UDRE0)) == 0) {}
UDR0 = c;
}
///////szövegküld
void UARTSzovegKuld( char *p)
{
while(*p)
{
UARTKuld( *p++);
}
}//szövegküld vége
void delrec(void){
for(int i=0; i<15;i++){
rec[i]=' ';
stat=0;};
}
void kuldrec(void){
for(int i=0; i<stat ;i++){
UARTKuld(rec[i]);}
}
//decimális szám küldése:
void outdec(long data, unsigned int ndigits) { //integer to dec=>string, és érték kiírása
static char sign, s[12];
_delay_us(10);
unsigned int i;
i=0; sign=' '; //alapvetően nincs előtte semmi
if(data<0) { sign='-'; data = -data;} //ha minusz, akk elé: -
do {
s[i]=data%10 + '0'; //integer átírása ASCII ba
data=data/10;
i++;
if(i==ndigits) {s[i]='.'; i++;}
} while(data>0);
UARTKuld(sign);
do{
UARTKuld(s[--i]); //összes karakteren végigmenni
} while(i);
}
uint8_t comm( char *p){
char azonos=1;
int szam=0;
for(szam=0; szam < 15; szam++)
{
if (rec[szam]!=( *p++))
{
azonos = 0;
break;
}
if(!*p) break;
}
return (azonos);}
uint16_t strtoint(int szam){
int ertek=0;
if (rec[szam]>='0' && rec[szam]<='9') {ertek += (rec[szam] - '0')*1000;};
szam+=1;
if (rec[szam]>='0' && rec[szam]<='9') {ertek += (rec[szam] - '0')*100;};
szam+=1;
if (rec[szam]>='0' && rec[szam]<='9') {ertek += (rec[szam] - '0')*10;};
szam+=1;
if (rec[szam]>='0' && rec[szam]<='9') {ertek += (rec[szam] - '0');};
return (ertek);}
void ready(void){
for(int i=0; i<14;i++)
{servo[i]=se[i];}
}
void init_servo(void){//servo init
//16bit pwm
DDRB|= _BV(DDB1)|_BV(DDB2)|_BV(DDB1); //pwm portd1 2 3
TCCR1A = (1<<COM1A1)| (1<<COM1B1);
TCCR1B = (1<<WGM13) | (1<<CS11) ;//Posztás 8al
ICR1 = 10000; //periódus: 20ms
OCR1B = 750;//servo2 1500us
}
uint16_t afterdelay(void){
int ertek=0;
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];
return(20000-ertek);}
void delay_1us(uint16_t delay_data) {//5us es késleltetés(így kevés memóriát foglal)
while(delay_data--) _delay_us(1); }
void s_pwm(void){
///////////////software pwm
PORTD=4;
delay_1us(servo[0]);
PORTD=8;
delay_1us(servo[1]);
PORTD=16;
delay_1us(servo[2]);
PORTD=32;
delay_1us(servo[3]);
PORTD=64;
delay_1us(servo[4]);
PORTD=128;
delay_1us(servo[5]);
PORTD=0;
PORTB=1;
delay_1us(servo[6]);
PORTB=8;
delay_1us(servo[7]);
PORTB=16;
delay_1us(servo[8]);
PORTB=32;
delay_1us(servo[9]);
PORTB=0;
PORTC=1;
delay_1us(servo[10]);
PORTC=2;
delay_1us(servo[11]);
PORTC=0;
}
int main(void){
bool echo=0; //(0-1)visszhang szemafor
DDRB=255;
PORTB=0;
DDRD=255;
PORTB=0;
DDRC=3;
PORTB=0;
delrec();
uart_init();
UARTSzovegKuld("Uart Online! Ready To Serial communication!");
init_servo();
sei();
se[0]=1000;
se[1]=1000;
se[2]=1000;
se[3]=1000;
se[4]=1000;
se[5]=1000;
se[6]=1000;
se[7]=1000;
se[8]=1000;
se[9]=1000;
se[10]=1000;
se[11]=1000;
ready();
///////
while(1){
s_pwm();
if (afterdelay()>0){delay_1us(afterdelay()/3);}
//uart kiértékelése
if (inter==1){
if (echo){UARTKuld(buffer);};
if (buffer==8){
delrec();
}
if (buffer=='?'){
kuldrec();
delrec();
}
if (buffer=='!'){
if (comm(">online")) {UARTSzovegKuld("System online!");}else
if (comm(">echo")) {UARTSzovegKuld("Echo ON!"); echo=1;}else
if (comm(">eoff")) {UARTSzovegKuld("Echo Off!"); echo=0;} else
if (comm (">info")) {UARTSzovegKuld ("Uart Online! "); UARTSzovegKuld ("| 38400bps | atmega48 | Majlath.tech 2012"); }
else {
UARTSzovegKuld("ERROR");
}
delrec();
}
if (buffer=='='){ //servo pos módisítás
UARTSzovegKuld("Servo modified!");
UARTKuld(' ');
UARTKuld(rec[0]);
UARTKuld(':');
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
se[rec[0]-'a']=strtoint(1);
outdec(se[0],0);} else {UARTSzovegKuld("ERROR IN SERVO TITLE!");
};
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
if (rec[0]=='A'){OCR1A=strtoint(1); outdec(OCR1A,0);} else
if (rec[0]=='B'){OCR1A=strtoint(1); outdec(OCR1B,0);}
else {UARTSzovegKuld("ERROR IN SERVO TITLE!");};
};
delrec();
buffer=0;
}
if (buffer=='%'){
int number=strtoint(1);
outdec(number,0);
delrec();}
if (buffer=='<'){
ready();
delrec();
}
//led jelzés
PORTB=1;
_delay_ms(1);
PORTB=0;
inter=0;
};
}
}
ISR(USART_RX_vect)
{
if(UCSR0A & (1 << RXC0)) {buffer = UDR0;}
rec[stat]=buffer;
stat+=1;
inter=1;
}
Mit gondolsz?
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..
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. #include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRB=(1<<PB0)|(1<<PB1);//a két led kimenet
DDRB&=~(1<<PB4);//a gomb bemenet
PORTB|=(1<<PB4);//a gomb felhúzóellenállásának bekapcsolása
uint8_t x=0;
while(1)
{
while(PINB&(1<<PB4))
{
DDRB|=(1<<PB4);//a lábat letiltom...
_delay_ms(25);//várok...
DDRB&=~(1<<PB4);//majd újra engedélyezem. (ezzel szűröm ki a pergést)
x++;
}
if(x==1)
{
PORTB|=(1<<PB0);
_delay_ms(500);
PORTB&=~(1<<PB0);
PORTB|=(1<<PB1);
_delay_ms(500);
PORTB&=~(1<<PB1);
}
if(x==2)
{
PORTB=(1<<PB0)|(1<<PB1);
_delay_ms(500);
PORTB&=~(1<<PB0);
PORTB&=~(1<<PB1);
_delay_ms(500);
}
if(x==3)
{
PORTB=(1<<PB0)^(1<<PB1);
}
if(x==4) x=0;
}
}
Ebben ott a chip. Nézd meg az Arduino ethernet projektet... Abban ez készen is van...
Tanulni sosem késő...
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.
Igen, ez.
Arduino ethernet alkalmazáscsomagja.
Tehát akkor ez tökéletes lesz az elvárásaimra, köszönöm! ...és a linket is.
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...
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?
Rendszerint nincs értelme, untig elég egy, de a lehetö legközelebb a lábakhoz.
Akkor viszont felmerül bennem a kérdés: Mindenhova el kell vezetni a VCC/GND-t vagy elegendő egy helyere?
|
|