嵌入式外设集 -- 旋钮编码器(360度)

目录

一、介绍

关注微信公众号--星之援工作室 发送关键字(360旋钮编码器)

使用的注意事项

技术参数

二、关键代码讲解

rotary.h

rotary.c

main.c 

三、参考

完整代码请关注卫星公众号进行获取和咨询


一、介绍

旋钮电位器是一种电子元器件,通常用于控制电路中的电阻值。它包括一个旋转式旋钮和一个电阻体。通过旋转旋钮,可以改变电阻体的阻值,从而改变电路中的电流、电压或功率等参数。旋钮电位器常用于音量控制、亮度控制、温度控制等应用领域。一般来说,旋钮电位器的阻值和功率是其最主要的性能指标。常见的旋钮电位器类型包括单轨、双轨、三轨等,同时还有分别用于直流和交流电路的电位器。

关注微信公众号--星之援工作室 发送关键字(360旋钮编码器)

➡️🫡🫡🫡🫡🫡🫡🫡🫡➡️

使用的注意事项

1. 本文章使用的编码器位360度,主要使用的外部中断已经io口的高低电平的判断进行电位器左右旋转的状态进行实时刷新和获取。

2. 主要哦本文章使用的电位器额定电压为5V,需要主要接入的电源部分。

技术参数

额定电压: DC 5V;

各相导线: 0.5mA(Max 5mA;Min 0.5mA)

公共导线:1mA(Max 10mA;Min 0.5mA)

使用温度范围::-30℃ to+80℃

二、关键代码讲解

 1.我们首先再rotary.h文件里进行io口的定义,并且使用一个结构体来储存我们的旋转变量,示例代码如下

rotary.h

#ifndef __EXTI_H
#define	__EXTI_H


#include "stm32f10x.h"
#include "sys.h"

//引脚定义
#define KEY1_INT_GPIO_PORT         GPIOB
#define KEY1_INT_GPIO_CLK          (RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO)
#define KEY1_INT_GPIO_PIN          GPIO_Pin_8
#define KEY1_INT_EXTI_PORTSOURCE   GPIO_PortSourceGPIOB
#define KEY1_INT_EXTI_PINSOURCE    GPIO_PinSource8
#define KEY1_INT_EXTI_LINE         EXTI_Line8
#define KEY1_INT_EXTI_IRQ          EXTI9_5_IRQn

#define KEY1_IRQHandler            EXTI9_5_IRQHandler


#define KEY2_INT_GPIO_PORT         GPIOB
#define KEY2_INT_GPIO_CLK          (RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO)
#define KEY2_INT_GPIO_PIN          GPIO_Pin_9
#define KEY2_INT_EXTI_PORTSOURCE   GPIO_PortSourceGPIOB
#define KEY2_INT_EXTI_PINSOURCE    GPIO_PinSource9
#define KEY2_INT_EXTI_LINE         EXTI_Line9
#define KEY2_INT_EXTI_IRQ          EXTI9_5_IRQn

#define KEY2_IRQHandler            EXTI9_5_IRQHandler

typedef struct
{
    u8 Left_State;  // 左旋转的标志位
    u8 Right_State; // 右旋转的标志位
		u16 Turn_Num; 	// 旋转度数

} Left_Right_Typedef; // 电导模式定义

extern Left_Right_Typedef turn_init;    // 旋转模式

#define Turn_Left  PBin(8) 
#define Turn_Right PBin(9) 


void EXTI_Key_Config(void);
//监测是否停止旋转
void Check_Turn(void);

#endif /* __EXTI_H */

2.通过io口的外部中端来监测那一边先触发,并将触发的状态进行更新,之后再通过轮询的方式监测io口高低电平的触发情况,以此来推断出我们的电位器是否处于旋转中,本代码都有详细的注释,示例代码如下

rotary.c

