51单片机封装库HML_FwLib_STC89

HML_FwLib_STC89

项目地址 https://github.com/MCU-ZHISHAN-IoT/HML_FwLib_STC89
这个项目主要是封装了8051和STC89(还有STC其他芯片系列, 例如STC10, STC11, STC90), 使得上层可以使用类似于STM的高级语言方式进行开发. 解决了开发过程极度依赖手册, 八进制配置数值不便于记忆的问题. 除了STC89, 这个账号下还提供了STC90, STC10, STC11这几个系列的封装库.

目录结构

HML_FwLib_STC89
├─doc      # store related documents about HML_FwLib_STC89
├─example  # 示例代码, 每个c文件代表一个功能示例
├─inc      # 头文件, 里面 macro.h 有这个库支持的芯片型号列表
├─obj      # 编译输出
├─src      # 这个库的c文件
├─usr      # 这个目录用于存储用户代码, 以及Makefile, 项目带了一个很完整的示例
├─LICENSE  # license of HML_FwLib_STC89
└─VERSION  # version code of HML_FwLib_STC89

这个库实现的类STM32的方法定义, 都在inc/hml/下的.h文件中, 可以对照参考.

快速开始

前置条件

  • 首先要安装编译器, sdcc, Ubuntu20.04自带的为3.8.0, 最新的为4.1.0, 可以自己编译安装
    执行sdcc --print-search-dirs查看库文件的位置. 默认的8051的库文件位置为/usr/local/share/sdcc/include/mcs51/
  • 安装烧录工具, stcgal, 直接用pip3 install stcgal安装然后执行stcgal -h查看输出

使用

  • 将代码clone到本地后, cd进入usr目录
  • 执行make help查看帮助, 这里有很详细的说明
  • 执行make -j编译

如果过程没问题, 你应当看到这样的输出

somewhere:~$ make -j
 - Collect MCU config information
[mcu-model] STC89C52RC (code=8192B, iram=256B, xram=256B)
[mcu-clock] 11.059200 MHz
[prescaler] 12T mode
 - Start to build!
CC  ../src/mem.c
CC  ../src/tim.c
CC  ../src/exti.c
CC  ../src/uart.c
CC  ../src/gpio.c
CC  ../src/rst.c
CC  ../src/util.c
CC  ../src/isp.c
CC  ../src/tim2.c
CC  ../src/wdt.c
 - Make static link library libhml_stc89.lib 
AR  ../obj/libhml_stc89.lib
 - Compile user source code 
CC  test.c
 - Generate .ihx file 
CC ../obj/output.ihx
 - Generate .hex file 
packihx: read 89 lines, wrote 160: OK.
===================================================
Make done!
---------------------------------------------------
completed at 2021-08-06 14:18:35
===================================================

如果需要使用其他编译选项, 例如指定芯片型号, 可以用

make -j MCU=stc89c52rc"
make rebuild MCU=stc89c52rc JOBS=4

用stcgal烧录

stcgal -P stc89 -b 115200 output.ihx

Makefile 分析

GNU Make 使用手册: https://www.gnu.org/software/make/manual/

在用户代码目录里有多个Makefile相关文件

Makefile          # make命令入口文件
Makefile.config   # 默认的make配置, 如果make时指定了CONF参数, 则使用CONF对应的配置文件
Makefile.help
Makefile.mcu
Makefile.version

分析一下主文件Makefile

#!/usr/bin/make

# ------------------------------------------------------------------------
# Author     : Weilun Fong | wlf@zhishan-iot.tk
# Date       : 2020-02-06
# Description: project Makefile
# E-mail     : mcu@zhishan-iot.tk
# Make-tool  : GNU Make (http://www.gnu.org/software/make/manual/make.html)
# Page       : https://hw.zhishan-iot.tk/page/hml/detail/fwlib_stc89.html
# Project    : HML_FwLib_STC89
# Version    : v0.3.1
# ------------------------------------------------------------------------

