这是一篇 2017–2018 年的嵌入式学习笔记,保留当时的工具、代码和实验过程。 查看系列目录

windows下用来开发51单片机的软件基本上被keil垄断了,如果你想抛弃微软,那么这篇文章就是为你准备的,我的开发环境是Ubuntu16.04,下面来介绍一下Linux开发51单片机的环境搭建.

首先我们要准备的:

1
2
3
编译器:         sdcc
文本编辑器: sublime (非必须,vim,gedit都可)
烧录软件: stcflash.py (外国友人写的一个脚本)

当然sdcc是跨平台的编译器,如果仅仅是想要熟悉一下sdcc的话,也可以在Windows下安装,然后使用stc进行编译.当然如果是Linux的,一切都是命令行的天下.如果想尝试图形的话,也可以尝试mcu8051,支持汇编和c的编程.

软件安装:

sublime:

百度sublime官网,然后下载,最新版本是sublime3,软件是付费的,但是可以无限试用

sdcc

安装代码如下:

1
sudo apt-get install sdcc

stcflash.py

这个是外国友人写的一个烧录脚本,在github上都可以下载到,把下面这段代码存为本地文件stcflash.py就可以了.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
#!/usr/bin/env python

# stcflash Copyright (C) 2013 laborer ([email protected])

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.


import time
import logging
import sys
import serial
import os.path
import binascii
import struct
import argparse


PROTOCOL_89 = "89"
PROTOCOL_12C5A = "12c5a"
PROTOCOL_12C52 = "12c52"
PROTOCOL_12Cx052 = "12cx052"

PROTOSET_89 = [PROTOCOL_89]
PROTOSET_12 = [PROTOCOL_12C5A, PROTOCOL_12C52, PROTOCOL_12Cx052]
PROTOSET_12B = [PROTOCOL_12C52, PROTOCOL_12Cx052]
PROTOSET_PARITY = [PROTOCOL_12C5A, PROTOCOL_12C52]


class Programmer:
def __init__(self, conn, protocol=None):
self.conn = conn
self.protocol = protocol

self.conn.timeout = 0.05
if self.protocol in PROTOSET_PARITY:
self.conn.parity = serial.PARITY_EVEN
else:
self.conn.parity = serial.PARITY_NONE

self.chkmode = 0

def __conn_read(self, size):
buf = bytearray()
while len(buf) < size:
s = bytearray(self.conn.read(size - len(buf)))
buf += s

logging.debug("recv: " + " ".join(["%02X" % i for i in s]))

if len(s) == 0:
raise IOError()

return list(buf)

def __conn_write(self, s):
logging.debug("send: " + " ".join(["%02X" % i for i in s]))

self.conn.write(bytearray(s))

def __conn_baudrate(self, baud, flush=True):
logging.debug("baud: %d" % baud)

if flush:
self.conn.flush()
time.sleep(0.2)

self.conn.baudrate = baud

