GD32E10x官方例程入门:从GPIO点灯到串口调试

发布时间:2026/11/5 13:58:14
GD32E10x官方例程入门:从GPIO点灯到串口调试 简介这份GD32E10x系列官方例程面向嵌入式硬件与单片机开发者基于ARM Cortex-M3内核汇集兆易创新GD32E10x的示例代码适合工业控制、消费电子、通信设备等场景的学习、验证与二次开发。压缩包共935个文件约11.16MB以288个h头文件、261个c源文件为主并配套37个Keil uvproj工程、36套IAR ewp/ewd工程及说明文档、启动文件、Makefile和少量PDF资料覆盖外设初始化、中断处理、驱动与应用程序等层次。已有880人学习说明其在入门与项目参考方面具有一定关注度。内容围绕时钟配置、GPIO、串口、ADC、定时器、CAN、USB等模块展开提供LED闪烁、通信采样等典型示例便于读者对照工程结构理解GD32E10x的寄存器与外设库用法缩短从熟悉芯片到搭建原型的时间也可作为STM32同类开发迁移时的参考。1. 从一颗会眨眼的小灯说起GD32E10x 官方例程到底是什么很多人第一次听到 GD32E10x 官方例程这个名字脑子里冒出来的画面是一堆打不开的.c文件和一屏看不懂的寄存器名还没开始就想关掉网页。说白了一点都不玄GD32E10x 是一颗基于 Cortex-M4 内核的单片机芯片而官方例程就是随芯片一起放出来的“现成作业本”——点灯、按键、串口收发、定时器计时、ADC 采样这些最基础的动作别人已经写好、编译过、在真实板子上跑通过一遍你下载下来照着跑就行。它解决的是零基础最痛的那个问题手里有板子、会一点 C 语言却完全不知道该先敲哪一行代码。这份东西适合刚接触嵌入式硬件、想真正让一颗芯片动起来的新手不适合急着做产品的人。2. 为什么新手该先读官方例程比啃手册快得多的入手路径刚拿到芯片资料的人通常会走进同一个死胡同先打开几百页的数据手册从第一页的引脚定义读起读到第三十页就开始犯困合上电脑什么也没记住。这不是你不够聪明而是顺序反了。手册天生是给“查”的不是给“读”的而例程天生是给“跑”的。先跑通一个能看见现象的例子再带着问题回去查手册效率完全是两个量级。这一章把“为什么先看例程”和“具体按什么顺序看”讲清楚后面几章才好动手。2.1 手册像字典例程像课本你可以把数据手册理解成一本字典它把每个寄存器的每一位都解释得清清楚楚但它不会告诉你“一个真实项目该从哪一步开始”。例程恰好补上了这一块——它是一份被拆成小步骤的完整流程。比如同样是配置一个引脚输出高电平手册告诉你“某寄存器的第 0 到 1 位控制模式”例程告诉你“先开时钟再配模式再写电平”一共三行代码顺序还给你排好了。字典查得到字课本教得会句子新手缺的是后者。我第一次接触这类芯片时犯过一个很典型的错误抱着手册硬啃了三天把时钟树的每一路分频都背了下来结果连一个灯都点不亮。后来是同事把例程里那二十几行main.c甩给我我照着抄了一遍、改了两个宏灯就亮了。那种“真的动起来了”的反馈比看三天手册管用得多。提示不要因为例程“看起来太简单”就跳过。简单的东西能跑通复杂的才有资格谈。2.2 例程里反复出现的四个动作时钟、引脚、外设、中断把官方例程包翻一遍你会发现不管哪个外设代码骨架几乎都是同一个套路来来回回就四个动作。看懂这四个动作你就看懂了八成例程开时钟任何外设在使用前都要先把它的时钟打开不开时钟你后面写的所有配置都会失效这是新手最常遇到的“代码没错但不生效”的根源。配引脚芯片的引脚大多身兼数职同一个引脚可以是普通输入输出也可以是串口的发送脚、定时器的输出脚。你要明确告诉它“这一次我要你当什么”。初始化外设设置波特率、工作模式、分频系数这类参数把外设从默认状态调成你要的状态。使能并处理最后打开外设然后在主循环或者中断服务函数里处理数据。这个套路不是死记硬背的教条而是一条检查清单。以后你写任何一段新代码跑不通的时候按这四步从头捋一遍绝大多数问题当场就露馅了。2.3 我建议的阅读顺序先跑通再回头读例程包里的文件夹通常是按外设名字排的字母顺序看着很整齐但绝对不是学习顺序。按字母读你很可能第一个打开的是 ADC第二个是 CAN两个都看不懂直接放弃。入门的话建议按这个顺序推进先 GPIO 点灯和按键这是唯一能立刻看见现象的外设负责给你信心再串口因为串口是你后面调试所有东西的“眼睛”越早点亮越好然后是定时器和中断这两个决定了你能不能写出“不卡死”的程序最后再碰 ADC、SPI、I2C、DMA 这些需要外部器件配合的外设。至于 USB、以太网这类复杂外设等你能独立写完一个小项目再回头看不然只会浪费时间。这个顺序背后的逻辑很简单先学能自己验证的再学需要别人配合的。点灯你自己就能看见串口你自己就能收到而 SPI 通信需要另一颗芯片配合出问题时你根本分不清是发送端错了还是接收端错了。3. 第一个例程怎么跑从打开工程到板子上的灯真的亮前面讲的都是心态和路线这一章开始动手。整个过程其实只有四件事认清文件夹、装好工具、打开工程、编译下载。真正卡住新手的往往不是写代码而是“工程打不开”“编译报一堆错”“下载成功但没反应”这三关。下面把每一关都拆开讲。3.1 先认清文件夹官方例程包一般长什么样解压之后你会看到一堆名字相似的目录第一次看确实容易懵。它们的典型分工是这样的目录/文件作用新手要不要动内核与启动文件目录启动汇编文件、内核相关头文件不要动外设固件库目录每个外设一个.c文件封装了寄存器操作只读不改例程目录按外设分文件夹每个外设一个可编译的小工程主要看这里工程模板目录一个空壳工程方便你新建项目后面自己写代码时用说明文档每个例程配套的简短说明跑之前扫一眼新手最容易犯的错是把“外设固件库目录”当成学习材料去逐个文件读。那些文件是给编译器看的不是给你看的几百个函数读下来只会崩溃。你要盯住的是例程目录里那个main.c通常只有几十行那才是精华。3.2 动手前要准备的三样东西第一样是开发环境。常见的做法是装一个集成开发环境IDE再单独安装这颗芯片的器件支持包两者缺一不可。只装 IDE 不装支持包打开工程会提示找不到器件编译按钮直接变灰。这一步装完建议先重启一次软件很多人卡在这里是因为缓存没刷新。第二样是例程包本身。下载后解压到一个路径里不带中文和空格的目录比如D:\work\gd32_demo不要放在桌面或者“我的文档”下面。这是血泪经验有些编译工具对中文路径处理得很糟糕报的错还特别莫名其妙你在代码里找半天其实是路径的锅。第三样是硬件。一块开发板、一根能传数据的 USB 线有些线只能充电插上去电脑毫无反应、以及板载的调试下载器。如果你还准备了 USB 转串口模块先放着等第 4 章讲串口时再拿出来。3.3 第一个能跑的例子让板子上的小灯闪起来找到 GPIO 相关的例程目录打开工程文件先别急着改代码直接点编译。如果编译结果是 0 错误说明环境和工程是匹配的这一步就成功了一大半。然后点下载看板子上有没有灯开始闪。如果例程本身写得比较绕你也可以在模板工程里自己写一份最小代码逻辑更清楚#include gd32e10x.h /* 软件延时只用于第一个点灯实验正式项目请换成定时器 */ static void delay_ms(uint32_t ms) { for (uint32_t i 0; i ms; i) { for (uint32_t j 0; j 8000; j) { __NOP(); /* 空操作防止循环被编译器整体优化掉 */ } } } int main(void) { /* 第一步打开 GPIOC 的时钟不开时钟后面所有配置都不生效 */ rcu_periph_clock_enable(RCU_GPIOC); /* 第二步把 PC13 配成推挽输出速度 50MHz 对点灯完全够用 */ gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13); while (1) { gpio_bit_set(GPIOC, GPIO_PIN_13); /* 输出高电平 */ delay_ms(500); /* 亮 500 毫秒 */ gpio_bit_reset(GPIOC, GPIO_PIN_13); /* 输出低电平 */ delay_ms(500); /* 灭 500 毫秒 */ } }这段代码里几个参数值得说清楚。rcu_periph_clock_enable()的参数是你要开哪一路时钟这里传RCU_GPIOC表示 C 端口用哪个端口就换成哪个写错了不会有任何报错只是灯永远不亮。gpio_init()的四个参数依次是端口、模式、速度、引脚号。模式里的GPIO_MODE_OUT_PP是推挽输出能主动输出高电平和低电平驱动 LED 就用它速度参数在点灯场景下随便选它影响的是引脚翻转的陡峭程度只有在高频通信里才需要认真挑。引脚号可以按位或比如GPIO_PIN_13 | GPIO_PIN_14就是同时配置两个脚。注意函数名以你手上那份固件库为准不同版本的库函数命名可能略有差异。编译报“未定义标识符”时先去库里搜一下同名函数不要硬改。还有一点很多人想不到灯亮还是灯灭取决于板子上 LED 的接法。如果 LED 一端接电源、一端接引脚共阳接法那么输出低电平才是亮反过来共阴接法输出高电平才亮。所以你写“高电平点亮结果灯是灭的”先别怀疑代码有可能只是接法相反把set和reset对调一下试试。3.4 编译通过但灯不亮按这个顺序查第一看下载是否真的成功。有些 IDE 会弹出“下载完成”但实际目标芯片根本没连上尤其是调试器驱动没装好的时候。重新点一次下载看有没有报错信息。第二看程序是否停在启动阶段。可以在main函数第一行下个断点如果连断点都停不住说明程序压根没跑起来问题在启动文件或者工程配置不在你的代码。第三核对引脚号。开发板的原理图上用户 LED 接的可能是 PC13也可能是 PA5、PB0每个板子都不一样。照着例程抄代码之前先花两分钟看一眼原理图能省掉半小时的自我怀疑。第四确认时钟真的开了。这是最高频的翻车点配置写得漂漂亮亮唯独忘了开时钟寄存器写进去跟写进空气一样毫无反应。4. 从点亮到好用时钟、GPIO 和串口这三件事灯会闪了说明工具链通了。但从“会点灯”到“能写点有用的东西”中间还隔着三块必须迈过去的台阶时钟、引脚模式、串口打印。这一章把这三块讲透学完你就能自己写一个“按键控制灯、同时把状态打印到电脑上”的小程序这在新手阶段已经算一个完整项目了。4.1 时钟先让芯片心跳起来别急着写业务芯片里所有外设都要吃时钟就像所有机器都要通电。上电之后芯片会先跑在一个内部的低速时钟上这个时钟精度一般、频率也不高够芯片“活着”但喂不饱串口和定时器。所以在正式代码里第一件事通常是把系统时钟切到更高的频率上——这个动作一般由启动阶段的系统初始化函数完成你不用自己写但要知道它存在。为什么必须知道因为所有跟“时间”相关的参数都建立在时钟频率之上。串口波特率是按时钟算出来的定时器的计数周期也是按时钟算出来的。如果系统时钟配错了串口输出的全是乱码定时器的时间会莫名差好几倍而代码看起来毫无问题。新手遇到“波特率明明设的 115200收到一堆乱码”第一反应应该是去查时钟配置而不是反复改波特率。具体怎么查在系统初始化相关的那份源文件里找到设置时钟的那段代码看它选了哪个时钟源、倍频到多少。如果你不确定就老实沿用官方例程里的配置别自己改。等你能独立读懂了再去动它。4.2 GPIO一个引脚能有几种身份引脚是芯片和外界打交道的唯一通道而它大多数时候不是“一种功能”而是“一组候选功能”。同一个引脚可以当普通输入读按键可以当普通输出点灯可以交给串口当发送脚也可以交给定时器输出 PWM 波。你要做的是在初始化时明确选一个身份。模式典型用途新手常见误用推挽输出驱动 LED、驱动小电流器件用来读按键永远读到固定值开漏输出多个器件共用一条总线不加外部上拉什么都读不到浮空输入外部电路自己有上下拉时使用直接接按键读数乱跳上拉/下拉输入接按键、接开关上拉下拉选反按键逻辑颠倒复用推挽串口、SPI 这类外设占用引脚忘了配复用外设完全没输出模拟输入ADC 采样配成数字输入采不到真实电压这张表不用背用的时候回来对一眼就行。真正要建立的意识是每次用引脚之前先问自己一句“这次它该当什么”。按键读不到、串口发不出、PWM 没波形十有八九是这一步没设对。按键还有一个绕不开的话题叫抖动。机械按键在按下和松开的瞬间电平会剧烈跳动几毫秒你的程序可能一瞬间读到十几个“按下”。解决办法要么是加一个小延时再读一次确认要么用定时器每隔几毫秒扫描一次。新手阶段用简单延时确认就够了别一上来就搞复杂的状态机。4.3 串口打印给自己装一双眼睛如果说点灯是给板子装了个喇叭那串口就是给板子装了个显示器。有了它你能把变量的值、程序的执行流程、出错的位置全部打印到电脑上调试效率提升的不是一点半点。做法是配置一个串口然后重定向标准输出函数让printf走串口发出去#include gd32e10x.h #include stdio.h /* 重定向 printf 的底层发送函数注意工程选项里要勾选 MicroLIB */ int fputc(int ch, FILE *f) { usart_data_transmit(USART0, (uint8_t)ch); /* 等待发送缓冲区空不等待会丢字符输出变成一堆残缺的乱码 */ while (RESET usart_flag_get(USART0, USART_FLAG_TBE)) { } return ch; } void log_init(void) { rcu_periph_clock_enable(RCU_GPIOA); /* 串口引脚所在端口的时钟 */ rcu_periph_clock_enable(RCU_USART0); /* 串口外设本身的时钟两个都要开 */ /* PA9 作发送、PA10 作接收这里按复用推挽配置 */ gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10); usart_baudrate_set(USART0, 115200U); /* 必须和电脑端串口工具一致 */ usart_word_length_set(USART0, USART_WL_8BIT); /* 8 位数据位 */ usart_stop_bit_set(USART0, USART_STB_1BIT); /* 1 位停止位 */ usart_parity_config(USART0, USART_PM_NONE); /* 无校验 */ usart_transmit_config(USART0, USART_TRANSMIT_ENABLE); usart_receive_config(USART0, USART_RECEIVE_ENABLE); usart_enable(USART0); /* 最后使能顺序别调 */ } int main(void) { log_init(); printf(hello, board is running\r\n); while (1) { } }几个参数解释一下。波特率 115200 是电脑端和板子端必须完全一致的约定两边差一点都会乱码。数据位 8、停止位 1、无校验这三项组成的组合俗称“8N1”是最通用的配置新手直接用这套就行。fputc里那个等待缓冲区空的循环不能省省掉之后高速打印时会丢字符输出的内容断断续续你会误以为是程序逻辑出了问题。在电脑这一侧你需要一个串口工具选对端口号设备管理器里能看到波特率设成 115200就能看到打印内容了。如果收到的是乱码按顺序检查三件事波特率是否一致、系统时钟是否配错、发送脚是否配成了复用模式。4.4 中断让芯片学会被打断轮询的写法是“我一直在问你好了没有”中断的写法是“你好了主动喊我”。按键、串口接收、定时器到点这些场景都适合用中断。新手第一次接触中断最容易在两件事上翻车一是中断服务函数的名字必须和启动文件里的名字一字不差写错了不会报错中断就是进不去二是中断里不能干重活打印、延时、死循环都别放进去否则整个系统像卡住一样。配置顺序一般是配好引脚和触发方式比如下降沿触发在中断控制器里打开对应的通道并设置优先级最后在中断服务函数里做最少量的处理比如只置一个标志位真正的活留给主循环干。这个“中断只置标志、主循环做处理”的习惯越早养成越好后面写多任务时才不会乱。5. 新手避坑五个最容易翻车的瞬间这一章专门写给“代码看着没问题就是不工作”的人。下面五条是新手阶段出现频率最高的坑每条都按“现象、原因、解决”写清楚中招了直接对照查。5.1 工程与环境相关的两个坑坑一打开工程就报一堆找不到文件的错。现象是编译输出里几十条“cannot open source input file”红色一片。原因通常有两个例程包解压路径带了中文或空格或者工程里用的是相对路径而你只复制了工程文件、没复制同级目录下的库文件。解决办法是把整个例程包完整解压到纯英文短路径下再打开工程如果还是报错检查工程设置里的头文件包含路径确认每一条都指向真实存在的目录。坑二编译零错误下载也提示成功但板子毫无反应。现象是灯不闪、串口没输出怎么改代码都没用。原因多半是下载器没真正连上目标芯片或者工程里选的芯片型号和板上实际型号不一致。解决方法是先点一次“连接/读取芯片 ID”能读到才说明链路是通的再核对工程配置里的器件型号型号选错时编译能过但下载进去的机器码跑不起来。5.2 代码与硬件相关的三个坑坑三串口打印全是乱码。现象是电脑上收到一堆看不懂的符号或者方块。原因按概率排序波特率两边不一致、系统时钟配置和预期不符、发送引脚没配成复用模式。解决方法是先把两边波特率都设成 115200 再试仍然乱码就去核对时钟配置最后检查引脚模式普通输出模式是发不出串口波形的。坑四按键读到的值乱跳按一次触发好几次。现象是打印出来的按键状态忽高忽低。原因是机械按键的抖动加上引脚配成了浮空输入电平没有确定参考。解决办法是把引脚改成上拉或下拉输入取决于按键另一端接电源还是接地再在检测到变化后加几毫秒延时重新确认一次。这一步做完抖动能压掉九成。坑五中断进不去或者进去一次就再也不出来了。现象是打了断点却从不命中或者程序跑飞。原因通常是中断服务函数名和启动文件里的名字不匹配或者中断里忘了清除中断标志位导致芯片一直以为中断还没处理完。解决办法是去启动文件里复制那个函数名一个字都别自己拼再确认中断服务函数里做了标志位清除动作。提示这五条坑的共同点是“代码看起来完全正确”。所以排查时不要盯着代码反复读要按“环境、配置、硬件、代码”的顺序一层层往下剥先把不可能的排除掉。6. 下一步学什么从跟着例程跑到写出自己的第一个驱动跑通点灯和串口之后很多人会陷入第二个迷茫期例程都会跑了然后呢我的建议是别再继续“顺着目录一个个跑”而是挑一个小目标把它完整做出来。目标可以很小比如“按键按一下灯亮、再按一下灯灭同时把按键次数打印到串口”。这个目标同时用到了引脚输入输出、中断或轮询、串口打印是一个完整的闭环。做完它你对这套东西的掌握程度会明显超过跑十个例程。再往后按这个路径推进比较稳阶段学什么判断自己过关的标准第一阶GPIO 输入输出、软件延时能不看例程独立写出点灯和按键第二阶串口收发、printf重定向能自己打印变量并定位一个逻辑错误第三阶定时器、中断、中断优先级能写出不卡死主循环的定时任务第四阶ADC 采样、PWM 输出能读一个电位器、调一个灯的亮度第五阶SPI/I2C 接外部器件、DMA能读懂外部器件的时序图并对着写驱动每一阶都有个共同要求先自己写写不出来再看例程。顺序反过来你永远只能抄。我见过太多人例程跑得飞快一到自己写就大脑空白原因就是从没经历过“卡住、想不通、最后自己解决”这个过程而这个过程中的挫败感恰恰是最有价值的部分。还有个小技巧值得单独说给自己准备一个“最小工程模板”。把时钟配置、串口打印、延时函数这些每个项目都要用的东西放在一个干净的空工程里以后开新项目直接复制它能省掉大量重复劳动和重复踩坑。这个模板不用一次做完每次踩了新坑就补一条进去半年后它会变成你最顺手的工具。从那以后我每次开新项目都强制先把最小工程跑一遍灯闪不闪、串口打不打得出来、时钟配置对不对。这三件事任何一件不过关我就绝不动业务代码——因为在一个地基没打好的工程上debug浪费的时间足够你把地基重新打三遍。希望帮到你。本文还有配套的精品资源点击获取