# Package Bash shell command 统一基础命令, 可以复用
export SHELL       := /bin/bash
export AWK         := awk
export BASENAME    := basename
export CAT         := cat
export CD          := cd
export DATE        := date
export ECHO        := echo
export EECHO       := $(ECHO) -e
export GREP        := grep
export LS          := ls
export RM          := rm -f
export TR          := tr
export TRUE        := true
export XARGS       := xargs

# Definition of toolchain 统一编译工具, 可以复用
CROSS_COMPILE      := sd
AR                 := $(CROSS_COMPILE)ar
CC                 := $(CROSS_COMPILE)cc
MAKE               := make --no-print-directory
PACKIHX            := packihx

# Mark special phony targets 定义编译目标, 可以复用
PHONY_LIST_IN      := clean distclean help rebuild version

# Definition of project basic path 项目路径定义, 可以复用
DIR_ROOT           := ..
DIR_INC            := $(DIR_ROOT)/inc
DIR_OUTPUT         := $(DIR_ROOT)/obj
DIR_SRC            := $(DIR_ROOT)/src

# Configure all custom parameters 这里处理自定义参数 CONF, 
SPACE              := $(empty) $(empty)
TITLE_COLOR        := \033[36m
ifeq ($(findstring $(MAKECMDGOALS), $(PHONY_LIST_IN)),) # 符合条件的才去包含, 
                                                        # 如果不在 PHONY_LIST_IN 中, 后面会提示 *** No rule to make target
    ifneq ($(CONF),)          # 如果 CONF 不为空则包含自定义的文件, 这里第二个参数为空值
        include $(CONF)
    else
        include Makefile.config
    endif
    include Makefile.mcu      # 这里包含了芯片型号对应的定义
endif

#  Definition of of print format 定义输出, 如果VERBOSE为1则输出命令, 且输出提示
ifeq ("$(VERBOSE)", "1")
    Q :=
    VECHO := @$(TRUE)
else
    Q := @
    VECHO := @$(ECHO)
endif

# Important file 组织编译中的目标文件, 输入文件, 输入参数等
FILE_HML_FWLIB     := libhml_stc89.lib    # 这是最后生成的库文件名称
HML_SRC_FILES      := $(wildcard $(DIR_SRC)/*.c) # wildcard会列出符合这个文件名格式的文件, 产生一个以空格分隔的字符串列表.
HML_REL_FILES      := $(patsubst $(DIR_SRC)/%.c, $(DIR_OUTPUT)/%.rel, $(HML_SRC_FILES)) # patsubst 在字符串中替换匹配的串
                                                                                        # 将c文件名列表变为rel文件列表
MYFILE             ?= test.c # := 是覆盖之前的值, ?= 是如果没有被赋值过就赋予等号后面的值, += 是添加等号后面的值
    # file check
    ifeq ($(findstring $(MAKECMDGOALS),$(PHONY_LIST_IN)),)
        ifneq ($(wildcard $(MYFILE)),$(MYFILE))
            $(error no such file $(CURDIR)/$(MYFILE))
        endif
    endif
MYFILE_NAME        := $(shell $(BASENAME) $(MYFILE) .c) # 取出MYFILE不带扩展名的文件名
MYFILE_REL         := $(DIR_OUTPUT)/$(MYFILE_NAME).rel
# Target file
TARGET             := output                            # 编译输出结果文件名
TARGET_FWLIB       := $(DIR_OUTPUT)/$(FILE_HML_FWLIB)

all: $(DIR_OUTPUT)/$(TARGET).hex
	@$(ECHO) ===================================================
	@$(ECHO) Make $(MAKECMDGOALS) done!
	@$(ECHO) ---------------------------------------------------
	@$(ECHO) completed at `$(DATE) "+%Y-%m-%d %H:%M:%S"`
	@$(ECHO) ===================================================

# Startup
startup:
	@$(EECHO) "$(TITLE_COLOR) - Start to build!\033[0m"

# 下面的格式就是标准的Makefile编译
# 目标 : 需要的文件
#   CC命令
# 自动变量, 参考 https://www.gnu.org/software/make/manual/make.html#Automatic-Variables
# ‘$<’ 第一个需要的文件名
# ‘$^‘ 所有需要的文件名, 用空格分隔
# ‘$@’ 目标文件名

# Compile HML source file(*.c) 先编译HML源文件
$(HML_SRC_FILES): startup
$(HML_REL_FILES): $(DIR_OUTPUT)/%.rel:$(DIR_SRC)/%.c
	$(VECHO) "CC  $<"
	$(Q)$(CC) $< $(CFLAGS) -o $@

# Generate static library
$(TARGET_FWLIB): $(HML_REL_FILES)
	@$(EECHO) "$(TITLE_COLOR) - Make static link library `basename $@` \033[0m"
	$(VECHO) "AR  $@"
	$(Q)$(AR) $(AFLAGS) $@ $^

# Compile user file
$(MYFILE_REL): $(MYFILE) $(TARGET_FWLIB)
	@$(EECHO) "$(TITLE_COLOR) - Compile user source code \033[0m"
	$(VECHO) "CC  $<"
	$(Q)$(CC) $< $(CFLAGS) -L$(DIR_OUTPUT) -lhml_stc89 -o $(DIR_OUTPUT)/`$(BASENAME) $@`

# Generate .hex file
$(DIR_OUTPUT)/$(TARGET).ihx: $(MYFILE_REL)
	@$(EECHO) "$(TITLE_COLOR) - Generate .ihx file \033[0m"
	$(VECHO) "CC $@"
	$(Q)$(CC) $^ $(DIR_OUTPUT)/$(FILE_HML_FWLIB) -o $@
$(DIR_OUTPUT)/$(TARGET).hex: $(DIR_OUTPUT)/$(TARGET).ihx
	@$(EECHO) "\033[36m - Generate .hex file \033[0m"
	$(Q)$(PACKIHX) $< > $@

# Phony targets 定义虚目标

# .PHONY用于定义一个虚目标. 正常情况, 按上面的格式, 冒号前面是编译中间产生的文件, 如果这个文件不存在, 那么这个编译在执行
# make的时候就会被执行, 比如下面的clean, 如果目录里没有clean这个文件, 那么每次都会执行这个clean. 而另一个问题就是如果
# 目录中已经有一个clean了, 那么在make clean的时候实际上就会不执行. 将其定义为.PHONY就可以避免这个问题, 格式:
# .PHONY: clean
# clean:
#         rm *.o temp

# [+] clean
.PHONY: clean
clean:
	$(CD) $(DIR_OUTPUT) && $(LS) | $(GREP) -vE -e ".gitkeep" -e ^$(MYFILE_NAME)* -e *.lib$$ -e *.hex$$ | $(XARGS) $(RM)
# [+] distclean
.PHONY: distclean
distclean:
	$(CD) $(DIR_OUTPUT) && $(LS) | $(GREP) -v ".gitkeep" | $(XARGS) $(RM)
# [+] help
.PHONY: help
help:
	@$(MAKE) -s -f Makefile.help
# [+] library
.PHONY: library
library: $(TARGET_FWLIB)
	@$(ECHO) ===================================================
	@$(ECHO) Make $(MAKECMDGOALS) done!
	@$(ECHO) ---------------------------------------------------
	@$(ECHO) completed at `$(DATE) "+%Y-%m-%d %H:%M:%S"`
	@$(ECHO) ===================================================
# [+] rebuild
.PHONY: rebuild
rebuild:
	@$(EECHO) "$(TITLE_COLOR) - Clean previous files \033[0m"
	@$(MAKE) distclean
	@$(MAKE) -f Makefile -j$(JOBS) $(MAKEFLAGS)
# [+] version
.PHONY: version
version:
	@$(MAKE) -s -f Makefile.version

编写代码

待更新

上一篇:C语言寒假大作战01


下一篇:C语言寒假大作战02