Linux环境下51单片机的烧写

最近将电脑装上了Win10+Ubuntu双系统,而且主力系统是Ubuntu,在想到51单片机调试时,突然想到是否能使用Ubuntu系统对其进行烧写。在网上查到确实有人也做过同样的事情,下面是我自己亲自实践遇到的问题以及解决方案。

本人系统环境:

                          ./+o+-       raoby@raoby-911
                  yyyyy- -yyyyyy+      OS: Ubuntu 20.04 focal
               ://+//////-yyyyyyo      Kernel: x86_64 Linux 5.4.0-40-generic
           .++ .:/++++++/-.+sss/`      Uptime: 4h 23m
         .:++o:  /++++++++/:--:/-      Packages: 2506
        o:+o+:++.`..```.-/oo+++++/     Shell: zsh 5.8
       .:+o:+o/.          `+sssoo+/    Resolution: 3840x1080
  .++/+:+oo+o:`             /sssooo.   DE: GNOME 3.36.2
 /+++//+:`oo+o               /::--:.   WM: Mutter
 \+/+o+++`o++o               ++////.   WM Theme: 
  .++.o+++oo+:`             /dddhhh.   GTK Theme: Yaru-light [GTK2/3]
       .+.o+oo:.          `oddhhhh+    Icon Theme: Yaru
        \+.++o+o``-````.:ohdhhhhh+     Font: Ubuntu 11
         `:o+++ `ohhhhhhhhyo++os:      Disk: 221G / 371G (63%)
           .o:`.syhhhhhhh/.oo++o`      CPU: Intel Core i7-8750H @ 12x 4.1GHz [66.0°C]
               /osyyyyyyo++ooo+++/     GPU: GeForce GTX 1050 Ti
                   ````` +oo+++o\:     RAM: 3626MiB / 15858MiB
                          `oo++.      

建立编译与烧录环境

编译器

Linux下确实有原生的嵌入式设备编译器——SDCC,安装也是十分的简单:

sudo apt install sdcc

SDCC编译出的文件很多,其中.ihx文件即为我最终需要的二进制文件。网上许多教程推荐使用其他工具将其转换为.hex文件后再转换为.bin文件,然而我使用烧写工具实测结果是这三种类型文件都可以进行烧写。

烧录器

STC官方给的烧录器只有Windows版,好在网上有人开发出了通用的python cli版本烧写程序stcflash。

stcflash

A command line programmer for STC 8051 microcontroller.

The programmer software provided by STC for their 8051-compatible microcontrollers (MCUs) only runs on Microsoft Windows. For developers who are more used to other operating systems, this project, named stcflash, provides a more convenient way to download program to STC 8051 microcontroller across different platforms. Other than its portability, stcflash also has the advantage of employing a simple command line interface, so integrating it in a development toolchain is fairly easy.

链接:https://github.com/laborer/stcflash

下载后将其中的stcflash.py文件放至待烧录文件的目录下。
该工具同时需求pySerial模块,在Ubuntu环境下可以使用命令

sudo apt install python3-serial

安装完成之后就可以使用烧录工具stcflash了。
方法:

sudo pyhton3 stcflash.py main.hex
# main.hex即为待烧写的文件

正常编译及烧录

源代码

简单做一个流水灯测试

/* **FILENAME:51.c */
#include "8051.h"
#define uint unsigned int
#define uchar unsigned char

uchar tab[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

void Delay(uint xms)
{
    uint i,j;
    for(i=xms;i>0;i--)
        for(j=110;j>0;j--);
}

void main()
{
    uchar i;
    while(1)
    {
        for(i=0;i<8;i++)
        {
            P1 = tab[i];
            Delay(100);
        }
    }
}

编译并烧录

$ sdcc 51.c
$ sudo python3 stcflash.py 51.ihx
[sudo] raoby 的密码: 
Connect to /dev/ttyUSB0 at baudrate 2400
Detecting target... done
 FOSC: 12.058MHz
 Model: STC89C52RC (ver6.6C) 
 ROM: 8KB
 [X] Reset stops watchdog
 [X] Internal XRAM
 [X] Normal ALE pin
 [X] Full gain oscillator
 [X] Not erase data EEPROM
 [X] Download regardless of P1
 [X] 12T mode
Baudrate: 38400
Erasing target... done
Size of the binary: 188
Programming: #################### done
Setting options... done

成功烧录~

遇到的问题

软件一直处在 'Detecting target...'状态,最后报错

TIM截图20200709120310.png
如网上许多教程以及Github上stcflash的使用说明一样,我在运行了烧写命令后不断开USB连接线,仅关闭单片机电源并重新打开,但是并没有任何效果。
开始时我以为是USB转串口的CH340驱动有问题,遂去寻找了CH340芯片驱动编译安装(期间也遇到了问题,详见 编译CH340驱动时遇到的问题 )。但最后发现并不是驱动问题,我使用的这个Ubuntu版本自带了USB转串口驱动。
在GitHub此项目的issue中也看到有人有类似的问题,有人说是芯片不支持。
我此时使用的是STC89C516RD+芯片,最终决定换成STC89C52RC芯片,结果换上后立即成功烧写……
所以说,最终还是芯片的问题,之前在Windows环境下这两种单片机的烧写模式也不相同。还是老老实实选用STC89C52RC吧……如果实在有STC89C516RD+芯片的使用需求还是要去Windows下使用官方工具进行烧写。
(不过有空的话我想试试看能否使用wine运行官方Windows工具并成功烧写)

编译CH340驱动时遇到的问题

下载CH340源码包并解压后,得到这么一个目录

CH341SER_LINUX
├── ch34x.c
├── ch34x.mod
├── Makefile
└── readme.txt

直接make,结果报错如下

$ make
make -C /lib/modules/5.4.0-40-generic/build  M=/home/raoby/CH341SER_LINUX  
make[1]: 进入目录“/usr/src/linux-headers-5.4.0-40-generic”
  AR      /home/raoby/CH341SER_LINUX/built-in.a
  CC [M]  /home/raoby/CH341SER_LINUX/ch34x.o
/home/raoby/CH341SER_LINUX/ch34x.c: In function ‘ch34x_close’:
/home/raoby/CH341SER_LINUX/ch34x.c:591:2: error: unknown type name ‘wait_queue_t’; did you mean ‘wait_event’?
  591 |  wait_queue_t wait;
      |  ^~~~~~~~~~~~
      |  wait_event
/home/raoby/CH341SER_LINUX/ch34x.c:591:15: warning: unused variable ‘wait’ [-Wunused-variable]
  591 |  wait_queue_t wait;
      |               ^~~~
/home/raoby/CH341SER_LINUX/ch34x.c:590:7: warning: unused variable ‘timeout’ [-Wunused-variable]
  590 |  long timeout;
      |       ^~~~~~~
/home/raoby/CH341SER_LINUX/ch34x.c:589:6: warning: unused variable ‘bps’ [-Wunused-variable]
  589 |  int bps;
      |      ^~~
/home/raoby/CH341SER_LINUX/ch34x.c: In function ‘wait_modem_info’:
/home/raoby/CH341SER_LINUX/ch34x.c:797:7: error: implicit declaration of function ‘signal_pending’ [-Werror=implicit-function-declaration]
  797 |   if( signal_pending(current) )
      |       ^~~~~~~~~~~~~~
cc1: some warnings being treated as errors
make[2]: *** [scripts/Makefile.build:275:/home/raoby/CH341SER_LINUX/ch34x.o] 错误 1
make[1]: *** [Makefile:1731:/home/raoby/CH341SER_LINUX] 错误 2
make[1]: 离开目录“/usr/src/linux-headers-5.4.0-40-generic”
make: *** [Makefile:5:default] 错误 2

ARM-Linux错误及问题总结 https://blog.csdn.net/qq_33194301/article/details/104510078#UbuntuCH340_228 这篇文章中作者给出的方法即为解决方案:

只需要添加头文件 #include <linux/sched/signal.h> 以及将592行附近的wait_queue_t wait语句屏蔽,然后重新编译即可。

最后修改:2020 年 08 月 05 日 10 : 24 PM
觉得有帮助的话,打赏一个呗~