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(
"WCH-Interrupt-fast")));
47extern "C" void EXTI0_IRQHandler(
void) { LibXR::CH32GPIO::CheckInterrupt(EXTI_Line0); }
50extern "C" void EXTI1_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
52extern "C" void EXTI1_IRQHandler(
void) { LibXR::CH32GPIO::CheckInterrupt(EXTI_Line1); }
55extern "C" void EXTI2_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
57extern "C" void EXTI2_IRQHandler(
void) { LibXR::CH32GPIO::CheckInterrupt(EXTI_Line2); }
60extern "C" void EXTI3_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
62extern "C" void EXTI3_IRQHandler(
void) { LibXR::CH32GPIO::CheckInterrupt(EXTI_Line3); }
65extern "C" void EXTI4_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
67extern "C" void EXTI4_IRQHandler(
void) { LibXR::CH32GPIO::CheckInterrupt(EXTI_Line4); }
70extern "C" void EXTI9_5_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
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)
83 __attribute__((interrupt(
"WCH-Interrupt-fast")));
85extern "C" void EXTI15_10_IRQHandler(
void)
87 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line10);
88 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line11);
89 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line12);
90 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line13);
91 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line14);
92 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line15);
97 : port_(port), pin_(pin), irq_(irq)
99 if (irq_ != NonMaskableInt_IRQn)
101 map_[GetEXTIID(pin)] =
this;
104 RCC_APB2PeriphClockCmd(ch32_get_gpio_periph(port_), ENABLE);
106 GPIO_InitTypeDef gpio_init = {};
107 gpio_init.GPIO_Pin = pin_;
108 gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
116 gpio_init.GPIO_Mode = (pull ==
Pull::UP) ? GPIO_Mode_IPU
118 : GPIO_Mode_IN_FLOATING;
121 gpio_init.GPIO_Mode = GPIO_Mode_Out_PP;
124 gpio_init.GPIO_Mode = GPIO_Mode_Out_OD;
128 GPIO_Init(port_, &gpio_init);
133 ConfigureEXTI(EXTI_Trigger_Rising);
136 ConfigureEXTI(EXTI_Trigger_Falling);
139 ConfigureEXTI(EXTI_Trigger_Rising_Falling);
148 EXTI->INTENR |=
static_cast<uint32_t
>(pin_);
154 EXTI->INTENR &= ~static_cast<uint32_t>(pin_);
158void CH32GPIO::OnInterrupt()
166void CH32GPIO::CheckInterrupt(uint32_t line)
168 if (EXTI_GetITStatus(line) != RESET)
170 EXTI_ClearITPendingBit(line);
172 const uint8_t ID = GetEXTIID(
static_cast<uint16_t
>(line));
173 if (
auto* gpio =
map_[ID])
180void CH32GPIO::ConfigureEXTI(EXTITrigger_TypeDef trigger)
182 EXTI_InitTypeDef exti = {};
183 uint8_t pin_source = GetEXTIID(pin_);
184 uint8_t port_source = 0xFF;
189 port_source = GPIO_PortSourceGPIOA;
193 else if (port_ == GPIOB)
195 port_source = GPIO_PortSourceGPIOB;
199 else if (port_ == GPIOC)
201 port_source = GPIO_PortSourceGPIOC;
205 else if (port_ == GPIOD)
207 port_source = GPIO_PortSourceGPIOD;
211 else if (port_ == GPIOE)
213 port_source = GPIO_PortSourceGPIOE;
217 else if (port_ == GPIOF)
219 port_source = GPIO_PortSourceGPIOF;
223 else if (port_ == GPIOG)
225 port_source = GPIO_PortSourceGPIOG;
229 else if (port_ == GPIOH)
231 port_source = GPIO_PortSourceGPIOH;
235 else if (port_ == GPIOI)
237 port_source = GPIO_PortSourceGPIOI;
241 ASSERT(port_source != 0xFF);
243 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
244 GPIO_EXTILineConfig(port_source, pin_source);
246 exti.EXTI_Line = 1 << pin_source;
247 exti.EXTI_Mode = EXTI_Mode_Interrupt;
248 exti.EXTI_Trigger = trigger;
249 exti.EXTI_LineCmd = ENABLE;
252 NVIC_EnableIRQ(irq_);
255uint8_t CH32GPIO::GetEXTIID(uint16_t pin)
257 ASSERT(pin != 0 && (pin &
static_cast<uint16_t
>(pin - 1)) == 0);
258 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.
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.
@ OK
操作成功 | Operation successful