def __model_database(self, model):
modelmap = {0xE0: ("12", 1, {(0x00, 0x1F): ("C54", ""),
(0x60, 0x7F): ("C54", "AD"),
(0x80, 0x9F): ("LE54", ""),
(0xE0, 0xFF): ("LE54", "AD"),
}),
0xE1: ("12", 1, {(0x00, 0x1F): ("C52", ""),
(0x20, 0x3F): ("C52", "PWM"),
(0x60, 0x7F): ("C52", "AD"),
(0x80, 0x9F): ("LE52", ""),
(0xA0, 0xBF): ("LE52", "PWM"),
(0xE0, 0xFF): ("LE52", "AD"),
}),
0xE2: ("11", 1, {(0x00, 0x1F): ("F", ""),
(0x20, 0x3F): ("F", "E"),
(0x70, 0x7F): ("F", ""),
(0x80, 0x9F): ("L", ""),
(0xA0, 0xBF): ("L", "E"),
(0xF0, 0xFF): ("L", ""),
}),
0xE6: ("12", 1, {(0x00, 0x1F): ("C56", ""),
(0x60, 0x7F): ("C56", "AD"),
(0x80, 0x9F): ("LE56", ""),
(0xE0, 0xFF): ("LE56", "AD"),
}),
0xD1: ("12", 2, {(0x20, 0x3F): ("C5A", "CCP"),
(0x40, 0x5F): ("C5A", "AD"),
(0x60, 0x7F): ("C5A", "S2"),
(0xA0, 0xBF): ("LE5A", "CCP"),
(0xC0, 0xDF): ("LE5A", "AD"),
(0xE0, 0xFF): ("LE5A", "S2"),
}),
0xD2: ("10", 1, {(0x00, 0x0F): ("F", ""),
(0x60, 0x6F): ("F", "XE"),
(0x70, 0x7F): ("F", "X"),
(0xA0, 0xAF): ("L", ""),
(0xE0, 0xEF): ("L", "XE"),
(0xF0, 0xFF): ("L", "X"),
}),
0xD3: ("11", 2, {(0x00, 0x1F): ("F", ""),
(0x40, 0x5F): ("F", "X"),
(0x60, 0x7F): ("F", "XE"),
(0xA0, 0xBF): ("L", ""),
(0xC0, 0xDF): ("L", "X"),
(0xE0, 0xFF): ("L", "XE"),
}),
0xF0: ("89", 4, {(0x00, 0x10): ("C5", "RC"),
(0x20, 0x30): ("C5", "RC"), #STC90C5xRC
}),
0xF1: ("89", 4, {(0x00, 0x10): ("C5", "RD+"),
(0x20, 0x30): ("C5", "RD+"), #STC90C5xRD+
}),
0xF2: ("12", 1, {(0x00, 0x0F): ("C", "052"),
(0x10, 0x1F): ("C", "052AD"),
(0x20, 0x2F): ("LE", "052"),
(0x30, 0x3F): ("LE", "052AD"),
}),
}

iapmcu = ((0xD1, 0x3F), (0xD1, 0x5F), (0xD1, 0x7F),
(0xD2, 0x7E), (0xD2, 0xFE),
(0xD3, 0x5F), (0xD3, 0xDF),
(0xE2, 0x76), (0xE2, 0xF6),
)

try:
model = tuple(model)

prefix, romratio, fixmap = modelmap[model[0]]

if model[0] in (0xF0, 0xF1) and 0x20 <= model[1] <= 0x30:
prefix = "90"

for key, value in fixmap.items():
if key[0] <= model[1] <= key[1]:
break
else:
raise KeyError()

infix, postfix = value

romsize = romratio * (model[1] - key[0])

try:
romsize = {(0xF0, 0x03): 13}[model]
except KeyError:
pass

if model[0] in (0xF0, 0xF1):
romfix = str(model[1] - key[0])
elif model[0] in (0xF2,):
romfix = str(romsize)
else:
romfix = "%02d" % romsize

name = "IAP" if model in iapmcu else "STC"
name += prefix + infix + romfix + postfix
return (name, romsize)

except KeyError:
return ("Unknown %02X %02X" % model, None)

def recv(self, timeout = 1, start = [0x46, 0xB9, 0x68]):
timeout += time.time()

while time.time() < timeout:
try:
if self.__conn_read(len(start)) == start:
break
except IOError:
continue
else:
logging.debug("recv(..): Timeout")
raise IOError()

chksum = start[-1]

s = self.__conn_read(2)
n = s[0] * 256 + s[1]
if n > 64:
logging.debug("recv(..): Incorrect packet size")
raise IOError()
chksum += sum(s)

s = self.__conn_read(n - 3)
if s[n - 4] != 0x16:
logging.debug("recv(..): Missing terminal symbol")
raise IOError()

