nrf52840实现按键的检测

【实验目的】

  1. 计数增功能:按一次按键S1,指示灯按二进制增加。
  2. 计数减功能:按一次按键S2,指示灯按二进制减少。
  3. 完成计数增功能,同时按S1,S2两个按键复位。
  4. 同时按S1、S3两个按键,实现翻转计数。

【实验环境】

        nrf52840、keil、电脑

【实验资源】

        IK-52840DK 开发板上设计了 4 个轻触按键 S1、S2、S3、S4,分别连接到 nRF52840 的 GPIO P0.11 P0.12 P0.24 和 P0.25。我们可以通过读取轻触按键对应的 GPIO 的状态来判断该按键是否按下。

在轻触按键的电路中,轻触按键一端接 GND,当轻触按键按下时,轻触按键触点导通, 轻触按键对应的引脚电平为低电平,这样,nRF52840 检测到按键对应的引脚为低电平时即 可判断按键按下。当轻触按键释放时,轻触按键触点断开,由于对应的引脚开启了内部上拉 电阻,所以轻触按键对应的引脚为高电平,这样,nRF52840 检测到按键对应的引脚为高电 平时即可判断按键释放。

【实验要求】

  1. 计数增功能:按一次按键S1,指示灯按二进制增加。
  2. 计数减功能:按一次按键S2,指示灯按二进制减少。
  3. 完成计数增功能,同时按S1,S2两个按键复位。
  4. 同时按S1、S3两个按键,实现翻转计数。

【实验步骤】

实验一:编写驱动led驱动,在此基础上,更进一步,编写按键的程序。想要设置led的点亮和熄灭,需要以下几个步骤:

1、初始化:配置用于驱动LED指示灯D1的管脚,即配置P0.13为输出

      nrf_gpio_cfg_output(LED_1);

2、LED指示灯D1初始状态设置为熄灭,即引脚P0.13为输出高电平

  nrf_gpio_pin_set(LED_1);

然后使用以下函数对led进行操控。

注意:首先判断是否有按键按下:if(nrf_gpio_pin_read(BUTTON_1) == 0 || nrf_gpio_pin_read(BUTTON_2) == 0||nrf_gpio_pin_read(BUTTON_3) == 0)

1、       if(nrf_gpio_pin_read(BUTTON_1) == 0 && nrf_gpio_pin_read(BUTTON_2) == 0)//判断按键1、2是否被按下

2、       else if(nrf_gpio_pin_read(BUTTON_1) == 0 && nrf_gpio_pin_read(BUTTON_3) == 0) 判断按键1、3是否被按下

3、       if(nrf_gpio_pin_read(BUTTON_1) == 0) 判断按键1是否被按下

4、       if(nrf_gpio_pin_read(BUTTON_2) == 0) 判断按键2是否被按下

以此完成1、计数增功能。2、计数减功能。3、完成计数增功能,同时按S1,S2两个按键复位。4、同时按S1、S3两个按键,实现翻转计数。

5、指示灯按二进制显示原理:把得到的数字,按位取反后进行比较,如果是0,则灯亮,否则灯灭。

