0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

第五章 GPIO输出——使用固件库点亮LED

W55MH32 来源:W55MH32 作者:W55MH32 2025-05-22 16:34 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

单芯片解决方案,开启全新体验——W55MH32 高性能以太网单片机

W55MH32是WIZnet重磅推出的高性能以太网单片机,它为用户带来前所未有的集成化体验。这颗芯片将强大的组件集于一身,具体来说,一颗W55MH32内置高性能Arm® Cortex-M3核心,其主频最高可达216MHz;配备1024KB FLASH与96KB SRAM,满足存储与数据处理需求;集成TOE引擎,包含WIZnet全硬件TCP/IP协议栈、内置MAC以及PHY,拥有独立的32KB以太网收发缓存,可供8个独立硬件socket使用。如此配置,真正实现了All-in-One解决方案,为开发者提供极大便利。

在封装规格上,W55MH32 提供了两种选择:QFN100和QFN68。

W55MH32L采用QFN100封装版本,尺寸为12x12mm,其资源丰富,专为各种复杂工控场景设计。它拥有66个GPIO、3个ADC、12通道DMA、17个定时器、2个I2C、5个串口、2个SPI接口(其中1个带I2S接口复用)、1个CAN、1个USB2.0以及1个SDIO接口。如此丰富的外设资源,能够轻松应对工业控制中多样化的连接需求,无论是与各类传感器、执行器的通信,还是对复杂工业协议的支持,都能游刃有余,成为复杂工控领域的理想选择。 同系列还有QFN68封装的W55MH32Q版本,该版本体积更小,仅为8x8mm,成本低,适合集成度高的网关模组等场景,软件使用方法一致。更多信息和资料请进入http://www.w5500.com/网站或者私信获取。

此外,本W55MH32支持硬件加密算法单元,WIZnet还推出TOE+SSL应用,涵盖TCP SSL、HTTP SSL以及 MQTT SSL等,为网络通信安全再添保障。

为助力开发者快速上手与深入开发,基于W55MH32L这颗芯片,WIZnet精心打造了配套开发板。开发板集成WIZ-Link芯片,借助一根USB C口数据线,就能轻松实现调试、下载以及串口打印日志等功能。开发板将所有外设全部引出,拓展功能也大幅提升,便于开发者全面评估芯片性能。

若您想获取芯片和开发板的更多详细信息,包括产品特性、技术参数以及价格等,欢迎访问官方网页:http://www.w5500.com/,我们期待与您共同探索W55MH32的无限可能。

wKgZPGgbOfaANhwzACodXd3sVzg463.png

第五章 GPIO输出——使用固件库点亮LED

本章参考资料:《W55MH32-参考手册》GPIO和RCC章节、库帮助文档。

利用库建立好的工程模板,就可以方便地使用标准库编写应用程序了,可以说从这一章我们真正开始迈入固件库开发的大门。LED灯的控制使用到GPIO外设的基本输出功能。

5.1 硬件设计

在本教程中W55MH32芯片与LED灯的连接见图LED硬件原理图 :

wKgZO2gu3yGAfkuzAAA-YOD2HOc501.png

此电路为参考电路,这个LED灯的阴极都是连接到W55MH32的GPIO引脚,只要我们控制GPIO引脚的电平输出状态,即可控制LED灯的亮灭。若您使用的实验板LED灯的连接方式或引脚不一样, 只需根据我们的工程修改引脚即可,程序的控制原理相同。

5.2 软件设计

5.2.1 编程要点

1.使能GPIO端口时钟

2.初始化GPIO目标引脚为推挽输出模式;

3.编写简单测试程序,控制GPIO引脚输出高、低电平。

5.2.2 代码分析

1. 头文件与宏定义

#include < stdlib.h > #include < string.h > #include < stdio.h > #include "delay.h" #include "w55mh32.h" #define GPIO_GROUP_TEST GPIOB // 使用GPIOB #define GPIO_MODE_TEST GPIO_Mode_Out_PP // 推挽输出模式 #define GPIO_SPEED_TEST GPIO_Speed_50MHz // 50MHz速度 #define GPIO_PIN1_TEST GPIO_Pin_0 // 引脚0 #define GPIO_PIN2_TEST GPIO_Pin_2 // 引脚2 #define GPIO_PIN3_TEST GPIO_Pin_3 // 引脚3 USART_TypeDef *USART_TEST = USART1; // 使用USART1

