上面是魔笛开发板上 LED 和按键的 IO 分布,我们通过信号量的方法来同步按键线程和LED 线程,实现当 enter 键按下后,点亮或关闭 LED 的动作。

/**********************************************************************************************************
*
* 模块名称 : 按键检测模块
* 文件名称 : key.c
* 版 本 : V1.0
* 说 明 :
* 修改记录 :
* 版本号 日期 作者 说明
*
* v1.0 2013-4-20 jiezhi320(UP MCU 工作室)
*
* Copyright (C), 2012-2013,
* 淘宝店: http://shop73275611.taobao.com
* QQ交流群: 258043068
*
**********************************************************************************************************/
#include <rtthread.h>
#include "stm32f10x.h"
#include "key.h" //#define KEY_DEBUG #ifdef KEY_DEBUG
#define printf rt_kprintf /*使用rt_kprintf来输出*/
#else
#define printf(...) /*无输出*/
#endif #define KEY_RCC RCC_APB2Periph_GPIOB
#define KEY_PORT GPIOB
#define KEY_UP_PIN GPIO_Pin_5
#define KEY_DOWN_PIN GPIO_Pin_9
#define KEY_LEFT_PIN GPIO_Pin_8
#define KEY_RIGHT_PIN GPIO_Pin_0
#define KEY_SET_PIN GPIO_Pin_1 #define KEY_ALL_NSET (0x0000|KEY_UP_PIN|KEY_DOWN_PIN|KEY_LEFT_PIN|KEY_RIGHT_PIN|KEY_SET_PIN) extern struct rt_semaphore key_sem;
static void key_scan(void);
static void rt_hw_key_init(void); void key_thread_entry(void* parameter)
{
rt_hw_key_init(); while()
{
key_scan();
rt_thread_delay();
}
} void rt_hw_key_init(void)
{ GPIO_InitTypeDef GPIO_InitStructure;
/* Enable the GPIO_LED Clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); /* Configure the GPIO_LED pin */
GPIO_InitStructure.GPIO_Pin = KEY_UP_PIN|KEY_DOWN_PIN|KEY_LEFT_PIN|KEY_RIGHT_PIN|KEY_SET_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(KEY_PORT, &GPIO_InitStructure);
} void key_scan(void)
{
static vu16 s_KeyCode;//内部检查按键使用
static vu8 s_key_debounce_count, s_key_long_count;
vu16 t_key_code; t_key_code = GPIO_ReadInputData(KEY_PORT) & KEY_ALL_NSET; if((t_key_code == KEY_ALL_NSET)||(t_key_code != s_KeyCode))
{
s_key_debounce_count = ; //第一次
s_key_long_count = ;
}
else
{
if(++s_key_debounce_count == DEBOUNCE_SHORT_TIME)
{ //短按键
switch(s_KeyCode)
{
case KEY_ALL_NSET & (~KEY_UP_PIN): //up break; case KEY_ALL_NSET & (~KEY_DOWN_PIN): //down break; case KEY_ALL_NSET & (~KEY_LEFT_PIN): //left break; case KEY_ALL_NSET & (~KEY_RIGHT_PIN): //right break; case KEY_ALL_NSET & (~KEY_SET_PIN): //set /* 释放一次信号量 */
rt_sem_release(&key_sem);
break; default: //其他组合不做处理
break; }
#ifdef KEY_DEBUG
printf("key %d is set\n", s_KeyCode);
#endif
}
if(s_key_debounce_count == DEBOUNCE_COUT_FIRST + DEBOUNCE_COUT_INTERVAL)
{ //连按键
s_key_debounce_count = DEBOUNCE_COUT_FIRST;
++s_key_long_count;
/*
switch(s_KeyCode)
{
case KEY_ALL_NSET & (~KEY_UP_PIN): //up break; case KEY_ALL_NSET & (~KEY_DOWN_PIN): //down break;
} */
} if(s_key_long_count == DEBOUNCE_LONG_TIME)
{ //长按键 s_key_long_count = DEBOUNCE_LONG_TIME;
}
}
s_KeyCode = t_key_code; // 保存本次键值 }
/**********************************************************************************************************
*
* 模块名称 : LED驱动模块
* 文件名称 : led.c
* 版 本 : V1.1
* 说 明 :
* 修改记录 :
* 版本号 日期 作者 说明
*
* v1.0 2013-4-20 jiezhi320(UP MCU 工作室)
*
* Copyright (C), 2012-2013,
* 淘宝店: http://shop73275611.taobao.com
* QQ交流群: 258043068
*
**********************************************************************************************************/
#include <rtthread.h>
#include <stm32f10x.h>
#include "led.h" // led define #define led1_rcc RCC_APB2Periph_GPIOF
#define led1_gpio GPIOF
#define led1_pin (GPIO_Pin_6) #define led2_rcc RCC_APB2Periph_GPIOF
#define led2_gpio GPIOF
#define led2_pin (GPIO_Pin_7) #define led3_rcc RCC_APB2Periph_GPIOF
#define led3_gpio GPIOF
#define led3_pin (GPIO_Pin_8) #define led4_rcc RCC_APB2Periph_GPIOF
#define led4_gpio GPIOF
#define led4_pin (GPIO_Pin_9) extern struct rt_semaphore key_sem; static void rt_hw_led_init(void); void rt_hw_led_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(led1_rcc|led2_rcc|led3_rcc|led4_rcc,ENABLE); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = led1_pin;
GPIO_Init(led1_gpio, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = led2_pin;
GPIO_Init(led2_gpio, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = led3_pin;
GPIO_Init(led1_gpio, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = led4_pin;
GPIO_Init(led2_gpio, &GPIO_InitStructure); } void led_thread_entry(void* paramete)
{
vu8 led_state = ;
rt_hw_led_init();
/* 无限循环*/
while ()
{
/* 以永久等待方式获取信号量*/
rt_sem_take(&key_sem, RT_WAITING_FOREVER);
/* 当得到信号量以后才有可能执行下面程序*/
led_state ^=;
if (led_state!=)
{
GPIO_ResetBits(led1_gpio,led1_pin|led2_pin|led3_pin|led4_pin);
rt_kprintf(" get semaphore ok, led all on \r\n");
}
else
{
GPIO_SetBits(led1_gpio,led1_pin|led2_pin|led3_pin|led4_pin);
rt_kprintf(" get semaphore ok, led all off \r\n");
}
}
}

在开发板上实际运行程序后,我们看到,信号量确实起到了按键线程和 led 线程之间的同步作用:只有当按键按下后, led 灯才会有动作。

RT-Thread信号量实际运用—按键点灯的更多相关文章

  1. RT Thread 通过ENV来配置SFUD,操作SPI Flash

    本实验基于正点原子stm32f4探索者板子 请移步我的RT Thread论坛帖子. https://www.rt-thread.org/qa/forum.php?mod=viewthread& ...

  2. STM32 + RT Thread OS 学习笔记[二]

    串口通讯例程 通过上面的练习,对STM32项目开发有了一个直观印象,接下来尝试对串口RS232进行操作. 1.   目标需求: 开机打开串口1,侦听上位机(使用电脑串口测试软件)发送的信息,然后原样输 ...

  3. STM32 + RT Thread OS 串口通讯

    1.   创建项目 a)   禁用Finsh和console b)   默认情况下,项目文件包含了finsh,它使用COM1来通讯,另外,console输出(rt_kprintf)也使用了COM1.因 ...

  4. STM32 + RT Thread OS 学习笔记[三]

    RTGUI 据说RTGUI是多线程的,因此与RT-Thread OS的耦合度较高,有可能要访问RT-Thread的线程控制块.如果要移植到其它OS,估计难度较大.目前还处于Alpha状态,最终将会包含 ...

  5. STM32 + RT Thread OS 学习笔记[四]

    1.  补注 a)      硬件,打通通讯通道 若学习者购买了学习板,通常可以在学习板提供的示例代码中找到LCD的相关驱动代码,基本上,这里的驱动的所有代码都可以从里面找到. 从上面的示意图可见,M ...

  6. RT thread 设备驱动组件之USART设备

    本文以stm32f4xx平台介绍串口驱动,主要目的是:1.RTT中如何编写中断处理程序:2.如何编写RTT设备驱动接口代码:3.了解串行设备的常见处理机制.所涉及的主要源码文件有:驱动框架文件(usa ...

  7. RT Thread的SPI设备驱动框架的使用以及内部机制分析

    注释:这是19年初的博客,写得很一般,理解不到位也不全面.19年末得空时又重新看了RTThread的SPI和GPIO,这次理解得比较深刻.有时间时再整理上传. -------------------- ...

  8. RT Thread SPI设备 使用

    后记: 之前,我把SPI的片选在Cubemx中配置成了SPI_NSS.现在我给它改为了GPIO_OUTPUT.  同时参考了别人的类似的一个操作无线模块(采用SPI设备驱动)的例子程序(清楚了RTT的 ...

  9. 优先级反转实验,使用信号量实现【RT-Thread学习笔记 5】

    RTOS中很经典的问题.就是在使用共享资源的时候,优先级低的进程在优先级高的进程之前执行的问题.这里模拟这种情况. 下面的实验模拟了优先级反转的情况: 先定义三个线程: //优先级反转实验 rt_se ...

随机推荐

  1. linux上ln链接命令详细说明

    ln是linux中又一个非常重要命令,它的功能是为某一个文件在另外一个位置建立一个同不的链接,这个命令最常用的参数是-s,具体用法是:ln –s 源文件 目标文件. 当我们需要在不同的目录,用到相同的 ...

  2. ava中Class.forName的作用浅谈

    转自:http://www.jb51.net/article/42648.htm Class.forName(xxx.xx.xx) 返回的是一个类 一.首先你要明白在java里面任何class都要装载 ...

  3. redis中模糊删除

    /usr/local/redis/bin/redis-cli -h xx.xx.xx.xx KEYS "*floor*" | xargs /usr/local/redis/bin/ ...

  4. Loadrunner请求自定义的http(json)文件and参数化

    Loadrunner请求自定义的http(json)文件and参数化      研究啦好些天这个东西啦 终于出来答案啦 嘿嘿 给大家分享一下 : 请求自定义的http文件用函数:web_custom_ ...

  5. spring获取webapplicationcontext,applicationcontext几种方法详解

    法一:在初始化时保存ApplicationContext对象代码: ApplicationContext ac = new FileSystemXmlApplicationContext(" ...

  6. DP+路径 URAL 1029 Ministry

    题目传送门 /* 题意:就是从上到下,找到最短路,输出路径 DP+路径:状态转移方程:dp[i][j] = min (dp[i-1][j], dp[i][j-1], dp[i][j+1]) + a[[ ...

  7. Redis作为多个Windows服务运行配置方法

    1.首先下载微软官方推荐的版本redis-2.8.12 2.开始配置,首先复制两份redis.conf并且重命名为redis6379.conf  redis6380.conf 里面的配置节点相应的更改 ...

  8. 正则表达式学习日记zz

    1."."为通配符,表示任何一个字符,例如:"a.c"可以匹配"anc"."abc"."acc": ...

  9. 响应式HTML5+CSS3 网站开发测试实践

    仅仅利用media query适配样式是远远不够的,并没有考虑触屏下的行为和特有的内容组织方式的不同.简单在桌面版基础上叠加mobile版的代码,会带来请求增多.流量.性能.代码冗余等诸多方面问题.有 ...

  10. Linq To Objects

    一.什么是Linq To Objects 从根本上说,Linq To Objects表示一种新的处理集合的方法.采用旧方法,必须编写指定如何从集合检索数据的复杂的foreach循环.而采用Linq方法 ...