Forum: Mikrocontroller und Digitale Elektronik ATmega168 mit anderem ATmega168 programmieren


von Alfred K. (devkid)


Lesenswert?

Hallo,

ich habe eine mySmartControl (ATmega168 - Master) von myAVR, den ich 
problemlos per USB -> UART -> Bootloader beschreiben kann. Mit diesem 
möchte ich einen zweiten ATmega168 (Slave) über SPI programmieren 
"lassen".

Ich habe dazu jeweils die Pins B3 (MOSI), B4 (MISO) und B5 (SCK) der 
beiden AVRs miteinander verbunden. B2 (SS) vom Slave hängt an B1 vom 
Master und wird im Code auf 0 gezogen, C6 (Reset) hängt an D4 vom Master 
und wird auch im Code auf 0 gezogen. B2 (SS) vom Master wird im Code auf 
1 gezogen.

Ports einschalten:
1
DDRB = (1 << PB2) | (1 << PB3) | (1 << PB5); PORTB = (1 << B2) /* für SS = 1 beim Master */
2
DDRC = PORTC = 0; /* für Reset = 0 beim Slave */
3
DDRD = PORTC = 0/* für SS = 0 beim Slave */

SPI einschalten:
1
SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);

"Programming Enable Instruction" senden:
1
unsigned char spi_xfer (unsigned char out)
2
{
3
  SPDR = out;
4
  while (!(SPSR & (1 << SPIF)));
5
  return SPDR;
6
}
7
8
...
9
10
spi_xfer (0xAC);
11
spi_xfer (0x53);
12
unsigned char x = spi_xfer (0);
13
spi_xfer (0);

Hier bekomme ich aber als x immer nur 0 raus :( Ich hab schon die ganzen 
Tag alles durchprobiert: den Slave erst kurz vor dem Programmieren 
einschalten, Clock-Prescaler beim Master auf 256 (damit es langsamer 
wird), nichts funktioniert.

Hat jemand eine Idee?

von Alfred K. (devkid)


Lesenswert?

Ok, das Problem hat sich erübrigt. Man darf Reset nicht von Anfang an 
auf GND legen, sondern erst eine Weile, nachdem der AVR Saft gekriegt 
hat. Im Manual stand, man soll Spannung anlegen, während Reset auf 0 
liegt; funktioniert so aber nicht.

Aber jetzt das nächste Problem:
Ich bekomm es einfach nicht auf die Reihe, den ATmega168 letztendlich zu 
flashen. Ich kann nun erfolgreich "Programming Enable"-Instruction 
senden und bekomme beim dritten Byte die erwartete 0x53 wieder. Das 
Auslesen der Signatur-Bytes funktioniert ebenfalls, und ich bekomme die 
passenden Bytes für meinen ATmega168 zurück.

Aber wie kann ich den AVR nun flashen? Wenn ich das richtig verstanden 
habe, muss ich zuerst nacheinander, byteweise (abwechselnd Low- und 
High-Byte mit verschiendenen Instructions) mit der "Load Program Memory 
Page"-Instruction einen Buffer füllen, der so groß ist wie eine Page. 
Anschließend müsste ich den Buffer mit der "Write Program Memory 
Page"-Instruction in den Flash schreiben lassen und danach kurz warten.

Aus dem Manual wird mir aber allerdings überhaupt nicht ersichtlich, wie 
ich die Adressen der einzelnen Bytes und der Pages angeben soll?! Hab 
schon alle Varianten durchprobiert, hab auch schon alle möglichen 
ISP-Programmer-Sources durchgeschaut, aber die verwenden teils 
unterschiedliche Varianten um die Adressen zu übergeben - alles sehr 
verwirrend.

Aus der Figure 27-8 hab ich mir dann für die Instructions das hier 
konstruiert:
Buffer beladen:
1
0x20 / 0x28  |||  0x00              |||  buffer_offset >> 1         |||  data_byte
Page schreiben:
1
0x4C         |||  page_offset >> 9  |||  (page_offset >> 1) & 0xFF  |||  0x00
wobei buffer_offset jeweils von 0 bis PAGESIZE (128 in diesem Fall) 
zählt und dann wieder von 0 an und page_offset 0 bis zur Anzahl der zu 
schreibenden Pages - 1 zählt.

Aber das funktioniert nicht. Auch wenn ich die entsprechenden Stellen 
wieder auslesen will kommt fast immer 0, manchmal Werte um 80 raus; 
könnte aber auch daran liegen, dass ich beim Auslesen ebenfalls die 
Adressen falsch angebe.

von Bernhard M. (boregard)


Lesenswert?

Das was Du machen willst, machen doch USBasp und Konsorten. Schau doch 
mal in deren Source code nach, wie die das machen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.