2#include "ch32_gpio.hpp"
6uint32_t LibXR::ch32_get_gpio_periph(GPIO_TypeDef* port)
12 else if (port == GPIOA)
14 return RCC_APB2Periph_GPIOA;
18 else if (port == GPIOB)
20 return RCC_APB2Periph_GPIOB;
24 else if (port == GPIOC)
26 return RCC_APB2Periph_GPIOC;
30 else if (port == GPIOD)
32 return RCC_APB2Periph_GPIOD;
36 else if (port == GPIOE)
38 return RCC_APB2Periph_GPIOE;
45extern "C" void EXTI0_IRQHandler(
void) __attribute__((interrupt));
47extern "C" void EXTI0_IRQHandler(
void) { LibXR::CH32GPIO::CheckInterrupt(EXTI_Line0); }
50extern "C" void EXTI1_IRQHandler(
void) __attribute__((interrupt));
52extern "C" void EXTI1_IRQHandler(
void) { LibXR::CH32GPIO::CheckInterrupt(EXTI_Line1); }
55extern "C" void EXTI2_IRQHandler(
void) __attribute__((interrupt));
57extern "C" void EXTI2_IRQHandler(
void) { LibXR::CH32GPIO::CheckInterrupt(EXTI_Line2); }
60extern "C" void EXTI3_IRQHandler(
void) __attribute__((interrupt));
62extern "C" void EXTI3_IRQHandler(
void) { LibXR::CH32GPIO::CheckInterrupt(EXTI_Line3); }
65extern "C" void EXTI4_IRQHandler(
void) __attribute__((interrupt));
67extern "C" void EXTI4_IRQHandler(
void) { LibXR::CH32GPIO::CheckInterrupt(EXTI_Line4); }
70extern "C" void EXTI9_5_IRQHandler(
void) __attribute__((interrupt));
72extern "C" void EXTI9_5_IRQHandler(
void)
74 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line5);
75 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line6);
76 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line7);
77 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line8);
78 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line9);
82extern "C" void EXTI15_10_IRQHandler(
void) __attribute__((interrupt));
84extern "C" void EXTI15_10_IRQHandler(
void)
86 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line10);
87 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line11);
88 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line12);
89 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line13);
90 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line14);
91 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line15);
96 : port_(port), pin_(pin), irq_(irq)
98 if (irq_ != NonMaskableInt_IRQn)
100 map_[GetEXTIID(pin)] =
this;
103 RCC_APB2PeriphClockCmd(ch32_get_gpio_periph(port_), ENABLE);
105 GPIO_InitTypeDef gpio_init = {};
106 gpio_init.GPIO_Pin = pin_;
107 gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
115 gpio_init.GPIO_Mode = (pull ==
Pull::UP) ? GPIO_Mode_IPU
117 : GPIO_Mode_IN_FLOATING;
120 gpio_init.GPIO_Mode = GPIO_Mode_Out_PP;
123 gpio_init.GPIO_Mode = GPIO_Mode_Out_OD;
127 GPIO_Init(port_, &gpio_init);
132 ConfigureEXTI(EXTI_Trigger_Rising);
135 ConfigureEXTI(EXTI_Trigger_Falling);
138 ConfigureEXTI(EXTI_Trigger_Rising_Falling);
147 EXTI->INTENR |=
static_cast<uint32_t
>(pin_);
148 return ErrorCode::OK;
153 EXTI->INTENR &= ~static_cast<uint32_t>(pin_);
154 return ErrorCode::OK;
157void CH32GPIO::OnInterrupt()
165void CH32GPIO::CheckInterrupt(uint32_t line)
167 if (EXTI_GetITStatus(line) != RESET)
169 EXTI_ClearITPendingBit(line);
171 const uint8_t ID = GetEXTIID(
static_cast<uint16_t
>(line));
172 if (
auto* gpio =
map_[ID])
179void CH32GPIO::ConfigureEXTI(EXTITrigger_TypeDef trigger)
181 EXTI_InitTypeDef exti = {};
182 uint8_t pin_source = GetEXTIID(pin_);
183 uint8_t port_source = 0xFF;
188 port_source = GPIO_PortSourceGPIOA;
192 else if (port_ == GPIOB)
194 port_source = GPIO_PortSourceGPIOB;
198 else if (port_ == GPIOC)
200 port_source = GPIO_PortSourceGPIOC;
204 else if (port_ == GPIOD)
206 port_source = GPIO_PortSourceGPIOD;
210 else if (port_ == GPIOE)
212 port_source = GPIO_PortSourceGPIOE;
216 else if (port_ == GPIOF)
218 port_source = GPIO_PortSourceGPIOF;
222 else if (port_ == GPIOG)
224 port_source = GPIO_PortSourceGPIOG;
228 else if (port_ == GPIOH)
230 port_source = GPIO_PortSourceGPIOH;
234 else if (port_ == GPIOI)
236 port_source = GPIO_PortSourceGPIOI;
240 ASSERT(port_source != 0xFF);
242 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
243 GPIO_EXTILineConfig(port_source, pin_source);
245 exti.EXTI_Line = 1 << pin_source;
246 exti.EXTI_Mode = EXTI_Mode_Interrupt;
247 exti.EXTI_Trigger = trigger;
248 exti.EXTI_LineCmd = ENABLE;
251 NVIC_EnableIRQ(irq_);
254uint8_t CH32GPIO::GetEXTIID(uint16_t pin)
256 ASSERT(pin != 0 && (pin &
static_cast<uint16_t
>(pin - 1)) == 0);
257 return __builtin_ctz(pin);
ErrorCode DisableInterrupt() override
禁用 GPIO 引脚中断。Disables the GPIO pin interrupt.
CH32GPIO(GPIO_TypeDef *port, uint16_t pin, GPIO::Direction direction=GPIO::Direction::OUTPUT_PUSH_PULL, GPIO::Pull pull=GPIO::Pull::NONE, IRQn_Type irq=NonMaskableInt_IRQn)
构造 GPIO 对象 / Construct GPIO object
ErrorCode EnableInterrupt() override
使能 GPIO 引脚中断。Enables the GPIO pin interrupt.
static CH32GPIO * map_[16]
EXTI 线路映射表 / EXTI line map.
void Run(bool in_isr, PassArgs &&... args) const
执行回调函数并传递参数 / Execute the callback with arguments
bool Empty() const
检查回调是否为空 / Check whether the callback is empty
Callback callback_
GPIO 事件的回调函数。Callback function for GPIO events.
Direction
定义 GPIO 引脚的方向类型。Defines the direction types for GPIO pins.
@ OUTPUT_PUSH_PULL
推挽输出模式。Push-pull output mode.
@ RISING_INTERRUPT
上升沿中断模式。Rising edge interrupt mode.
@ FALL_RISING_INTERRUPT
双沿触发中断模式。Both edge interrupt mode.
@ OUTPUT_OPEN_DRAIN
开漏输出模式。Open-drain output mode.
@ FALL_INTERRUPT
下降沿中断模式。Falling edge interrupt mode.
Pull
定义 GPIO 引脚的上拉/下拉模式。Defines the pull-up/pull-down configurations for GPIO pins.
@ DOWN
下拉模式。Pull-down mode.