#include "rotary.h"
Left_Right_Typedef turn_init;    // 旋转模式
 /**
  * @brief  配置嵌套向量中断控制器NVIC
  * @param  无
  * @retval 无
  */
static void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* 配置NVIC为优先级组1 */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  
  /* 配置中断源:按键1 */
  NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
  /* 配置抢占优先级 */
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /* 配置子优先级 */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  /* 使能中断通道 */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  
  /* 配置中断源:按键2,其他使用上面相关配置 */  
  NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ;
  NVIC_Init(&NVIC_InitStructure);
}

 /**
  * @brief  配置 IO为EXTI中断口,并设置中断优先级
  * @param  无
  * @retval 无
  */
void EXTI_Key_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure; 
	EXTI_InitTypeDef EXTI_InitStructure;

	/*开启按键GPIO口的时钟*/
	RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE);
  RCC_APB2PeriphClockCmd(KEY2_INT_GPIO_CLK,ENABLE);
												
	/* 配置 NVIC 中断*/
	NVIC_Configuration();
	
/*--------------------------KEY1配置-----------------------------*/
	/* 选择按键用到的GPIO */	
  GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;
  /* 配置为浮空输入 */	
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
  GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);

	/* 选择EXTI的信号源 */
  GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE); 
  EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;
	
	/* EXTI为中断模式 */
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	/* 上升沿中断 */
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  /* 使能中断 */	
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
	
  /*--------------------------KEY2配置-----------------------------*/
	/* 选择按键用到的GPIO */	
  GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN;
  /* 配置为浮空输入 */	
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
  GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);

	/* 选择EXTI的信号源 */
  GPIO_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE, KEY2_INT_EXTI_PINSOURCE); 
  EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;
	
	/* EXTI为中断模式 */
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	/* 下降沿中断 */
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  /* 使能中断 */	
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
}
//监测是否停止旋转
void Check_Turn(void)
{
	//左转
	if(Turn_Left==0&&turn_init.Left_State>0){
		if(turn_init.Turn_Num<=360){
			turn_init.Turn_Num++;
		}
		//重置触发
		turn_init.Left_State=5;
	}
	//判断是否停止旋转
	else if(Turn_Left==1&&turn_init.Left_State>0)
	{
		turn_init.Left_State--;
	}
	// 右转
	if(Turn_Right==0&&turn_init.Right_State>0){
		if(turn_init.Turn_Num>0){
			turn_init.Turn_Num--;
		}
		//重置触发
		turn_init.Right_State=5;
	}
	//判断是否停止旋转
	else if(Turn_Right==1&&turn_init.Right_State>0)
	{
		turn_init.Right_State--;
	}
}
//外部中断触发
void KEY1_IRQHandler(void)
{
  //确保是否产生了EXTI Line中断
	if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) 
	{
		// 排除已触发状态
		if(turn_init.Right_State==0){
			// 左转	
			turn_init.Left_State=5;

		}

	
    //清除中断标志位
		EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);     
	}  
	
	 //确保是否产生了EXTI Line中断
	if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET) 
	{
		// 排除已触发状态
		if(turn_init.Left_State==0){
			// 右转	
			turn_init.Right_State=5;

		}

    //清除中断标志位
		EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);     
	}  
}

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

3.最后我们直接在主函数进行轮询判断即可,也可以放到我们的定时器中执行,在这个了我给了一个延时,让他大约每30ms执行一次监测,节约硬件的cup

main.c 

/*--------------------------------------------------------*
 *                                       								  *
 *   星之援网络科技工作室学习资料v1.0    									*
 *		 时间:2022.7.14                    								*
 *		 程序介绍:外部中断               								  *
 *		 实现效果:按键改变板载LED的状态   								  *
 *     需求请联系:13648103287                            *
 *--------------------------------------------------------*
*/

