当前位置:网站首页>潘多拉 IOT 开发板学习(RT-Thread)—— 实验1 LED 闪烁实验(学习笔记)
潘多拉 IOT 开发板学习(RT-Thread)—— 实验1 LED 闪烁实验(学习笔记)
2022-07-02 03:36:00 【小辉_Super】
本文代码参考 RT-Thread 官方 BSP
实验功能
例程源码:(main.c)
该实验实现了 LED_R 的闪烁,亮灭间隔为 500 ms。
/* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2018-08-16 armink first implementation */
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
/* 配置 LED 灯引脚 */
#define LED_PIN PIN_LED_R
int main(void)
{
unsigned int count = 1;
/* 设置 LED 引脚为输出模式 */
rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);
while (count > 0)
{
/* LED 灯亮 */
rt_pin_write(LED_PIN, PIN_LOW);
LOG_D("led on, count: %d", count);
rt_thread_mdelay(500);
/* LED 灯灭 */
rt_pin_write(LED_PIN, PIN_HIGH);
LOG_D("led off");
rt_thread_mdelay(500);
count++;
}
return 0;
}
代码剖析
rt_pin_mode()
该函数的作用是 GPIO Pin 的初始化,定义为
/* 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);
}
参数 pin 是一个 rt_base_t 变量(long),下面的 GET_PIN() 是 STM32 的 pin 值宏定义,第一个参数填大写字母,第二个参数填数字。
#define GET_PIN(PORTx,PIN) (rt_base_t)((16 * ( ((rt_base_t)__STM32_PORT(PORTx) - (rt_base_t)GPIOA)/(0x0400UL) )) + PIN)
#define __STM32_PORT(port) GPIO##port // ## 是字符连接符,假如 port 为 A,则表示 GPIOA
例如实验中的
#define PIN_LED_R GET_PIN(E, 7),表示 GPIOE GPIO_Pin7
目前 RT-Thread 支持的引脚工作模式包括:
#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 /* 开漏输出 */
在 bsp 的 drv_gpio.c 文件中,有底层 GPIO 驱动,下面是 STM32 的 GPIO 模式设置的驱动函数(大家应该很熟悉,就是用 HAL 库写的 GPIO 初始化代码)
static void stm32_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode)
{
const struct pin_index *index;
GPIO_InitTypeDef GPIO_InitStruct;
index = get_pin(pin);
if (index == RT_NULL)
{
return;
}
/* Configure GPIO_InitStructure */
GPIO_InitStruct.Pin = index->pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
if (mode == PIN_MODE_OUTPUT)
{
/* output setting */
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
}
else if (mode == PIN_MODE_INPUT)
{
/* input setting: not pull. */
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
}
else if (mode == PIN_MODE_INPUT_PULLUP)
{
/* input setting: pull up. */
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
}
else if (mode == PIN_MODE_INPUT_PULLDOWN)
{
/* input setting: pull down. */
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
}
else if (mode == PIN_MODE_OUTPUT_OD)
{
/* output setting: od. */
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
}
HAL_GPIO_Init(index->gpio, &GPIO_InitStruct);
}
rt_pin_write()
GPIO 写函数,下面是函数的定义,
void rt_pin_write(rt_base_t pin, rt_base_t value)
{
RT_ASSERT(_hw_pin.ops != RT_NULL);
_hw_pin.ops->pin_write(&_hw_pin.parent, pin, value);
}
和 GPIO 模式配置函数类似,它其实也会调用底层驱动里对应的函数,该底层函数是通过 HAL_GPIO_WritePin() 来完成 GPIO Pin 的修改。
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);
}
rt_thread_mdelay()
这是 RT-Thread 的毫秒级延时函数,定义如下:
rt_err_t rt_thread_mdelay(rt_int32_t ms)
{
rt_tick_t tick;
// 获取需要的时钟节拍
tick = rt_tick_from_millisecond(ms);
// 阻塞相应的节拍时间
return rt_thread_sleep(tick);
}
rt_tick_from_millisecond()
/** * 算出 ms 对应的时钟节拍数 * * * @param ms the specified millisecond * - Negative Number wait forever * - Zero not wait * - Max 0x7fffffff * * @return the calculated tick */
rt_tick_t rt_tick_from_millisecond(rt_int32_t ms)
{
rt_tick_t tick;
if (ms < 0)
{
tick = (rt_tick_t)RT_WAITING_FOREVER; // -1
}
else
{
// 将“每秒节拍数” / 1000 * ms,算出对应的秒节拍数
tick = RT_TICK_PER_SECOND * (ms / 1000);
// 加上小于 1000ms 部分的节拍数
tick += (RT_TICK_PER_SECOND * (ms % 1000) + 999) / 1000;
}
/* return the calculated tick */
return tick;
}
rt_thread_sleep()
线程睡眠(挂起)函数,参数是系统节拍数:
/** * 该函数能让当前线程挂起一段时间(由 tick 决定) * * @param tick the sleep ticks * * @return RT_EOK */
rt_err_t rt_thread_sleep(rt_tick_t tick)
{
register rt_base_t temp;
struct rt_thread *thread;
/* set to current thread */
thread = rt_thread_self();
RT_ASSERT(thread != RT_NULL);
RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
/* disable interrupt */
temp = rt_hw_interrupt_disable();
/* suspend thread */
rt_thread_suspend(thread);
/* reset the timeout of thread timer and start it */
rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &tick);
rt_timer_start(&(thread->thread_timer));
/* enable interrupt */
rt_hw_interrupt_enable(temp);
rt_schedule();
/* clear error number of this thread to RT_EOK */
if (thread->error == -RT_ETIMEOUT)
thread->error = RT_EOK;
return RT_EOK;
}
LOG_D()
本实验中,我们可以将 LOG_D() 视为 rt_kprintf(),
#define dbg_log_line(lvl, color_n, fmt, ...) \ do \ {
\ _DBG_LOG_HDR(lvl, color_n); \ rt_kprintf(fmt, ##__VA_ARGS__); \ _DBG_LOG_X_END; \ } \ while (0)
LOG_D 是 RT-Thread 内核里的一个日志打印函数,详情可见:《RT-Thread 文档中心——ulog 日志》
RT-Thread 的日志 API 包括:

边栏推荐
- [punch in] flip the string (simple)
- Qt的网络连接方式
- Pointer array & array pointer
- Exchange rate query interface
- Introduction to Robotics II. Forward kinematics, MDH method
- < job search> process and signal
- 滴滴开源DELTA:AI开发者可轻松训练自然语言模型
- [C Advanced] brother Peng takes you to play with strings and memory functions
- Knowing things by learning | self supervised learning helps improve the effect of content risk control
- 蓝桥杯单片机省赛第十二届第一场
猜你喜欢
![[mv-3d] - multi view 3D target detection network](/img/aa/741b36ead2dfaa5a165401b8d657b7.jpg)
[mv-3d] - multi view 3D target detection network

MD5 of Oracle

蓝桥杯单片机省赛第十二届第一场

Detailed explanation of ThreadLocal

傅里叶级数

halcon图像矫正

Which of PMP and software has the highest gold content?

ThreadLocal详解

Uniapp uses canvas to generate posters and save them locally
![[HCIA continuous update] working principle of OSPF Protocol](/img/bc/4eeb091c511fd563fb1e00c8c8881a.jpg)
[HCIA continuous update] working principle of OSPF Protocol
随机推荐
KL divergence is a valuable article
接口调试工具模拟Post上传文件——ApiPost
Introduction to Robotics II. Forward kinematics, MDH method
Custom classloader that breaks parental delegation
What is the binding path of SAP ui5
UI (New ui:: MainWindow) troubleshooting
Halcon image rectification
ThreadLocal详解
FFMpeg AVFrame 的概念.
Continuous assignment of Verilog procedure
Account management of MySQL
How to do medium and long-term stocks, and what are the medium and long-term stock trading skills?
蓝桥杯单片机省赛第十一届第一场
Kotlin basic learning 16
Learn PWN from CTF wiki - ret2shellcode
uniapp 使用canvas 生成海报并保存到本地
Global and Chinese markets for infant care equipment, 2022-2028: Research Report on technology, participants, trends, market size and share
What do you know about stock selling skills and principles
Basic syntax of unity script (6) - specific folder
Global and Chinese market of gynaecological health training manikin 2022-2028: Research Report on technology, participants, trends, market size and share