8051 算是一個比較簡單的 microcontroller ,但基本該有的處理能力都還是有的,它是屬於8位元處理器架構,成本極低,很好取得,在露天或淘寶購物網站就可以輕鬆取得 (都比一杯手搖杯便宜XD)。
但最大需要克服的問題是要如何把我們寫好的 8051 code 燒錄到MCU 當中?
很棒的是這邊Atmel 89SXX 系列 (AT89S51 / AT89S52)MCU 已經有內建 ISP(In System Program) 可線上燒錄的功能。 (注意AT89C51/AT89C51 沒有預先提供ISP功能)。
89SXX 提供一個 SPI interface (Serial Peripheral Interface Bus) 可以將你寫的程式碼燒到MCU 當中。
什麼是ISP(In System Program)?? (待補連結)
Step 1: 將arduino UNO 作為ISP燒錄器
將以下Firmware燒錄至Arduino UNO 當中
/**
PROGRAMMING AN ATMEL AT89S51/52 USING ARDUINO
RELEASED AS IS WITHOUT WARRANTY
I AM NOT LIABLE FOR ANY DAMAGE DONE TO YOUR HARDWARE
THIS PROJECT IS FOR EDUCATIONAL PURPOSES ONLY
Credits to NICK PABLO for the Arduino Sketch
TIKTAK (C) 2014
**/
#define dummyData 0xAA
#define RDY 75
#define NRDY 76
const int _MISO = 4;
const int _MOSI = 5;
const int _CLK = 3;
const int RST = 2;
/* Variable definition block */
byte data;
byte AL,AH; // 16-bit address
byte lockByte; // embed lock bits here
byte SigH,SigL; // Signature Bytes
void setup()
{
pinMode(_MISO, INPUT);
pinMode(_MOSI, OUTPUT);
pinMode(_CLK, OUTPUT);
pinMode(RST, OUTPUT);
Serial.begin(115200); // depends on the setting of the host PC
}
void loop()
{
while (!Serial.available()); // wait for character
if (Serial.available() > 0)
switch (Serial.read())
{
case 'p': Serial.write(progEnable());
break;
case 'r': readProgmem();
Serial.write(data);
break;
case 'a': while(!Serial.available());
AL = Serial.read();
break;
case 'A': while(!Serial.available());
AH = Serial.read();
break;
case 'd': while(!Serial.available());
data = Serial.read();
break;
case 'S': AH = 0;
AL = 0;
SigH = readSign();
Serial.write(SigH);
break;
case 's': AH = 2;
AL = 0;
SigL = readSign();
Serial.write(SigL);
AH = 1;
AL = 0;
SigL = readSign();
Serial.write(SigL);
break; // read SigL
case 'o': digitalWrite(RST,1);break;
case 'c': digitalWrite(RST,0);break;
case 'e': eraseChip();
Serial.write(RDY);
break;
case 'j': break;
case 'w': writeProgmem();
break;
}
}
unsigned char SendSPI(unsigned char data)
{
uint8_t retval = 0;
uint8_t intData = data;
int t;
for (int ctr = 0; ctr < 7; ctr++)
{
if (intData & 0x80) digitalWrite(_MOSI,1);
else digitalWrite(_MOSI,0);
digitalWrite(_CLK,1);
delayMicroseconds(1);
t = digitalRead(_MISO);
digitalWrite(_CLK,0);
if (t) retval |= 1; else retval &= 0xFE;
retval<<=1;
intData<<= 1;
delayMicroseconds(1);
}
if (intData & 0x80) digitalWrite(_MOSI,1);
else digitalWrite(_MOSI,0);
digitalWrite(_CLK,1);
delayMicroseconds(1);
t = digitalRead(_MISO);
digitalWrite(_CLK,0);
if (t) retval |= 1;
else retval &= 0xFE;
return retval;
}
byte progEnable()
{
SendSPI(0xAC);
SendSPI(0x53);
SendSPI(dummyData);
return SendSPI(dummyData);
}
void eraseChip()
{
SendSPI(0xAC);
SendSPI(0x9F);
SendSPI(dummyData);
SendSPI(dummyData);
delay(520);
}
void readProgmem()
{
SendSPI(0x20);
SendSPI(AH);
SendSPI(AL);
data = SendSPI(dummyData);
}
void writeProgmem()
{
SendSPI(0x40);
SendSPI(AH);
SendSPI(AL);
SendSPI(data);
}
void writeLockBits()
{
SendSPI(0xAC);
SendSPI(lockByte);
SendSPI(dummyData);
SendSPI(dummyData);
}
void readLockBits()
{
SendSPI(0x24);
SendSPI(dummyData);
SendSPI(dummyData);
lockByte = SendSPI(dummyData);
}
byte readSign()
{
SendSPI(0x28);
SendSPI(AH);
SendSPI(AL);
return SendSPI(dummyData);
}
Step 2: AT89S51/AT89S52的周邊硬體
以下是基本的MCU 基本周邊電路,另外也可以在任何port接上LED做為測試用。
Step 3: 把Arduino 和 AT89S51/AT89S52 接在一起
Arduino Pin2 接到 89S52 的 Reset pin9
Arduino Pin3 接到 89S52 的 pin8
Arduino Pin4 接到 89S52 的 pin7
Arduino Pin5 接到 89S52 的 pin6
Step 4: 利用programming 軟體把資料灌到arduino 再燒到89S51當中
開啟燒 89s51/52 code的軟體。,並確認arduino已連接到電腦。 同樣可以透過 COM PORT 進行驗證
- 選擇正確com port,並按下connect
- 按下Identify 按鈕,如果有成功連接,視窗左下角會有 "AT89S51/52 Detected" 的提示
- 現在可以Open Hex 按鈕選擇要燒到89S51/52 的Hex檔案
- 最後點選Upload Hex 按鈕燒入,就等待燒錄完成!
參考資料