void printled(int count){

      nrf_gpio_pin_write(LED_1,~count&0x01);//1111 1110

      nrf_gpio_pin_write(LED_2,~count&0x02);//1111 1101 8+4+1

      nrf_gpio_pin_write(LED_3,~count&0x04);//1111 1011 8+2+1

      nrf_gpio_pin_write(LED_4,~count&0x08);//1111 0111 4+2+1}

软件流程图如下:

展示实验运行结果和结论,需要有文字描述和截图。

在本次任务中,我成功在IK-52840DK开发板上实现以下功能:①计数增功能:按一次按键S1,指示灯按二进制增加。②计数减功能:按一次按键S2,指示灯按二进制减少。③复位功能:同时按S1和S2两个按键,计数器复位。④翻转计数功能:同时按S1和S3两个按键,实现计数方向的翻转。

为了实现这些功能,我们编写相应的程序代码,并通过读取按键的状态来控制LED的显示。

通过本次实验,我不仅掌握了基本的GPIO控制和按键检测,还学会了如何实现计数器的增减、复位和翻转功能。这些技能为未来的嵌入式系统开发打下了坚实的基础。未来,我将继续深入学习嵌入式系统的相关知识,探索更多复杂的应用场景。

[实验代码]

实验代码如下:

#include <stdbool.h>

#include <stdint.h>

#include "nrf_delay.h"

#include "boards.h"

#include "nrf_log.h"

#include "nrf_log_ctrl.h"

#include "nrf_log_default_backends.h"

#include "stdio.h"

#include "string.h"

#include "ctype.h"



// 定义LED引脚

#define LED1 NRF_GPIO_PIN_MAP(0, 13)

#define LED2 NRF_GPIO_PIN_MAP(0, 14)

#define LED3 NRF_GPIO_PIN_MAP(0, 15)

#define LED4 NRF_GPIO_PIN_MAP(0, 16)



// 初始化日志模块

static void log_init(void)

{

    ret_code_t err_code = NRF_LOG_INIT(NULL);

    APP_ERROR_CHECK(err_code);

    NRF_LOG_DEFAULT_BACKENDS_INIT();

}



// 设置GPIO高电平时的输出电压为3.3V

static void gpio_output_voltage_setup_3v3(void)

{

    if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) !=

        (UICR_REGOUT0_VOUT_3V3 << UICR_REGOUT0_VOUT_Pos))

    {

        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;

        while (NRF_NVMC->READY == NVMC_READY_READY_Busy)

        {

        }



        NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~((uint32_t)UICR_REGOUT0_VOUT_Msk)) |

                            (UICR_REGOUT0_VOUT_3V3 << UICR_REGOUT0_VOUT_Pos);



        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;

        while (NRF_NVMC->READY == NVMC_READY_READY_Busy)

        {

        }



        NVIC_SystemReset();

    }

}



// 计数器变量

volatile uint8_t count = 0;

// 计数方向翻转标志

volatile bool flip_count = false;



// 检查按钮状态并更新计数器

void check_buttons()

{

    static bool s1_pressed = false;

    static bool s2_pressed = false;

    static bool s3_pressed = false;



    bool s1_state = nrf_gpio_pin_read(BUTTON_1) == 0;

    bool s2_state = nrf_gpio_pin_read(BUTTON_2) == 0;

    bool s3_state = nrf_gpio_pin_read(BUTTON_3) == 0;



    if (s1_state && !s1_pressed)

    {

        if (s2_state)

        {

            count = 0; // 按钮1和2同时按下,复位计数器

        }

        else if (s3_state)

        {

            flip_count = !flip_count; // 按钮1和3同时按下,翻转计数方向

        }

        else

        {

            if (!flip_count)

            {

                count = (count + 1) % 16; // 正向计数

            }

            else

            {

                count = (count - 1) & 0x0F; // 反向计数

            }

        }

        s1_pressed = true;

    }

    else if (!s1_state)

    {

        s1_pressed = false;

    }



    if (s2_state && !s2_pressed)

    {

        if (s1_state)

        {

            count = 0; // 按钮1和2同时按下,复位计数器

        }

        else

        {

            if (!flip_count)

            {

                count = (count - 1) & 0x0F; // 反向计数

            }

            else

            {

                count = (count + 1) % 16; // 正向计数

            }

        }

        s2_pressed = true;

    }

    else if (!s2_state)

    {

        s2_pressed = false;

    }



    if (s3_state && !s3_pressed)

    {

        if (s1_state)

        {

            flip_count = !flip_count; // 按钮1和3同时按下,翻转计数方向

        }

        s3_pressed = true;

    }

    else if (!s3_state)

    {

        s3_pressed = false;

    }

}



// 更新LED状态

void update_leds()

{

    nrf_gpio_pin_write(LED1, !(count & 0x01));        // 显示最低位

    nrf_gpio_pin_write(LED2, !((count >> 1) & 0x01)); // 显示第1位

    nrf_gpio_pin_write(LED3, !((count >> 2) & 0x01)); // 显示第2位

    nrf_gpio_pin_write(LED4, !((count >> 3) & 0x01)); // 显示最高位

}



// 主函数

int main(void)

{

    gpio_output_voltage_setup_3v3(); // 设置GPIO输出电压为3.3V

    log_init();                      // 初始化日志模块

    bsp_board_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS); // 初始化LED和按钮



    NRF_LOG_INFO("led blinky example started"); // 打印启动信息

    NRF_LOG_FLUSH();



    while (true)

    {

        check_buttons(); // 检查按钮状态

        update_leds();   // 更新LED状态

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路弥行至

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值