Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
GPIO
PIN_GPIO通用驱动
搞懂rt-thread对STM32的GPIO操作
发布于 2024-05-14 14:10:03 浏览:541
订阅该版
先看STM32数据手册中,GPIO的寄存器映射: ![GPIO地址映射](https://oss-club.rt-thread.org/uploads/20240514/95feb7f825a3fb7e80dbecd00025d3d9.png) 至少有两点可以确定: 1. 从GPIOA到GPIOH,地址是连续的 2. 每组GPIO基地址相差`0x400` 依据这,rt-thread在给GPIO编号的时候,给每组port定义一个偏移,偏移单位是`0x400` |port| 偏移几个单位 | |--|--| | GPIOA | 0 | |GPIOB|1| |GPIOC|2| |...|...| 比如,知道了GPIO的基地址是`0x48000000`,那么GPIOB的基地址是 ```c 0x48000000 + 0x400 * 1 ``` rt-thread中给GPIO的编号规则是这样的: |pin| number | |--|--| | PA0~PA15 | 0~15 | |PB0~PB15|16~31| |PC0~PC15|32~47| |...|...| drv_gpio.c文件中有如下代码: ```c #define PIN_NUM(port, no) (((((port) & 0xFu) << 4) | ((no) & 0xFu))) #define PIN_PORT(pin) ((uint8_t)(((pin) >> 4) & 0xFu)) #define PIN_NO(pin) ((uint8_t)((pin) & 0xFu)) ... #define PIN_STPORT(pin) ((GPIO_TypeDef *)(GPIOA_BASE + (0x400u * PIN_PORT(pin)))) #define PIN_STPIN(pin) ((uint16_t)(1u << PIN_NO(pin))) ``` 比如:有一个pin的编号是33,经过以下宏运算 `PIN_PORT(33) ` 结果是`2` 相当于除16的结果 `PIN_NO(33)` 结果是`1` 相当于除16的余数 `PIN_STPORT(33)` 结果是`(GPIO_TypeDef *)(GPIOA_BASE + (0x400u * 2))`,近一步宏替换后是`(GPIO_TypeDef*)(0x48000800)`,这与官方手册和HAL库中定义是匹配的 `PIN_STPIN(33)` 结果是`(uint16_t)(1)` 所以,`33`对应的是`PC1` 相反地,知道管脚名得到编号就是这样的: ```c #define GET_PIN(PORTx,PIN) (rt_base_t)((16 * ( ((rt_base_t)__STM32_PORT(PORTx) - (rt_base_t)GPIOA_BASE)/(0x0400UL) )) + PIN) // 摘自drv_gpio.h ``` 比如 `GET_PIN(C, 1)`,一步步替换宏定义后 ```c (rt_base_t)((16 * ( ((rt_base_t)GPIOC_BASE - (rt_base_t)GPIOA_BASE)/(0x0400UL) )) + 1) // 替换__STM32_PORT(C) (rt_base_t)((16 * ( (0x48000800 - 0x48000000)/(0x0400UL) )) + 1) // 替换GPIOX_BASE (rt_base_t)((16 * ( 2 )) + 1) (rt_base_t)((32) + 1) ``` 显然结果是`33` `rt_pin_mode`, `rt_pin_write`, `rt_pin_read`等系统API都是都是基于pin编号来操作的 ```c rt_pin_write(33, 0) < = > HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET); ``` drv_gpio.c中 ```c static void stm32_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value) { GPIO_TypeDef *gpio_port; uint16_t gpio_pin; if (PIN_PORT(pin) < PIN_STPORT_MAX) { gpio_port = PIN_STPORT(pin); gpio_pin = PIN_STPIN(pin); HAL_GPIO_WritePin(gpio_port, gpio_pin, (GPIO_PinState)value); } } ``` pin.c中 ```c int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void *user_data) { _hw_pin.parent.type = RT_Device_Class_Miscellaneous; _hw_pin.parent.rx_indicate = RT_NULL; _hw_pin.parent.tx_complete = RT_NULL; ... _hw_pin.ops = ops; _hw_pin.parent.user_data = user_data; /* register a character device */ rt_device_register(&_hw_pin.parent, name, RT_DEVICE_FLAG_RDWR); return 0; } ... void rt_pin_write(rt_base_t pin, rt_base_t value) { RT_ASSERT(_hw_pin.ops != RT_NULL); _hw_pin.ops->pin_write(&_hw_pin.parent, pin, value); } ``` pin.c文件中定义了一个`rt_device_pin`类型的变量`_hw_pin`,初始化注册的时候,其成员变量`ops`初始化为`_stm32_pin_ops` ```c const static struct rt_pin_ops _stm32_pin_ops = { stm32_pin_mode, stm32_pin_write, stm32_pin_read, stm32_pin_attach_irq, stm32_pin_dettach_irq, stm32_pin_irq_enable, stm32_pin_get, }; ... int rt_hw_pin_init(void) { ... return rt_device_pin_register("pin", &_stm32_pin_ops, RT_NULL); } ``` `rt_pin_write` -> `_hw_pin.ops->pin_write` -> `stm32_pin_write` -> `HAL_GPIO_WritePin`
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
Z_Y
这家伙很懒,什么也没写!
文章
11
回答
41
被采纳
1
关注TA
发私信
相关文章
1
drivers- pin
2
bsp 里面的drivers/gpio.c 少了一个功能
3
stm32f407移植RTT中gpio设备驱动问题
4
config PB4(NJTRST) to GPIO
5
RT-Thread的GPIO设备驱动问题
6
关于pin.c文件中语句可能出现的bug
7
RT-Thread学习笔记--线程创建与官方Pin设备驱动调用
8
【应用笔记】小白也能玩转RT-Thread之通用GPIO设备【官方出品
9
串口引脚定义中的GPIO_Pin_sources是社么意思?
10
RTT -GPIO 使用例程
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
ulog
C++_cpp
at_device
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
13
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
本月文章贡献
程序员阿伟
8
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
5
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部