这学期有51单片机课程,平时调试代码不用windows,查阅了一些资料,不太能用,现在将51单片机在ubuntu下(Linux通用)开发和下载说明一下:需要用到SDCC和stcgal。
推荐使用HML_FwLib_STC89!!!
具体参考:https://blog.csdn.net/ZhangRelay/article/details/109196577
/*****************************************************************************
* 头文件 *
*****************************************************************************/
#include "hml/hml.h"
#define LSA P1_5
#define LSB P1_6
#define LSC P1_7
/*****************************************************************************
* 初始化 *
*****************************************************************************/
char receiver;
void sys_init(void)
{
UART_configTypeDef uc;
uc.baudrate = 4800;
uc.baudGenerator = PERIPH_TIM_2;
uc.interruptState = DISABLE;
uc.interruptPriority = UTIL_interruptPriority_0;
uc.mode = UART_mode_1;
uc.multiBaudrate = DISABLE;
uc.receiveState = ENABLE;
UART_config(&uc);
enableAllInterrupts();
LSA = 0;
LSB = 0;
LSC = 0;
}
/*****************************************************************************
* 主函数 *
*****************************************************************************/
void main(void)
{
sys_init();
unsigned char j=0,sel=0x00;
while(true)
{
while(RI==0);
RI=0;
receiver=UART_getByte();
if(receiver=='1')
{
UART_sendString("你真的已经放弃学习单片机了吗?\r\n");
for(j=0,sel=0x7F;j<8;j++)
{
P0=sel;
sleep(125);
sel=sel>>1|0x80;
}
sel=0xFF;
P0=sel;
sleep(100);
}
if(receiver=='2')
{
UART_sendString("是的,完全学不会啊!\r\n");
for(j=0,sel=0xFE;j<8;j++)
{
P0=sel;
sleep(125);
sel=sel<<1|0x01;
}
sel=0xFF;
P0=sel;
sleep(100);
}
receiver=0;
}
}
已测试Linux通用,Ubuntu16.04,18.04.20.04均可。
资源下载:https://download.csdn.net/download/ZhangRelay/12820423
SDCC是可重定目标的,优化的标准C(ANSI C89,ISO C99,ISO C11)编译器套件,针对的是基于Intel MCS51的微处理器(8031、8032、8051、8052 等), Maxim(以前为Dallas),DS80C390, 飞思卡尔(以前基于Motorola)基于HC08 (hc08,s08), 基于Zilog Z80的MCU (z80,z180,gbz80,Rabbit 2000/3000,Rabbit 3000A,TLCS-90),Padauk(pdk14,pdk15)和 STMicroelectronics STM8。支持Padauk(pdk13),Microchip PIC16和PIC18 目标的工作正在进行中 。可以将其重新定位为其他微处理器。
SDCC套件是从具有不同FOSS许可证的不同来源派生的几个组件的集合。SDCC编译器套件包括:
SDCC最初由Sandeep Dutta编写,并根据GPL许可发布。自最初发布以来,已经进行了许多错误修复和改进。自1999年12月起,代码已移至SourceForge,所有“用户都变成开发者”都可以访问同一源树。SDCC会不断更新所有用户和开发人员的输入。
简要介绍一下吧:
解压sdcc压缩文件(这里使用最新4.0.0版本),全部文档在sdcc-4.0.0/share/sdcc/doc。
cd sdcc-4.0.0 cp -r * /usr/local
sdcc -mmcs51 xxx.c
最简单安装方法:
sudo apt install sdcc
stcgal是用于STC MCU Ltd的命令行闪存编程工具。8051兼容的微控制器。
STC微控制器具有基于UART/USB的引导加载程序(BSL)。它利用基于数据包的协议通过串行链路刷新代码存储器和IAP存储器。这称为系统内编程(ISP)。BSL还用于配置各种(类似保险丝的)设备选项。不幸的是,该协议没有公开记录,STC仅提供(粗略的)Windows GUI应用程序进行编程。
stcgal是STC的Windows软件的功能全面的开源替代品;它支持多种MCU,非常便携,适合自动化。
安装stcgal(可能需要root /管理员权限):
pip3 install stcgal
Collecting stcgal
Downloading https://files.pythonhosted.org/packages/b0/68/4924bd584b9e47639b28a1900cbced4e90deac7905fd996108ee2fcf975c/stcgal-1.6-py3-none-any.whl
Collecting tqdm>=4.0.0 (from stcgal)
Downloading https://files.pythonhosted.org/packages/28/7e/281edb5bc3274dfb894d90f4dbacfceaca381c2435ec6187a2c6f329aed7/tqdm-4.48.2-py2.py3-none-any.whl (68kB)
100% |████████████████████████████████| 71kB 754kB/s
Collecting pyserial>=3.0 (from stcgal)
Using cached https://files.pythonhosted.org/packages/0d/e4/2a744dd9e3be04a0c0907414e2a01a7c88bb3915cbe3c8cc06e209f59c30/pyserial-3.4-py2.py3-none-any.whl
Installing collected packages: tqdm, pyserial, stcgal
Successfully installed pyserial-3.4 stcgal-1.6 tqdm-4.48.2
如果网络问题,请尝试如下命令:
pip3 install stcgal -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com
调用stcgal并显示用法:
stcgal -h
usage: stcgal [-h] [-a] [-r RESETCMD]
[-P {stc89,stc12a,stc12b,stc12,stc15a,stc15,stc8,usb15,auto}]
[-p PORT] [-b BAUD] [-l HANDSHAKE] [-o OPTION] [-t TRIM] [-D]
[-V]
[code_image] [eeprom_image]
stcgal 1.6 - an STC MCU ISP flash tool
(C) 2014-2018 Grigori Goronzy and others
https://github.com/grigorig/stcgal
positional arguments:
code_image code segment file to flash (BIN/HEX)
eeprom_image eeprom segment file to flash (BIN/HEX)
optional arguments:
-h, --help show this help message and exit
-a, --autoreset cycle power automatically by asserting DTR
-r RESETCMD, --resetcmd RESETCMD
shell command for board power-cycling (instead of DTR
assertion)
-P {stc89,stc12a,stc12b,stc12,stc15a,stc15,stc8,usb15,auto}, --protocol {stc89,stc12a,stc12b,stc12,stc15a,stc15,stc8,usb15,auto}
protocol version (default: auto)
-p PORT, --port PORT serial port device
-b BAUD, --baud BAUD transfer baud rate (default: 19200)
-l HANDSHAKE, --handshake HANDSHAKE
handshake baud rate (default: 2400)
-o OPTION, --option OPTION
set option (can be used multiple times, see
documentation)
-t TRIM, --trim TRIM RC oscillator frequency in kHz (STC15+ series only)
-D, --debug enable debug output
-V, --version print version info and exit
stcgal -P stc89 xxx.ihx
程序需要做一些修改的,以LED灯为例吧:
#include <reg52.h> //52系列单片机头文件
sbit LSA = P1^5; //LED位选译码地址引脚A
sbit LSB = P1^6; //LED位选译码地址引脚B
sbit LSC = P1^7; //LED位选译码地址引脚C
int main(void)
{
while(1) //主程序中设置死循环程序,保证周而复始运行
{
//使LED灯的总开关三极管Q6导通,+5V加到LED灯组
LSA = 0;
LSB = 0;
LSC = 0;
P0 = 0xfe; //点亮一个发光二极管
}
}
在sdcc下需修改为:
#include <8052.h>
#define LSA P1_5
#define LSB P1_6
#define LSC P1_7
int main(void)
{
while(1)
{
LSA = 0;
LSB = 0;
LSC = 0;
P0 = 0xfe;
}
}
Linux下无需安装驱动!!!
sdcc -mmcs51 led.c
stcgal -P stc89 led.ihx
闪烁:
#include <8052.h>
#define LSA P1_5 //LED位选译码地址引脚A
#define LSB P1_6 //LED位选译码地址引脚B
#define LSC P1_7 //LED位选译码地址引脚C
#define Led10 P0_7 //定义P0.7名字为led10
int main(void)
{
unsigned int a; //定义无符号的整型变量a
while(1)
{
//使LED灯的总开关三极管Q6导通,+5V加到LED灯组
LSA = 0;
LSB = 0;
LSC = 0;
Led10 = 0; //点亮LED10
a = 50000;
while(a--); //50000次的循环,通过消耗时间以达到延时的目的
Led10 = 1;; //熄灭LED10
a = 50000;
while(a--); //延时
}
}
呼吸灯:
#include <8052.h>
#define LSA P1_5 //LED位选译码地址引脚A
#define LSB P1_6 //LED位选译码地址引脚B
#define LSC P1_7 //LED位选译码地址引脚C
#define Led10 P0_7 //定义P0.7名字为led10
int atime=64;
void delay(unsigned int pms) //延时函数
{
unsigned int x;
unsigned int y;
for(x=pms;x>0;x--)
for(y=11;y>0;y--)
;
}
void ledfade(unsigned int i) //呼吸灯
{
Led10 = 0;
delay(i);
Led10 = 1;
delay(atime-i);
}
int main(void)
{
int a; //定义无符号的整型变量a
while(1)
{
//使LED灯的总开关三极管Q6导通,+5V加到LED灯组
LSA = 0;
LSB = 0;
LSC = 0;
for(a=0;a<atime;a++)
{
ledfade(a);
}
for(a=atime;a>0;a--)
{
ledfade(a);
}
}
}
呼吸跑马灯???(需改进优化哦!)
#include <8052.h>
#define LSA P1_5 //LED位选译码地址引脚A
#define LSB P1_6 //LED位选译码地址引脚B
#define LSC P1_7 //LED位选译码地址引脚C
#define Led10 P0_0 //定义P0.0名字为led10
#define Led11 P0_1 //定义P0.0名字为led11
#define Led12 P0_2 //定义P0.0名字为led12
#define Led13 P0_3 //定义P0.0名字为led13
#define Led14 P0_4 //定义P0.0名字为led14
#define Led15 P0_5 //定义P0.0名字为led15
#define Led16 P0_6 //定义P0.0名字为led16
#define Led17 P0_7 //定义P0.0名字为led17
int atime=64;
void delay(unsigned int pms) //延时函数
{
unsigned int x;
unsigned int y;
for(x=pms;x>0;x--)
for(y=11;y>0;y--)
;
}
void ledfade0(unsigned int i) //呼吸灯
{
Led10 = 0;
delay(i);
Led10 = 1;
delay(atime-i);
}
void ledfade1(unsigned int i) //呼吸灯
{
Led11 = 0;
delay(i);
Led11 = 1;
delay(atime-i);
}
void ledfade2(unsigned int i) //呼吸灯
{
Led12 = 0;
delay(i);
Led12 = 1;
delay(atime-i);
}
void ledfade3(unsigned int i) //呼吸灯
{
Led13 = 0;
delay(i);
Led13 = 1;
delay(atime-i);
}
void ledfade4(unsigned int i) //呼吸灯
{
Led14 = 0;
delay(i);
Led14 = 1;
delay(atime-i);
}
void ledfade5(unsigned int i) //呼吸灯
{
Led15 = 0;
delay(i);
Led15 = 1;
delay(atime-i);
}
void ledfade6(unsigned int i) //呼吸灯
{
Led16 = 0;
delay(i);
Led16 = 1;
delay(atime-i);
}
void ledfade7(unsigned int i) //呼吸灯
{
Led17 = 0;
delay(i);
Led17 = 1;
delay(atime-i);
}
int main(void)
{
int a; //定义无符号的整型变量a
while(1)
{
//使LED灯的总开关三极管Q6导通,+5V加到LED灯组
LSA = 0;
LSB = 0;
LSC = 0;
for(a=0;a<atime;a++)
{
ledfade0(a);
}
for(a=atime;a>0;a--)
{
ledfade0(a);
}
for(a=0;a<atime;a++)
{
ledfade1(a);
}
for(a=atime;a>0;a--)
{
ledfade1(a);
}
for(a=0;a<atime;a++)
{
ledfade2(a);
}
for(a=atime;a>0;a--)
{
ledfade2(a);
}
for(a=0;a<atime;a++)
{
ledfade3(a);
}
for(a=atime;a>0;a--)
{
ledfade3(a);
}
for(a=0;a<atime;a++)
{
ledfade4(a);
}
for(a=atime;a>0;a--)
{
ledfade4(a);
}
for(a=0;a<atime;a++)
{
ledfade5(a);
}
for(a=atime;a>0;a--)
{
ledfade5(a);
}
for(a=0;a<atime;a++)
{
ledfade6(a);
}
for(a=atime;a>0;a--)
{
ledfade6(a);
}
for(a=0;a<atime;a++)
{
ledfade7(a);
}
for(a=atime;a>0;a--)
{
ledfade7(a);
}
}
}
如果需要将51接入机器人操作系统ROS,可以参考:
MacOS:
此部分内容和ubuntu类似!
$ brew install sdcc
虽然有编译器,也都是c代码,但是语法上还是有那么一点点不同,根据文档以及网上的说法:
Mac sdcc | Windows Keil c | |
---|---|---|
头文件 | 8051.h/8052.h | reg51.h/reg52.h |
IO端口 | P2_0 | P2^0 |
IO口定义 | #define LED P2_0 | sbit LED = P2^0 |
中断函数 | void INT0_ISR() __interrupt 0 | void INT0_ISR() interrupt 0 |
参考示例:
#include<8052.h>
#define uchar unsigned char
#define uint unsigned int
#define lcden P2_5
#define lcdrs P1_0
#define rw P1_1
#define dula P2_6
#define wela P2_7
uchar table[] = "Hello World!";
uchar num;
void delay(uint z) {
uint x, y;
for(x = z; x > 0; x--)
for(y = 110; y > 0; y--);
}
void write_com(uchar com) {
lcdrs = 0;
P0 = com;
delay(5);
lcden = 1;
delay(5);
lcden = 0;
}
void write_data(uchar date) {
lcdrs = 1;
P0 = date;
delay(5);
lcden = 1;
delay(5);
lcden = 0;
}
void init() {
rw = 0;
dula = 0;
wela = 0;
lcden = 0;
write_com(0x38);
write_com(0x0e);
write_com(0x06);
write_com(0x01);
write_com(0x80);
}
void main() {
init();
for(num = 0; num < 12; num++) {
write_data(table[num]);
delay(100);
}
while(1);
}
然后编译:
$ sdcc helloword.c
成功执行后,生成了一堆文件,.asm、.ihx、.lk、.lst…,这里要下载到单片机ROM的只有.ihx文件。
stcgal
$ pip install git+https://github.com/grigorig/stcgal.git
$ pip install tqdm
先来看下设备信息:
$ stcgal -P stc89 -p /dev/cu.wchusbserialfd130
Waiting for MCU, please cycle power: done
Target model:
Name: STC89C52RC/LE52R
Magic: F002
Code flash: 8.0 KB
EEPROM flash: 6.0 KB
Target frequency: 11.030 MHz
Target BSL version: 6.6C
Target options:
cpu_6t_enabled=False
bsl_pindetect_enabled=False
eeprom_erase_enabled=False
clock_gain=high
ale_enabled=True
xram_enabled=True
watchdog_por_enabled=False
Disconnected!
OK了,注意在提示“Waiting for MCU, please cycle power:”的时候关掉电源再打开就可以了。
好啦,下载来试试烧录吧,就用上面生成的helloworld.ihx
:
$ stcgal -P stc89 -p /dev/cu.wchusbserialfd130 helloworld.ihx
Waiting for MCU, please cycle power: done
Target model:
Name: STC89C52RC/LE52R
Magic: F002
Code flash: 8.0 KB
EEPROM flash: 6.0 KB
Target frequency: 11.030 MHz
Target BSL version: 6.6C
Target options:
cpu_6t_enabled=False
bsl_pindetect_enabled=False
eeprom_erase_enabled=False
clock_gain=high
ale_enabled=True
xram_enabled=True
watchdog_por_enabled=False
Loading flash: 293 bytes (Intel HEX)
Switching to 19200 baud: checking setting testing done
Erasing 2 blocks: done
Writing flash: 640 Bytes [00:00, 1699.01 Bytes/s]
Setting options: done
Disconnected!