1@page page_device_pin PIN Device
2
3# Introduction of Pin
4
5The pins on the chip are generally divided into four categories: power supply, clock, control, and I/O. The I/O pins are further divided into General Purpose Input Output (GPIO) and function-multiplexed I/O (such as SPI/I2C/UART, etc.) pins, referring to their usage mode.
6
7Most MCU pins have more than one function. Their internal structure is different and their supported functionality are different. The actual function of the pin can be switched through different configurations. The main features of the General Purpose Input Output (GPIO) port are as follows:
8
9* Programmable Interrupt: The interrupt trigger mode is configurable. Generally, there are five interrupt trigger modes as shown in the following figure:
10
11  ![5 Interrupt Trigger Modes](figures/pin2.png)
12
13* Input and output modes can be controlled.
14
15   * Output modes generally include Output push-pull, Output open-drain, Output pull-up, and Output pull-down. When the pin is in the output mode, the connected peripherals can be controlled by configuring the level of the pin output to be high or low.
16
17   * Input modes generally include: Input floating,  Input pull-up,  Input pull-down, and  Analog. When the pin is in the input mode, the level state of the pin can be read, that is, high level or low level.
18
19# Access PIN Device
20
21The application accesses the GPIO through the PIN device management interface provided by RT-Thread. The related interfaces are as follows:
22
23| Function | **Description**             |
24| ---------------- | ---------------------------------- |
25| rt_pin_mode()  | Set pin mode |
26| rt_pin_write()     | Set the pin level |
27| rt_pin_read()   | Read pin level |
28| rt_pin_attach_irq()  | Bind pin interrupt callback function |
29| rt_pin_irq_enable()   | Enable pin interrupt |
30| rt_pin_detach_irq()  | Detach pin interrupt callback function |
31
32## Obtain Pin Number
33
34The pin numbers provided by RT-Thread need to be distinguished from the chip pin numbers, which not the same. The pin numbers are defined by the PIN device driver and are related to the specific chip used. There are two ways to obtain the pin number: use the macro definition or view the PIN driver file.
35
36### Use Macro Definition
37
38If you use the BSP in the `rt-thread/bsp/stm32` directory, you can use the following macro to obtain the pin number:
39
40```c
41GET_PIN(port, pin)
42```
43
44The sample code for the pin number corresponding to LED0 with pin number PF9 is as follows:
45
46```c
47#define LED0_PIN        GET_PIN(F, 9)
48```
49
50### View Driver Files
51
52If you use a different BSP, you will need to check the PIN driver code `drv_gpio.c` file to confirm the pin number. There is an array in this file that holds the number information for each PIN pin, as shown below:
53
54```c
55static const rt_uint16_t pins[] =
56{
57    __STM32_PIN_DEFAULT,
58    __STM32_PIN_DEFAULT,
59    __STM32_PIN(2, A, 15),
60    __STM32_PIN(3, B, 5),
61    __STM32_PIN(4, B, 8),
62    __STM32_PIN_DEFAULT,
63    __STM32_PIN_DEFAULT,
64    __STM32_PIN_DEFAULT,
65    __STM32_PIN(8, A, 14),
66    __STM32_PIN(9, B, 6),
67    ... ...
68}
69```
70
71Take `__STM32_PIN(2, A, 15)` as an example, 2 is the pin number used by RT-Thread, A is the port number, and 15 is the pin number, so the pin number corresponding to PA15 is 2.
72
73## Set Pin Mode
74
75Before the pin is used, you need to set the input or output mode first, and the following functions are used:
76
77```c
78void rt_pin_mode(rt_base_t pin, rt_base_t mode);
79```
80
81| Parameter | **Discription**    |
82| --------- | ------------------ |
83| pin       | Pin number         |
84| mode      | Pin operation mode |
85
86At present, the pin working mode supported by RT-Thread can take one of the five macro definition values as shown. The mode supported by the chip corresponding to each mode needs to refer to the specific implementation of the PIN device driver:
87
88```c
89#define PIN_MODE_OUTPUT 0x00            /* Output */
90#define PIN_MODE_INPUT 0x01             /* Input */
91#define PIN_MODE_INPUT_PULLUP 0x02      /* input Pull up  */
92#define PIN_MODE_INPUT_PULLDOWN 0x03    /* input Pull down  */
93#define PIN_MODE_OUTPUT_OD 0x04         /* output Open drain  */
94```
95
96An example of use is as follows:
97
98```c
99#define BEEP_PIN_NUM            35  /* PB0 */
100
101/* Buzzer pin is in output mode */
102rt_pin_mode(BEEP_PIN_NUM, PIN_MODE_OUTPUT);
103```
104
105## Set The Pin Level
106
107The function to set the pin output level is as follows:
108
109```c
110void rt_pin_write(rt_base_t pin, rt_base_t value);
111```
112
113| **Parameter** | Discription      |
114|----------|-------------------------|
115| pin      | Pin number        |
116| value    | Level logic value, which can take one of two macro definition values: PIN_LOW means low level, or PIN_HIGH means high level |
117
118Examples of use are as follows:
119
120```c
121#define BEEP_PIN_NUM            35  /* PB0 */
122
123/* Beep's pin is in output mode */
124rt_pin_mode(BEEP_PIN_NUM, PIN_MODE_OUTPUT);
125/* Set low level */
126rt_pin_write(BEEP_PIN_NUM, PIN_LOW);
127```
128
129## Read Pin Level
130
131The functions to read the pin level are as follows:
132
133```c
134int rt_pin_read(rt_base_t pin);
135```
136
137| Parameter  | Description |
138| ---------- | ----------- |
139| pin        | Pin number  |
140| **return** | ——          |
141| PIN_LOW    | Low level   |
142| PIN_HIGH   | High level  |
143
144Examples of use are as follows:
145
146```c
147#define BEEP_PIN_NUM            35  /* PB0 */
148int status;
149
150/* Buzzer pin is in output mode */
151rt_pin_mode(BEEP_PIN_NUM, PIN_MODE_OUTPUT);
152/* Set low level */
153rt_pin_write(BEEP_PIN_NUM, PIN_LOW);
154
155status = rt_pin_read(BEEP_PIN_NUM);
156```
157
158## Bind Pin Interrupt Callback Function
159
160To use the interrupt functionality of a pin, you can use the following function to configure the pin to some interrupt trigger mode and bind an interrupt callback function to the corresponding pin. When the pin interrupt occurs, the callback function will be executed.:
161
162```c
163rt_err_t rt_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode,
164                           void (*hdr)(void *args), void *args);
165```
166
167| Parameter  | Description                                                  |
168| ---------- | ------------------------------------------------------------ |
169| pin        | Pin number                                                   |
170| mode       | Interrupt trigger mode                                       |
171| hdr        | Interrupt callback function. Users need to define this function |
172| args       | Interrupt the parameters of the callback function, set to RT_NULL when not needed |
173| return     | ——                                                           |
174| RT_EOK     | Binding succeeded                                            |
175| error code | Binding failed                                               |
176
177Interrupt trigger mode mode can take one of the following five macro definition values:
178
179```c
180#define PIN_IRQ_MODE_RISING 0x00         /* Rising edge trigger */
181#define PIN_IRQ_MODE_FALLING 0x01        /* Falling edge trigger */
182#define PIN_IRQ_MODE_RISING_FALLING 0x02 /* Edge trigger (triggered on both rising and falling edges)*/
183#define PIN_IRQ_MODE_HIGH_LEVEL 0x03     /* High level trigger */
184#define PIN_IRQ_MODE_LOW_LEVEL 0x04      /* Low level trigger */
185```
186
187Examples of use are as follows:
188
189```c
190#define KEY0_PIN_NUM            55  /* PD8 */
191/* Interrupt callback function */
192void beep_on(void *args)
193{
194    rt_kprintf("turn on beep!\n");
195
196    rt_pin_write(BEEP_PIN_NUM, PIN_HIGH);
197}
198static void pin_beep_sample(void)
199{
200    /* Button 0 pin is the input mode */
201    rt_pin_mode(KEY0_PIN_NUM, PIN_MODE_INPUT_PULLUP);
202    /* Bind interrupt, rising edge mode, callback function named beep_on */
203    rt_pin_attach_irq(KEY0_PIN_NUM, PIN_IRQ_MODE_FALLING, beep_on, RT_NULL);
204}
205```
206
207## Enable Pin Interrupt
208
209After binding the pin interrupt callback function, use the following function to enable pin interrupt:
210
211```c
212rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled);
213```
214
215| **Parameter** | **Description** |
216|----------|----------------|
217| pin      | Pin number |
218| enabled  | Status, one of two values: PIN_IRQ_ENABLE, and PIN_IRQ_DISABLE |
219| **return** | ——             |
220| RT_EOK   | Enablement succeeded |
221| error code | Enablement failed |
222
223Examples of use are as follows:
224
225```c
226#define KEY0_PIN_NUM            55  /* PD8 */
227/* Interrupt callback function */
228void beep_on(void *args)
229{
230    rt_kprintf("turn on beep!\n");
231
232    rt_pin_write(BEEP_PIN_NUM, PIN_HIGH);
233}
234static void pin_beep_sample(void)
235{
236    /* Key 0 pin is the input mode */
237    rt_pin_mode(KEY0_PIN_NUM, PIN_MODE_INPUT_PULLUP);
238    /* Bind interrupt, rising edge mode, callback function named beep_on */
239    rt_pin_attach_irq(KEY0_PIN_NUM, PIN_IRQ_MODE_FALLING, beep_on, RT_NULL);
240    /* Enable interrupt */
241    rt_pin_irq_enable(KEY0_PIN_NUM, PIN_IRQ_ENABLE);
242}
243```
244
245## Detach Pin Interrupt Callback Function
246
247You can use the following function to detach the pin interrupt callback function:
248
249```c
250rt_err_t rt_pin_detach_irq(rt_int32_t pin);
251```
252
253| **Parameter** | **Description**      |
254| ------------- | -------------------- |
255| pin           | Pin number           |
256| **return**    | ——                   |
257| RT_EOK        | Detachment succeeded |
258| error code    | Detachment failed    |
259
260After the pin detaches the interrupt callback function, the interrupt is not closed. You can also call the bind interrupt callback function to bind the other callback functions again.
261
262```c
263#define KEY0_PIN_NUM            55  /* PD8 */
264/* Interrupt callback function */
265void beep_on(void *args)
266{
267    rt_kprintf("turn on beep!\n");
268
269    rt_pin_write(BEEP_PIN_NUM, PIN_HIGH);
270}
271static void pin_beep_sample(void)
272{
273    /* Key 0 pin is the input mode */
274    rt_pin_mode(KEY0_PIN_NUM, PIN_MODE_INPUT_PULLUP);
275    /* Bind interrupt, rising edge mode, callback function named beep_on */
276    rt_pin_attach_irq(KEY0_PIN_NUM, PIN_IRQ_MODE_FALLING, beep_on, RT_NULL);
277    /* Enable interrupt */
278    rt_pin_irq_enable(KEY0_PIN_NUM, PIN_IRQ_ENABLE);
279    /* Detach interrupt callback function */
280    rt_pin_detach_irq(KEY0_PIN_NUM);
281}
282```
283
284# PIN Device Usage Example
285
286The following sample code is the pin device usage example. The main steps of the sample code are as follows:
287
2881. Set the corresponding pin of the beep to the output mode and give a default low state.
289
2902. Set the key 0 and button 1 corresponding to the input mode, then bind the interrupt callback function and enable the interrupt.
291
2923. When the key 0 is pressed, the beep starts to sound, and when the key 1 is pressed, the beep stops.
293
294```c
295/*
296 * Program listing: This is a PIN device usage routine
297 * The routine exports the pin_beep_sample command to the control terminal
298 * Command call format:pin_beep_sample
299 * Program function: control the buzzer by controlling the level state of the corresponding pin of the buzzer by pressing the button
300*/
301
302#include <rtthread.h>
303#include <rtdevice.h>
304
305/* Pin number, determined by looking at the device driver file drv_gpio.c */
306#ifndef BEEP_PIN_NUM
307    #define BEEP_PIN_NUM            35  /* PB0 */
308#endif
309#ifndef KEY0_PIN_NUM
310    #define KEY0_PIN_NUM            55  /* PD8 */
311#endif
312#ifndef KEY1_PIN_NUM
313    #define KEY1_PIN_NUM            56  /* PD9 */
314#endif
315
316void beep_on(void *args)
317{
318    rt_kprintf("turn on beep!\n");
319
320    rt_pin_write(BEEP_PIN_NUM, PIN_HIGH);
321}
322
323void beep_off(void *args)
324{
325    rt_kprintf("turn off beep!\n");
326
327    rt_pin_write(BEEP_PIN_NUM, PIN_LOW);
328}
329
330static void pin_beep_sample(void)
331{
332    /* Beep pin is in output mode */
333    rt_pin_mode(BEEP_PIN_NUM, PIN_MODE_OUTPUT);
334    /* Default low level */
335    rt_pin_write(BEEP_PIN_NUM, PIN_LOW);
336
337    /* KEY 0 pin is the input mode */
338    rt_pin_mode(KEY0_PIN_NUM, PIN_MODE_INPUT_PULLUP);
339    /* Bind interrupt, falling edge mode, callback function named beep_on */
340    rt_pin_attach_irq(KEY0_PIN_NUM, PIN_IRQ_MODE_FALLING, beep_on, RT_NULL);
341    /* Enable interrupt */
342    rt_pin_irq_enable(KEY0_PIN_NUM, PIN_IRQ_ENABLE);
343
344    /* KEY 1 pin is input mode */
345    rt_pin_mode(KEY1_PIN_NUM, PIN_MODE_INPUT_PULLUP);
346    /* Binding interrupt, falling edge mode, callback function named beep_off */
347    rt_pin_attach_irq(KEY1_PIN_NUM, PIN_IRQ_MODE_FALLING, beep_off, RT_NULL);
348    /* Enable interrupt */
349    rt_pin_irq_enable(KEY1_PIN_NUM, PIN_IRQ_ENABLE);
350}
351/* Export to the msh command list */
352MSH_CMD_EXPORT(pin_beep_sample, pin beep sample);
353```
354