libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
ch32_gpio.hpp
1#pragma once
2
3#include "gpio.hpp"
4#include "libxr.hpp"
5
6#include DEF2STR(LIBXR_CH32_CONFIG_FILE)
7
8namespace LibXR
9{
10
11typedef enum
12{
13#if defined(GPIOA)
14 CH32_GPIOA,
15#endif
16#if defined(GPIOB)
17 CH32_GPIOB,
18#endif
19#if defined(GPIOC)
20 CH32_GPIOC,
21#endif
22#if defined(GPIOD)
23 CH32_GPIOD,
24#endif
25#if defined(GPIOE)
26 CH32_GPIOE,
27#endif
28#if defined(GPIOF)
29 CH32_GPIOF,
30#endif
31#if defined(GPIOG)
32 CH32_GPIOG,
33#endif
34#if defined(GPIOH)
35 CH32_GPIOH,
36#endif
37#if defined(GPIOI)
38 CH32_GPIOI,
39#endif
40 CH32_GPIO_NUMBER
41} ch32_gpio_group_t;
42
43static uint32_t CH32GetGPIOPeriph(GPIO_TypeDef* port)
44{
45 if (false)
46 {
47 }
48#if defined(GPIOA)
49 else if (port == GPIOA)
50 return RCC_APB2Periph_GPIOA;
51#endif
52#if defined(GPIOB)
53 else if (port == GPIOB)
54 return RCC_APB2Periph_GPIOB;
55#endif
56#if defined(GPIOC)
57 else if (port == GPIOC)
58 return RCC_APB2Periph_GPIOC;
59#endif
60#if defined(GPIOD)
61 else if (port == GPIOD)
62 return RCC_APB2Periph_GPIOD;
63#endif
64#if defined(GPIOE)
65 else if (port == GPIOE)
66 return RCC_APB2Periph_GPIOE;
67#endif
68#if defined(GPIOF)
69 else if (port == GPIOF)
70 return RCC_APB2Periph_GPIOF;
71#endif
72#if defined(GPIOG)
73 else if (port == GPIOG)
74 return RCC_APB2Periph_GPIOG;
75#endif
76#if defined(GPIOH)
77 else if (port == GPIOH)
78 return RCC_APB2Periph_GPIOH;
79#endif
80#if defined(GPIOI)
81 else if (port == GPIOI)
82 return RCC_APB2Periph_GPIOI;
83#endif
84 return 0;
85}
86
87class CH32GPIO : public GPIO
88{
89 public:
90 CH32GPIO(GPIO_TypeDef* port, uint16_t pin,
92 GPIO::Pull pull = GPIO::Pull::NONE, IRQn_Type irq = NonMaskableInt_IRQn)
93 : port_(port), pin_(pin), irq_(irq)
94 {
95 if (irq_ != NonMaskableInt_IRQn)
96 {
97 NVIC_EnableIRQ(irq_);
98 map[GetEXTIID(pin)] = this;
99 }
100
101 RCC_APB2PeriphClockCmd(CH32GetGPIOPeriph(port_), ENABLE);
102
103 GPIO_InitTypeDef gpio_init = {};
104 gpio_init.GPIO_Pin = pin_;
105 gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
106
107 switch (direction)
108 {
112 case Direction::INPUT:
113 gpio_init.GPIO_Mode = (pull == Pull::UP) ? GPIO_Mode_IPU
114 : (pull == Pull::DOWN) ? GPIO_Mode_IPD
115 : GPIO_Mode_IN_FLOATING;
116 break;
118 gpio_init.GPIO_Mode = GPIO_Mode_Out_PP;
119 break;
121 gpio_init.GPIO_Mode = GPIO_Mode_Out_OD;
122 break;
123 }
124
125 GPIO_Init(port_, &gpio_init);
126
127 switch (direction)
128 {
130 ConfigureEXTI(EXTI_Trigger_Rising);
131 break;
133 ConfigureEXTI(EXTI_Trigger_Falling);
134 break;
136 ConfigureEXTI(EXTI_Trigger_Rising_Falling);
137 break;
138 default:
139 break;
140 }
141 }
142
143 bool Read() override { return GPIO_ReadInputDataBit(port_, pin_) == Bit_SET; }
144
145 ErrorCode Write(bool value) override
146 {
147 if (value)
148 GPIO_SetBits(port_, pin_);
149 else
150 GPIO_ResetBits(port_, pin_);
151 return ErrorCode::OK;
152 }
153
154 ErrorCode EnableInterrupt() override
155 {
156 EXTI->INTENR |= (1 << GetEXTIID(pin_));
157 return ErrorCode::OK;
158 }
159
160 ErrorCode DisableInterrupt() override
161 {
162 EXTI->INTENR &= ~(1 << GetEXTIID(pin_));
163 return ErrorCode::OK;
164 }
165
166 ErrorCode SetConfig(Configuration config) override
167 {
168 GPIO_InitTypeDef gpio_init = {};
169 gpio_init.GPIO_Pin = pin_;
170 gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
171
172 switch (config.direction)
173 {
174 case Direction::INPUT:
175 gpio_init.GPIO_Mode = (config.pull == Pull::UP) ? GPIO_Mode_IPU
176 : (config.pull == Pull::DOWN) ? GPIO_Mode_IPD
177 : GPIO_Mode_IN_FLOATING;
178 break;
180 gpio_init.GPIO_Mode = GPIO_Mode_Out_PP;
181 break;
183 gpio_init.GPIO_Mode = GPIO_Mode_Out_OD;
184 break;
188 gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
189 break;
190 }
191
192 GPIO_Init(port_, &gpio_init);
193
194 switch (config.direction)
195 {
197 ConfigureEXTI(EXTI_Trigger_Rising);
198 break;
200 ConfigureEXTI(EXTI_Trigger_Falling);
201 break;
203 ConfigureEXTI(EXTI_Trigger_Rising_Falling);
204 break;
205 default:
206 break;
207 }
208
209 return ErrorCode::OK;
210 }
211
212 void OnInterrupt()
213 {
214 if (!callback_.Empty())
215 {
216 callback_.Run(true);
217 }
218 }
219
220 static void CheckInterrupt(uint32_t line)
221 {
222 if (EXTI_GetITStatus(line) != RESET)
223 {
224 EXTI_ClearITPendingBit(line);
225 map[GetEXTIID(line)]->OnInterrupt();
226 }
227 }
228
229 static inline CH32GPIO* map[16] = {nullptr};
230
231 private:
232 GPIO_TypeDef* port_;
233 uint16_t pin_;
234 IRQn_Type irq_;
235
236 void ConfigureEXTI(EXTITrigger_TypeDef trigger)
237 {
238 EXTI_InitTypeDef exti = {};
239 uint8_t pin_source = __builtin_ctz(pin_);
240 uint8_t port_source = 0xFF;
241
242#if defined(GPIOA)
243 if (port_ == GPIOA) port_source = GPIO_PortSourceGPIOA;
244#endif
245#if defined(GPIOB)
246 else if (port_ == GPIOB)
247 {
248 port_source = GPIO_PortSourceGPIOB;
249 }
250#endif
251#if defined(GPIOC)
252 else if (port_ == GPIOC)
253 {
254 port_source = GPIO_PortSourceGPIOC;
255 }
256#endif
257#if defined(GPIOD)
258 else if (port_ == GPIOD)
259 {
260 port_source = GPIO_PortSourceGPIOD;
261 }
262#endif
263#if defined(GPIOE)
264 else if (port_ == GPIOE)
265 {
266 port_source = GPIO_PortSourceGPIOE;
267 }
268#endif
269#if defined(GPIOF)
270 else if (port_ == GPIOF)
271 {
272 port_source = GPIO_PortSourceGPIOF;
273 }
274#endif
275#if defined(GPIOG)
276 else if (port_ == GPIOG)
277 {
278 port_source = GPIO_PortSourceGPIOG;
279 }
280#endif
281#if defined(GPIOH)
282 else if (port_ == GPIOH)
283 {
284 port_source = GPIO_PortSourceGPIOH;
285 }
286#endif
287#if defined(GPIOI)
288 else if (port_ == GPIOI)
289 {
290 port_source = GPIO_PortSourceGPIOI;
291 }
292#endif
293
294 ASSERT(port_source != 0xFF);
295
296 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
297 GPIO_EXTILineConfig(port_source, pin_source);
298
299 exti.EXTI_Line = 1 << pin_source;
300 exti.EXTI_Mode = EXTI_Mode_Interrupt;
301 exti.EXTI_Trigger = trigger;
302 exti.EXTI_LineCmd = ENABLE;
303 EXTI_Init(&exti);
304
305 NVIC_EnableIRQ(irq_);
306 }
307
308 static uint8_t GetEXTIID(uint16_t pin) { return __builtin_ctz(pin); }
309};
310
311} // namespace LibXR
ErrorCode EnableInterrupt() override
使能 GPIO 引脚中断。Enables the GPIO pin interrupt.
ErrorCode SetConfig(Configuration config) override
配置 GPIO 引脚参数。Configures the GPIO pin settings.
ErrorCode Write(bool value) override
写入 GPIO 引脚状态。Writes the GPIO pin state.
bool Read() override
读取 GPIO 引脚状态。Reads the GPIO pin state.
ErrorCode DisableInterrupt() override
禁用 GPIO 引脚中断。Disables the GPIO pin interrupt.
void Run(bool in_isr, PassArgs &&...args) const
执行回调函数,并传递参数。 Executes the callback function, passing the arguments.
Definition libxr_cb.hpp:208
bool Empty() const
检查回调是否为空。 Checks if the callback is empty.
Definition libxr_cb.hpp:223
通用输入输出(GPIO)接口类。General Purpose Input/Output (GPIO) interface class.
Definition gpio.hpp:13
Callback callback_
GPIO 事件的回调函数。Callback function for GPIO events.
Definition gpio.hpp:56
Direction
定义 GPIO 引脚的方向类型。Defines the direction types for GPIO pins.
Definition gpio.hpp:20
@ 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.
@ INPUT
输入模式。Input mode.
@ FALL_INTERRUPT
下降沿中断模式。Falling edge interrupt mode.
Pull
定义 GPIO 引脚的上拉/下拉模式。Defines the pull-up/pull-down configurations for GPIO pins.
Definition gpio.hpp:35
@ NONE
无上拉或下拉。No pull-up or pull-down.
@ DOWN
下拉模式。Pull-down mode.
@ UP
上拉模式。Pull-up mode.
LibXR 命名空间
Definition ch32_gpio.hpp:9
存储 GPIO 配置参数的结构体。Structure storing GPIO configuration parameters.
Definition gpio.hpp:46
Pull pull
GPIO 上拉/下拉配置。GPIO pull-up/pull-down configuration.
Definition gpio.hpp:48
Direction direction
GPIO 引脚方向。GPIO pin direction.
Definition gpio.hpp:47