首页 > 其他分享 >CMS32L051使用旋转编码器

CMS32L051使用旋转编码器

时间:2024-09-18 10:20:28浏览次数:3  
标签:knob 触发 编码器 tick value 旋转 mgr CMS32L051 first

文章目录

概要

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中断中的,计时可能不是很准,不过对于旋钮的信号是够用的,如果需要使用精准定时,可以单独使用一个定时器进行计时。

标签:knob,触发,编码器,tick,value,旋转,mgr,CMS32L051,first
From: https://blog.csdn.net/wwfsdffinf/article/details/142250944

相关文章

  • CMS32L051定时器时钟选择
    文章目录概要代码小结概要CMS32L051的定时器搭载两个通用定时器单元,每个单元含有4个通道。每个通用定时器单元有4个16位定时器。各16位定时器称为“通道”,既能分别用作独立的定时器,也能组合多个通道用作高级的定时器功能。定时器时钟选择寄存器m(TPSm)是16位寄存器,选......
  • 旋转链表
    旋转链表开头:对于链表的建立已经熟悉,那我们现在讲讲旋转链表的如何实现,当然旋转链表的建立是在已经掌握普通链表的基础上讲解。正文:旋转链表,顾名思义就是让链表“动起来”。即:使链表尾部最后的结点转到链表首部的位置。假设已经建立好一条6个结点的链表,它的初始状态如下图:我......
  • opencv学习:图像旋转的两种方法,旋转后的图片进行模板匹配代码实现
    图像旋转在图像处理中,rotate和rot90是两种常见的图像旋转方法,它们在功能和使用上有一些区别。下面我将分别介绍这两种方法,并解释它们的主要区别rot90 方法rot90方法是NumPy提供的一种数组旋转函数,它主要用于对二维数组(如图像)进行90度的旋转。这个方法比较简单,只支持9......
  • 深度学习自编码器 - 正则自编码器篇
    序言深度学习领域中,自编码器(Autoencoder\text{Autoencoder}Autoencoder)作为一种无监督学习技术,凭借其独特的结构在数据降维、特征提取、异常检测及数据去噪等方面展现出......
  • Arduino ESP32 oled显示,增量式编码器测距程序
      ESP3214引脚接编码器A,13引脚接编码器B,21、22为I2C默认引脚,程序根据编码器A触发ESP32的22脚中断,然后判断编码器B在ESP32的21脚状态是高电平还是低电平,来决定编码器是正转还是反转,也就是数值应该加还是减。   程序设计为编码器转一圈为1000个脉冲也就是编码器分辨率......
  • WebGL系列教程七(二维及三维旋转、平移、缩放)
    目录1前言2二维2.1平移2.2旋转2.3缩放3三维3.1平移3.2旋转3.2.1绕XXX轴旋转3.2.2绕......
  • 旋转按钮—C#自定义控件1
    C#自定义控件—旋转按钮 C#用户控件之旋转按钮按钮功能:手自动旋转,标签文本显示、点击二次弹框确认(源码在最后边);【制作方法】找到控件的中心坐标,画背景外环、内圆;再绘制矩形开关,进行角度旋转即可获得;【关键节点】No.1获取中心坐标,思考要绘制图形的相对坐标、宽度......
  • 刷题活动(旋转和翻转)
        前两天打了CCPC网络赛(让打老实了),现在认识到了刷题的重要性,于是我开创了这么个栏目,我们一起刷一下题。    还是在ACwing网站上刷题 旋转和翻转         首先,申一下题目,输入一个数字n,来表示矩阵的行和列,之后输入两个矩阵,判断一下两个矩阵相......
  • 2.10 某容器内侧是由曲线x^2+y^2=4y(1<=y<=3)与x^2+y^2=4(y<=1)绕y轴旋转一周而形成的曲
    点击查看代码fromscipy.integrateimportquadimportnumpyasnp#第一部分:抛物线旋转体(修正后)defV1_quad(y):returnnp.pi*(4*y-y**2)V1_corrected,_=quad(V1_quad,1,3)#第二部分保持不变V2=0.5*(4/3)*np.pi*2**3-(1......
  • 通过方向计算四元数旋转
    1//已知方向,求物体的旋转2publicstaticQuaternionGetRotation(Vector3knownDirection)3{4knownDirection.Normalize();5//Unity中的世界坐标系中,正前方通常为Vector3.forward(0,0,1)6Ve......