利用时间片轮询实现GPIO按键识别

一、引脚说明:

Pair引脚为P11引脚

二、设计思路:

1、硬件设计思路:

硬件电路说明:该电路是是外部上拉电路。

当按键抬起时,单片机采集到的电平为高电平(1)。

当按键按下时,单片机引脚采集到的电平为低电平(0)。

2、软件设计思路:

采取时间片轮询的方式,每10ms轮询一次。

三、程序设计:

1、引脚初始化:

void key_init(void)

{

        GPIO_InitTypeDef GPIO_InitStruct;//定义结构体对象
        GPIO_InitStruct.GPIO_Pin    = GPIO_Pin_1;//选择引脚   这里是pin1
        GPIO_InitStruct.GPIO_Mode   = GPIO_Mode_IN;//选择模式为输入
        GPIO_InitStruct.GPIO_Ctrl  = GPIO_Control_DIG;//设置为数字量
        GPIO_InitStruct.GPIO_PuPd  = GPIO_PuPd_NOPULL;//不进行上下拉,电平取决于外部电压
        GPIO_Init(GPIO_PORT1, &GPIO_InitStruct);//对GPIO进行设置

}

2、按键识别程序

#define KEY (GPIO_ReadInputDataBit(GPIO_PORT1,GPIO_Pin_1) == 0)//按键按下标识

unsigned int key_low = 0;//用来装载按键按下的时间

unsigned int key_task_time = 0;//用来处理按键任务的时间

unsigned char key = 0;//用来存放按键是否按下有效

unsigned char key_scan(void)

{

if(time_ms(key_task_time ,10))//10ms读取一次按键状态
    {
        key_task_time = get_time();//更新时间
        if(KEY)//如果按键被按下
        {
            key_low++;//低电平的时间自增
            if(key_low >= 20)//低电平的时间大于200ms,认定此次按键按下有效
            {           
                key = 1;//按键按下有效
            }

             else

                {

                       key = 0;

                }
        }
        else key_low = 0;//低电平时间清0
    }

return key;

}

3、定时器设定

这里用到的时钟是TIM41。

unsigned int task_time = 0;

void Tim41_IntervalTimer(void)//定时器设置1ms
{
    TIM_InitTypeDef TIM_InitStructure;

    TIM_InitStructure.TIM         = TIM41;                   //specify the 8 channels TIM
    TIM_InitStructure.TIM_Channel = TTM_Channel_0;
    TIM_InitStructure.TIM_ClkDivision = TIM_CLK0_Div32768;  // specify the operation clk=1khz of tim for 32Mhz fclk
    TIM_InitStructure.TIM_Period[TIM_CH0_Counter]   = 2;                //specify the  time =1*(1/1000) =1ms
    TIM_InitStructure.TIM_Trigger     = TIM_Trigger_Software; //specify the software trigger
    TIM_InitStructure.TIM_Mode        = TIM_Mode_Interval;  // external event
    TIM_InitStructure.TIM_StartInt    = TIM_StartInt_Disable;
    TIM_Init(&TIM_InitStructure);

    ISR_Register(TM10_IRQn, tim41_channel0_interrupt);
}

void tim41_channel0_interrupt(void *msg)
{
    task_time++;
  INTC_ClearPendingIRQ(TM10_IRQn);    // clear INTTM00 interrupt flag
}

unsigned char time_ms(unsigned int start, unsigned int timeout)
{
    return ((unsigned int)(task_time - start) > timeout);
}

4、引用的头文件

#include "gpio.h"//引用系统的GPIO库

#include "tim.h"//引用系统的时钟库

5、main函数调用

int main()

{

unsigned char key = 0;

key_init();

Tim41_IntervalTimer();

while(1)

        {

                key = key_scan();

        }

}

  • 19
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
时间轮询是一种常见的实现多任务调度的方法。它将 CPU 的时间片分配给多个任务,每个任务在一个时间段内运行一定的时间,在时间片结束之后,操作系统会切换到下一个任务,直至所有任务完成。以下是一个简单的时间轮询例程的伪代码: ``` while (true) { for (i = 0; i < num_tasks; i++) { if (tasks[i].state == RUNNING) { // 如果当前任务正在运行 tasks[i].run_time++; // 增加运行时间 if (tasks[i].run_time >= time_slice) { // 如果运行时间达到时间片 tasks[i].state = READY; // 将任务状态设置为就绪 tasks[i].run_time = 0; // 重置运行时间 } } } for (i = 0; i < num_tasks; i++) { if (tasks[i].state == READY) { // 如果当前任务处于就绪状态 tasks[i].state = RUNNING; // 将任务状态设置为运行 run_task(&tasks[i]); // 运行任务 } } } ``` 在这个例程中,我们假设有一个任务列表 `tasks`,每个任务包含一个状态(运行、就绪、阻塞等)和已经运行的时间。在时间轮询的过程中,我们逐个检查每个任务的状态,如果任务正在运行,就增加它的运行时间,并检查是否达到时间片的限制。如果是,则将任务状态设置为就绪,并将运行时间重置为 0。在第二个循环中,我们检查所有就绪的任务,并将它们的状态设置为运行,然后运行它们。 当然,实际的时间轮询例程可能会更加复杂,需要考虑任务的优先级、阻塞和唤醒等情况,但是以上的伪代码可以作为一个基本的框架来理解时间轮询的原理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值