使用SDCC开发新定义NBK开发板1:基础环境设置


前言

在前面提到作者收到了新定义电子有限公司提供的NBK-RD8x3x核心开发板以及NBK-EBS001触控拓展板,由于新定义仅提供了基于Keil的开发包,本文将在此基础上将一部分代码移植到SDCC,也算对上篇文章的填坑。


一、背景

1. SDCC (Small Device C Compiler)

为什么需要使用SDCC?原因在于相较于昂贵的Keil,SDCC免费开源,遵循GPL-v2协议,同时支持多种MCU。SDCC支持的MCU包括:基于Intel MCS51 的MCU(8031、8032、8051、8052 等)、Maxim(以前称为 Dallas)DS80C390 变体、Freescale( 基于 HC08(HC08、S08)、基于 Zilog Z80 的 MCU(Z80、Z180、SM83、Rabbit 2000、2000A、3000A、TLCS-90)、Padauk(pdk14、pdk15)和 STMicroElectronics STM8 1,同时SDCC提供了完整的C语言标准库,包括I/O、数学、字符串处理等函数。此外,SDCC还支持使用汇编语言进行底层优化和嵌入到生成的代码中。SDCC在开源社区中广泛使用,适用于嵌入式系统开发、微控制器项目和单片机的应用。
SDCC与Keil语法拓展主要不同在于SFR,寄存器寻址,与中断关键字的不同:

项目SDCCKeil
扩展关键字名称以两个下划线开头,如__interrupt, __bit无需下划线
特殊功能寄存器(SFR)__sfr __at 0x80 Jcqmz;sfr Jcqmz = 0x80;
特殊功能寄存器位寻址__sbit __at 0x87 wei;sbit wei = Jcqmz ^ 7;
中断服务(ISR)函数需要在main函数前声明不需要

2. 易码魔盒(RDEasyCodeCube)

cube

易码魔盒(简称魔盒)是新定义的一种代码自动生成工具集成了代码生成、引脚配置、时钟初始化、MCU选型,外设配置等功能,目的是简化开发过程,降低用户的开发门槛。
魔盒使用图形化编程,可以自动生成标准化的底层配置代码 、驱动代码、逻辑代码。
由于目前魔盒仅支持生成Keil工程,SDCC用户需要自行按照新定义提供的BSP,转义,编译。
因此先利用生成Keil工程,再对Keil工程进行改造即可完成移植,整个过程大致如下图所示。

Keil工程
魔盒
关键字替换
SDCC

二、代码时间

本文主要介绍第一个移植任务:使用SDCC开发一个驱动LED的程序

1. 工程生成

首先进入魔盒,在MCU筛选 中选择欲开发的单片机型号,在此选择开发板板载MCU——RD8T36P48
MCU
随后点击点击这里开始工程
project
project_generate

接下来还需设置系统时钟和管脚功能:
在此开发板外置32MHz振荡器作为系统时钟, 按照NBK开发板PCB 2 , 以及触控评估板PCB3对针脚设置:
footsp
footsp2

2. 关键字转换

使用魔盒生成Keil工程后,开始修改关键字,幸运的是已经有对应的小工具帮助完成这项工作:Keil-C51-C-to-SDCC-C-Converter4
converter

  • 蓝框: 填入对应单片机头文件,这里填入内容:RD8T36x_C.h
  • 红框:Keil c文件,这里转换gpio文件:rd8_gpio.c
  • 绿框:最终获得的SDCC文件

可以看到 SFR与SBIT已被替换
注意: 若提示缺少compiler.h,可从此下载

3. 编译

为了点亮开发板上的LED,编写一些基础函数:

  • gpio初始函数
void led_init(void) {
    GPIO_Init(GPIO0, GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_5|GPIO_PIN_6,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO5, GPIO_PIN_0|GPIO_PIN_1,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO4, GPIO_PIN_6|GPIO_PIN_1|GPIO_PIN_0,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO3, GPIO_PIN_7|GPIO_PIN_3|GPIO_PIN_2|GPIO_PIN_1,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO2, GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO0, GPIO_PIN_0|GPIO_PIN_1,GPIO_MODE_OUT_PP);
	
	GPIO_WriteHigh(GPIO0, GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_5|GPIO_PIN_6);
	GPIO_WriteHigh(GPIO5, GPIO_PIN_0|GPIO_PIN_1);
	GPIO_WriteHigh(GPIO4, GPIO_PIN_6|GPIO_PIN_1|GPIO_PIN_0);
	GPIO_WriteHigh(GPIO3, GPIO_PIN_7|GPIO_PIN_3|GPIO_PIN_2|GPIO_PIN_1);
	GPIO_WriteHigh(GPIO2, GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6);
	GPIO_WriteHigh(GPIO0, GPIO_PIN_0|GPIO_PIN_1);
}
  • LED状态设置函数
void LED_ShowSet(unsigned char LED, LED_STEAE_ENUM State)
{
	switch(LED)
	{
		case 1:
			LED1 = !State;
			break;
		case 2:
			LED2 = !State;
			break;
		case 3:
			LED3 = !State;
			break;
		case 4:
			LED4 = !State;
			break;
		case 5:
			LED5 = !State;
			break;
		case 6:
			LED6 = !State;
			break;
		case 7:
			LED7 = !State;
			break;
		case 8:
			LED8 = !State;
			break;
		case 9:
			LED9 = !State;
			break;
		case 10:
			LED10 = !State;
			break;
		case 11:
			LED11 = !State;
			break;
		case 12:
			LED12 = !State;
			break;
		case 13:
			LED13 = !State;
			break;
		case 14:
			LED14 = !State;
			break;
		case 15:
			LED15 = !State;
			break;
		case 16:
			LED16 = !State;
			break;
		case 17:
			LED17 = !State;
			break;
		case 18:
			LED18 = !State;
			break;
		case 19:
			LED19 = !State;
			break;
		case 20:
			LED20 = !State;
			break;
		
	}
}

完整的代码如下:

// blink.c
#include <rd8_gpio.h>

typedef enum 
{
	LED_DI = 0,
	LED_EN = 1
}LED_STEAE_ENUM;

#define LED1 P23
#define LED2 P22
#define LED3 P31
#define LED4 P32
#define LED5 P33
#define LED6 P37
#define LED7 P40
#define LED8 P41
#define LED9 P46
#define LED10 P51
#define LED11 P50
#define LED12 P06
#define LED13 P05
#define LED14 P03
#define LED15 P02
#define LED16 P01
#define LED17 P24
#define LED18 P25
#define LED19 P26
#define LED20 P00

void led_init(void) {
    GPIO_Init(GPIO0, GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_5|GPIO_PIN_6,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO5, GPIO_PIN_0|GPIO_PIN_1,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO4, GPIO_PIN_6|GPIO_PIN_1|GPIO_PIN_0,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO3, GPIO_PIN_7|GPIO_PIN_3|GPIO_PIN_2|GPIO_PIN_1,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO2, GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO0, GPIO_PIN_0|GPIO_PIN_1,GPIO_MODE_OUT_PP);
	
	GPIO_WriteHigh(GPIO0, GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_5|GPIO_PIN_6);
	GPIO_WriteHigh(GPIO5, GPIO_PIN_0|GPIO_PIN_1);
	GPIO_WriteHigh(GPIO4, GPIO_PIN_6|GPIO_PIN_1|GPIO_PIN_0);
	GPIO_WriteHigh(GPIO3, GPIO_PIN_7|GPIO_PIN_3|GPIO_PIN_2|GPIO_PIN_1);
	GPIO_WriteHigh(GPIO2, GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6);
	GPIO_WriteHigh(GPIO0, GPIO_PIN_0|GPIO_PIN_1);
}

void LED_ShowSet(unsigned char LED, LED_STEAE_ENUM State)
{
	switch(LED)
	{
		case 1:
			LED1 = !State;
			break;
		case 2:
			LED2 = !State;
			break;
		case 3:
			LED3 = !State;
			break;
		case 4:
			LED4 = !State;
			break;
		case 5:
			LED5 = !State;
			break;
		case 6:
			LED6 = !State;
			break;
		case 7:
			LED7 = !State;
			break;
		case 8:
			LED8 = !State;
			break;
		case 9:
			LED9 = !State;
			break;
		case 10:
			LED10 = !State;
			break;
		case 11:
			LED11 = !State;
			break;
		case 12:
			LED12 = !State;
			break;
		case 13:
			LED13 = !State;
			break;
		case 14:
			LED14 = !State;
			break;
		case 15:
			LED15 = !State;
			break;
		case 16:
			LED16 = !State;
			break;
		case 17:
			LED17 = !State;
			break;
		case 18:
			LED18 = !State;
			break;
		case 19:
			LED19 = !State;
			break;
		case 20:
			LED20 = !State;
			break;
		
	}
}

void main(void) {
    led_init();
    int i=0; 
    while(1) {
        for (i=1; i<=20; i++) {
            LED_ShowSet(i, LED_EN);
        }
    }
}

由于SDCC一次只可编译一个文件,对于本工程而言还需要分别编译链接:

# output rd_gpio.rel
$ sdcc -c rd_gpio.c
# blink.c contain main()
$ sdcc blink.c rd_gpio.rel

由于SDCC默认将输出Intel Hex文件(.ihx),为了烧入还需要将ihx文件转换为hex

$ packihx blink.ihx > blink.hex

4. 烧录

获得hex文件之后,接下来即可使用NBK ISP烧录了:
在这里插入图片描述

四. 结果

灯
可以看到开发板上的灯已被全部点亮了

总结

本文介绍了在NBK开发板上,Keil移植SDCC的基本流程,然后可以看到相较于Keil IDE的直接,SDCC工作流相对复杂,接下来将使用CMAKE对移植流程使用cmake进行优化。

参考


  1. SDCC Home ↩︎

  2. NBK开发板开发资源 ↩︎

  3. NBK触控评估板资源 ↩︎

  4. Keil转换SDCC ↩︎

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值