CMS32L051使用旋转编码器

文章目录

概要

CMS32L051使用外部中断的方式识别旋转编码器的方向。

  1. 选取其中一个信号A进行外部中断触发,由于信号A空闲时处于高电平,因此初始化时外部中断使用下降沿触发;
  2. 触发第一个下降沿后,判断当前是否已经触发了上升沿,如果已经触发上升沿,则需要判断当前与触发上升沿的时间间隔是否大于1ms,如果小于则不往下执行。大于1ms则清除上升沿触发标志,置位下降沿触发标志,记录当前触发的时间戳,改用上升沿触发。
  3. 如果触发第一个下降沿后,没有触发上升沿则置位下降沿触发标志,记录当前触发的时间戳,改用上升沿触发。
  4. 触发上升沿后,判断当前时间戳和第一个下降沿的时间戳差值,如果大于2ms则根据另一个信号B的电平状态判断旋钮的方向,低电平则是逆时针,高电平则是顺时针。清除下升沿触发标志,置位上降沿触发标志,记录当前触发的时间戳,改用上升沿触发。
  5. 如果小于2ms则不往下执行。加入触发间隔判断是为了消抖。消抖结果如下图所示,绿色的是使用GPIO在有效下降沿和上升沿进行的翻转,黄色是信号A。
    在这里插入图片描述

代码

  1. bsp_knob.c
#include "UserConfigure.h"

typedef struct
{
    uint8_t a_first_falling;
	uint8_t a_first_rising;
    uint8_t knob_value;
    uint8_t last_knob_value;

    uint32_t a_first_falling_tick;
	uint32_t a_first_rising_tick;
} knob_mgr_t;

/* Private variables ---------------------------------------------------------*/
static knob_mgr_t knob_mgr = {
    0
};

void bsp_knob_set_exti_rising(void)
{
	INTM->EGN0 &= ~(1 << 2);
	INTM->EGP0 &= ~(1 << 2);
	INTM->EGN0 |= 0 << 2;
	INTM->EGP0 |= 1 << 2;
}

void bsp_knob_set_exti_falling(void)
{
	INTM->EGN0 &= ~(1 << 2);
	INTM->EGP0 &= ~(1 << 2);
	INTM->EGN0 |= 1 << 2;
	INTM->EGP0 |= 0 << 2;
}

/********************************************************************************
*******************************************************************************/
void ENCODER_A_EXT_ISR(void)
{
	uint32_t diff_tick = 0;
	
	if (!knob_mgr.a_first_falling) {
		if (knob_mgr.a_first_rising) {
			diff_tick = TICK_DIFF(HAL_GetTick(), knob_mgr.a_first_rising_tick);
			if (diff_tick >= 1) {  // 大于1ms
				knob_mgr.a_first_rising = 0;
				knob_mgr.a_first_falling = 1;
				bsp_knob_set_exti_rising();  // 上升沿
				knob_mgr.a_first_falling_tick = HAL_GetTick();
				DBG_OUT_L();
			}
		} else {
			knob_mgr.a_first_falling = 1;
			bsp_knob_set_exti_rising();  // 上升沿
			knob_mgr.a_first_falling_tick = HAL_GetTick();
			DBG_OUT_L();
		}
	} else {
		diff_tick = TICK_DIFF(HAL_GetTick(), knob_mgr.a_first_falling_tick);
		if (diff_tick >= 2) {  // 大于2ms
			if (Bit_RESET == GPIO_ReadInputDataBit(GPIO_PORT1, GPIO_Pin_3)) {
				if (knob_mgr.knob_value) {
					knob_mgr.knob_value--;
				}
			} else {
				if (knob_mgr.knob_value < 0xff) {
					knob_mgr.knob_value++;
				}
			}
			DBG_OUT_H();
//			printf("%u\r",diff_tick);
			knob_mgr.a_first_falling = 0;
			knob_mgr.a_first_rising = 1;
			bsp_knob_set_exti_falling();
			knob_mgr.a_first_rising_tick = HAL_GetTick();
		}
	}
	
	INTC_ClearPendingIRQ(INTP2_IRQn);
}

/**************************************************************************************
***************************************************************************************/
void bsp_knob_init(void)
{
	INTP_InitTypeDef INTP_InitStructure;

	INTP_InitStructure.INTP_Select  = INTP2 ;           //  选择外部中断INTP0
	INTP_InitStructure.EXTI_Trigger = Trigger_Falling;  //  设置外部中断,下降沿触发
	INTP_Init(&INTP_InitStructure);

	ISR_Register(INTP2_IRQn, ENCODER_A_EXT_ISR);        //  中断服务路径注册
	NVIC_SetPriority(INTP2_IRQn, 1);
	INTP_Start(INTP2);                                  //  Enable INTP2 Interrupt
}

void bsp_knop_poll(void)
{
	if (knob_mgr.last_knob_value != knob_mgr.knob_value) {
		printf("%u\r", knob_mgr.knob_value);
		bsp_ws2812b_fill_solid_rgb(bsp_ws2812b_set_rgb(0, 0, knob_mgr.knob_value));
		bsp_ws2812b_send();
		knob_mgr.last_knob_value = knob_mgr.knob_value;
	}
}

/***********************END OF FILE***********************/

小结

  1. 当前使用的时间计数是在定时器1ms中断中的,计时可能不是很准,不过对于旋钮的信号是够用的,如果需要使用精准定时,可以单独使用一个定时器进行计时。
CMS32L051是一款低功耗、高性能的ARM Cortex-M0+内核微控制器。它具有丰富的外设和功能,适用于各种嵌入式应用场景。以下是一些关于CMS32L051学习笔记的介绍: 1. 硬件介绍:CMS32L051微控制器具有32位ARM Cortex-M0+内核,工作频率可达到50MHz。它包含了多个外设,如通用串行接口、通用定时器、模拟比较器等,可以满足各种应用需求。 2. 开发环境:为了进行CMS32L051的开发,你可以使用Keil MDK开发环境或者其他支持ARM Cortex-M系列的开发工具。Keil MDK提供了一套完整的开发工具链,包括编译器、调试器和仿真器,方便进行代码编写、调试和下载。 3. 编程语言:CMS32L051可以使用C语言进行编程。你可以通过编写C语言代码来控制微控制器的各个外设,并实现所需的功能。 4. 外设编程:CMS32L051具有丰富的外设,包括GPIO、UART、SPI、I2C等。你可以学习如何初始化和配置这些外设,并使用相应的库函数进行数据的读写和控制。 5. 中断处理:中断是嵌入式系统中常用的一种事件处理机制。你可以学习如何配置和处理CMS32L051的中断,以实现对外部事件的响应和处理。 6. 低功耗设计:CMS32L051具有低功耗特性,适用于电池供电的应用场景。你可以学习如何进行低功耗设计,包括使用低功耗模式、优化代码和外设的使用等。 7. 调试技巧:在开发过程中,调试是非常重要的一环。你可以学习如何使用调试器和仿真器进行代码的单步调试、变量查看和性能分析,以提高开发效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值