[Arduino] 利用Arduino Uno 燒錄 8051 程式

jesselin
9 min readSep 20, 2023

--

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當中

89S52Programmer.exe軟體下載

開啟燒 89s51/52 code的軟體。,並確認arduino已連接到電腦。 同樣可以透過 COM PORT 進行驗證

  1. 選擇正確com port,並按下connect
  2. 按下Identify 按鈕,如果有成功連接,視窗左下角會有 "AT89S51/52 Detected" 的提示
  3. 現在可以Open Hex 按鈕選擇要燒到89S51/52 的Hex檔案
  4. 最後點選Upload Hex 按鈕燒入,就等待燒錄完成!

參考資料

https://www.jcbrolabs.org/8051-arduino

https://www.instructables.com/ARDUINO-AS-A-8051-PROGRAMMER/

--

--

jesselin

紀錄自己看過的技術,並分享給大家,目前任職 firmware engineer