前言
platformIO虽然可以用于编译8051,但是修改头文件包含路径,以及编译器选项都较为麻烦。Embedded IDE界面类似Visual Studio,设置较为方便。
环境
正文
一,安装Embedded IDE和SDCC编译器
platformIO使用的也是SDCC编译器,但是Embedded IDE需要自己下载安装SDCC编译器
- 下载安装SDCC编译器:
sdcc官方网页 sdcc-4.1.0-x64-setup.exe - Embedded IDE 配置 sdcc 编译器路径
点击下图中的构建配置即可配置。
二,单片机头文件
首先,如果是STC-ISP系列的单片机可以在下图下载软件界面的头文件栏获取对应的头文件。
这个头文件 SDCC无法直接使用。 这是因为SDCC 使用了一些非标准的关键字
头文件转换方法一
使用附件一:main.c代码进行转换,转换的时候注意待转换文件中不得包含特别长的注释(也可能出现其他的问题,这个是C代码问题,有兴趣可以重写)。
sfr P0 = 0x80;
sbit P00 = P0^0;
SFR(P0, 0x80);
SBIT(P00, 0x80, 0);
转换后就可以直接使用了。
头文件转换方法二(推荐)
使用perl脚本
这个脚本是sdcc源码文件中自带的,用于keil头文件转sdcc头文件。 但是实际使用时,我又做了一些修改,修改后的脚本见附件2:keil2sdcc.pl 运行脚本需要安装perl运行环境:官方 perl strawberry版本下载地址
解决vscode 不能识别 sdcc 扩展语法问题
最后为了vscode能够正确的标记表示语法,还需要加上下面的代码
#ifndef __SDCC
#include <lint.h>
#error "This header file must be used for SDCC compiler !"
#endif
#include <compiler.h>
lint.h 是sdcc自带的一个头文件,里面是sdcc自定义的关键字的空定义,可以用来避免vscode语法检查报错。 具体实现详见附件3:stc89xx.h
三,附件
1,main.c
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char* args[])
{
string filename = "STC89xx.h";
ifstream file_in(filename.c_str());
string s;
string previous_addr;
while( getline(file_in,s) )
{
if(s[0] == '/' || s[0] == '#')
cout << s << endl;
else if(s.length() > 4)
{
string::size_type type_end = s.find_first_of(' ');
string type = s.substr(0, type_end);
string::size_type name_begin = s.find_first_not_of(' ', type_end);
string::size_type name_end = s.find_first_of(' ', name_begin);
string name = s.substr(name_begin, name_end - name_begin);
string::size_type addr_begin = s.find_first_not_of(" =", name_end);
string::size_type addr_end = s.find_first_of(" ;", addr_begin);
string addr = s.substr(addr_begin, addr_end - addr_begin);
string comment;
bool haveComment = true;
if(addr_end == s.length() - 1)
{
haveComment = false;
}
if(haveComment)
{
string::size_type comment_begin = s.find_first_not_of("; ", addr_end);
comment = s.substr(comment_begin);
}
if(type == "sfr")
{
cout << "SFR(" << name << ", " << addr << ");";
if(haveComment) cout << comment;
cout << endl;
previous_addr = addr;
}
else if(type == "sbit")
{
string bit_offset = addr.substr(addr.length()-1);
cout << "SBIT(" << name << ", " << previous_addr << ", " << bit_offset << ");";
if(haveComment) cout << comment;
cout << endl;
}
}
}
return 0;
}
2,keil2sdcc.pl (在sdcc原版上修改后)
use strict;
my %data;
while(<>)
{
s/\r//g;
if(/^(\s*)EXTERN\s*xdata\s*volatile\s*BYTE\s*(\w+(?:\s*\[\s*\d+\s*\])?)\s+_AT_\s*([^;]+);(.*)$/) {
print "$1EXTERN xdata at $3 volatile BYTE $2;$4\n";
next;
}
if(/^(\s*)sfr\s*(\w+)\s*=\s*([^;]+);(.*)$/) {
print "$1SFR($2, $3);$4\n";
$data{-$2} = $3;
next;
}
if(/^(\s*)sbit\s*(\w+)\s*=\s*(\w+)\s*\^\s*([^;]+);(.*)$/) {
print "$1SBIT($2, $data{-$3}, $4);$5\n";
next;
}
if(/^(\s*)\/\/(.*)$/) {
print "$1//$2\n";
next;
}
if(/^(\s*)\/\*(.*)$/) {
my($ws,$cmt) = ($1,"$2\n");
$cmt .= <> while $cmt !~ /\*\/\s*$/;
$cmt =~ s/\r//g;
print "$ws/*$cmt";
next;
}
if(/^(\s*)\#(.*)$/) {
print "$1#$2\n";
next;
}
if(/^(\s*)$/) {
print "\n";
next;
}
chomp;
die "Unconvertable line: \"$_\"\n";
}
3,stc89xx.h (使用perl脚本转换后)
#ifndef __STC89C5xRC_RDP_H__
#define __STC89C5xRC_RDP_H__
#ifndef __SDCC
#include <lint.h>
#error "This header file must be used for SDCC compiler !"
#endif
#include <compiler.h>
typedef unsigned int u16;
typedef unsigned char u8;
SFR(P4, 0xe8);
SBIT(P46, 0xe8, 6);
SBIT(P45, 0xe8, 5);
SBIT(P44, 0xe8, 4);
SBIT(P43, 0xe8, 3);
SBIT(P42, 0xe8, 2);
SBIT(P41, 0xe8, 1);
SBIT(P40, 0xe8, 0);
SFR(XICON, 0xc0);
SFR(WDT_CONTR, 0xe1);
SFR(ISP_DATA, 0xe2);
SFR(ISP_ADDRH, 0xe3);
SFR(ISP_ADDRL, 0xe4);
SFR(ISP_CMD, 0xe5);
SFR(ISP_TRIG, 0xe6);
SFR(ISP_CONTR, 0xe7);
SFR(P0, 0x80);
SBIT(P00, 0x80, 0);
SBIT(P01, 0x80, 1);
SBIT(P02, 0x80, 2);
SBIT(P03, 0x80, 3);
SBIT(P04, 0x80, 4);
SBIT(P05, 0x80, 5);
SBIT(P06, 0x80, 6);
SBIT(P07, 0x80, 7);
SFR(P1, 0x90);
SBIT(P10, 0x90, 0);
SBIT(P11, 0x90, 1);
SBIT(P12, 0x90, 2);
SBIT(P13, 0x90, 3);
SBIT(P14, 0x90, 4);
SBIT(P15, 0x90, 5);
SBIT(P16, 0x90, 6);
SBIT(P17, 0x90, 7);
SFR(P2, 0xA0);
SBIT(P20, 0xA0, 0);
SBIT(P21, 0xA0, 1);
SBIT(P22, 0xA0, 2);
SBIT(P23, 0xA0, 3);
SBIT(P24, 0xA0, 4);
SBIT(P25, 0xA0, 5);
SBIT(P26, 0xA0, 6);
SBIT(P27, 0xA0, 7);
SFR(P3, 0xB0);
SBIT(P30, 0xB0, 0);
SBIT(P31, 0xB0, 1);
SBIT(P32, 0xB0, 2);
SBIT(P33, 0xB0, 3);
SBIT(P34, 0xB0, 4);
SBIT(P35, 0xB0, 5);
SBIT(P36, 0xB0, 6);
SBIT(P37, 0xB0, 7);
SFR(PSW, 0xD0);
SFR(ACC, 0xE0);
SFR(B, 0xF0);
SFR(SP, 0x81);
SFR(DPL, 0x82);
SFR(DPH, 0x83);
SFR(PCON, 0x87);
SFR(TCON, 0x88);
SFR(TMOD, 0x89);
SFR(TL0, 0x8A);
SFR(TL1, 0x8B);
SFR(TH0, 0x8C);
SFR(TH1, 0x8D);
SFR(IE, 0xA8);
SFR(IP, 0xB8);
SFR(SCON, 0x98);
SFR(SBUF, 0x99);
SFR(AUXR, 0x8E);
SFR(AUXR1, 0xA2);
SFR(SADDR, 0xA9);
SFR(IPH, 0xB7);
SFR(SADEN, 0xB9);
SFR(T2CON, 0xC8);
SFR(T2MOD, 0xC9);
SFR(RCAP2L, 0xCA);
SFR(RCAP2H, 0xCB);
SFR(TL2, 0xCC);
SFR(TH2, 0xCD);
SBIT(CY, 0xD0, 7);
SBIT(AC, 0xD0, 6);
SBIT(F0, 0xD0, 5);
SBIT(RS1, 0xD0, 4);
SBIT(RS0, 0xD0, 3);
SBIT(OV, 0xD0, 2);
SBIT(F1, 0xD0, 1);
SBIT(P, 0xD0, 0);
SBIT(TF1, 0x88, 7);
SBIT(TR1, 0x88, 6);
SBIT(TF0, 0x88, 5);
SBIT(TR0, 0x88, 4);
SBIT(IE1, 0x88, 3);
SBIT(IT1, 0x88, 2);
SBIT(IE0, 0x88, 1);
SBIT(IT0, 0x88, 0);
SBIT(EA, 0xA8, 7);
SBIT(EC, 0xA8, 6);
SBIT(ET2, 0xA8, 5);
SBIT(ES, 0xA8, 4);
SBIT(ET1, 0xA8, 3);
SBIT(EX1, 0xA8, 2);
SBIT(ET0, 0xA8, 1);
SBIT(EX0, 0xA8, 0);
SBIT(PT2, 0xB8, 5);
SBIT(PS, 0xB8, 4);
SBIT(PT1, 0xB8, 3);
SBIT(PX1, 0xB8, 2);
SBIT(PT0, 0xB8, 1);
SBIT(PX0, 0xB8, 0);
SBIT(RD, 0xB0, 7);
SBIT(WR, 0xB0, 6);
SBIT(T1, 0xB0, 5);
SBIT(T0, 0xB0, 4);
SBIT(INT1, 0xB0, 3);
SBIT(INT0, 0xB0, 2);
SBIT(TXD, 0xB0, 1);
SBIT(RXD, 0xB0, 0);
SBIT(SM0, 0x98, 7);
SBIT(FE, 0x98, 7);
SBIT(SM1, 0x98, 6);
SBIT(SM2, 0x98, 5);
SBIT(REN, 0x98, 4);
SBIT(TB8, 0x98, 3);
SBIT(RB8, 0x98, 2);
SBIT(TI, 0x98, 1);
SBIT(RI, 0x98, 0);
SBIT(T2EX, 0x90, 1);
SBIT(T2, 0x90, 0);
SBIT(TF2, 0xC8, 7);
SBIT(EXF2, 0xC8, 6);
SBIT(RCLK, 0xC8, 5);
SBIT(TCLK, 0xC8, 4);
SBIT(EXEN2, 0xC8, 3);
SBIT(TR2, 0xC8, 2);
SBIT(C_T2, 0xC8, 1);
SBIT(CP_RL2, 0xC8, 0);
#endif
参考文献
- SDCC编译器 + VSCode开发 8位微控制器
- Embedded IDE 文档
- 突然要用 STC 写个东西,但是发现没有SDCC头文件,写个工具
- sdcc官方手册
|