Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
DIY综合交流区
[RealTouch例程]使用信号量实现按键轮询检测
发布于 2012-08-16 20:54:52 浏览:6203
订阅该版
实验目的 ? 了解信号量用作多个线程进行同步的使用方式 ? 掌握轮询实现按键检测的用法 ? 熟悉使用RT-Thread中信号量相关API 硬件说明 本实验使用RT-Thread官方的Realtouch开发板作为实验平台。涉及到的硬件主要为: ? 串口3,作为rt_kprintf输出。 ? 按键IO口 具体请参见《Realtouch开发板使用手册》 实验原理及程序结构 实验设计 本实验是在RT-Thread中通过轮询方式按键的检测功能。创建一个线程,以一定的时间间隔周期运行,扫描硬件系统中的物理按键,当检测到有按键按下时,发布一个按键信号量。创建另外一个线程来使用按键,为了简单起见,它将通过获取按键信号量,当取得这个信号量时,将按键信息打印出到串口。 源程序说明 本实验对应kernel_sem_keypolling。 系统依赖 在rtconfig.h中需要开启 ``` #define RT_USING_SEMAPHORE``` 此项必选,选择此项后才可以使用信号量相关API。 ``` #define RT_USING_HEAP``` 此项可选,开启此项可以创建动态信号量,如果使用静态信号量,则此项不是必要的 ``` #define RT_USING_CONSOLE``` 此项必须,本实验使用rt_kpriintf向串口打印按键信息,因此需要开启此项 主程序说明 在applications/application.c中,在系统init线程中完成按键GPIO初始化。参考原理图可知,这些按键已经在开发板上已经下拉模式,因此所有按键GPIO口都设置为悬空模式,这样当有键按下时,对应的GPIO口的电平就会为高,相关代码如下。 初始化按键GPIO口 ```#include "stm32f4xx.h" #define KEY_PORT GPIOF #define KEY_PIN (GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10| GPIO_Pin_11) #define KEY_CLCOK RCC_AHB1Periph_GPIOF void rt_init_thread_entry(void* parameter) { //gpio init GPIO_InitTypeDef GPIO_InitStructure; /* GPIOA GPIOB Periph clock enable */ RCC_AHB1PeriphClockCmd(KEY_CLCOK , ENABLE); /* Configure Pin in input pushpull mode */ GPIO_InitStructure.GPIO_Pin = KEY_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(KEY_PORT, &GPIO_InitStructure); } ```在int rt_application_init()中初始化静态线程,名为“keyp”的thread1。 初始化线程代码 ``` rt_thread_init(&thread1, "keyp", //producer rt_thread_entry1, RT_NULL, &thread1_stack[0], sizeof(thread1_stack),11,25); rt_thread_startup(&thread1); ```创建信号量代码如下所示。 创建信号量代码 ```static int key; static struct rt_semaphore sem; int rt_application_init() { rt_err_t result; result = rt_sem_init(&sem, "sem", 0, RT_IPC_FLAG_FIFO); f (result != RT_EOK) { rt_kprintf("error, init sem failed! "); return 0; } ```其处理线程处理函数如下,此线程周期启动,100ms启动一次检测按键,当检测到按键按下后,延时20ms后再次检测按键以实现按键去抖。如果的确检测到按键,则发布信号量。 线程1代码 ```ALIGN(RT_ALIGN_SIZE) static char thread1_stack[1024]; struct rt_thread thread1; static void rt_thread_entry1(void* parameter) { int temp; while (1) { key = GPIO_ReadInputData(KEY_PORT); if (key & KEY_PIN) { temp = key; rt_thread_delay(RT_TICK_PER_SECOND / 50); key = GPIO_ReadInputData(KEY_PORT); if (key == temp) rt_sem_release(&sem); } rt_thread_delay(RT_TICK_PER_SECOND/10); } } ```接下来在创建线程2,通过获取按键信号量,来获得线程1中得到的按键,并将按键信息通过串口发送的PC机上。 线程2代码 ```ALIGN(RT_ALIGN_SIZE) static char thread2_stack[1024]; struct rt_thread thread2; static int key; static void rt_thread_entry2(void* parameter) { while (1) { rt_sem_take(&sem, RT_WAITING_FOREVER); if (key & KEY_PIN) { rt_kprintf("some keys has been pressed : %x ", key); } } } ```编译调试及观察输出信息 编译请参见《RT-Thread配置开发环境指南》完成编译烧录,参考《Realtouch开发板使用手册》完成硬件连接,连接扩展板上的串口和jlink。 运行后可以看到如下信息: 串口信息 | / - RT - Thread Operating System / | 1.1.0 build Aug 13 2012 2006 - 2012 Copyright by rt-thread team 此时按下按键S2至S7,即可看到如下信息。 串口信息 some keys has been pressed : 40 some keys has been pressed : 80 some keys has been pressed : 100 some keys has been pressed : 200 some keys has been pressed : 400 some keys has been pressed : 800 结果分析 整个程序运行过程中各个线程的状态变化: Thread2 获取按键信号量,因为此时信号量中值为0,Thread2会被挂起。Thread1周期检测按键,当检测到按键时,Thread1发布信号量,此时有两种情况: 如果Thread2的优先级比Thread1的优先级高,此时Thread1会立刻被唤醒并执行,在其线程处理函数中,将按键信息发送至串口,while循环,继续执行rt_sem_take,此时信号量的值已经为0,Thread1再次被挂起。此时系统中优先级最高的线程为Thread2,因此内核将调度此线程继续周期按键检测功能。 如果Thread2的优先级比Thread1的优先级高,Thread1会从挂起态回到就绪态,但偶需Thread2优先级更高,因此Thread2继续运行,如果没有按键按下,Thread1会调用rt_threa_delay,Thread1挂起,此时Thread2为系统优先级最高的线程,会被立即调度执行,在线程处理函数中打印Thread1获取到的按键信息。 总结 本实验的原理是使用信号量实现两个线程之间的同步。 本实验使用静态信号量以及静态线程来进行按键轮询检测,读者可以改成动态信号量以及动态线程来实现同样的功能。 [attach]0[/attach] 下载附件 [实验2_3使用信号量实现按键轮询检测.pdf](https://oss-club.rt-thread.org/uploads/88_bfe9691ea05d94b3832010d97895228a.pdf) 下载附件 [1_kernel_sem_keypolling.zip](https://oss-club.rt-thread.org/uploads/3089_b3bd3cd2310e1a55e00854220c5b2714.zip)
查看更多
4
个回答
默认排序
按发布时间排序
bloom5
2012-09-05
这家伙很懒,什么也没写!
添加例程 [attach]1283[/attach]
lujun723
2012-10-09
这家伙很懒,什么也没写!
take操作会使信号量数值减一吗? 如果不会,那第一次按键过后,sem的值就一直为一了
bernard
2012-10-09
这家伙很懒,什么也没写!
take会使得它减一,直到为0. 然后不再减了。
撰写答案
登录
注册新账号
关注者
0
被浏览
6.2k
关于作者
shaolin
这家伙很懒,什么也没写!
提问
115
回答
444
被采纳
0
关注TA
发私信
相关问题
1
[项目]搞个开源的硬件项目
2
硬件计划贴,及时更新,欢迎提意见
3
软件计划贴,及时更新,欢迎提意见::WMA,MOUNT,LWIP等问题急需解决.
4
MMS协议
5
定点的wma解压库-libwma
6
QQ群记录 [20090821]
7
STM32网络收音机PCB报名征集
8
第一版调试记录
9
第二版硬件讨论
10
RADIO项目相关模块规格--欢迎大家自己做板时规格与此兼容,减少重复劳动
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
在RT-Thread Studio中构建前执行python命令
2
研究一了一段时间RTT,直接标准版上手太难,想用nano,但又舍不得组件
3
CherryUSB开发笔记(一):FSDEV USB IP核的 HID Remote WakeUp (USB HID 远程唤醒) 2025-01-18 V1.1
4
RT-thread 缩写字典
5
RT Thread 源码分析笔记 :线程和调度器
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
Bootloader
AT
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
I2C_IIC
ESP8266
UART
WIZnet_W5500
ota在线升级
PWM
cubemx
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
用户名由3_15位
7
个答案
1
次被采纳
bernard
4
个答案
1
次被采纳
xusiwei1236
4
个答案
1
次被采纳
踩姑娘的小蘑菇
1
个答案
1
次被采纳
张世争
1
个答案
1
次被采纳
本月文章贡献
聚散无由
2
篇文章
14
次点赞
catcatbing
2
篇文章
5
次点赞
Wade
2
篇文章
2
次点赞
Ghost_Girls
1
篇文章
6
次点赞
xiaorui
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部