Bygga en ISP Shield för Arduino (6 / 6 steg)
Steg 6: Lägg till Arduino, chip och kod!
Du kan nu programmera Arduino Bootloaders från inom IDE och även AVR markerna enligt med AVRDUDE, men jag ska förklara hur man gör allt detta på en mindre produkt orienterade Instructable.
Denna skiss förvandlar Arduino till en AVRISP
med följande stift:
10: slav reset
11: MOSI
12: MISO
13: SCKSätta en LED (med motstånd) på följande stift:
7: fel - lyser upp om något går fel (Använd röda om det är logiskt)
8: programmering - i kommunikation med slav
6: heartbeat - visar programmeraren körs (bort, se not nedan)
Valfritt - Piezo speaker på stift A3
//
Oktober 2009 av David A. Mellis
-Stöd för kommandot Läs signatur
//
Februari 2009 av Randall Bohn
-Stöd för skrivning till EEPROM (det tog så lång tid?)
Windows-användare bör överväga Winavr's avrdude i stället för den
avrdude ingår med Arduino programvara.
//
Januari 2008 av Randall Bohn
-Tack till Amplificar för att hjälpa mig med protokollet STK500
-AVRISP/STK500 (mk jag) protokollet används i uppstartshanteraren arduino
-SPI funktioner häri framkallades för AVR910_ARD programmerare
-Mer information på http://code.google.com/p/mega-isp
//
Mars 2012 - William Phelps
ändra om du vill arbeta med Arduino IDE 1.0 som har kortare seriell mottagningsbuffert
getEOP() nu blir hela begäran innan avrisp() anropas för att bearbeta det
Serial.Print((Char) xxx) ändras till Serial.write(xxx)
uint8_t ändras till byte
lagt till stöd för Piezo speaker
flyttade Pmode LED-A0
bort "heartbeat" på stift 6, La kort blip fel led istället
Varför är det så att PROG_FLASH och PROG_DATA faktiskt inte göra något???
Testade med Arduino IDE 22 och 1,0
IDE 22-5148 byte
IDE 1.0-5524 byte!Januari 2014 - Ben grå
Sätta den hjärtslag ledde tillbaka och bytte runt stiften lite för lysdioderna.LÅNGSAM HASTIGHET CHIP RADERA OCH SÄKRING BRÄNNER
//
Aktivera LOW_SPEED så att du kan radera chips som annars inte skulle
för att vara igång med en klocka för långsam för programmeraren.
//
Detta tillät mig att återställa flera ATMega328 som hade ingen starthanteraren och den
första anvisning var att ställa in klockan på den lägsta hastigheten. Brukar detta
typ av återvinning kräver hög spänning programmering, men gör detta trick
bara bra.
//
Hur gå vidare:
// 1. Aktivera LOW_SPEED och ladda den till programmeraren.
// 2. Radera och bränna säkringarna på target uC. Exempel för ATMega328:
Arduino-1.0.1/Hardware/tools/avrdude-Carduino-1.0.1/hardware/tools/avrdude.conf-patmega328p-cstk500v1 -P /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A900cf1Q-if00-port0-b19200 -e - Ulock: w: 0x3F: m - Uefuse: w: 0x05: m - Uhfuse: w: 0xDA: m - Ulfuse: w: 0xF7: m
// 3. Kommentera LOW_SPEED och ladda den tillbaka till programmeraren.
// 4. Programmet mål uC som vanligt. Exempel:
Arduino-1.0.1/Hardware/tools/avrdude-Carduino-1.0.1/hardware/tools/avrdude.conf-patmega328p-cstk500v1 -P /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A900cf1Q-if00-port0-b19200-Uflash:w:firmware.hex:i
//
Anmärkning 1: EXTRA_SPI_DELAY har lagts till kan du sakta ner SPI ännu mer. Du kan
spela med värdet om det inte fungerar med standard.
Anmärkning 2: LOW_SPEED kommer alow du bara radera chip och bränna säkringarna! Det
misslyckas om du försöker programmera mål uC hitåt!
#define LOW_SPEED
#ifdef LOW_SPEED
#define EXTRA_SPI_DELAY 125
#else
#define EXTRA_SPI_DELAY 0
#endif
#include "pins_arduino.h" / / definierar SS, MOSI, MISO, SCK
#define RESET SS
#define LED_ERR 7
#define LED_PMODE 8
#define LED_HB 6
#define PIEZO A3
#define HWVER 2
#define SWMAJ 1
#define SWMIN 18
STK definitioner
CONST byte STK_OK = 0x10;
CONST byte STK_FAILED = 0x11;
CONST byte STK_UNKNOWN = 0x12;
CONST byte STK_INSYNC = 0x14;
CONST byte STK_NOSYNC = 0x15;
CONST byte CRC_EOP = 0x20; OK är det ett utrymme...
CONST byte STK_GET_SYNC = 0x30;
CONST byte STK_GET_SIGNON = 0x31;
CONST byte STK_GET_PARM = 0x41;
CONST byte STK_SET_PARM = 0x42;
CONST byte STK_SET_PARM_EXT = 0x45;
CONST byte STK_PMODE_START = 0x50;
CONST byte STK_PMODE_END = 0x51;
CONST byte STK_SET_ADDR = 0x55;
CONST byte STK_UNIVERSAL = 0x56;
CONST byte STK_PROG_FLASH = 0x60;
CONST byte STK_PROG_DATA = 0x61;
CONST byte STK_PROG_PAGE = 0x64;
CONST byte STK_READ_PAGE = 0x74;
CONST byte STK_READ_SIGN = 0x75;
//// TONES ==========================================
Börja med att definiera förhållandet mellan
Obs, period, och frekvens.
#define c 3830 / / 261 Hz
#define d 3400 / / 294 Hz
#define e 3038 / / 329 Hz
#define f 2864 / / 349 Hz
#define g 2550 / / 392 Hz
#define a 2272 / / 440 Hz
#define b 2028 / / 493 Hz
#define C 1912 / / 523 Hz
void puls (int pin, int gånger);
int fel = 0;
int pmode = 0;
adress för läsning och skrivning, genom STK_SET_ADDR kommandot
int _addr;
byte _buffer [256]; seriell port buffert
int pBuffer = 0; buffert pekaren
int iBuffer = 0; buffert index
byte buff [256]; tillfällig buffert
booleska EOP_SEEN = false;
void setup() {
Serial.BEGIN(19200);
pinMode (PIEZO, OUTPUT);
beep(1700, 40);
EOP_SEEN = false;
iBuffer = pBuffer = 0;
pinMode (LED_PMODE, OUTPUT);
puls (LED_PMODE, 2);
pinMode (LED_ERR, OUTPUT);
puls (LED_ERR, 2);
pinMode (LED_HB, OUTPUT);
puls (LED_HB, 2);
pinMode (9, OUTPUT);
setup high freq PWM på stift 9 (timer 1)
50% intermittens -> 8 MHz
OCR1A = 0;
ICR1 = 1;
OC1A utgång, snabb PWM
TCCR1A = _BV(WGM11) | _BV(COM1A1);
TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); ingen klocka prescale
}
#define beget16(addr) (* addr * 256 + *(addr+1))
TypeDef struct param {
byte devicecode;
byte översyn;
byte progtype;
byte parmode;
byte polling;
byte selftimed;
byte lockbytes;
byte fusebytes;
int flashpoll;
int eeprompoll;
int pagesize;
int eepromsize;
int flashsize;
}
parametern;
parametern param;
Detta ger ett hjärtslag på stift 6, så du kan berätta programvaran körs.
byte hbval = 128;
int8_t hbdelta = 4;
void heartbeat() {
om (hbval > 192) hbdelta = - hbdelta;
om (hbval < 32) hbdelta = - hbdelta;
om (hbval > 250) hbdelta = - hbdelta;
om (hbval < 10) hbdelta = - hbdelta;
hbval += hbdelta;
analogWrite (LED_HB, hbval);
Delay(20);
}
void getEOP() {
int minL = 0;
byte avrch = 0;
byte bl = 0;
tag (!. EOP_SEEN) {
medan (Serial.available() > 0) {
byte ch = Serial.read();
_buffer [iBuffer] = ch;
iBuffer = (++ iBuffer) % 256; ökning och wrap
om (iBuffer == 1) avrch = ch; Spara-kommando
om ((avrch == STK_PROG_PAGE) & & (iBuffer == 3)) {
minL = 256 * _buffer [1] _buffer [2] + 4.
}
om ((iBuffer>minL) & & (ch == CRC_EOP)) {
EOP_SEEN = sant;
}
}
IF (!. EOP_SEEN) {
heartbeat(); ljus hjärtslagen LED
om (bl == 100) {
Pulse(LED_ERR,1,10); blinka den röda lysdioden
bl = 0;
// }
bl ++;
Delay(10);
}
}
}
serialEvent inte används så skiss skulle vara kompatibelt med äldre IDE-versioner
void serialEvent() {
int minL = 0;
byte avrch = 0;
medan (Serial.available() > 0)
// {
byte ch = Serial.read();
_buffer [iBuffer] = ch;
iBuffer = (++ iBuffer) % 256; ökning och wrap
om (iBuffer == 1) avrch = ch; Spara-kommando
om ((avrch == STK_PROG_PAGE) & & (iBuffer == 3)) {
minL = 256 * _buffer [1] _buffer [2] + 4.
// }
om ((iBuffer>minL) & & (ch == CRC_EOP)) {
EOP_SEEN = sant;
// }
// }
//}
void loop(void) {
är pmode aktiv?
om (pmode) digitalWrite (LED_PMODE, hög);
annat digitalWrite (LED_PMODE, låg);
digitalWrite (LED_PMODE, låg);
finns det ett fel?
om (fel) digitalWrite (LED_ERR, hög);
annat digitalWrite (LED_ERR, låg);
getEOP();
har vi fått en komplett begäran? (slutar med CRC_EOP)
om (EOP_SEEN) {
digitalWrite (LED_PMODE, hög);
EOP_SEEN = false;
avrisp();
iBuffer = pBuffer = 0; starta om buffert
}
}
byte getch() {
om (pBuffer == iBuffer) {/ / snurra tills data tillgängliga???
puls (LED_ERR, 1);
beep(1700, 20);
fel ++;
återvända -1;
}
byte ch = _buffer [pBuffer]; få nästa röding
pBuffer = (++ pBuffer) % 256; ökning och wrap
returnera ch;
}
void readbytes (int n) {
för (int x = 0; x < n; x ++) {
buff [x] = getch();
}
}
#define PTIME 20
void puls (int pin, int gånger, int ptime) {
göra {
digitalWrite (pin, hög);
Delay(ptime);
digitalWrite (pin, låg);
Delay(ptime);
gånger--;
}
medan (tider > 0);
}
{Ogiltig puls (int pin, int gånger)
puls (stift, tider, 50);
}
void spi_init() {
byte x;
SPCR = 0X53;
#ifdef LOW_SPEED
SPCR = SPCR| B00000011;
#endif
x = SPSR;
x = SPDR;
}
void spi_wait() {
göra {
}
medan (! () SPSR & (1 << SPIF)));
}
byte spi_send (byte b) {
byte svar;
#ifdef LOW_SPEED
CLI();
CLKPR = B10000000;
CLKPR = B00000011;
SEI();
#endif
SPDR = b;
spi_wait();
svar = SPDR;
#ifdef LOW_SPEED
CLI();
CLKPR = B10000000;
CLKPR = B00000000;
SEI();
#endif
returnera svar;
}
byte spi_transaction (byte a, byte b, byte c, byte d) {
byte n;
spi_send(a);
n=spi_send(b);
om (n! = en) fel = -1;
n=spi_send(c);
återvända spi_send(d);
}
void replyOK() {
om (EOP_SEEN == true) {
om (CRC_EOP == getch()) {/ / EOP bör nästa röding
Serial.write(STK_INSYNC);
Serial.write(STK_OK);
}
annat {
puls (LED_ERR, 2);
Serial.write(STK_NOSYNC);
fel ++;
}
}
void breply (byte b) {
om (CRC_EOP == getch()) {/ / EOP bör nästa röding
Serial.write(STK_INSYNC);
Serial.write(b);
Serial.write(STK_OK);
}
annat {
Serial.write(STK_NOSYNC);
fel ++;
}
}
void get_parameter (byte c) {
Switch(c) {
fall 0x80:
breply(HWVER);
bryta;
fall 0x81:
breply(SWMAJ);
bryta;
fall 0x82:
breply(SWMIN);
bryta;
fall 0x93:
breply('S'); seriell programmerare
bryta;
standard:
breply(0);
}
}
void set_parameters() {
kalla detta efter att ha läst parameter packet till buff]
param.devicecode = buff [0];
param.revision = buff [1].
param.progtype = buff [2].
param.parmode = buff [3].
param.polling = buff [4].
param.selftimed = buff [5].
param.lockbytes = buff [6].
param.fusebytes = buff [7].
param.flashpoll = buff [8].
Ignorera buff [9] (= buff[8])
getch(); ignorera andra värdet
Varning: inte säker på om byteordningen för följande
Följande är 16 bitar (big endian)
param.eeprompoll = beget16 (& buff[10]);
param.PageSize = beget16 (& buff[12]);
param.eepromsize = beget16 (& buff[14]);
32 bitar flashsize (big endian)
param.flashsize = buff [16] * 0x01000000
+ buff [17] * 0x00010000
+ buff [18] * 0x00000100
+ buff [19].
}
void start_pmode() {
spi_init();
efter förseningar kanske inte fungerar på alla mål...
pinMode (RESET, OUTPUT);
digitalWrite (RESET, hög);
pinMode (SCK, OUTPUT);
digitalWrite (SCK, låg);
Delay(50+EXTRA_SPI_DELAY);
digitalWrite (RESET, låg);
Delay(50+EXTRA_SPI_DELAY);
pinMode (MISO, indata);
pinMode (MOSI, OUTPUT);
spi_transaction (0xAC, 0x53, 0x00, 0x00);
pmode = 1;
}
void end_pmode() {
pinMode (MISO, indata);
pinMode (MOSI, indata);
pinMode (SCK, indata);
pinMode (RESET, indata);
pmode = 0;
}
void universal() {
int w;
byte ch;
för (w = 0; w < 4; w ++) {
buff [w] = getch();
// }
readbytes(4);
CH = spi_transaction (buff [0], buff [1], buff [2], buff[3]);
breply(CH);
}
{Ogiltig flash (byte hilo, int addr, byte data)
spi_transaction (0x40 + 8 * hilo, addr >> 8 & 0xFF, addr & 0xFF, data);
}
void commit (int addr) {
spi_transaction (0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0);
}
#define _current_page(x) (här & 0xFFFFE0)
int current_page (int addr) {
om (param.pagesize == 32) returnera addr & 0xFFFFFFF0;
om (param.pagesize == 64) returnera addr & 0xFFFFFFE0;
om (param.pagesize == 128) returnera addr & 0xFFFFFFC0;
om (param.pagesize == 256) returnera addr & 0xFFFFFF80;
returnera addr;
}
byte write_flash (int längd) {
om (param.pagesize < 1) {
återvända STK_FAILED;
}
om (param.pagesize! = 64) återvända STK_FAILED;
int sida = current_page(_addr);
int x = 0;
medan (x < längd) {
om (sida! = current_page(_addr)) {
Commit(Page);
sidan = current_page(_addr);
}
Flash (låg, _addr, buff[x++]);
Flash (HIGH, _addr, buff[x++]);
_addr ++;
}
Commit(Page);
återvända STK_OK;
}
byte write_eeprom (int längd) {
här är en word-adress, så vi använder här * 2
Detta skriver byte för byte,
sidan skriva kan vara snabbare (4 byte i taget)
för (int x = 0; x < längd; x ++) {
spi_transaction (0xC0, 0x00, _addr * 2 + x, buff[x]);
Delay(45);
}
återvända STK_OK;
}
void program_page() {
byte resultatet = STK_FAILED;
int längd = 256 * getch() + getch();
om (längd > 256) {
Serial.write(STK_FAILED);
fel ++;
hemkomst.
}
char memtype = (char)getch();
för (int x = 0; x < längd; x ++) {
buff [x] = getch();
// }
readbytes(length);
om (CRC_EOP == getch()) {
Serial.write(STK_INSYNC);
växel (memtype) {
fallet "E":
resultat = (byte)write_eeprom(length);
bryta;
fallet "F":
resultat = (byte)write_flash(length);
bryta;
}
Serial.write(Result);
om (resultatet! = STK_OK) {
fel ++;
}
}
annat {
Serial.write(STK_NOSYNC);
fel ++;
}
}
byte flash_read (byte hilo, int addr) {
återgå spi_transaction (0x20 + hilo * 8,
(addr >> 8) & 0xFF,
addr & 0xFF,
0);
}
char flash_read_page(int length) {
för (int x = 0; x < längd; x+= 2) {
byte låg = flash_read (låg, _addr);
Serial.write (låg);
byte hög = flash_read (hög, _addr);
Serial.write (hög);
_addr ++;
}
återvända STK_OK;
}
char eeprom_read_page(int length) {
Här har vi återigen en word adress
för (int x = 0; x < längd; x ++) {
byte ee = spi_transaction (0xA0, 0x00, _addr * 2 + x, 0xFF);
Serial.write (ee);
}
återvända STK_OK;
}
void read_page() {
byte resultatet = (byte) STK_FAILED;
int längd = 256 * getch() + getch();
char memtype = getch();
om (CRC_EOP! = getch()) {
Serial.write(STK_NOSYNC);
hemkomst.
}
Serial.write(STK_INSYNC);
om (memtype == "F") resultat = flash_read_page(length);
om (memtype == "E") resultat = eeprom_read_page(length);
Serial.write(Result);
hemkomst.
}
void read_signature() {
om (CRC_EOP! = getch()) {
Serial.write(STK_NOSYNC);
fel ++;
hemkomst.
}
Serial.write(STK_INSYNC);
byte hög = spi_transaction (0x30, 0x00, 0x00, 0x00);
Serial.write(High);
byte mitten = spi_transaction (0x30, 0x00, 0x01, 0x00);
Serial.write(Middle);
byte låg = spi_transaction (0x30, 0x00, 0x02, 0x00);
Serial.write(Low);
Serial.write(STK_OK);
}
//////////////////////////////////////////
//////////////////////////////////////////
////////////////////////////////////
////////////////////////////////////
int avrisp() {
byte data låg, hög;
byte avrch = getch();
växel (avrch) {
fall STK_GET_SYNC: / / få i synk
replyOK();
bryta;
fall STK_GET_SIGNON: / / få tecken
om (getch() == CRC_EOP) {
Serial.write(STK_INSYNC);
Serial.write ("AVR ISP");
Serial.write(STK_OK);
}
bryta;
fall STK_GET_PARM: / / 0x41
get_parameter(getch());
bryta;
fall STK_SET_PARM: / / 0x42
readbytes(20);
set_parameters();
replyOK();
bryta;
fall STK_SET_PARM_EXT: / / utökade parametrar - ignore för nu
readbytes(5);
replyOK();
bryta;
fall STK_PMODE_START: / / 0x50
beep(2272, 20);
start_pmode();
replyOK();
bryta;
fall STK_PMODE_END: //0x51
beep(1912, 50);
fel = 0;
end_pmode();
replyOK();
bryta;
fall STK_SET_ADDR: / / 0x55
_addr = getch() + 256 * getch();
replyOK();
bryta;
fall STK_UNIVERSAL: //UNIVERSAL 0x56
Universal();
bryta;
fall STK_PROG_FLASH: //STK_PROG_FLASH???
låg = getch();
hög = getch();
replyOK();
bryta;
fall STK_PROG_DATA: //STK_PROG_DATA???
data = getch();
replyOK();
bryta;
fall STK_PROG_PAGE: //STK_PROG_PAGE
beep(1912, 20);
program_page();
bryta;
fall STK_READ_PAGE: //STK_READ_PAGE
read_page();
bryta;
fall STK_READ_SIGN: //STK_READ_SIGN
read_signature();
bryta;
förväntar sig ett kommando, inte CRC_EOP
Detta är hur vi kan få tillbaka i synk
fall CRC_EOP:
Serial.write(STK_NOSYNC);
bryta;
något annat vi kommer tillbaka STK_UNKNOWN
standard:
om (CRC_EOP == getch())
Serial.write(STK_UNKNOWN);
annat
Serial.write(STK_NOSYNC);
}
}
ett pip utan att använda PWM
{Ogiltig beep (int tonen, lång varaktighet)
lång tid förflutit = 0;
medan (förflutit < (längd * 10000)) {
digitalWrite (PIEZO, hög);
delayMicroseconds(tone / 2);
digitalWrite (PIEZO, låg);
delayMicroseconds(tone / 2);
Hålla reda på hur länge vi pulsade
avverkade += tonar;
// }
//}