GD32-舵机的原理

GD32-舵机的原理

舵机的现一脉宽与舵机转动角度



旋转编码器的原理

顺时针:A的下降沿时,B处于高电平;

逆时针:A的下降沿时,B处于低电平;

复制代码
#ifndef _ENCODER_DRIVE_H
#define _ENCODER_DRIVE_H

#include "gd32f10x.h"
#include "systick.h"

#define ENCODER_L_PORT  GPIOA
#define ENCODER_L_PIN   GPIO_PIN_6

#define ENCODER_R_PORT  GPIOB
#define ENCODER_R_PIN   GPIO_PIN_14

#define ENCODER_D_PORT  GPIOA
#define ENCODER_D_PIN   GPIO_PIN_7


void encoder_init(void);    //初始化旋转编码器
void gpio_config(void);     //io口的配置
void exti_config(void);     //中断的配置

bit_status read_D(void);
bit_status read_L(void);
bit_status read_R(void);

uint8_t get_coder_num(void);
bool get_coder_d_flg(void);
#endif

#include "encoder_drive.h"

volatile uint8_t encoder_num = 0;
volatile bool encoder_d_flg = FALSE;     //标识旋转编码器被按下奇数次FALSE还是偶数次TRUE
volatile uint8_t encoder_direct_flg = 0; //可能的旋转方向标识

void encoder_init(void){    //初始化旋转编码器
	gpio_config();
	exti_config();
}

void gpio_config(void){     //io口的配置
	// 使能RCU时钟
	rcu_periph_clock_enable(RCU_GPIOA);
	rcu_periph_clock_enable(RCU_GPIOB);
	
	// 初始化io口的工作模式
	gpio_init(ENCODER_L_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, ENCODER_L_PIN);
	gpio_init(ENCODER_R_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, ENCODER_R_PIN);
	gpio_init(ENCODER_D_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, ENCODER_D_PIN);
}

//中断的配置
void exti_config(void){
	rcu_periph_clock_enable(RCU_AF);
	
	// 使能PA6线(exti_6)上的中断,表示L
	nvic_irq_enable(EXTI5_9_IRQn, 2U, 2U);
	gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOA, GPIO_PIN_SOURCE_6);// 给它配置中断源(io口)
	exti_init(EXTI_6, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
	exti_interrupt_flag_clear(EXTI_6);
	
	// 使能PB14线上的中断, 表示R
	nvic_irq_enable(EXTI10_15_IRQn, 2U, 2U);
	gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOB, GPIO_PIN_SOURCE_14);// 给它配置中断源(io口)
	exti_init(EXTI_14, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
	exti_interrupt_flag_clear(EXTI_14);
	
}

void EXTI5_9_IRQHandler(void){
	if(exti_interrupt_flag_get(EXTI_6) == SET){ //是否为EXTI_6触发的中断
		if(read_R() == SET){  //左转
			encoder_direct_flg = 1;  // 可能左转
		}else if(read_R() ==RESET){ //右一次可能的右转
			if(encoder_direct_flg == 2){  // 确认右转
				encoder_num = encoder_num < 1 ? 1 : encoder_num;
				encoder_num--;
				encoder_direct_flg = 0;
			}
		}
	}
	
	exti_interrupt_flag_clear(EXTI_6);
}


void EXTI10_15_IRQHandler(void){
	if(exti_interrupt_flag_get(EXTI_14) == SET){ //是否为EXTI_14触发的中断,即R引脚触发
		if(read_L() == SET){  //可能右转,第一次
			encoder_direct_flg = 2;  //记录右转的可能性
		}else if(read_L() ==RESET){ // 可能是第二次左转
			if(encoder_direct_flg == 1){  // 第一次、第二次可能左转叠加,
				encoder_num++;  //保证encoder++之后的结果不能大于180
				encoder_num = encoder_num > 180 ? 180 : encoder_num;
				encoder_direct_flg = 0;
			}
		}
	}
	
	exti_interrupt_flag_clear(EXTI_14);
}


bit_status read_D(void){
	return gpio_input_bit_get(ENCODER_D_PORT, ENCODER_D_PIN);
}
bit_status read_L(void){
	return gpio_input_bit_get(ENCODER_L_PORT, ENCODER_L_PIN);
}

bit_status read_R(void){
	return gpio_input_bit_get(ENCODER_R_PORT, ENCODER_R_PIN);
}

uint8_t get_coder_num(void){
	return encoder_num;
}

bool get_coder_d_flg(void){
	if(read_D() == RESET){//如果coder_d口输入是0
		delay_1ms(10);//等待10ms
		if(read_D() == RESET){//再次查看coder_d口输入是不是0
			while(read_D() == RESET);//如果还是0,等待0结束
			encoder_d_flg = encoder_d_flg ? FALSE : TRUE;//然后给encoder_d_flg取反
		} //否则,encoder_d_flg值不变
	}//否则 encoder_d_flg值不变
	
	return encoder_d_flg;
}
相关推荐
乐观勇敢坚强的老彭4 分钟前
信奥C++一维数组笔记
开发语言·c++·笔记
这就是佬们吗12 分钟前
Python入门⑤-异常处理、文件操作与实战项目
开发语言·数据库·python·算法·pycharm
asdzx6724 分钟前
Python PDF 拆分实战指南:单页拆分与按需页码范围拆分
开发语言·python·pdf
孬甭_34 分钟前
C++ vector
开发语言·c++
AOwhisky1 小时前
Python 学习笔记(第五期)——组合数据类型:列表、元组、集合与字典精讲——核心知识点自测与详解
开发语言·笔记·python·学习·云计算
灯澜忆梦10 小时前
GO_并发编程---定时器
开发语言·后端·golang
-银雾鸢尾-10 小时前
C#中的StringBuilder相关方法
开发语言·c#
-银雾鸢尾-11 小时前
C#中结构体与类的区别;抽象类与接口的区别
开发语言·c#
大模型码小白12 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程
段一凡-华北理工大学13 小时前
向量数据库实战:选型、调优与落地~系列文章12:文本分块策略实战:chunk_size 怎么选?重叠多少?
开发语言·数据库·后端·oracle·rust·工业智能体·高炉智能化