【STM32】STM32之限位开关

本篇博文最后修改时间:2016年12月29日,01:13。


一、简介

本文介绍如何在STM32上使用限位开关


二、实验平台

库版本:STM32F10x_StdPeriph_Lib_V3.5.0

编译软件:MDK4.53

硬件平台:STM32开发板(主芯片stm32f103c8t6)

仿真器:JLINK


版权声明

博主:甜甜的大香瓜

声明:喝水不忘挖井人,转载请注明出处。

原文地址:http://blog.csdn.NET/feilusia

联系方式:897503845@qq.com

香瓜BLE之CC2541群:127442605

香瓜BLE之CC2640群:557278427

香瓜BLE之Android群:541462902

香瓜单片机之STM8/STM32群:164311667
甜甜的大香瓜的小店(淘宝店):https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i

四、实验前提

在进行本文步骤前,请先阅读并实现以下博文:

1、《STM32之NVIC》:http://blog.youkuaiyun.com/feilusia/article/details/52819709


五、 基础知识

1、限位开关是什么?

答:限位开关其实就是会复原开关的开关按键。

也就是说按下限位开关的开关能触发STM32的IO中断,而松开手指时限位开关会复原


2、限位开关有什么用?

答:通常被用于限制电机转动角度来使用。

例如两个限位开关形成45°的夹角,一旦电机转动触发任意其中一个限位开关,STM32检测到限位开关的中断则停止电机,不能再继续往此方向转动。


3、限位开关有什么优缺点?

答:限位开关的优点是以物理的方式触发单片机中断,因此不增加功耗。缺点是经常使用的话限位开关易损坏。


4、限位开关在软件上应如何开发?

答:由于限位开关通常是两个,因此按照普通按键的形式写两个按键,在按键中断中做停止电机等处理即可。


六、实验步骤

1、编写并添加限位开关驱动

1)编写驱动GUA_Limit_Switch.c(存放在“……\HARDWARE”)

//******************************************************************************              
//name:             GUA_Limit_Switch.c             
//introduce:        限位开关驱动      
//author:           甜甜的大香瓜                     
//email:            897503845@qq.com         
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2016.12.28                     
//******************************************************************************      
#include "stm32f10x.h" 
#include "GUA_Limit_Switch.h"

/*********************宏定义************************/
//引脚宏定义
#define GUA_LIMIT_SWITCH_UP_PORT							GPIOA
#define GUA_LIMIT_SWITCH_UP_PIN								GPIO_Pin_1

#define GUA_LIMIT_SWITCH_DOWN_PORT						GPIOA
#define GUA_LIMIT_SWITCH_DOWN_PIN							GPIO_Pin_4

/*********************内部函数************************/ 
static void GUA_Limit_Switch_IO_Init(void);
static void GUA_Limit_Switch_Exti_Init(void);

//******************************************************************************            
//name:             GUA_Limit_Switch_IO_Init           
//introduce:        限位开关的IO初始化         
//parameter:        none                 
//return:           none         
//author:           甜甜的大香瓜                 
//email:            897503845@qq.com     
//QQ group          香瓜单片机之STM8/STM32(164311667)                  
//changetime:       2016.12.28                     
//****************************************************************************** 
static void GUA_Limit_Switch_IO_Init(void)
{	
	//IO结构体
	GPIO_InitTypeDef GPIO_InitStructure;
		
	//时钟使能
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); 	
	
	//UP配置
	GPIO_InitStructure.GPIO_Pin = GUA_LIMIT_SWITCH_UP_PIN;  		
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 
	GPIO_Init(GUA_LIMIT_SWITCH_UP_PORT, &GPIO_InitStructure);	
	
	//DOWN配置
	GPIO_InitStructure.GPIO_Pin = GUA_LIMIT_SWITCH_DOWN_PIN;  		
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 
	GPIO_Init(GUA_LIMIT_SWITCH_DOWN_PORT, &GPIO_InitStructure);
}

//******************************************************************************            
//name:             GUA_Limit_Switch_Exti_Init           
//introduce:        限位开关的IO中断初始化         
//parameter:        none                 
//return:           none         
//author:           甜甜的大香瓜                 
//email:            897503845@qq.com     
//QQ group          香瓜单片机之STM8/STM32(164311667)                  
//changetime:       2016.12.28                     
//****************************************************************************** 
static void GUA_Limit_Switch_Exti_Init(void)
{	
	EXTI_InitTypeDef EXTI_InitStructure;

	//UP中断配置
	EXTI_ClearITPendingBit(EXTI_Line1);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);  

	EXTI_InitStructure.EXTI_Line = EXTI_Line1;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;  
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);
	
	//DOWN中断配置
	EXTI_ClearITPendingBit(EXTI_Line4);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource4);  

	EXTI_InitStructure.EXTI_Line = EXTI_Line4;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;  
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);	
}