头文件:包含标准库和自定义头文件(如延时和芯片相关库)。

宏定义:

GPIO_GROUP_TEST:指定使用 GPIOB。

GPIO_MODE_TEST:设置为推挽输出(GPIO_Mode_Out_PP),用于驱动外部设备(如 LED)。

GPIO_PIN1_TEST/Pin2/Pin3:定义三个输出引脚(PB0、PB2、PB3)。

串口配置:使用 USART1 进行通信。

2. 函数声明

void UART_Configuration(uint32_t bound); // 串口配置函数 void GPIO_Configuration(void); // GPIO配置函数

3. main 函数(主逻辑)

int main(void) { RCC_ClocksTypeDef clocks; delay_init(); // 初始化延时 UART_Configuration(115200); // 配置串口(波特率115200) RCC_GetClocksFreq(&clocks); // 获取系统时钟频率 // 打印系统时钟信息 printf("SYSCLK: %3.1fMhz, HCLK: %3.1fMhz, PCLK1: %3.1fMhz, PCLK2: %3.1fMhz, ADCCLK: %3.1fMhzn", (float)clocks.SYSCLK_Frequency / 1000000, ...); printf("GPIO IO Out Tset.n"); // 打印测试信息 GPIO_Configuration(); // 配置GPIO为输出 // 无限循环:流水灯效果 while (1) { // 依次点亮PB0 → PB2 → PB3 GPIO_SetBits(GPIOB, GPIO_Pin_0); delay_ms(200); GPIO_SetBits(GPIOB, GPIO_Pin_2); delay_ms(200); GPIO_SetBits(GPIOB, GPIO_Pin_3); delay_ms(200); // 依次熄灭PB0 → PB2 → PB3 GPIO_ResetBits(GPIOB, GPIO_Pin_0); delay_ms(200); GPIO_ResetBits(GPIOB, GPIO_Pin_2); delay_ms(200); GPIO_ResetBits(GPIOB, GPIO_Pin_3); delay_ms(200); } }

初始化:延时、串口、时钟频率获取。

串口输出:打印系统时钟信息和测试提示。

GPIO 配置:设置 GPIOB 的三个引脚为输出。

流水灯逻辑:

GPIO_SetBits:置高电平(熄灭 LED)。

GPIO_ResetBits:置低电平(点亮 LED)。

delay_ms(200):每个动作间隔 200ms,形成循环闪烁。

4. GPIO_Configuration 函数(GPIO 初始化)

void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 使能GPIOB时钟 // 配置PB0、PB2、PB3为推挽输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_3; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); // 初始化GPIOB }

时钟使能:启用 GPIOB 的时钟。

引脚配置:

引脚:PB0、PB2、PB3(通过位或运算同时配置)。

模式:推挽输出(GPIO_Mode_Out_PP),适合驱动 LED 等外设。

速度:50MHz(满足高频操作需求)。

5. UART_Configuration 函数(串口初始化)

void UART_Configuration(uint32_t bound) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; // 使能USART1和GPIOA时钟(PA9/TX, PA10/RX) RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); // 配置TX引脚(PA9):复用推挽输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 配置RX引脚(PA10):浮空输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); // 配置USART1参数 USART_InitStructure.USART_BaudRate = bound; // 波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 8位数据 USART_InitStructure.USART_StopBits = USART_StopBits_1; // 1位停止位 USART_InitStructure.USART_Parity = USART_Parity_No; // 无校验 USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // 收发模式 USART_Init(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE); // 使能USART1 }

引脚配置:

PA9(TX):复用推挽输出(用于发送数据)。

PA10(RX):浮空输入(用于接收数据)。

串口参数:115200 波特率、8 位数据、1 位停止位、无校验。

6. 串口输出函数(SER_PutChar 和 fputc)

int SER_PutChar(int ch) { while (!USART_GetFlagStatus(USART_TEST, USART_FLAG_TC)); // 等待发送完成 USART_SendData(USART_TEST, (uint8_t)ch); // 发送字符 return ch; } int fputc(int c, FILE *f) { if (c == 'n') SER_PutChar('r'); // 换行时添加回车(适配终端) return SER_PutChar(c); // 重定向printf到串口 }

SER_PutChar:通过 USART 发送单个字符,等待发送完成标志(USART_FLAG_TC)。

fputc:重定向 C 库的printf函数到串口,支持换行符(n)自动添加回车(r)。

5.2.3 下载验证

把编译好的程序下载到开发板并复位,可看到LED亮灭交互。

5.3 W55MH32标准库补充知识

5.3.1 SystemInit函数去哪了?

这个函数在W55MH32标准库的“system_w55mh32.c”文件中定义了,而我们的工程已经包含该文件。标准库中的SystemInit函数把芯片的系统时钟设置成了72MHz, 即此时AHB时钟频率为72MHz,APB2为72MHz,APB1为36MHz。当W55MH32芯片上电后,执行启动文件中的指令后,会调用该函数,设置系统时钟为以上状态。

5.3.2 断言

5.3.2.1 断言的作用

在 W55MH32 开发过程中,开发者编写的代码需要对各种参数和状态进行检查。断言提供了一种简单有效的方式,用于在代码中插入检查点,验证某些条件是否满足。如果条件不满足,断言会触发错误,帮助开发者快速定位和解决问题。具体见代码清单:GPIO输出-1 :

代码清单:GPIO输出-1 GPIO_Init函数的断言部分

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) { uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00; /* Check the parameters */ assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode)); assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin)); /* ------- 以下内容省略,跟前面我们定义的函数内容相同----- */

