1、接近开关说明
接近开关有PNP型和NPN型,还分常开与常闭。接近开关允许的电压范围在6~36V,本项目中给接近开关接入的为12V电压。PNP型,感应到金属时信号端与正极输出端接通输出高电平,信号输出端输出信号电压和正极输出端接入的电压相等,即为12V。由于单片机IO口能承受的最高电压为3.3V,所以需要给接近开关信号电压降压。降压电路如下图所示,然而实际测得无信号输出的时候,即接近开关未感应到金属时,OUT端输出电压为2.5V左右,有信号输出时为3.3V左右,电平边沿跨度不大,无法被输入捕获。于是,改进了该电路,去除了3.3V的电压,结果为无信号输入时为0V,有信号输入时为3.3V左右,可以被捕获,可以测得转速。
由于项目中电机转速高,需要采样频率高得接近开关,于是选择了齿轮转速传感器(实际上也是接近开关,不过采样频率能达到10KHz)。该传感器为NPN常开型,无输出信号时悬空(啥也没),有输出信号时输出端与负极输出端接通输出低电平,故NPN与PNP型的接近开关信号端电路又不一样。最后电路为3.3V电压串联10K上拉电阻再接上接近开关的信号端,最后接入GND形成闭合电路。整体电路在未感应到金属时输出高电平,有感应时输出低电平。
2、程序
程序主要有主程序、串口、时钟配置和中断服务程序5部分。
串口和时钟配置程序完全移植之前的代码,不需要特别的改动。
中断服务程序将测量脉宽的程序改成测量频率,即捕获两次上升沿。
主程序就是根据频率计算转速。
程序:
mian.c
#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp_usart.h"
#include "bsp_GeneralTim.h"
#include "bsp_led.h"
int main(void)
{
float n1,n2;
// int i,temp=0;
// float transmisson_radio[3]={1,2,3};
float time1,time2;
// TIM 计数器的驱动时钟
float TIM2_PscCLK = 72000000 / (GENERAL_TIM2_PSC+1);
float TIM3_PscCLK = 72000000 / (GENERAL_TIM3_PSC+1);
/* 串口初始化 */
USART_Config();
/* 定时器初始化 */
GENERAL_TIM_Init();
LED_GPIO_Config();
printf ( "\r\n STM32 输入捕获实验\r\n" );
printf ( "\r\n 电机转速测量\r\n" );
while ( 1 )
{
if(TIM2_ICUserValueStructure.Capture_FinishFlag == 1)
{
// 计算高电平时间的计数器的值
time1 = TIM2_ICUserValueStructure.Capture_Period * (GENERAL_TIM2_PERIOD+1) +
(TIM2_ICUserValueStructure.Capture_CcrValue+1);
n1=60*TIM2_PscCLK/time1;
// 打印高电平脉宽时间
printf ( "\r\n测得电机1转速:%0.4f r/min\r\n",n1);
TIM2_ICUserValueStructure.Capture_FinishFlag = 0;
}
if(TIM3_ICUserValueStructure.Capture_FinishFlag == 1)
{
// 计算高电平时间的计数器的值
time2 = TIM3_ICUserValueStructure.Capture_Period * (GENERAL_TIM3_PERIOD+1) +
(TIM3_ICUserValueStructure.Capture_CcrValue+1);
n2=60*TIM3_PscCLK/time2;
// 打印高电平脉宽时间
printf ( "\r\n测得电机2转速:%0.4f r/min\r\n",n2);
TIM3_ICUserValueStructure.Capture_FinishFlag = 0;
}
// Delay(0xfff);
if(TIM2_FLAG==1 && TIM3_FLAG==1)
{
if(n1>=n2)
{
printf("传动比:%0.5f \r\n",n1/n2);
if((n1/n2<2.47 && n1/n2>2.421)||(n1/n2<1.3635 && n1/n2>1.3365))
{
GPIO_ResetBits(LED1_GPIO_PORT, LED1_GPIO_PIN);
GPIO_SetBits(LED2_GPIO_PORT, LED2_GPIO_PIN);
// printf("判断1\r\n");