chksum += sum(s[:-(1+self.chkmode)])
if self.chkmode > 0 and chksum & 0xFF != s[-2]:
logging.debug("recv(..): Incorrect checksum[0]")
raise IOError()
elif self.chkmode > 1 and (chksum >> 8) & 0xFF != s[-3]:
logging.debug("recv(..): Incorrect checksum[1]")
raise IOError()

return (s[0], s[1:-(1+self.chkmode)])

def send(self, cmd, dat):
buf = [0x46, 0xB9, 0x6A]

n = 1 + 2 + 1 + len(dat) + self.chkmode + 1
buf += [n >> 8, n & 0xFF, cmd]

buf += dat

chksum = sum(buf[2:])
if self.chkmode > 1:
buf += [(chksum >> 8) & 0xFF]
buf += [chksum & 0xFF, 0x16]

self.__conn_write(buf)

def detect(self):
for i in range(1000):
try:
self.__conn_write([0x7F, 0x7F])
cmd, dat = self.recv(0.015, [0x68])
break
except IOError:
pass
else:
raise IOError()

self.fosc = (float(sum(dat[0:16:2]) * 256 + sum(dat[1:16:2])) / 8
* self.conn.baudrate / 580974)
self.info = dat[16:]
self.version = "%d.%d%c" % (self.info[0] >> 4,
self.info[0] & 0x0F,
self.info[1])
self.model = self.info[3:5]

self.name, self.romsize = self.__model_database(self.model)

logging.info("Model ID: %02X %02X" % tuple(self.model))
logging.info("Model name: %s" % self.name)
logging.info("ROM size: %s" % self.romsize)

if self.protocol is None:
try:
self.protocol = {0xF0: PROTOCOL_89, #STC89/90C5xRC
0xF1: PROTOCOL_89, #STC89/90C5xRD+
0xF2: PROTOCOL_12Cx052, #STC12Cx052
0xD1: PROTOCOL_12C5A, #STC12C5Ax
0xD2: PROTOCOL_12C5A, #STC10Fx
0xE1: PROTOCOL_12C52, #STC12C52x
0xE2: PROTOCOL_12C5A, #STC11Fx
0xE6: PROTOCOL_12C52, #STC12C56x
}[self.model[0]]
except KeyError:
pass

if self.protocol in PROTOSET_PARITY:
self.chkmode = 2
self.conn.parity = serial.PARITY_EVEN
else:
self.chkmode = 1
self.conn.parity = serial.PARITY_NONE

if self.protocol is not None:
del self.info[-self.chkmode:]

logging.info("Protocol ID: %s" % self.protocol)
logging.info("Checksum mode: %d" % self.chkmode)
logging.info("UART Parity: %s"
% {serial.PARITY_NONE: "NONE",
serial.PARITY_EVEN: "EVEN",
}[self.conn.parity])

for i in range(0, len(self.info), 16):
logging.info("Info string [%d]: %s"
% (i // 16,
" ".join(["%02X" % j for j in self.info[i:i+16]])))

def print_info(self):
print(" FOSC: %.3fMHz" % self.fosc)
print(" Model: %s (ver%s) " % (self.name, self.version))
if self.romsize is not None:
print(" ROM: %dKB" % self.romsize)

if self.protocol == PROTOCOL_89:
switches = [( 2, 0x80, "Reset stops watchdog"),
( 2, 0x40, "Internal XRAM"),
( 2, 0x20, "Normal ALE pin"),
( 2, 0x10, "Full gain oscillator"),
( 2, 0x08, "Not erase data EEPROM"),
( 2, 0x04, "Download regardless of P1"),
( 2, 0x01, "12T mode")]

elif self.protocol == PROTOCOL_12C5A:
switches = [( 6, 0x40, "Disable reset2 low level detect"),
( 6, 0x01, "Reset pin not use as I/O port"),
( 7, 0x80, "Disable long power-on-reset latency"),
( 7, 0x40, "Oscillator high gain"),
( 7, 0x02, "External system clock source"),
( 8, 0x20, "WDT disable after power-on-reset"),
( 8, 0x04, "WDT count in idle mode"),
(10, 0x02, "Not erase data EEPROM"),
(10, 0x01, "Download regardless of P1")]
print(" WDT prescal: %d" % 2**((self.info[8] & 0x07) + 1))

