从Keil迁移到SDCC

前言

当前,在单片机开发领域,Keil是广泛被采用的开发工具。然而,其编辑器功能相较于现代的VScode显得相当陈旧和不足。过去,我也曾试验过使用platformIO,其核心理念是对SDCCstcgal进行封装,从而提供一个更加集成的开发环境。

现在,我们将基于SDCCstcgal来搭建一个全新的单片机开发环境。我们将现有代码从Keil迁移到SDCC,确保原有的Keil代码能够在新环境中顺畅运行。

本文使用的示例项目地址:uart_temp

正文

一、安装SDCC和stcgal

下载链接

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 C51SDCC
头文件reg51.h/reg52.h8051.h/8052.h
端口P2^0P2_0
端口定义sbit LED1=P2^0;#define LED1 P2_0替换的时候注意删除后面的分号
中断声明void uart() interrupt 4 using 0void uart(void) __interrupt (4) __using (0)
特殊类型sbit,sfr,bit,code__sbit,__sfr,__bit,__codeKeil中的很多特殊类型前面加上__就是sdcc中对应的类型。
_nop()_Keil C51专有#define _nop_() __asm NOP __endasm
intrins.hKeil 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.ihx

INC := ./include
SRC := $(wildcard $(SRCDIR)/*.c)
# OBJ := $(SRC:%.c=%.rel)
OBJ := $(patsubst src/%.c, obj/%.rel, $(SRC))  

.PHONY: all clean

all: uart_temp.hex

clean:
	-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.hex

flash: 
	-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

参考文献

  • 23
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值