講完UART設備之后,我們已經熟悉RT-Thread I/O 設備模型了,回頭看看基本的 PIN 設備。
目錄
前言
一、PIN 設備模型解析
1.1 初識 GPIO 操作函數
1.2 PIN 設備框架
1.3 PIN 設備驅動框架層
實現的函數
PIN 設備控制塊
注冊函數
1.4 PIN 設備驅動層
實現的函數
初始化函數
☆引腳定義☆
二、PIN 設備操作函數
2.1 獲取 PIN 索引號方法
2.2 操作函數
2.2.1 設置 GPIO 模式
2.2.2 設置/ 讀取 GPIO 電平
2.2.3 綁定/脫離中斷回調函數
2.2.4 使能中斷
三、PIN 設備示例
結語
前言
我們學習一個 MCU 的最基本的 GPIO 口,也就是 PIN 設備模型,我們還沒有講過,至于原因之前也說了,因為 PIN 設備的操作函數與我們介紹的 I/O 設備模型的通用函數名稱不太對應,對于新手來說先將 PIN 設備可能會讓人難以理解。
所以前面的文章我們先講了 UART 設備模型,從源碼分析了一下 UART 設備的設計思路,從設備驅動層,和設備驅動框架層再到 I/O 設備管理層,最后到應用層,我們都理過一遍。
有了前面的經驗,本文我們就來學習了解 RT-Thread PIN設備 。
??
本 RT-Thread 專欄記錄的開發(fā)環(huán)境:
RT-Thread記錄(一、RT-Thread 版本、RT-Thread Studio開發(fā)環(huán)境 及 配合CubeMX開發(fā)快速上手)
RT-Thread記錄(二、RT-Thread內核啟動流程 — 啟動文件和源碼分析)
??
RT-Thread 設備篇系列博文鏈接:
RT-Thread記錄(十、全面認識 RT-Thread I/O 設備模型)
RT-Thread記錄(十一、I/O 設備模型之UART設備 — 源碼解析)
RT-Thread記錄(十二、I/O 設備模型之UART設備 — 使用測試)
一、PIN 設備模型解析
一直說到 PIN 設備有點特殊,和我們講 I/O 設備模型時候的設備感覺有一點區(qū)別的,那么到底怎么個特殊法?我們還是需要具體來分析一下:
1.1 初識 GPIO 操作函數
我們還是從上層的 I/O 設備管理層來開始,看看 PIN 設備管理層提供的訪問 GPIO 的接口有哪些:
我們可以發(fā)現,上面的 PIN 設備管理接口的操作函數,與我們將的通用的函數完全不一樣,如下圖:
這也是為什么我們將設備示例的時候沒有先講 PIN 設備的原因,怕很多小伙伴剛開始不理解,那么為什么會這樣呢?
1.2 PIN 設備框架
我們通過前面的 UART 設備的分析,已經知道了設備的基本的框架了,首先我們來看一下 上一篇文章講到的 UART 設備框架:
對于 PIN 設備來說,框架總結如下圖表:
?? 前面一直說 PIN 設備有點特別,那只不過是因為官方說明中 應用程序調用的不是 I/O 設備管理層的接口函數,而是直接調用的 PIN 設備驅動框架層的接口函數:
知道了這一點的話,其實我們都不需要進行過多的分析,具體的過程分析可以查看前面幾篇博文,我們這里只需要對 PIN 設備驅動框架層 和 設備驅動層的接口簡單的了解一下,畢竟 GPIO 的操作還是很簡單的。
1.3 PIN 設備驅動框架層
通過上面的說明,我們知道 PIN 設備的使用是直接調用的 設備驅動框架層的接口,所以我們來看看 PIN 設備驅動框架層的文件(pin.c
)有哪些函數接口:
實現的函數
//私有的
static struct rt_device_pin _hw_pin;
static rt_size_t _pin_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
static rt_size_t _pin_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
static rt_err_t _pin_control(rt_device_t dev, int cmd, void *args)
//可調用的
int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void *user_data);
/* Get pin number by name,such as PA.0,P0.12 */
rt_base_t rt_pin_get(const char *name);
void rt_pin_mode(rt_base_t pin, rt_base_t mode);
void rt_pin_write(rt_base_t pin, rt_base_t value);
int rt_pin_read(rt_base_t pin);
rt_err_t rt_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode,
void (*hdr)(void *args), void *args);
rt_err_t rt_pin_detach_irq(rt_int32_t pin);
rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled);
挑一個函數簡單看看:
/* RT-Thread Hardware PIN APIs */
void rt_pin_mode(rt_base_t pin, rt_base_t mode)
{
RT_ASSERT(_hw_pin.ops != RT_NULL);
_hw_pin.ops->pin_mode(&_hw_pin.parent, pin, mode);
}
函數先斷言判斷_hw_pin.ops這個結構體是否有效,有效的情況下就設置引腳的模式。
第一個參數是引腳的索引號(這個在我們下面講解 PIN 設備驅動層的時候會有說明什么是索引號),
第二個參數是引腳模式(具體的模式我們也會再下面講解GPIO 設置時候統(tǒng)一說明)。
PIN 設備控制塊
在 RT-Thread 中 PIN 設備作為一個對象,那么肯定有他的對象控制塊,和我們前面學習的所有的對象一樣,在pin.h
中有 PIN 設備的對象結構體:
/* pin device and operations for RT-Thread */
struct rt_device_pin
{
struct rt_device parent; // rt_device 我們前面講過的,所有 device 的父類
const struct rt_pin_ops *ops;
};
struct rt_pin_ops
{
void (*pin_mode)(struct rt_device *device, rt_base_t pin, rt_base_t mode);
void (*pin_write)(struct rt_device *device, rt_base_t pin, rt_base_t value);
int (*pin_read)(struct rt_device *device, rt_base_t pin);
/* TODO: add GPIO interrupt */
rt_err_t (*pin_attach_irq)(struct rt_device *device, rt_int32_t pin,
rt_uint32_t mode, void (*hdr)(void *args), void *args);
rt_err_t (*pin_detach_irq)(struct rt_device *device, rt_int32_t pin);
rt_err_t (*pin_irq_enable)(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled);
rt_base_t (*pin_get)(const char *name);
};
?? PIN 設備的訪問函數都是在 PIN 設備控制塊中的結構體成員 ops
中實現的,也是通過這個結構體成員與 底層驅動層關聯起來 —— 在設備驅動層定義rt_pin_ops
類型的變量,實現這些操作函數。
注冊函數
在 PIN設備初始化的時候,rt_hw_pin_init()
會調用 rt_device_pin_register
函數進行 PIN 設備的初始化。
PIN 設備注冊函數,使用這個注冊函數,可以綁定底層驅動層的函數,也同時將設備接口提供給上層 I/O 設備管理層:
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;
#ifdef RT_USING_DEVICE_OPS
_hw_pin.parent.ops = &pin_ops;
#else
_hw_pin.parent.init = RT_NULL; //PIN 設備不需要
_hw_pin.parent.open = RT_NULL; //
_hw_pin.parent.close = RT_NULL; //
_hw_pin.parent.read = _pin_read; //* 把設備的read操作綁定在pin.c的_pin_read函數 */
_hw_pin.parent.write = _pin_write; //同上
_hw_pin.parent.control = _pin_control; //同上
#endif
/*
把drv_gpio.c所實現的_stm32_pin_ops綁定在_hw_pin.ops上
因為 PIN 設備驅動層使用的注冊函數為:
rt_device_pin_register("pin", &_stm32_pin_ops, RT_NULL);
*/
_hw_pin.ops = ops;
_hw_pin.parent.user_data = user_data;
/*
register a character device
/* 將其注冊進device設備框架中 */
*/
rt_device_register(&_hw_pin.parent, name, RT_DEVICE_FLAG_RDWR);
return 0;
}
在注冊函數中:_hw_pin.ops = ops;
這個操作就把設備驅動層實現的硬件操作函數給關聯到了 設備驅動框架層。
官方說明的 PIN 設備訪問的接口就是在 設備驅動框架層 提供的函數接口。
但是我們看到:
_hw_pin.parent.read = _pin_read; //把設備的read操作綁定在pin.c的_pin_read函數
_hw_pin.parent.write = _pin_write;
_hw_pin.parent.control = _pin_control;
這說明我們不僅可以使用 rt_pin_read
獲取 PIN 設備的值,還可以使用 rt_device_read
獲取 PIN 設備的值?。?!
?? 在 RT-Thread 的 PIN 設備模型中, rt_pin_read
函數和 rt_device_read
函數效果一樣。
1.4 PIN 設備驅動層
PIN 設備驅動層,直接與硬件打交道的層面,對于我們使用的 STM32 來說,里面的很多操作我們應該都不會陌生,我們也簡單了解下里面的函數,主要的目的在于實現 PIN 設備控制塊中 rt_pin_ops
成員中的幾個函數:
實現的函數
static const struct pin_index *get_pin(uint8_t pin)
static void stm32_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value)
static int stm32_pin_read(rt_device_t dev, rt_base_t pin)
static void stm32_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode)
rt_inline rt_int32_t bit2bitno(rt_uint32_t bit)
rt_inline const struct pin_irq_map *get_pin_irq_map(uint32_t pinbit)
static rt_err_t stm32_pin_attach_irq(struct rt_device *device, rt_int32_t pin,
rt_uint32_t mode, void (*hdr)(void *args), void *args)
static rt_err_t stm32_pin_dettach_irq(struct rt_device *device, rt_int32_t pin)
static rt_err_t stm32_pin_irq_enable(struct rt_device *device, rt_base_t pin,
rt_uint32_t enabled)
/*一個重要的結構體*/
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,
};
rt_inline void pin_irq_hdr(int irqno)
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
void EXTI0_IRQHandler(void)
...//一系列的外部中斷函數
...
int rt_hw_pin_init(void)
我們簡單來看一個函數,根本不需要過多的解釋:
static void stm32_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value)
{
const struct pin_index *index;
index = get_pin(pin);
if (index == RT_NULL)
{
return;
}
HAL_GPIO_WritePin(index->gpio, index->pin, (GPIO_PinState)value);
}
初始化函數
初始化函數雖然重要,但是簡單,看一下就能明白,首先就是熟悉的 GPIO 時鐘初始化,
然后就是調用設備注冊函數,設備名稱 pin ,也是在這里定義的,如果改成其他的,在 shell 工具中使用 list_device 就會顯示其他的名稱了。
第二個參數,就是將設備驅動層中實現的對硬件的操作函數關聯到 PIN 設備驅動框架層以供應用程序使用用。
int rt_hw_pin_init(void)
{
#if defined(__HAL_RCC_GPIOA_CLK_ENABLE)
__HAL_RCC_GPIOA_CLK_ENABLE();
#endif
#if defined(__HAL_RCC_GPIOB_CLK_ENABLE)
__HAL_RCC_GPIOB_CLK_ENABLE();
#endif
#if defined(__HAL_RCC_GPIOC_CLK_ENABLE)
__HAL_RCC_GPIOC_CLK_ENABLE();
#endif
#if defined(__HAL_RCC_GPIOD_CLK_ENABLE)
__HAL_RCC_GPIOD_CLK_ENABLE();
#endif
#if defined(__HAL_RCC_GPIOE_CLK_ENABLE)
__HAL_RCC_GPIOE_CLK_ENABLE();
#endif
#if defined(__HAL_RCC_GPIOF_CLK_ENABLE)
__HAL_RCC_GPIOF_CLK_ENABLE();
#endif
#if defined(__HAL_RCC_GPIOG_CLK_ENABLE)
#ifdef SOC_SERIES_STM32L4
HAL_PWREx_EnableVddIO2();
#endif
__HAL_RCC_GPIOG_CLK_ENABLE();
#endif
#if defined(__HAL_RCC_GPIOH_CLK_ENABLE)
__HAL_RCC_GPIOH_CLK_ENABLE();
#endif
#if defined(__HAL_RCC_GPIOI_CLK_ENABLE)
__HAL_RCC_GPIOI_CLK_ENABLE();
#endif
#if defined(__HAL_RCC_GPIOJ_CLK_ENABLE)
__HAL_RCC_GPIOJ_CLK_ENABLE();
#endif
#if defined(__HAL_RCC_GPIOK_CLK_ENABLE)
__HAL_RCC_GPIOK_CLK_ENABLE();
#endif
return rt_device_pin_register("pin", &_stm32_pin_ops, RT_NULL);
}
☆引腳定義☆
在驅動文件中,關于 GPIO 引腳的定義方式(STM32為例),我們有必要說明一下。
與 UART 不同的是,GPIO 配置簡單能夠更直接關聯硬件,所以 HAL 庫并沒有為 GPIO 提供句柄結構體描述,在 HAL 庫中描述 GPIO 使用了兩個參數:GPIO_TypeDef* GPIOx和GPIO_Pin,比如:
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
而在 RT-Thread 中,其定義了一個結構體 pin_index
,通過一個變量即可描述一個 GPIO,如下:
/* STM32 GPIO driver */
struct pin_index
{
int index;
GPIO_TypeDef *gpio;
uint32_t pin;
};
針對這個結構體,驅動程序中給了一些補充的操作:
/*
相當于結構體pin_index以宏定義的形式被初始化
用C語言字符串連接定義引腳信息
index 引腳的索引號,用戶可自行定義的驅動程序定義的引腳編號
gpio 相當于HAL庫中的GPIO_TypeDef
gpio_index 相當于HAL庫中的GPIO_Pin
例如宏__STM32_PIN(0, A, 0) 就表示結構體內容為 {0, GPIOA, GPIO_PIN_0}
*/
#define __STM32_PIN(index, gpio, gpio_index) \
{ \
index, GPIO##gpio, GPIO_PIN_##gpio_index \
}
//保留未使用的宏定義,有些IO口未使用,使用這個宏定義
#define __STM32_PIN_RESERVE \
{ \
-1, 0, 0 \
}
static const struct pin_index pins[] =
{
#if defined(GPIOA)
__STM32_PIN(0 , A, 0 ),
__STM32_PIN(1 , A, 1 ),
__STM32_PIN(2 , A, 2 ),
__STM32_PIN(3 , A, 3 ),
__STM32_PIN(4 , A, 4 ),
__STM32_PIN(5 , A, 5 ),
__STM32_PIN(6 , A, 6 ),
__STM32_PIN(7 , A, 7 ),
__STM32_PIN(8 , A, 8 ),
__STM32_PIN(9 , A, 9 ),
__STM32_PIN(10, A, 10),
__STM32_PIN(11, A, 11),
__STM32_PIN(12, A, 12),
__STM32_PIN(13, A, 13),
__STM32_PIN(14, A, 14),
__STM32_PIN(15, A, 15),
#if defined(GPIOB)
__STM32_PIN(16, B, 0),
__STM32_PIN(17, B, 1),
//后面省略很多......
首先宏定義#define __STM32_PIN(index, gpio, gpio_index)
:
其中##
為C語言連接符,其功能是在帶參數的宏定義中將兩個子串(token)聯接起來,從而形成一個新的子串,例如宏__STM32_PIN(0, A, 0)
就表示結構體內容為 {0, GPIOA, GPIO_PIN_0}
,就等于定義了一個pin_index
結構體。
然后宏定義__STM32_PIN_RESERVE
:
預留的IO樓,有些IO口未使用,使用這個宏定義
接下來的結構體數組pins
:
pins
為pin_index
結構體類型的數組,RT-Thread 使用 pins
數組對 所有的 GPIO 引腳進行初始化定義。
這樣就相當于芯片上所支持的 IO 口都進行了初始化定義,每一個 GPIO 都有了一個對應的索引號index。
在 RT-Thread 提供的 PIN 設備操作函數中void rt_pin_mode(rt_base_t pin, rt_base_t mode);, 他的第一個參數也不是類似 PIN設備控制塊之類的數據結構,而是一個引腳索引號,就是對應的上面這個index。
引腳中斷的分析和 引腳定義類似,可自行查看代碼,這里就不過多說明。
二、PIN 設備操作函數
文章開頭我們雖然已經認識過 PIN 設備的操作函數,但是我們沒有對函數參數可取值做說明,學習 API 的使用還是老樣子,直接放函數原型然后看注釋。
2.1 獲取 PIN 索引號方法
在我們使用某個 GPIO 的時候,第一步要做的就是獲取 GPIO 的索引號,即上文說到的index
。因為對 PIN 設備的訪問操作都是通過這個索引號進行的。
在 RT-Thread 中,提供了 3種方式獲取 PIN 設備索引號:
方法一: 使用函數rt_pin_get()
:
在 pin.c
文件中提供了一個函數:
rt_base_t rt_pin_get(const char *name)
里面的參數為一個名字,那么這個名字是什么呢?在函數申明有注釋:
對于STM32而言,使用示例如下:
//獲取索引號
pin_number = rt_pin_get("PA.9"); // pin_number 就是索引號
//設置GPIO模式
rt_pin_mode(pin_number , PIN_MODE_INPUT_PULLUP);
方法二: 使用宏定義GET_PIN
:
在drv_common.h
文件中有宏定義,可以直接獲取 GPIO 的索引號:
#define __STM32_PORT(port) GPIO##port##_BASE
#define GET_PIN(PORTx,PIN) (rt_base_t)((16 * ( ((rt_base_t)__STM32_PORT(PORTx) - (rt_base_t)GPIOA_BASE)/(0x0400UL) )) + PIN)
對于STM32而言,使用示例如下:
//獲取索引號
#define LED0_PIN GET_PIN(B, 9)
//LED0 點亮或者熄滅
#define LED0(n) (n ? rt_pin_write(LED0_PIN, PIN_HIGH) : rt_pin_write(LED0_PIN, PIN_LOW))
方法三: 查看驅動文件drv_gpio.c
:
上面講解 PIN 設備驅動層的時候說到過,所有的 GPIO 對應的索引號都會在驅動文件中定義,直接查看文件使用索引號就可以:
對于STM32而言,使用示例如下:
//對應驅動文件,下面的代碼含義就是 設置 PA0 的模式為 PIN_MODE_INPUT_PULLUP
rt_pin_mode(0, PIN_MODE_INPUT_PULLUP);
說明,查看驅動文件的方式并不直觀。
2.2 操作函數
操作函數說明老樣子
2.2.1 設置 GPIO 模式
/*
參數 描述
pin 引腳編號:索引號
mode 引腳工作模式
工作模式可選:
#define PIN_MODE_OUTPUT 0x00 輸出
#define PIN_MODE_INPUT 0x01 輸入
#define PIN_MODE_INPUT_PULLUP 0x02 上拉輸入
#define PIN_MODE_INPUT_PULLDOWN 0x03 下拉輸入
#define PIN_MODE_OUTPUT_OD 0x04 開漏輸出
*/
void rt_pin_mode(rt_base_t pin, rt_base_t mode);
2.2.2 設置/ 讀取 GPIO 電平
設置引腳電平:
/*
參數 描述
pin 引腳編號
value 電平邏輯值,
value 取值:
PIN_LOW 低電平,
PIN_HIGH 高電平
*/
void rt_pin_write(rt_base_t pin, rt_base_t value);
讀取引腳電平:
/*
參數 描述
pin 引腳編號
返回
PIN_LOW 低電平
PIN_HIGH 高電平
*/
int rt_pin_read(rt_base_t pin);
2.2.3 綁定/脫離中斷回調函數
綁定中斷回調函數:
/*
參數 描述
pin 引腳編號
mode 中斷觸發(fā)模式
hdr 中斷回調函數,用戶需要自行定義這個函數
args 中斷回調函數的參數,不需要時設置為 RT_NULL
返回 ——
RT_EOK 綁定成功
錯誤碼 綁定失敗
其中 mode 可選參數:
#define PIN_IRQ_MODE_RISING 0x00 上升沿觸發(fā)
#define PIN_IRQ_MODE_FALLING 0x01 下降沿觸發(fā)
#define PIN_IRQ_MODE_RISING_FALLING 0x02 邊沿觸發(fā)(上升沿和下降沿都觸發(fā))
#define PIN_IRQ_MODE_HIGH_LEVEL 0x03 高電平觸發(fā)
#define PIN_IRQ_MODE_LOW_LEVEL 0x04 低電平觸發(fā)
*/
rt_err_t rt_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode,
void (*hdr)(void *args), void *args);
脫離中斷回調函數:
/*
參數 描述
pin 引腳編號
返回 ——
RT_EOK 脫離成功
錯誤碼 脫離失敗
*/
rt_err_t rt_pin_detach_irq(rt_int32_t pin);
說明:引腳脫離了中斷回調函數以后,中斷并沒有關閉,還可以調用綁定中斷回調函數再次綁定其他回調函數。
2.2.4 使能中斷
綁定好引腳中斷回調函數后需要使用下面的函數使能引腳中斷:
/*
參數 描述
pin 引腳編號
enabled 狀態(tài)
返回 ——
RT_EOK 使能成功
錯誤碼 使能失敗
enabled 可取 2 種值之一:
PIN_IRQ_ENABLE (開啟)
PIN_IRQ_DISABLE (關閉)
*/
rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled);
三、PIN 設備示例
只要明白了PIN 設備模型原理,使用起來還是很簡單的,我們先看一下原理圖:
程序如下,測試OK,太簡單所以沒有什么好說的:
...
//添加這兩個頭文件
#include
#include "board.h"
...
static struct rt_thread led1_thread; //led1線程
static char led1_thread_stack[256];
static rt_thread_t key1_thread = RT_NULL; //
#define LED1_PIN GET_PIN(D, 9)
#define LED2_PIN GET_PIN(D, 8)
#define KEY1_PIN GET_PIN(D, 11)
#define KEY2_PIN GET_PIN(D, 10)
#define key1_read rt_pin_read(KEY1_PIN)
#define LED1_ON rt_pin_write(LED1_PIN, PIN_LOW);
#define LED1_OFF rt_pin_write(LED1_PIN, PIN_HIGH);
#define LED2_ON rt_pin_write(LED2_PIN, PIN_LOW);
#define LED2_OFF rt_pin_write(LED2_PIN, PIN_HIGH);
//#define LED0(n) (n ? rt_pin_write(LED0_PIN, PIN_HIGH) : rt_pin_write(LED0_PIN, PIN_LOW))
static void led1_thread_entry(void *par){
while(1){
LED1_ON;
rt_thread_mdelay(1000);
LED1_OFF;
rt_thread_mdelay(1000);
}
}
static void key1_thread_entry(void *par){
while(1){
if(key1_read == 0){
rt_thread_mdelay(10); //去抖動
if(key1_read == 0){
rt_kprintf("key1 kicked..\r\n");
}
while(key1_read == 0){rt_thread_mdelay(10);//去抖動
}
}
rt_thread_mdelay(1);
}
}
int main(void)
{
MX_USART1_UART_Init();
// MX_GPIO_Init(); //使用設備模型不需要初始化這個
/*配置LED管腳為輸出*/
rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);
rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT);
/*配置按鍵為輸入*/
rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT);
rt_pin_mode(KEY2_PIN, PIN_MODE_INPUT);
/*LED默認狀態(tài)*/
rt_pin_write(LED1_PIN, 1);
rt_pin_write(LED2_PIN, 0);
rt_err_t rst2;
rst2 = rt_thread_init(&led1_thread,
"led1_blink ",
led1_thread_entry,
RT_NULL,
&led1_thread_stack[0],
sizeof(led1_thread_stack),
RT_THREAD_PRIORITY_MAX -1,
50);
if(rst2 == RT_EOK){
rt_thread_startup(&led1_thread);
}
key1_thread = rt_thread_create("key1_control",
key1_thread_entry,
RT_NULL,
512,
RT_THREAD_PRIORITY_MAX -2,
50);
/* 如果獲得線程控制塊,啟動這個線程 */
if (key1_thread != RT_NULL)
rt_thread_startup(key1_thread);
...//后面省略
結語
本文我們詳細的分析了 RT-Thread I/O 設備模型之PIN設備,最終看來,使用 PIN 設備模型操作還是特別的簡單的。
其實關鍵的部分還是在于理解 PIN 設備模型的原理,理解了以后使用起來也更加的得心應手。
GPIO設備雖然簡單,但是文章寫下來也1W多字了,即便以前對 PIN 設備有點模糊,只要看了本文,相信大家肯定有撥云見日的感覺!
希望大家多多支持!本文就到這里,謝謝!
審核編輯:湯梓紅
-
GPIO
+關注
關注
16文章
1204瀏覽量
52051 -
PIN
+關注
關注
1文章
304瀏覽量
24284 -
RT-Thread
+關注
關注
31文章
1285瀏覽量
40081
發(fā)布評論請先 登錄
相關推薦
評論