elif self.protocol in PROTOSET_12B:
switches = [(8, 0x02, "Not erase data EEPROM")]

else:
switches = []

for pos, bit, desc in switches:
print(" [%c] %s" % ("X" if self.info[pos] & bit else " ", desc))

def handshake(self):
baud0 = self.conn.baudrate

for baud in [115200, 57600, 38400, 28800, 19200,
14400, 9600, 4800, 2400, 1200]:

t = self.fosc * 1000000 / baud / 32
if self.protocol not in PROTOSET_89:
t *= 2

if abs(round(t) - t) / t > 0.03:
continue

if self.protocol in PROTOSET_89:
tcfg = 0x10000 - int(t + 0.5)
else:
if t > 0xFF:
continue
tcfg = 0xC000 + 0x100 - int(t + 0.5)

baudstr = [tcfg >> 8,
tcfg & 0xFF,
0xFF - (tcfg >> 8),
min((256 - (tcfg & 0xFF)) * 2, 0xFE),
int(baud0 / 60)]

logging.info("Test baudrate %d (accuracy %0.4f) using config %s"
% (baud,
abs(round(t) - t) / t,
" ".join(["%02X" % i for i in baudstr])))

if self.protocol in PROTOSET_89:
freqlist = (40, 20, 10, 5)
else:
freqlist = (30, 24, 20, 12, 6, 3, 2, 1)

for twait in range(0, len(freqlist)):
if self.fosc > freqlist[twait]:
break

logging.info("Waiting time config %02X" % (0x80 + twait))

self.send(0x8F, baudstr + [0x80 + twait])

try:
self.__conn_baudrate(baud)
cmd, dat = self.recv()
break
except Exception:
logging.info("Cannot use baudrate %d" % baud)

time.sleep(0.2)
self.conn.flushInput()
finally:
self.__conn_baudrate(baud0, False)

else:
raise IOError()

logging.info("Change baudrate to %d" % baud)

self.send(0x8E, baudstr)
self.__conn_baudrate(baud)
self.baudrate = baud

cmd, dat = self.recv()

def erase(self):
if self.protocol in PROTOSET_89:
self.send(0x84, [0x01, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33])
cmd, dat = self.recv(10)
assert cmd == 0x80

else:
self.send(0x84, ([0x00, 0x00, self.romsize * 4,
0x00, 0x00, self.romsize * 4]
+ [0x00] * 12
+ [i for i in range(0x80, 0x0D, -1)]))
cmd, dat = self.recv(10)
if dat:
logging.info("Serial number: "
+ " ".join(["%02X" % j for j in dat]))

def flash(self, code):
code = list(code) + [0x00] * (511 - (len(code) - 1) % 512)

for i in range(0, len(code), 128):
logging.info("Flash code region (%04X, %04X)" % (i, i + 127))

addr = [0, 0, i >> 8, i & 0xFF, 0, 128]
self.send(0x00, addr + code[i:i+128])
cmd, dat = self.recv()
assert dat[0] == sum(code[i:i+128]) % 256

yield (i + 128.0) / len(code)

def options(self, **kwargs):
erase_eeprom = kwargs.get("erase_eeprom", None)

dat = []
fosc = list(bytearray(struct.pack(">I", int(self.fosc * 1000000))))

if self.protocol == PROTOCOL_89:
if erase_eeprom is not None:
self.info[2] &= 0xF7
self.info[2] |= 0x00 if erase_eeprom else 0x08
dat = self.info[2:3] + [0xFF]*3

