输入:按键和RF遥控器


#include "hal.h" // 替换为实际使用的硬件抽象层头文件名

// 设定常量
#define KEY_NOT_PRESSED 0x0
#define LONG_PRESS_COUNT 200
#define REPEAT_DELAY 75
#define MAX_LONG_PRESS 1000

// 定义按键状态结构体
typedef struct
{
    unsigned int repeatDelay;    // 重复延时
    unsigned char quickCount;    // 快速按下计数
    unsigned int longCount;      // 长按计数
    unsigned long current;       // 当前按键值
    unsigned long previous;      // 上一次的按键值
    unsigned long quickPrevious; // 上一次快速按下的按键值
    unsigned char pressed;       // 按键被按下的标志
    unsigned char longPressed;   // 长按标志
    unsigned char down;          // 按键按下的瞬间标志
    unsigned char up;            // 按键抬起的瞬间标志
} KeyState;

KeyState ks = {0}; // 初始化按键状态

// 初始化按键
void KeyInit(void)
{
    // 初始化硬件相关代码
}

// 清除按键状态
void KeyClear(void)
{
    ks.repeatDelay = 0;
    ks.quickCount = 0;
    ks.longCount = 0;
    ks.current = KEY_NOT_PRESSED;
    ks.previous = KEY_NOT_PRESSED;
    ks.quickPrevious = KEY_NOT_PRESSED;
    ks.pressed = 0;
    ks.longPressed = 0;
    ks.down = 0;
    ks.up = 0;
}

// 检查按键状态(应该定期调用此函数)
void KeyScan(void)
{
    ks.current = hal_GetKey(); // 获取当前按键值

    if (ks.current != KEY_NOT_PRESSED)   // 如果有按键被按下
    {
        if (ks.previous == ks.current)   // 检测到持续按压同一个按键
        {
            ks.pressed = 1;
            // 长按计数递增,但不超过最大值
            if (ks.longCount < MAX_LONG_PRESS)
            {
                ks.longCount++;
            }
            // 如果长按计数超过了阈值,则设置长按标志
            if (ks.longCount >= LONG_PRESS_COUNT)
            {
                ks.longPressed = 1;
            }
        }
        else     // 检测到按键值变更,说明发生了新的按键行为
        {
            if (ks.quickPrevious == ks.current)
            {
                ks.quickCount++;
            }
            else
            {
                ks.quickCount = 1;
            }
            ks.repeatDelay = REPEAT_DELAY;
            ks.quickPrevious = ks.current;
            ks.down = 1; // 标记按键被按下的瞬间
            ks.longCount = 0; // 重置长按计数
        }
        ks.previous = ks.current; // 更新上一次的按键值
    }
    else     // 如果当前没有按键被按下
    {
        ks.pressed = 0;
        ks.longPressed = 0;
        // 如果上一次有按键被按下,现在没有按键按下,说明按键抬起
        if (ks.previous != KEY_NOT_PRESSED)
        {
            ks.up = 1;
        }
        else
        {
            ks.up = 0;
        }

        ks.previous = KEY_NOT_PRESSED;
        // 处理重复延时递减
        if (ks.repeatDelay > 0)
        {
            ks.repeatDelay--;
        }
        if (ks.repeatDelay == 0)
        {
            ks.quickPrevious = KEY_NOT_PRESSED;
            ks.quickCount = 0;
        }
    }
}



#include <stdint.h> // 使用标准整数类型

// 定义一些常量避免魔法数字
#define TIMEOUT_TH 32
#define BIT_CNT_TH 25
#define BIT_RD_TH 8

// volatile因为键值可能在中断中被修改
volatile uint32_t gRfKeyVal = 0;

uint32_t gReadData; // 存储读取的遥控键值的全局变量

uint8_t loTimeout = 0; // IO低电平超时计数器
uint8_t hiTimeout = 0; // IO高电平超时计数器
uint8_t lastData = 0;  // 上次IO电平值

uint8_t bitCnt = 0; // 读取的位计数器

void rfKeyInit(void)
{
    #if (RfKeyType == RfKeyType_IoWidthCode)
    // 这里假设有设置IO端口为输出/输入的宏
    RFKEY_POWER_IO_Output();      // 将功率IO设置为输出
    RFKEY_DATA_IO_Input();        // 将数据IO设置为输入
    RFKEY_POWER_IO_Ctrl(RFKEY_POWER_ON); // 打开功率IO
    #endif
}

unsigned char rfKeyRead(uint32_t *keyval)
{
    if ((*keyval) == gRfKeyVal)
    {
        return 0; // 键值没有变化
    }
    else
    {
        (*keyval) = gRfKeyVal; // 键值更新
        return 1; // 有键值变化
    }
}

void GetRfKeyValue(void)
{
    static uint8_t hiTimeCnt = 0; // 作为局部静态变量的高电平时间计数器

    if (RFKEY_DATA_IO_Channel == 0)   // 检测到低电平
    {
        if (loTimeout < TIMEOUT_TH)
        {
            loTimeout++;
            if (loTimeout >= TIMEOUT_TH)
            {
                if (bitCnt == BIT_CNT_TH)
                {
                    gRfKeyVal = gReadData; // 成功读取完整的RF键值
                }
                else
                {
                    gRfKeyVal = 0; // 错误或不完整键值
                }
                // 重置变量为读取下一个值
                gReadData = 0;
                bitCnt = 0;
            }
        }
        else
        {
            return; // 超时则直接返回
        }

        hiTimeout = 0; // 高电平计时器清零

        if (lastData == 1)
        {
            lastData = 0;
            if (hiTimeCnt >= BIT_RD_TH)
            {
                gReadData |= 1; // 最后一位设为1
            }

            gReadData <<= (bitCnt < 32); // 数据位左移
            bitCnt += (bitCnt < 32); // 位计数加1
        }
    }
    else     // 检测到高电平
    {
        if (hiTimeout < TIMEOUT_TH)
        {
            hiTimeout++;
            if (hiTimeout >= TIMEOUT_TH)
            {
                gReadData = 0;
                gRfKeyVal = 0;
                bitCnt = 0;
            }
        }
        else
        {
            return; // 超时则返回
        }

        loTimeout = 0; // 低电平计时器清零

        if (lastData == 0)
        {
            lastData = 1;
            hiTimeCnt = 0; // 高电平时间计数器清零
        }
        else
        {
            hiTimeCnt++; // 如果还是高电平,时间计数增加
        }
    }
}

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值