网站运营的具体工作包括哪些,wordpress wp json,淘宝客做网站,网站计数器php硬件#xff1a;STM32F103ZET6、ST-LINK、usb转串口工具、4个LED灯、1个蜂鸣器、4个1k电阻、2个按键、面包板、杜邦线 文章目录 前言一、PIN设备介绍1. 引脚编号获取2. 设置引脚的输入/输出模式3. 设置引脚的电平值4. 读取引脚的电平值5. 绑定引脚中断回调函数6. 脱离引脚中断… 硬件STM32F103ZET6、ST-LINK、usb转串口工具、4个LED灯、1个蜂鸣器、4个1k电阻、2个按键、面包板、杜邦线 文章目录 前言一、PIN设备介绍1. 引脚编号获取2. 设置引脚的输入/输出模式3. 设置引脚的电平值4. 读取引脚的电平值5. 绑定引脚中断回调函数6. 脱离引脚中断回调函数7. 使能中断 二、任务1LED灯双闪控制1. 任务描述2. 代码编写 三、任务2蜂鸣器控制查询法1. 任务描述2. 代码编写3. 测试 四、任务3蜂鸣器控制中断回调法1. 任务描述2. 代码编写3. 测试 五、任务4同时实现LED闪烁和按键控制喇叭1. 任务描述2. 代码编写3. 测试 总结 前言
在嵌入式系统中GPIO是最常用的一种设备在RT-Thread操作系统中把GPIO命名为PIN设备。 一、PIN设备介绍
RT-Thread通过PIN设备对芯片的GPIO引脚进行管理应用程序可以通过其提供的一组PIN设备管理接口来操作GPIOPIN设备管理接口如表所示
接口描述rt_pin_get()获取引脚编号rt_pin_mode()设置引脚模式rt_pin_write()设置引脚电平rt_pin_read()读取引脚电平rt_pin_attach_irq()绑定引脚中断回调函数rt_pin_irq_enable()使能引脚中断rt_pin_detach_irq()脱离引脚中断回调函数
1. 引脚编号获取
引脚变化和芯片的引脚号不是同一概念。RT-Thread的PIN设备驱动程序把芯片的不同引脚赋予不同的编号操作PIN设备时需要使用引脚编号来指定对哪个引脚进行操作。 可通过三种方法获得引脚编号: 1API法 利用rt_pin_get() 函数来获取引脚编号例如获取PD9的引脚编号则可以使用 pin_number rt_pin_get(PD.9) 2宏定义法 对于STM32芯片可以使用GET_PIN(PORTx,PIN)获取引脚编号如硬件的PD9用于驱动LED_R_PIN则可以把宏LED_R_PIN定义为相应的引脚编号如下 #define LED_R_PIN GET_PIN(D, 9) 3查看驱动文件 在drivers/drv_gpio.c中pin[]数组定义了硬件平台的GPIO引脚编号通过查看该数组得到引脚PD9的编号为57。 具体数组代码如下
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),__STM32_PIN(18, B, 2),__STM32_PIN(19, B, 3),__STM32_PIN(20, B, 4),__STM32_PIN(21, B, 5),__STM32_PIN(22, B, 6),__STM32_PIN(23, B, 7),__STM32_PIN(24, B, 8),__STM32_PIN(25, B, 9),__STM32_PIN(26, B, 10),__STM32_PIN(27, B, 11),__STM32_PIN(28, B, 12),__STM32_PIN(29, B, 13),__STM32_PIN(30, B, 14),__STM32_PIN(31, B, 15),
#if defined(GPIOC)__STM32_PIN(32, C, 0),__STM32_PIN(33, C, 1),__STM32_PIN(34, C, 2),__STM32_PIN(35, C, 3),__STM32_PIN(36, C, 4),__STM32_PIN(37, C, 5),__STM32_PIN(38, C, 6),__STM32_PIN(39, C, 7),__STM32_PIN(40, C, 8),__STM32_PIN(41, C, 9),__STM32_PIN(42, C, 10),__STM32_PIN(43, C, 11),__STM32_PIN(44, C, 12),__STM32_PIN(45, C, 13),__STM32_PIN(46, C, 14),__STM32_PIN(47, C, 15),
#if defined(GPIOD)__STM32_PIN(48, D, 0),__STM32_PIN(49, D, 1),__STM32_PIN(50, D, 2),__STM32_PIN(51, D, 3),__STM32_PIN(52, D, 4),__STM32_PIN(53, D, 5),__STM32_PIN(54, D, 6),__STM32_PIN(55, D, 7),__STM32_PIN(56, D, 8),__STM32_PIN(57, D, 9),__STM32_PIN(58, D, 10),__STM32_PIN(59, D, 11),__STM32_PIN(60, D, 12),__STM32_PIN(61, D, 13),__STM32_PIN(62, D, 14),__STM32_PIN(63, D, 15),2. 设置引脚的输入/输出模式
宏定义描述PIN_MODE_OUTPUT推挽输出PIN_MODE_OUTPUT_OD开漏输出硬件需要外接上拉电阻PIN_MODE_INPUT输入PIN_MODE_INPUT_PULLUP上拉输入引脚悬空时为高电平PIN_MODE_INPUT_PULLDOWN下拉输入引脚悬空时为低电平引脚可通过以下函数设置输入/输出模式
void rt_pin_mode(rt_base_t pin, rt_base_t mode)
pin:引脚编号 mode输入/输出模式所对应的宏
#define LED_R_PIN GET_PIN(D, 9)
rt_pin_mode(LED_R_PIN, PIN_MODE_OUTPUT);3. 设置引脚的电平值
设置函数如下 void rt_pin_write(rt_base_t pin, rt_base_t value) pin引脚编号 value高电平为PIN_HIGH低电平为PIN_LOW
4. 读取引脚的电平值
设置函数如下 int rt_pin_read(rt_base_t pin) pin引脚编号 返回值高电平为PIN_HIGH低电平为PIN_LOW
5. 绑定引脚中断回调函数
引脚作为中断输入时需要设置引脚的中断触发方式引脚的中断触发模式有5种RT-Thread中分别有5个宏与之对应具体如下
宏定义描述PIN_IQR_MODE_RISING上升沿触发PIN_IQR_MODE_FALLING下降沿触发PIN_IQR_MODE_RISING_FALLING双边沿触发PIN_IQR_MODE_HIGH_LEVEL高电平触发PIN_IQR_MODE_LOW_LEVEL低电平触发
当引脚产生中断时通过中断回调函数响应中断。绑定中断回调函数到引脚后引脚有中断发生就会执行对应的中断回调函数。
具体函数如下 rt_err_t rt_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void *args) pin引脚编号 mode中断触发模式 hdr中断回调函数指针用户需要自定义这个函数 args中断回调函数的参数不需要设置时为RT_NULL 返回绑定成功为RT_EOK失败产生错误码
6. 脱离引脚中断回调函数
如不希望响应中断或者想更换中断响应函数则可以使用如下脱离引脚中断回调函数 rt_err_t rt_pin_detach_irq(rt_int32_t pin) pin引脚编号 返回脱离成功为RT_EOK失败产生错误码
7. 使能中断
rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled) pin引脚编号 enablePIN_IRQ_ENABLE(开启)PIN_IRQ_DISABLE(关闭) 返回使能成功为RT_EOK失败产生错误码
二、任务1LED灯双闪控制
1. 任务描述
控制LED1、LED2轮流闪烁。通过本任务学习PIN设备输出功能的设置方法。 2. 代码编写
在项目的main.c文件中编写如下代码
#include rtthread.h
#include rtdevice.h
#include drv_common.h/* 定义左右转向灯的控制引脚 */
#define LED_L_PIN GET_PIN(D, 8)
#define LED_R_PIN GET_PIN(D, 9)int main(void)
{/* 把引脚设置为推拉输出模式 */rt_pin_mode(LED_L_PIN, PIN_MODE_OUTPUT);rt_pin_mode(LED_R_PIN, PIN_MODE_OUTPUT);while (1){rt_pin_write(LED_L_PIN, PIN_HIGH);//灭左灯rt_pin_write(LED_R_PIN, PIN_LOW);//亮右灯rt_thread_mdelay(500);//延迟500毫秒rt_pin_write(LED_L_PIN, PIN_LOW);//亮左灯rt_pin_write(LED_R_PIN, PIN_HIGH);//灭右灯rt_thread_mdelay(500);}return RT_EOK;
}三、任务2蜂鸣器控制查询法
1. 任务描述
通过按键控制蜂鸣器的开关。当按键按下时蜂鸣器响起当按键松开时蜂鸣器关闭。通过本任务学习PIN设备输入功能的使用。
2. 代码编写
#include rtthread.h
#include rtdevice.h
#include drv_common.h/* 定义左右转向灯的控制引脚 */
#define BEEP_PIN GET_PIN(A, 5)
#define KEY1_PIN GET_PIN(A, 0)int main(void)
{/* 把蜂鸣器引脚设置为推拉模式 */rt_pin_mode(BEEP_PIN, PIN_MODE_OUTPUT);/* 把按键引脚设置为上拉输入模式 */rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT_PULLUP);while (1){if(PIN_LOWrt_pin_read(KEY1_PIN)){//按键按下rt_thread_mdelay(20);//延时去抖if(PIN_LOWrt_pin_read(KEY1_PIN))rt_pin_write(BEEP_PIN, PIN_LOW);//蜂鸣器响}elsert_pin_write(BEEP_PIN, PIN_HIGH);//否则蜂鸣器不响rt_thread_mdelay(300);//每0.3秒进行一次按键扫描}return RT_EOK;
}3. 测试
按下按键蜂鸣器发声松开按键停止发声但是经过多次尝试发现按键检测成功率较低所以需要利用中断进行改进。
四、任务3蜂鸣器控制中断回调法
1. 任务描述
通过按键控制蜂鸣器的开关。当按键按下时蜂鸣器响起当按键松开时蜂鸣器关闭。通过本任务掌握PIN设备中断回调函数的使用方法。
2. 代码编写
#include rtthread.h
#include rtdevice.h
#include drv_common.h#define BEEP_PIN GET_PIN(A, 5) //定义蜂鸣器的控制引脚
#define KEY1_PIN GET_PIN(A, 0) //定义按键的控制引脚/* 定义中断回调函数实现 */
void beep_on(void *args)
{/* 判断按键是否按下 */if(PIN_LOWrt_pin_read(KEY1_PIN)){/* 按键按下驱动蜂鸣器响 */rt_pin_write(BEEP_PIN, PIN_LOW);/* 等待按键台起 */while(PIN_LOWrt_pin_read(KEY1_PIN));/* 关闭蜂鸣器 */rt_pin_write(BEEP_PIN, PIN_HIGH);}
}
int main(void)
{rt_pin_mode(BEEP_PIN, PIN_MODE_OUTPUT); //把蜂鸣器引脚设置为推拉模式rt_pin_write(BEEP_PIN, PIN_HIGH); //初始化蜂鸣器默认状态为不响/* 把按键引脚设置为上拉输入模式 */rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT_PULLUP);/* 绑定中断下降沿触发模式回调函数名为beep_on */rt_pin_attach_irq(KEY1_PIN, PIN_IRQ_MODE_FALLING, beep_on, RT_NULL);rt_pin_irq_enable(KEY1_PIN, PIN_IRQ_ENABLE); //使能中断return RT_EOK;
}
3. 测试
按下按键蜂鸣器发声松开按键停止发声经过多次尝试发现按键检测成功率较高所以中断法比查询法更具优势。
五、任务4同时实现LED闪烁和按键控制喇叭
1. 任务描述
本任务功能为同时实现LED灯双闪功能和按键控制蜂鸣器的功能要求两个功能不能相互影响按键检测灵敏度要高即每次发生按键按下的事件程序都能成功检测该事件并开启蜂鸣器。
2. 代码编写
#include rtthread.h
#include rtdevice.h
#include drv_common.h#define DBG_TAG main
#define DBG_LVL DBG_LOG
#include rtdbg.h/* 定义左右转向灯的控制引脚 */
#define LED_L_PIN GET_PIN(D, 8)
#define LED_R_PIN GET_PIN(D, 9)
/* 定义蜂鸣器的控制引脚 */
#define BEEP_PIN GET_PIN(A, 5)
/* 定义按键的控制引脚 */
#define KEY1_PIN GET_PIN(A, 0)/* 定义中断回调函数 */
void beep_on(void *args)
{/* 判断按键是否按下 */if(PIN_LOWrt_pin_read(KEY1_PIN)){rt_pin_write(BEEP_PIN, PIN_LOW); //按按键下驱动蜂鸣器响 while(PIN_LOWrt_pin_read(KEY1_PIN)); //等待按键台起rt_pin_write(BEEP_PIN, PIN_HIGH); //关闭蜂鸣器}
}int main(void)
{/* 把LED灯引脚设置为输出模式 */rt_pin_mode(LED_L_PIN, PIN_MODE_OUTPUT);rt_pin_mode(LED_R_PIN, PIN_MODE_OUTPUT);/* 把蜂鸣器引脚设置为推拉模式 */rt_pin_mode(BEEP_PIN, PIN_MODE_OUTPUT);/* 初始化蜂鸣器默认状态为不响 */rt_pin_write(BEEP_PIN, PIN_HIGH);/* 把按键引脚设置为上拉输入模式 */rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT_PULLUP);/* 绑定中断下降沿触发模式回调函数名为beep_on */rt_pin_attach_irq(KEY1_PIN, PIN_IRQ_MODE_FALLING, beep_on, RT_NULL);rt_pin_irq_enable(KEY1_PIN, PIN_IRQ_ENABLE); // 使能中断 while(1){rt_pin_write(LED_L_PIN, PIN_HIGH);//亮左灯rt_pin_write(LED_R_PIN, PIN_LOW);//灭右灯rt_thread_mdelay(500);//延迟500毫秒rt_pin_write(LED_L_PIN, PIN_LOW);//灭左灯rt_pin_write(LED_R_PIN, PIN_HIGH);//亮右灯rt_thread_mdelay(500);}return RT_EOK;
}3. 测试
测试过程如下 1系统启动后观察左右转向灯是否轮流闪烁 2当按下按键时喇叭是否发出响声 3当松开按键时喇叭是否停止发出响声 4一直按住按键不松开观察灯的闪烁情况。 测试结果 1系统启动后左右转向灯轮流闪烁 2当按下按键时喇叭发出响声 3当松开按键时喇叭停止发出响声 4一直按住按键不松开喇叭发出响声灯停止闪烁。 总结
从任务4测试结果中我们可以发现按键功能影响了闪灯的功能说明两个功能还是没有很好地解耦依然存在相互影响的情况。 出现这种情况主要是由于中断回调函数中存在需要长时间等待的代码当按键一直按住不松开的时候中断回调函数由于一直停留在等待按键松开的地方而无法退出中断处理。而中断的优先级又高于main()线程的优先级从而导致main()线程无法得到执行。 通常我们不应该在中断回调函数中进行长时间的处理中断回调函数应该只做一些必要的快速处理操作而把长时间的处理操作放到线程中实现。 关于线程和优先级的概念我们在下一节讲述。