【STM32】外部时钟|红外反射光电开关

1.外部时钟

单片机如何对外部触发进行计数?先看一下内部时钟,内部时钟是接在APB1和APB2时钟线上的,APB1,APB2来自stm32单片机内部的脉冲信号,也叫内部时钟。我们用来定时。同样我们可以把外部的信号接入单片机,来对其进行计数功能呢?
在这里插入图片描述
这个GPIO口的数据就是外部的信号,当时为了保证稳定性,而是采用下面这种做法
在这里插入图片描述
我们知道每一个定时器都有四个输入通道TI1 ~TI4,而TI3 ~TI4不接入触发控制器,也就先不说,对于TI1和TI2对外部输入信号会做滤波处理,以及边沿检测,TI1FP1和TI2FP2既可以选择是上升沿,也可以下降沿触发,也可以双边沿触发,而TI1_ED只能双边沿触发,以及还有一个外部触发器单独的,ETR需要经过极性选择,边沿检测,预分频和输入滤波,边沿检测只能检测到上升沿,但是极性选择可以翻转电平,所以说既能检测高电平,也能检测到低电平,由于ETR输入到触发器的信号只能是内部时钟频率的1/4,所以我们可以调节预分频器改变,输入滤波的话是会有一定的抖动,而抖动的话,时间不会太长,所以我们可以根据一定频率的采样信号来进行采样,N次采样后,这N次采样到的电平是一样的,就说明不是抖动,因为抖动时间不会太长,所以还没有达到N次就出现电平不一样,来进行滤波.
触发器会在TI1FP1和TI2FP2和TI1_ED和ETR中选择一个信号进行控制,也被称为外部时钟模式1,而在ETR输入滤波后面也会直接接入到触发控制器,不借用从模式控制器

2.红外反射光电开关原理

在这里插入图片描述
VCC和GND来给模块供电,类似蓝色的灯泡用来发射红外光,而黑色的小灯泡用来接收红外光,黑色小灯泡检测出来的红外光强度以模拟量的形式输出到AO口,当接收的红外光强度很强(灯泡前有物体)时,对应的模拟量电压就越小,当接收红外光强度很弱时(灯泡前有黑色物体时或没有物体时),对应模拟量的电压就越大。
当接收红外光强度很强时,指示灯就会亮。
很强很弱的区分是有一个阈值,这个阈值可以由该模块上的一个电位器来调节,大于该阈值说明接收红外光强度低,但是AO模拟量电压大。
我们会用到他的DO引脚,当AO的电压大于阈值时,DO输出高电平,当AO电压小于阈值时,DO输出低电平。
总结:当灯泡前有物体,DO输出低电平,灯泡前有黑色物体时或没有物体时,DO输出高电平。

3.使用

我们可以将DO引脚当做ETR外部输入的信号,然后通过外部时钟模式1来对其脉冲来计数,将计数的结果打印在屏幕上。
注意主频时钟频率不要选择太大,因为滤波的时候,他的采样频率适合主频时钟频率有关系的,主频频率越大的话,采样频率就越大,相同的采集次数,假如说会采集5次,频率越大就是更小的时间间隔采集一次,这样有的抖动也就会逃脱滤波器的滤波。
在这里插入图片描述
定时器2的ETR是在PA0上,所以将DO引脚接在单片机的PA0引脚即可
在这里插入图片描述
这里的滤波要设置15,要不然等一下会在黑白交替的时候会有好多抖动,如果不滤波的话,这些抖动也会算在计数中。

#include <stdio.h>
#include "string.h"
#include "oled.h"
int main(void)
{

  
 


  
  OLED_Init();
  HAL_TIM_Base_Start(&htim2);//开启定时器2来对ETR外部输入信号计数
  int count=0;
  char message[50]="";


  while (1)
  {
	  count=__HAL_TIM_GET_COUNTER(&htim2);//将计数值放在count中

	  OLED_NewFrame();
	  sprintf(message,"count:%d",count);
	  OLED_PrintString(15, 15,message, &font16x16, OLED_COLOR_NORMAL);

	   OLED_ShowFrame();
	   HAL_Delay(100);

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

根据视频可以看出共计数19次,实现对下表黑条进行计数

在这里插入图片描述
同时我们可以使用外部时钟模式1中的TI1_ED进行双边沿检测,对于黑色条纹会有一个高电平,双边沿就会计数*2;

### STM32三轮小车循迹避障实现方案 #### 1. 系统概述 基于STM32F407微控制器的三轮循迹避障小车项目提供了完整的硬件设计和软件编程指导。此项目利用TB6612电机驱动模块控制两个直流电机,通过三路红外线传感器完成路径跟踪,并采用单个红外避障传感器处理障碍物检测[^1]。 #### 2. 主要组件介绍 - **核心处理器**: 使用高性能ARM Cortex-M4内核的STM32F407作为主控芯片。 - **电机驱动器**: TB6612是一款双H桥DC/步进马达驱动IC, 可以为两台独立运作的直流电动机供电并支持正反转操作。 - **循迹传感器组**: 包含三个IR发射接收对管组成的阵列用于识别地面黑白线条或其他对比度明显的边界条件。 - **避障探测装置**: 单一或多个红外反射光电开关负责感知周围环境中的固定物体位置信息。 #### 3. 软件架构说明 程序逻辑主要分为初始化配置、状态监测循环以及响应动作执行几个部分: ##### 初始化阶段 ```c // 定义全局变量存储当前工作模式(正常行驶 vs 寻找出路) volatile uint8_t mode = NORMAL_MODE; void setup() { // 设置GPIO引脚方向及外设时钟使能 GPIO_Init(); // 配置定时器产生PWM输出给定转速指令至电机接口 TIM_PWM_Config(); // 启用外部中断服务例程以便实时捕捉传感器变化事件 EXTI_Interrupt_Enable(); } ``` ##### 运行期间的状态判断与决策制定 ```c while (true) { switch(mode){ case NORMAL_MODE: TrackLine(); /* 执行常规轨迹跟随算法 */ CheckObstacle(); /* 并定期检查是否存在潜在碰撞风险 */ break; case AVOIDANCE_MODE: FindWayOut(); /* 尝试绕过阻碍恢复正常运行轨道 */ break; default: StopCar(); /* 默认情况下保持静止等待进一步指示 */ break; } } ``` ##### 动作实施细节 对于具体的转向行为,则依赖于预先设定好的PID参数调整左右两侧轮子之间的速度差异从而达到预期效果: ```c float CalculateSpeedDifference(float error){ static float lastError = 0; static int integralSum = 0; const float Kp = 1.2f, Ki = 0.5f, Kd = 0.3f; integralSum += error * SAMPLE_TIME_MS / 1000.f; float derivativeTerm = (error - lastError)/(SAMPLE_TIME_MS / 1000.f); lastError = error; return Kp*error + Ki*integralSum + Kd*derivativeTerm; } void AdjustMotorSpeeds(int leftPowerAdjustment, int rightPowerAdjustment){ SetLeftMotorDutyCycle(BASE_SPEED + leftPowerAdjustment); SetRightMotorDutyCycle(BASE_SPEED + rightPowerAdjustment); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

#小多子

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

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

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

打赏作者

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

抵扣说明:

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

余额充值