资讯详情

STM32 CubeMax TCRT5000L光电对管巡线 原理与实现

STM32 CubeMax TCRT5000L光电巡管 原理与实现

1. 光电对管的原理

电子生产中使用的光电对管通常是,该系列分为,两者的区别在于针脚的长度不同

在每个管道中包含一个光电二极管和一个,红外光电二极管不断向外发射红外线,红外线经外部环境反射后被光敏三极管吸收,光敏三极管导通的程度和吸收的红外线强度成正比。所以只要检测光敏三极管导通的程度就知道反射红外线材料的性质。一般颜色深的材质吸收红外线多,颜色浅的材质反射红外线多,这就是我们检测黑线的基本原理

根据原理图,光敏三极管导通后的输出值是连续的,所以我们可以通过ADC读取模拟值并将其送入单片机进行处理,以获得非常高的灵敏度。这种做法的缺点是算法复杂。如果管道数量较多,则会对其进行处理ADC提出高要求。因此,为了简单起见,我们通常将这个模拟值发送到一个在这种情况下,输出值只有0和1两种情况,单片机的负担会小以应付大多数场合

使用比较器的典型电路长度是目前的主流做法(仅供参考),使用多个光电将管道排成一排检测黑线

图中的三角形是电压比较器的符号,型号是LM393

典型的实物就像这样,是某宝买的模块

如果要买现成的模块,最好看一下上面有没有(直插贴片都可以),有电位器的一般可以调整比较器,可测黑线的灵敏度可以调整(上面没有电位器,可能要自己换电阻…)

此时的算法编写相对简单,只要使用GPIO读取高低电平

2. CubeMax配置

以上面发的那个实物模块为例,一共有5个光电对管,我们就需要5个输入引脚。这里最好使用而不是GPIO使用中断输入可以避免轮询检测,节省一些GPIO资源

因此,我们需要配置5个GPIO在配置引脚时,外部中断输入引脚,例如,作为中断输入,PA1和PB1.由于数字相同的引脚是共用的中断线,字母后引脚将覆盖字母前引脚(PB会覆盖PA),字母靠前的引脚的中断就不起作用了(详见数据手册)

由于该模块检测到黑线输出较低,因此需要设置为

最后,记得把外面,否则,中断冲突可能导致卡死,例如在外部输入中断函数中调用HAL_Delay时,就会与Time base中断冲突导致卡死

其他基本配置不再重复

3. 接线

模块与STM32的接线如下

对管模块 STM32
5V 5V
GND GND
OUT1 PB0
OUT2 PB1
OUT3 PB10
OUT4 PB11
OUT5 PB12

4. 代码编写

eletube.h内容如下

#ifndef _ELETUBE_H_  #define _ELETUBE_H_      #include "stm32f1xx.h"  #include <stdio.h>      ////光电管中断输入引脚  #define ETUBE_PIN_1  GPIO_PIN_0  #define ETUBE_PIN_2  GPIO_PIN_1  #define ETUBE_PIN_3  GPIO_PIN_10  #define ETUBE_PIN_4  GPIO_PIN_11  #define ETUBE_PIN_5  GPIO_PIN_12      #define ETUBE_PORT_1 GPIOB  #define ETUBE_PORT_2 GPIOB  #define ETUBE_PORT_3 GPIOB  #define ETUBE_PORT_4 GPIOB  #define ETUBE_PORT_5 GPIOB      void Etube_Check(void);//输出检测情况      #endif  

eletube.c内容如下

#include "eletube.h"      uint8_t etubeCkeck[5] = {1,1,1,1,1};//存储每个对管检测到黑线的状态,1未检测到,0探测到      void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)////输入中断处理函数  {      if(GPIO_Pin == ETUBE_PIN_1)//1号引脚      {          if(HAL_GPIO_ReadPin(ETUBE_PORT_1, ETUBE_PIN_1)//上升沿          {              etubeCkeck[0] = 1;          }          if(!HAL_GPIO_ReadPin(ETUBE_PORT_1, ETUBE_PIN_1)///下降沿          {              etubeCkeck[0] = 0;          }      }          else if(GPIO_Pin == ETUBE_PIN_2)//2号引脚      {          if(HAL_GPIO_ReadPin(ETUBE_PORT_2, ETUBE_PIN_2)//上升沿          {              etubeCkeck[1] = 1;          }          if(!HAL_GPIO_ReadPin(ETUBE_PORT_2, ETUBE_PIN_2)//下降沿          {              etubeCkeck[1] = 0;          }      }          else if(GPIO_Pin == ETUBE_PIN_3)//3号引脚      {          if(HAL_GPIO_ReadPin(ETUBE_PORT_3, ETUBE_PIN_3)//上升沿          {              etubeCkeck[2] = 1;          }          if(!HAL_GPIO_ReadPin(ETUBE_PORT_3, ETUBE_PIN_3)///下降沿          {              etubeCkeck[2] = 0;          }      }      else if(GPIO_Pin == ETUBE_PIN_4)//4号引脚      {          if(HAL_GPIO_ReadPin(ETUBE_PORT_4, ETUBE_PIN_4)//上升沿          {              etubeCkeck[3] = 1;          }          if(!HAL_GPIO_ReadPin(ETUBE_PORT_4, ETUBE_PIN_4)///下降沿          {              etubeCkeck[3] = 0;          }      }      else if(GPIO_Pin == ETUBE_PIN_5)//4号引脚      {          if(HAL_GPIO_ReadPin(ETUBE_PORT_5, ETUBE_PIN_5)//上升沿          {              etubeCkeck[4] = 1;          }          if(!HAL_GPIO_ReadPin(ETUBE_PORT_5, ETUBE_PIN_5)///下降沿          {              etubeCkeck[4] = 0;          }      }  }      void Etube_Check(void)//输出检测情况  {     uint8_t i = 0;      for(i = 0;i < 5;i  )      {          if(etubeCkeck[i] == 0) printf("  ");

        else if(etubeCkeck[i] == 1) printf("1  ");

        else {};

  

        printf("\r\n");

    }

}

之后在main函数里调用探测情况输出函数即可

while (1)

  {

    /* USER CODE END WHILE */

  

    /* USER CODE BEGIN 3 */

    Etube_Check();

    HAL_Delay(500);

  }

(记得自己将printf重定义)

5. 结果

输出正常,很ok

标签: 18种直插三极管包9011三极管对管电位器l0直插三极管68三极管f1

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台