//******************************************************************************        
//name:             GUA_Limit_Switch_Check_Pin        
//introduce:        限位开关检测触发状态    
//parameter:        nGUA_Limit_Switch_Status:GUA_LIMIT_SWITCH_STATUS_UP or GUA_LIMIT_SWITCH_STATUS_DOWN       
//return:           GUA_LIMIT_SWITCH_STATUS_IDLE or GUA_LIMIT_SWITCH_STATUS_TRIGGER      
//author:           甜甜的大香瓜             
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2016.12.28                     
//******************************************************************************   
GUA_U8 GUA_Limit_Switch_Check_Pin(GUA_U8 nGUA_Limit_Switch_Status)    
{    
  //UP限位开关
  if(nGUA_Limit_Switch_Status == GUA_LIMIT_SWITCH_STATUS_UP)
  {
    //没触发
    if(GPIO_ReadInputDataBit(GUA_LIMIT_SWITCH_UP_PORT, GUA_LIMIT_SWITCH_UP_PIN) == Bit_SET) 
    {
      return GUA_LIMIT_SWITCH_STATUS_IDLE;
    }
    //触发
    else
    {
      return GUA_LIMIT_SWITCH_STATUS_TRIGGER;    
    }  
  }
  //DOWN限位开关
  else
  {
    //没触发
    if(GPIO_ReadInputDataBit(GUA_LIMIT_SWITCH_DOWN_PORT, GUA_LIMIT_SWITCH_DOWN_PIN) == Bit_SET) 
    {
      return GUA_LIMIT_SWITCH_STATUS_IDLE;
    }
    //触发
    else
    {
      return GUA_LIMIT_SWITCH_STATUS_TRIGGER;    
    }    
  }  
} 

//******************************************************************************        
//name:             GUA_Limit_Switch_Init        
//introduce:        限位开关初始化     
//parameter:        none       
//return:           none      
//author:           甜甜的大香瓜             
//email:            897503845@qq.com           
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2016.12.28                     
//****************************************************************************** 
void GUA_Limit_Switch_Init(void)
{
  //初始化IO
  GUA_Limit_Switch_IO_Init();
	
  //初始化IO的中断配置
  GUA_Limit_Switch_Exti_Init();
}

2) 编写驱动头文件GUA_ Limit_Switch.h(存放在“ …… \HARDWARE ”)
//******************************************************************************              
//name:             GUA_Limit_Switch.h             
//introduce:        限位开关驱动头文件      
//author:           甜甜的大香瓜                     
//email:            897503845@qq.com         
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2016.12.28                     
//******************************************************************************  
#ifndef _GUA_LIMIT_SWITCH_H_
#define _GUA_LIMIT_SWITCH_H_

/*********************宏定义************************/   
#ifndef GUA_U8        
typedef unsigned char GUA_U8;        
#endif    

#ifndef GUA_8        
typedef signed char GUA_8;        
#endif      
      
#ifndef GUA_U16        
typedef unsigned short GUA_U16;        
#endif 

#ifndef GUA_16        
typedef signed short GUA_16;        
#endif         
      
#ifndef GUA_U32        
typedef unsigned long GUA_U32;        
#endif 

#ifndef GUA_32        
typedef signed long GUA_32;       
#endif

#ifndef GUA_U64    
typedef unsigned long long GUA_U64;  
#endif

#ifndef GUA_64    
typedef signed long long GUA_64;  
#endif

//可读的限位开关
#define GUA_LIMIT_SWITCH_STATUS_UP                    0            //UP限位开关
#define GUA_LIMIT_SWITCH_STATUS_DOWN                  1            //DWON限位开关

//限位开关的触发状态
#define GUA_LIMIT_SWITCH_STATUS_TRIGGER               0            //限位开关触发
#define GUA_LIMIT_SWITCH_STATUS_IDLE                  1            //D位开关没触发

/*********************外部函数声明************************/ 
GUA_U8 GUA_Limit_Switch_Check_Pin(GUA_U8 nGUA_Limit_Switch_Status);  
void GUA_Limit_Switch_Init(void);

#endif

3) 工程中添加GUA_Limit_Switch.c


4)在MDK设置中添加串口驱动源文件路径



2、设置NVIC中断优先级(GUA_NVIC.c的GUA_NVIC_Init中

	//限位开关UP键
	GUA_NVIC_Config(NVIC_PriorityGroup_2, EXTI1_IRQn, 1, 0, ENABLE);	

	//限位开关DOWN键
	GUA_NVIC_Config(NVIC_PriorityGroup_2, EXTI4_IRQn, 1, 1, ENABLE);	

3、写中断服务函数(stm32f10x_it.c中)

1)写中断服务函数