elif self.protocol == PROTOCOL_12C5A:
if erase_eeprom is not None:
self.info[10] &= 0xFD
self.info[10] |= 0x00 if erase_eeprom else 0x02
dat = (self.info[6:9] + [0xFF]*5 + self.info[10:11]
+ [0xFF]*6 + fosc)

elif self.protocol in PROTOSET_12B:
if erase_eeprom is not None:
self.info[8] &= 0xFD
self.info[8] |= 0x00 if erase_eeprom else 0x02
dat = (self.info[6:11] + fosc + self.info[12:16] + [0xFF]*4
+ self.info[8:9] + [0xFF]*7 + fosc + [0xFF]*3)

elif erase_eeprom is not None:
logging.info("Modifying options is not supported for this target")
return False

if dat:
self.send(0x8D, dat)
cmd, dat = self.recv()

return True

def terminate(self):
logging.info("Send termination command")

self.send(0x82, [])
self.conn.flush()
time.sleep(0.2)

def unknown_packet_1(self):
if self.protocol in PROTOSET_PARITY:
logging.info("Send unknown packet (50 00 00 36 01 ...)")
self.send(0x50, [0x00, 0x00, 0x36, 0x01] + self.model)
cmd, dat = self.recv()
assert cmd == 0x8F and not dat

def unknown_packet_2(self):
if self.protocol not in PROTOSET_PARITY:
for i in range(5):
logging.info("Send unknown packet (80 00 00 36 01 ...)")
self.send(0x80, [0x00, 0x00, 0x36, 0x01] + self.model)
cmd, dat = self.recv()
assert cmd == 0x80 and not dat

def unknown_packet_3(self):
if self.protocol in PROTOSET_PARITY:
logging.info("Send unknown packet (69 00 00 36 01 ...)")
self.send(0x69, [0x00, 0x00, 0x36, 0x01] + self.model)
cmd, dat = self.recv()
assert cmd == 0x8D and not dat


def autoisp(conn, baud, magic):
if not magic:
return

bak = conn.baudrate
conn.baudrate = baud
conn.write(bytearray(ord(i) for i in magic))
conn.flush()
time.sleep(0.5)
conn.baudrate = bak


def program(prog, code, erase_eeprom=None):
sys.stdout.write("Detecting target...")
sys.stdout.flush()

prog.detect()

print(" done")

prog.print_info()

if prog.protocol is None:
raise IOError("Unsupported target")

if code is None:
return

prog.unknown_packet_1()

sys.stdout.write("Baudrate: ")
sys.stdout.flush()

prog.handshake()

print(prog.baudrate)

prog.unknown_packet_2()

sys.stdout.write("Erasing target...")
sys.stdout.flush()

prog.erase()

print(" done")

print("Size of the binary: %d" % len(code))

# print("Programming: ", end="", flush=True)
sys.stdout.write("Programming: ")
sys.stdout.flush()

oldbar = 0
for progress in prog.flash(code):
bar = int(progress * 20)
sys.stdout.write("#" * (bar - oldbar))
sys.stdout.flush()
oldbar = bar

print(" done")

prog.unknown_packet_3()

sys.stdout.write("Setting options...")
sys.stdout.flush()

if prog.options(erase_eeprom=erase_eeprom):
print(" done")
else:
print(" failed")

prog.terminate()


# Convert Intel HEX code to binary format
def hex2bin(code):
buf = bytearray()
base = 0
line = 0

for rec in code.splitlines():
# Calculate the line number of the current record
line += 1

try:
# bytes(...) is to support python<=2.6
# bytearray(...) is to support python<=2.7
n = bytearray(binascii.a2b_hex(bytes(rec[1:3])))[0]
dat = bytearray(binascii.a2b_hex(bytes(rec[1:n*2+11])))
except:
raise Exception("Line %d: Invalid format" % line)

if rec[0] != ord(":"):
raise Exception("Line %d: Missing start code \":\"" % line)
if sum(dat) & 0xFF != 0:
raise Exception("Line %d: Incorrect checksum" % line)

