本文主要是介绍从Keil迁移到SDCC,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
前言
当前,在单片机开发领域,Keil是广泛被采用的开发工具。然而,其编辑器功能相较于现代的VScode显得相当陈旧和不足。过去,我也曾试验过使用platformIO,其核心理念是对SDCC和stcgal进行封装,从而提供一个更加集成的开发环境。
现在,我们将基于SDCC和stcgal来搭建一个全新的单片机开发环境。我们将现有代码从Keil迁移到SDCC,确保原有的Keil代码能够在新环境中顺畅运行。
本文使用的示例项目地址:uart_temp
正文
一、安装SDCC和stcgal
下载链接
- SDCC - Small Device C Compiler (sourceforge.net)
- grigorig/stcgal: Open Source STC MCU ISP flash tool (github.com)
SDCC的特点:
-
开源免费、支持常见MCU
-
一次只能编译一个文件,多个文件需要编写Makefile
-
对c99标准支持的比Keil C51更好,更像一个标准的C语言编译器
-
SDCC代码生成的体积会比较大,原因如下:
在GCC编译器中,
-ffunction-sections
和-fdata-sections
参数是用来将每个函数和数据段分别放在单独的section中。这样做的好处是在链接阶段,未被引用的函数和数据可以被识别并删除,从而减小最终的执行文件大小。而-Wl,--gc-sections
参数则是告诉链接器去删除未使用的函数和数据段。然而,SDCC(Small Device C Compiler)并不支持这些GCC的特性。这可能导致SDCC编译的单片机程序的最终执行文件比使用GCC编译的更大,因为即使某些代码没有被调用,它也会被包含在执行文件中。为了解决这个问题,有些SDCC库的开发者选择在每个源文件中只放置一个函数,尽管这样做会让代码看起来更加分散和不易读。
stcgal的特点:
- 开源免费,支持 STC MCU Ltd. 8051 系列单片机
- 支持命令行操作,stc-isp可以用于烧录单片机,但是软件是闭源的。不支持命令行操作
二、从Keil迁移到SDCC
Keil C51 | SDCC | ||
---|---|---|---|
头文件 | reg51.h/reg52.h | 8051.h/8052.h | |
端口 | P2^0 | P2_0 | |
端口定义 | sbit LED1=P2^0; | #define LED1 P2_0 | 替换的时候注意删除后面的分号; |
中断声明 | void uart() interrupt 4 using 0 | void uart(void) __interrupt (4) __using (0) | |
特殊类型 | sbit,sfr,bit,code | __sbit,__sfr,__bit,__code | Keil中的很多特殊类型前面加上__就是sdcc中对应的类型。 |
_nop()_ | Keil C51专有 | #define _nop_() __asm NOP __endasm | |
intrins.h | Keil C51专有, SDCC需自己创建 | 自行创建 |
intrins.h文件内容图下,请自行创建
#ifndef _INTRINS_H_
#define _INTRINS_H_/* warning: __push __pop 使用堆栈临时保存 sfr 数据,必需成对使用! __push(x);... // 保护代码块__pop(x); //缺少无该语句编译不会出错,但运行错误!
*/#define __push(x) __asm push _##x __endasm /* void _push_ (unsigned char _sfr); */#define __pop(x) __asm pop _##x __endasm /* void _pop_ (unsigned char _sfr); */#define _push_ __push /*兼容 keil c51*/#define _pop_ __pop /*兼容 keil c51*//* 安全使用保护宏: pushSfr(x);... // 受保护代码块popSfr(x); // 缺少无该语句编译出错,确保生成正确代码。
*/#define pushSfr(x) do{\__push(x)#define popSfr(x) __pop(x);\}while(0)#endif //_INTRINS_H_
常见编译问题:
- 待补充
三、编写Makefile
示例项目地址:uart_temp
项目结构如下:
D:\PROJECT\UART_TEMP
├─include
├─obj
└─src
对应的Makefile如下:
# set CC TOOL
CC := sdcc
PACKIHX := packihx
CFLAGS := -DUSE_FLOATS=1# set DIR
INCDIR = include
SRCDIR = src
OBJDIR = obj
TARGET = obj/main.ihxINC := ./include
SRC := $(wildcard $(SRCDIR)/*.c)
# OBJ := $(SRC:%.c=%.rel)
OBJ := $(patsubst src/%.c, obj/%.rel, $(SRC)) .PHONY: all cleanall: uart_temp.hexclean:-del /q obj\*$(OBJ):obj/%.rel:src/%.c-$(CC) $(CFLAGS) -I $(INC) -c $^ -o $@$(TARGET): $(OBJ)-$(CC) $^ -o $@uart_temp.hex: $(TARGET)-$(PACKIHX) $(TARGET) > uart_temp.hexflash: -stcgal -P stc89 -p COM3 .\uart_temp.hex#led.bin:led.hex
# objcopy -I ihex -O binary led.hex led.bin#led.hex:main.ihx
# packihx main.ihx > led.hex# led.bin:main.ihx
# makebin main.ihx led.bin
需要注意的是:
- sdcc编译生成
.rel
不生成.o
- sdcc链接得到
.ihx
,需要使用packihx转换成.hex
- sdcc一次只能编译一个文件
四、编译、烧录
编译命令,编译得到.\uart_temp.hex
make clean all
烧录前,确认单片机连接的串口号,并将Makefile中的COM3为单片机使用的串口号
烧录命令
make flash
参考文献
-
如何评价 SDCC (Small Device C Compiler) 编译器套件? - 知乎 (zhihu.com)
-
8951单片机Keil C 迁移 SDCC - 简书 (jianshu.com)
-
MAC 开发C51 - 简书 (jianshu.com)
-
还在用Keil做51单片机开发吗?快来试试开源的SDCC吧 - 知乎 (zhihu.com)
-
SDCC - Small Device C Compiler (sourceforge.net)
-
grigorig/stcgal: Open Source STC MCU ISP flash tool (github.com)
这篇关于从Keil迁移到SDCC的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!