基本上每个库函数的开头都会有这样类似的内容,这里的“assert_param”实际是一个宏,在库函数中它用于检查输入参数是否符合要求, 若不符合要求则执行某个函数输出警告,“assert_param”的定义见代码清单:GPIO输出-2 :

代码清单:GPIO输出-2 w55mh32_conf.h文件中关于断言的定义

#ifdef USE_FULL_ASSERT /** * @brief assert_param 宏用于函数的输入参数检查 * @param expr:若expr值为假,则调用assert_failed函数 * 报告文件名及错误行号 * 若expr值为真,则不执行操作 */ #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) /* 错误输出函数 ------------------------------------------------------- */ void assert_failed(uint8_t* file, uint32_t line); #else #define assert_param(expr) ((void)0) #endif

这段代码的意思是,假如我们不定义“USE_FULL_ASSERT”宏,那么“assert_param”就是一个空的宏(#else与#endif之间的语句生效),没有任何操作。 从而所有库函数中的assert_param实际上都无意义,我们就当看不见好了。

假如我们定义了“USE_FULL_ASSERT”宏,那么“assert_param”就是一个有操作的语句(#if与#else之间的语句生效), 该宏对参数expr使用C语言中的问号表达式进行判断,若expr值为真,则无操作(void 0),若表达式的值为假, 则调用“assert_failed”函数,且该函数的输入参数为“__FILE__”及“__LINE__”, 这两个参数分别代表 “assert_param”宏被调用时所在的“文件名”及“行号”。

但库文件只对“assert_failed”写了函数声明,没有写函数定义,实际用时需要用户来定义, 我们一般会用printf函数来输出这些信息,见代码清单:GPIO输出-3 :

代码清单:GPIO输出-3 assert_failed 输出错误信息

void assert_failed(uint8_t * file, uint32_t line) { printf(“rn 输入参数错误,错误文件名=%s,行号=%s”,file,line); }

那么为什么函数输入参数不对的时候,assert_param宏中的expr参数值会是假呢?这要回到GPIO_Init函数,看它对assert_param宏的调用, 它被调用时分别以“IS_GPIO_ALL_PERIPH(GPIOx)”、“IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin)”等作为输入参数,也就是说被调用时, expr实际上是一条针对输入参数的判断表达式。例如“IS_GPIO_PIN”的宏定义:

#define IS_GPIO_PIN(PIN) ((PIN) != (uint32_t)0x00)

若它的输入参数 PIN 值为0,则表达式的值为假,PIN非0时表达式的值为真。 我们知道用于选择GPIO引脚号的宏“GPIO_Pin_x”的值至少有一个数据位为1, 这样的输入参数才有意义,若GPIO_InitStruct->GPIO_Pin的值为0,输入参数就无效了。配合“IS_GPIO_PIN”这句表达式, “assert_param”就实现了检查输入参数的功能。对assert_param宏的其它调用方式类似,大家可以自己看库源码来研究一下。

5.3.3 Doxygen注释规范

在W55MH32标准库以及我们自己编写的文件中,可以看到一些比较特别的注释,类似代码清单:GPIO输出-4:

代码清单:GPIO输出-4 Doxygen注释规范

/** * @brief 初始化控制LED的IO * @param 无 * @retval 无 */

这是一种名为“Doxygen”的注释规范,如果在工程文件中按照这种规范去注释,可以使用Doxygen软件自动根据注释生成帮助文档。 我们所说非常重要的库帮助文档

5.3.4 防止头文件重复包含

在W55MH32标准库的所有头文件以及我们自己编写的.h头文件中,可看到类似代码清单:GPIO输出-5的宏定义。 它的功能是防止头文件被重复包含,避免引起编译错误。

代码清单:GPIO输出-5 防止头文件重复包含的宏

#ifndef __LED_H #define __LED_H /*此处省略头文件的具体内容*/ #endif /* end of __LED_H */

在头文件的开头,使用“#ifndef”关键字,判断标号“__LED_H”是否被定义,若没有被定义,则从“#ifndef”至“#endif”关键字之间的内容都有效, 也就是说,这个头文件若被其它文件“#include”,它就会被包含到其该文件中了,且头文件中紧接着使用“#define”关键字定义上面判断的标号“__LED_H”。 当这个头文件被同一个文件第二次“#include”包含的时候, 由于有了第一次包含中的“#define __LED_H”定义,这时再判断“#ifndef__LED_H”, 判断的结果就是假了,从“#ifndef”至“#endif”之间的内容都无效,从而防止了同一个头文件被包含多次,编译时就不会出现“redefine(重复定义)”的错误了。

一般来说,我们不会直接在C的源文件写两个“#include”来包含同一个头文件,但可能因为头文件内部的包含导致重复,这种代码主要是避免这样的问题。

WIZnet 是一家无晶圆厂半导体公司,成立于 1998 年。产品包括互联网处理器 iMCU™,它采用 TOE(TCP/IP 卸载引擎)技术,基于独特的专利全硬连线 TCP/IP。iMCU™ 面向各种应用中的嵌入式互联网设备。

WIZnet 在全球拥有 70 多家分销商,在香港、韩国、美国设有办事处,提供技术支持和产品营销。

香港办事处管理的区域包括:澳大利亚、印度、土耳其、亚洲(韩国和日本除外)。

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • led
    led
    +关注

    关注

    243

    文章

    24447

    浏览量

    687572
  • GPIO
    +关注

    关注

    16

    文章

    1313

    浏览量

    55736
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    【「高速数字设计(基础篇)」阅读体验】第五章 去耦电容

    最近在啃《高速数字设计》,第五章“去耦电容:远交近攻”把高速电路里电源噪声的问题讲透了,对于做硬件设计的同学来说,这简直是“电源完整性”的入门必读。 为啥去耦电容是刚需? 数字IC切换逻辑状态
    发表于 11-19 20:35

    蜂鸟E203在黑金XC7A200T型FPGA上点亮LED并实现流水灯

    使用的GPIO口(共32个GPIO口,我们用到个,三个用于LED输出,两个用于中断触发)。 2、在main函数中完成对使用
    发表于 10-31 09:04

    RVMCU课堂「11」: 手把手教你玩转RVSTAR—GPIO使用篇

    GPIO是通用输入输出接口(General Purpose Input Output)的简称,是微控制器最基本也是最常用的外设,本期内容将介绍GPIO的基本原理,然后通过「点亮
    发表于 10-31 07:16

    第2 点亮你的LED

    本章的标题是点亮LED,虽然任务很简单,但是需要了解的单片机基础知识却很多,特别是对于初学者,刚开始要在头脑中建立一个单片机的概念,然后通过点亮一个LED小灯来增加初学者对单片机的兴趣
    的头像 发表于 10-13 15:52 318次阅读
    第2<b class='flag-5'>章</b>  <b class='flag-5'>点亮</b>你的<b class='flag-5'>LED</b>

    【创龙TLT113-MiniEVM开发板试用体验】点亮LED

    源(3.3V),负极连接GPIO引脚。 点亮条件 :GPIO输出低电平时形成电流通路(低电平驱动)或高电平驱动(根据电路设计)。 本开发板LED
    发表于 08-05 21:36

    【创龙TL3562-MiniEVM开发板试用体验】3、点亮LED

    0 > %s/brightness熄灭LED 三、通过其他GPIO点亮LED 从开发板板上找一个GPIO 就用
    发表于 07-29 16:06

    第五章 W55MH32 UDP示例

    本文介绍了在 W55MH32 芯片上实现 UDP 通信及数据回环测试的方法。阐述了 UDP 协议的概念、特点、应用场景、报文传输流程和报文结构,展示了实现过程,借助网络调试工具完成测试。
    的头像 发表于 07-24 09:13 666次阅读
    <b class='flag-5'>第五章</b> W55MH32 UDP示例

    【VisionFive 2单板计算机试用体验】GPIO点亮LED

    测试板卡GPIO点亮LED灯。 一、搭建环境 1.1、文档 按照官方的应用文档搭建测试环境GPIO点亮
    发表于 06-30 07:31

    RK3568驱动指南|第十二篇 GPIO子系统-第130 GPIO的调试方法

    RK3568驱动指南|第十二篇 GPIO子系统-第130 GPIO的调试方法
    的头像 发表于 06-03 11:32 999次阅读
    RK3568驱动指南|第十二篇 <b class='flag-5'>GPIO</b>子系统-第130<b class='flag-5'>章</b> <b class='flag-5'>GPIO</b>的调试方法

    AS32X601驱动系列教程 GPIO_点亮LED详解

    在嵌入式开发的奇妙旅程中,GPIO(通用输入输出接口)作为芯片与外部世界交互的重要桥梁,扮演着不可或缺的角色。从简单的 LED 灯控制,到复杂的外设通信,GPIO 的灵活运用为开发者打
    的头像 发表于 05-23 16:14 559次阅读
    AS32X601驱动系列教程 <b class='flag-5'>GPIO</b>_<b class='flag-5'>点亮</b><b class='flag-5'>LED</b>详解

    RK3568驱动指南|第十二篇 GPIO子系统-第135 GPIO子系统与pinctrl子系统相结合实验

    RK3568驱动指南|第十二篇 GPIO子系统-第135 GPIO子系统与pinctrl子系统相结合实验
    的头像 发表于 05-23 13:47 750次阅读
    RK3568驱动指南|第十二篇 <b class='flag-5'>GPIO</b>子系统-第135<b class='flag-5'>章</b> <b class='flag-5'>GPIO</b>子系统与pinctrl子系统相结合实验

    德赛西威第五代智能座舱G10PH硬件平台首发点亮

    2025上海国际车展盛大举行,全球汽车智能化科技焦点汇聚于此。德赛西威在展会现场展示重大技术突破——第五代智能座舱G10PH硬件平台成功首发点亮,距离该平台在今年1月国际消费电子展(CES)上全球首发仅时隔三个月。
    的头像 发表于 04-30 11:40 915次阅读

    HTR3310 10路LED驱动器和GPIO控制器中文手册

          HTR3310是一款10路多功能LED驱动器和GPIO控制器2.5V~5.5V电源供电。10个IO端口中的任何一个都可以配置为LED模式或GPIO模式。此外,任何
    发表于 04-14 16:31 2次下载

    HTR3316 16路LED驱动器和GPIO控制器中文手册

         HTR3316是一款16路多功能LED驱动器和GPIO控制器,2.5V~5.5V电源供电。16个IO端口中的任何一个都可以配置为LED模式或GPIO模式。此外,任何
    发表于 04-11 17:51 2次下载

    汽车电路初识

    第一 汽车电路分析基础第二 汽车电路图识读第三 典型汽车电器电路分析第四 汽车电路检修第五章 汽车电子电路图识读
    发表于 03-10 18:04 7次下载