Zephyr程序初探(5):thread程序

5 篇文章 0 订阅

这次的程序使用了中断、thread、semaphore,按键被按下后GPIO的中断callback被执行,发送semaphore使检测按键的thread得以执行,然后判断长按或者短按发送相应semaphore让相应的thread执行,除输出信息外LED会根据短按或者长按来闪烁1或者2次。

#include <zephyr.h>
#include <board.h>
#include <device.h>
#include <gpio.h>
#include <misc/util.h>
#include <misc/printk.h>

/* define LED and Button pin */
#define LED_PORT    LED0_GPIO_PORT
#define LED_PIN     LED0_GPIO_PIN
#define LED_FLASH_TIME  100//ms

#define BTN_PORT    SW0_GPIO_NAME
#define BTN_PIN     SW0_GPIO_PIN

/* define semaphore */
K_SEM_DEFINE(semPress, 0, 1);
K_SEM_DEFINE(semHold, 0, 1);
K_SEM_DEFINE(semBtnIntr, 0, 1);

/* define global device */
struct device *gDevLed;
struct device *gDevBtn;

static struct gpio_callback gpio_cb;

/* define thread parameter */
#define STACKSIZE   1024
#define PRIORITY_EVENT  7
#define PRIORITY_INTR   6

void ledOnOff(uint32_t on)
{
    gpio_pin_write(gDevLed, LED_PIN, !on);
}
void ledFlash(uint32_t times)
{
    while(times) {
        ledOnOff(1);
        k_sleep(LED_FLASH_TIME);
        ledOnOff(0);

        if(--times)
            k_sleep(LED_FLASH_TIME);
    }
}
uint32_t isKeyDown(void)
{
    uint32_t val;
    gpio_pin_read(gDevBtn, BTN_PIN, &val);
    return !val;
}

void threadPress(void *dummy1, void *dummy2, void *dummy3)
{
    ARG_UNUSED(dummy1);
    ARG_UNUSED(dummy2);
    ARG_UNUSED(dummy3);
    while(1) {
        k_sem_take(&semPress, K_FOREVER);
        printk("btn pressed\n");
        ledFlash(1);
    }
}
void threadHold(void *dummy1, void *dummy2, void *dummy3)
{
    ARG_UNUSED(dummy1);
    ARG_UNUSED(dummy2);
    ARG_UNUSED(dummy3);
    while(1) {
        k_sem_take(&semHold, K_FOREVER);
        printk("btn hold\n");
        ledFlash(2);
    }
}
void threadBtnIntr(void *dummy1, void *dummy2, void *dummy3)
{
    ARG_UNUSED(dummy1);
    ARG_UNUSED(dummy2);
    ARG_UNUSED(dummy3);
    uint32_t count;
    bool bHold;
    while(1) {
        k_sem_take(&semBtnIntr, K_FOREVER);
        count = 0;
        bHold = false;
        do {
            k_sleep(50);
            count++;
            if(count > 6) {
                bHold = true;
                break;
            }
        }while(isKeyDown());

        if(bHold)
            k_sem_give(&semHold);
        else
            k_sem_give(&semPress);
    }
}


K_THREAD_DEFINE(threadPress_id, STACKSIZE, threadPress, NULL, NULL, NULL, 
        PRIORITY_EVENT, 0, K_NO_WAIT);
K_THREAD_DEFINE(threadHold_id, STACKSIZE, threadHold, NULL, NULL, NULL, 
        PRIORITY_EVENT, 0, K_NO_WAIT);
K_THREAD_DEFINE(threadBtnIntr_id, STACKSIZE, threadBtnIntr, NULL, NULL, NULL, 
        PRIORITY_INTR, 0, K_NO_WAIT);

void btnIntrCb(struct device *gpio, struct gpio_callback *cb, uint32_t pin)
{
    k_sem_give(&semBtnIntr);
}

void helloMsg(void)
{
    printk("\n************************************************\n");
    printk("**\n");
    printk("** Welcome to visit http://blog.csdn.net/veabol\n");
    printk("** Thread program start!\n");
    printk("**\n");
    printk("************************************************\n");
}

void main (void)
{

    helloMsg();

    printk("configure led\n");
    gDevLed = device_get_binding(LED_PORT);
    if (!gDevLed) {
        printk("error\n");
        return;
    }
    gpio_pin_configure(gDevLed, LED_PIN, GPIO_DIR_OUT);
    ledOnOff(0);

    printk("configure button\n");
    gDevBtn = device_get_binding(BTN_PORT);
    if (!gDevBtn) {
        printk("error\n");
        return;
    }
    gpio_pin_configure(gDevBtn, BTN_PIN, 
        GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | GPIO_INT_ACTIVE_LOW | GPIO_PUD_PULL_UP);
    gpio_init_callback(&gpio_cb, btnIntrCb, BIT(BTN_PIN));
    gpio_add_callback(gDevBtn, &gpio_cb);
    gpio_pin_enable_callback(gDevBtn, BTN_PIN);
}

通过系统函数K_SEM_DEFINE定义三个信号量semPress,semHold,semBtnIntrK_THREAD_DEFINE初始化三个thread,分别用于等待按键中断和短按和长按的事件,threadBtnIntr()等待semBtnIntr即按键中断的发生,threadPress()是短按的线程等待semPress被发送,threadHold()是长按的线程等待semHold被发送。
main()函数初始化LED和按键,注册并使能按键的callback函数btnIntrCb(),当中断发生时btnIntrCb()被调用,并且发送信号使threadBtnIntr()得以继续执行,根据按键持续的时间长短分别发送短按和长按的信号 ,相应的线程也得以执行,测试时对按键进行短按和长按能够看到LED闪烁1次或者2次,通过串口能够看到如何信息:

************************************************
**
** Welcome to visit http://blog.csdn.net/veabol
** Thread program start!
**
************************************************
configure led
configure button
btn pressed
btn pressed
btn hold
btn hold
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值