#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "rotary.h" 
#include "usart.h"
int main(void)
{
	u16 i;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 	 //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	delay_init();
	// 串口初始化
	uart_init(115200);

	// LED 端口初始化 
	LED_GPIO_Config();
	/* 初始化EXTI中断,按下按键会触发中断,
	*  KEY1_IRQHandler和KEY2_IRQHandler,处理中断。
	*/
	EXTI_Key_Config(); 

	printf("init ok\n");
  while(1)
	{
		i++;
		if(i%3==0){
			//监测旋钮
			Check_Turn();
		}
		if(i%25==0){
			//监测旋钮
			i=0;
			printf("旋转数据: %d\n",turn_init.Turn_Num);
		}
		delay_ms(10);
	}
}

三、参考

STM32读取旋钮编码器icon-default.png?t=N7T8https://blog.csdn.net/qq_36958104/article/details/103577486?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170202402116800182182895%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=170202402116800182182895&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-6-103577486-null-null.nonecase&utm_term=%E6%97%8B%E9%92%AE%E7%BC%96%E7%A0%81%E5%99%A8&spm=1018.2226.3001.4450
STM32 编码器驱动/旋转编码器旋钮encodericon-default.png?t=N7T8https://blog.csdn.net/denghuajing/article/details/122683502?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170202402116800182119214%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=170202402116800182119214&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~top_click~default-1-122683502-null-null.nonecase&utm_term=%E6%97%8B%E9%92%AE%E7%BC%96%E7%A0%81%E5%99%A8&spm=1018.2226.3001.4450


完整代码请关注卫星公众号进行获取和咨询


  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是用汇编语言以51单片机为例的代码实现控制步进电机转动,转速通过电位器旋钮进行调速,并将电位器的采电压通过串口发送到电脑串口终端,通讯格式为9600, 8, N, 1: ``` ; 51单片机控制步进电机转动,转速通过电位器旋钮进行调速 ; 电位器电压通过串口发送到电脑串口终端,通讯格式:9600, 8, N, 1 ; P0.0 ~ P0.3 接步进电机的A ~ D 4个控制信号 ; P1.0 接电位器信号 ; P3.0, P3.1 分别接串口的RXD, TXD ORG 0 ; 程序入口地址 MOV P0, #0 ; P0口初始值为0,步进电机不转动 MOV P1, #0 ; P1口初始值为0,电位器不采 MOV TMOD, #20h ; 定时器1工作方式2,8位自动重装载 MOV TH1, #-3 ; 波特率9600,TH1初始值为-3 MOV SCON, #50h ; 串口工作方式1,8位数据,无校验位,1位停止位 SETB TR1 ; 启动定时器1 SETB ES ; 启用串口中断 SETB EA ; 全局中断允许 LOOP: MOV A, P1 ; 读取电位器信号 MOV P1, #0 ; 清零电位器信号 MOV R1, A ; 将电位器值保存到R1寄存器 MOV A, #4 ; 设置最小转速值(最大延时) SUBB A, R1 ; 计算转速对应的延时值 MOV R0, A ; 将延时值保存到R0寄存器 MOV A, P0 ; 读取步进电机控制信号 CPL A.0 ; 取反A0位,使步进电机控制信号发生变化 MOV P0, A ; 将控制信号输出到P0口 ACALL DELAY ; 延时等待下一个控制信号 SJMP LOOP ; 跳回循环 DELAY: MOV R2, #0FFh ; 设置计数器初值为0FFh DELAY_LOOP: DJNZ R2, DELAY_LOOP ; 计数器不为0则继续循环 DJNZ R0, DELAY_LOOP ; 延时计数不为0则继续循环 RET ; 延时结束返回 SERIAL_ISR: JNB RI, SERIAL_ISR_END ; 接收中断标志未置位则跳过 CLR RI ; 清除接收中断标志 MOV SBUF, R1 ; 发送电位器值 SERIAL_ISR_END: RETI ; 退出中断 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

阿柒学起来

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

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

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

打赏作者

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

抵扣说明:

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

余额充值