//******************************************************************************            
//name:             EXTI1_IRQHandler           
//introduce:        中断服务函数         
//parameter:        none                 
//return:           none         
//author:           甜甜的大香瓜                 
//email:            897503845@qq.com     
//QQ group          香瓜单片机之STM8/STM32(164311667)                  
//changetime:       2016.10.19                     
//******************************************************************************
void EXTI1_IRQHandler(void)
{
  if(EXTI_GetITStatus(EXTI_Line1) == SET)
  {
		/*
		//Up键,反转才停止
		if(stMotor_Config_2.DirectionSteps < 0)
		{
			stMotor_Config_2.Status = MOTOR_CONFIG_STATUS_IDLE;       //电机Y停止   
		}
    */
    //清除标志位  
    EXTI_ClearITPendingBit(EXTI_Line1);
  }
}

//******************************************************************************            
//name:             EXTI4_IRQHandler           
//introduce:        中断服务函数         
//parameter:        none                 
//return:           none         
//author:           甜甜的大香瓜                 
//email:            897503845@qq.com     
//QQ group          香瓜单片机之STM8/STM32(164311667)                  
//changetime:       2016.10.19                     
//******************************************************************************
void EXTI4_IRQHandler(void)
{
  if(EXTI_GetITStatus(EXTI_Line4) == SET)
  {
		/*
		//Down键,正转才停止  
		if(stMotor_Config_2.DirectionSteps > 0)
		{
			stMotor_Config_2.Status = MOTOR_CONFIG_STATUS_IDLE;       //电机Y停止   
		}
    */
    //清除标志位  
    EXTI_ClearITPendingBit(EXTI_Line4);
  }
}
这里分别写了两个限位开关,并且简单举例限制电机。

4、在应用层中调用

1)添加驱动头文件(main.c中)

#include "GUA_Limit_Switch.h"

2) 添加驱动初始化代码(main.c的main函数中)

  //限位开关初始化
  GUA_Limit_Switch_Init();

七、实验结果

仿真并设置断点在两个限位开关的中断服务函数中,全速运行后分别按下限位开关,可分别进中断服务函数。

因此实验成功。




### STM32 上实现限位开关功能 #### 创建新项目 打开STM32CubeMX,创建新的工程。在工程配置页面选择适用的STM32型号和时钟配置。进入Pinout & Configuration选项卡,找到用于连接限位开关的GPIO引脚,并将其配置为输入模式[^1]。 #### 配置 GPIO 输入 为了检测限位开关的状态变化,需要将对应的GPIO引脚设置成下拉或上拉电阻模式。通常情况下会采用内部上拉/下拉的方式简化外部电路设计: - 如果限位开关闭合时接地,则应选用内部上拉; - 若闭合连通电源则需使用内部下拉。 ```c // 初始化 GPIO 引脚为输入模式并使能内部上拉电阻 __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); ``` #### 编写读取逻辑 编写一段简单的程序周期性地轮询该引脚电平状态,判断是否有触发事件发生。可以利用定时器中断或其他机制来定期执行此操作以提高响应速度。 ```c if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET){ // 当前处于低电平表示限位开关被按下 } else{ // 此处代表高电平时的情况即未按下的常态 } ``` 对于更复杂的应用场景还可以考虑加入去抖动处理防止误判以及通过回调函数的形式异步通知主控单元有位置到达信号到来等特性增强鲁棒性和灵活性[^2]。 #### 使用 Keil 进行开发调试 考虑到当前所选芯片架构特点及其广泛接受度较高的集成环境建议优先选用Keil MDK作为主要IDE来进行后续编码工作。由于其良好的兼容性和丰富的资源库支持能够有效提升工作效率降低学习成本[^3]。 #### 主控制循环中的应用实例 假设在一个自动化控制系统中,限位开关用来监测机械臂的位置是否达到预设边界。可以在`main_control_loop()`函数内增加如下伪代码片段完成相应业务流程管理: ```c void main_control_loop(void) { while (1) { ... // 检查限位开关状态 if(is_limit_switch_triggered()){ stop_mechanical_arm_movement(); log_event("Mechanical arm reached limit position"); } ... HAL_Delay(MAIN_LOOP_DELAY); } } bool is_limit_switch_triggered(){ static uint8_t last_state = HIGH_LEVEL; bool current_state; current_state = !HAL_GPIO_ReadPin(LIMIT_SWITCH_PORT, LIMIT_SWITCH_PIN); if(current_state != last_state && current_state == LOW_LEVEL){ delay_ms(DEBOUNCE_TIME_MS); // 去除抖动延迟 if(!HAL_GPIO_ReadPin(LIMIT_SWITCH_PORT, LIMIT_SWITCH_PIN)){ last_state = LOW_LEVEL; return true; } else { last_state = HIGH_LEVEL; } } return false; } ``` 上述代码实现了对限位开关状态的持续监控,并且加入了基本的防抖措施确保动作准确性[^4]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

甜甜的大香瓜

谢谢你的支持^_^

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

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

打赏作者

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

抵扣说明:

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

余额充值