if dat[3] == 0: # Data record
addr = base + (dat[1] << 8) + dat[2]
# Allocate memory space and fill it with 0xFF
buf[len(buf):] = [0xFF] * (addr + n - len(buf))
# Copy data to the buffer
buf[addr:addr+n] = dat[4:-1]

elif dat[3] == 1: # EOF record
if n != 0:
raise Exception("Line %d: Incorrect data length" % line)

elif dat[3] == 2: # Extended segment address record
if n != 2:
raise Exception("Line %d: Incorrect data length" % line)
base = ((dat[4] << 8) + dat[5]) << 4

elif dat[3] == 4: # Extended linear address record
if n != 2:
raise Exception("Line %d: Incorrect data length" % line)
base = ((dat[4] << 8) + dat[5]) << 16

else:
raise Exception("Line %d: Unsupported record type" % line)

return buf


def main():
if sys.platform == "win32":
port = "COM3"
elif sys.platform == "darwin":
port = "/dev/tty.usbserial"
else:
port = "/dev/ttyUSB0"

parser = argparse.ArgumentParser(
description=("Stcflash, a command line programmer for "
+ "STC 8051 microcontroller.\n"
+ "https://github.com/laborer/stcflash"))
parser.add_argument("image",
help="code image (bin/hex)",
type=argparse.FileType("rb"), nargs='?')
parser.add_argument("-p", "--port",
help="serial port device (default: %s)" % port,
default=port)
parser.add_argument("-l", "--lowbaud",
help="initial baud rate (default: 2400)",
type=int,
default=2400)
parser.add_argument("-r", "--protocol",
help="protocol to use for programming",
choices=["89", "12c5a", "12c52", "12cx052", "auto"],
default="auto")
parser.add_argument("-a", "--aispbaud",
help="baud rate for AutoISP (default: 4800)",
type=int,
default=4800)
parser.add_argument("-m", "--aispmagic",
help="magic word for AutoISP")
parser.add_argument("-v", "--verbose",
help="be verbose",
default=0,
action="count")
parser.add_argument("-e", "--erase_eeprom",
help=("erase data eeprom during next download"
+"(experimental)"),
action="store_true")
parser.add_argument("-ne", "--not_erase_eeprom",
help=("do not erase data eeprom next download"
+"(experimental)"),
action="store_true")

opts = parser.parse_args()

opts.loglevel = (logging.CRITICAL,
logging.INFO,
logging.DEBUG)[min(2, opts.verbose)]

opts.protocol = {'89': PROTOCOL_89,
'12c5a': PROTOCOL_12C5A,
'12c52': PROTOCOL_12C52,
'12cx052': PROTOCOL_12Cx052,
'auto': None}[opts.protocol]

if not opts.erase_eeprom and not opts.not_erase_eeprom:
opts.erase_eeprom = None

logging.basicConfig(format=("%(levelname)s: "
+ "[%(relativeCreated)d] "
+ "%(message)s"),
level=opts.loglevel)

if opts.image:
code = bytearray(opts.image.read())
opts.image.close()
if os.path.splitext(opts.image.name)[1] in (".hex", ".ihx"):
code = hex2bin(code)
else:
code = None

print("Connect to %s at baudrate %d" % (opts.port, opts.lowbaud))

with serial.Serial(port=opts.port,
baudrate=opts.lowbaud,
parity=serial.PARITY_NONE) as conn:
if opts.aispmagic:
autoisp(conn, opts.aispbaud, opts.aispmagic)
program(Programmer(conn, opts.protocol), code, opts.erase_eeprom)


if __name__ == "__main__":
main()

最后别忘记把stcflash.py添加到环境变量里面,这样每次烧录就不用复制文件了.

编译

对于编译也很简单

1
sdcc XX.c

编译会生成很多文件,我们要用的就是ihx后缀的文件

烧录

python stcflash.py XX.ihx

接着单片机重新上电就好了。