上篇[电机控制基础——定时器基础知识与PWM输出原理](https://bbs.eeworld.com.cn/thread-1157028-1-1.html)介绍了定时器的**输出**功能,本篇介绍定时器的**输入**功能。 # 1 问题引出 在单片机与嵌入式开发中,某些场景需要捕获传感器的高电平(或低电平)信号的持续时间,如红外解码信号、编码器输入信号等。 如下图,以单一的一段高电平输入信号为例,如何测量这段高电平的时间呢? 从直观上理解,就是要不断的检测这个信号,当信号从0变到1时,记录一个时间,再从1变到0时,记录另一个时间,两个时间差就是高电平的持续时间了。那具体要怎么编程呢?这就要用到定时器了。
# 2 定时器的捕获原理 上篇介绍了定时器的输出功能,本篇是利用定时器的输入功能,来计算脉冲时长。如下图: - 定时器的CNT计数器在不停的计数 - 首先配置定时器的输入通道为上升沿捕获,这样当检测到从0到1的跳变时,CCR1就会先保存当前的CNT值,同时CNT会清零重新开始计数 - 然后将定时器的输入通道为下降沿捕获,当检测从1到0的跳变时,CCR2就会先保存当前的CNT值 - 在这期间,CNT的计数值可能会溢出,这不影响,记录下溢出的次数,并重新开始计数即可 - 最终,t2-t1的高电平时间,就可以通过N次的溢出时间加CCR2保存的时间来计算获得了
# 3 定时器常用的寄存器 上篇介绍了定时器输出PWM时用到的几个寄存器(CR、CCMR、CNT、PSC、ARR、CCR等),这里再介绍几个捕获信号时需要用到的几个寄存器: ## 3.1 捕获/比较模式寄存器CCMR1 CCMR寄存器上篇已有介绍,只是上篇仅介绍了输出模式下的功能,本篇再介绍一下它在输入模式下的功能: 这些通道可用于**输入(捕获模式)**或**输出(比较模式)模式**。通道方向通过配置相应的 CCxS 位进行定义。此寄存器的所有其它位在输入模式和输出模式下的功能均不同。对于任一给定位 - OCxx 用于说明通道配置为输出时该位对应的功能 - ICxx 则用于说明通道配置为输入时 该位对应的功能 因此,必须注意同一个位在输入阶段和输出阶段具有不同的含义。
这里仅先介绍**输入模式**下的功能: - 位 15:12 **IC2F**:输入捕获 2 滤波器 (Input capture 2 filter) - 位 11:10 **IC2PSC[1:0]**:输入捕获 2 预分频器 (Input capture 2 prescaler) - 位 9:8 **CC2S**:捕获/比较 2 选择 (Capture/compare 2 selection) 用法参照下面的CC1S通道1 - 位 7:4 **IC1F**:输入捕获 1 滤波器 (Input capture 1 filter) 数字滤波器由事件计数器组成,每 N 个事件才视为一个有效边沿: - 0000:无滤波器 - 0001~1111:其它频率的滤波器 - 位 3:2 **IC1PSC**:输入捕获 1 预分频器 (Input capture 1 prescaler) 此位域定义 CC1 输入 (IC1) 的预分频比。只要 CC1E=0(TIMx_CCER 寄存器),预分频器便立即复位。 - 00:无预分频器,捕获输入上每检测到一个边沿便执行捕获 - 01~11:每发生 2 (4、8)个事件便执行一次捕获 - 位 1:0 **CC1S**:捕获/比较 1 选择 (Capture/Compare 1 selection),此位域定义通道方向(输入/输出)以及所使用的输入。 - 00:CC1 通道配置为输出 - 01:CC1 通道配置为输入,IC1 映射到 TI1 上 - 10:CC1 通道配置为输入,IC1 映射到 TI2 上 - 11:CC1 通道配置为输入,IC1 映射到 TRC 上。此模式仅在通过 TS 位(TIMx_SMCR 寄存器)选择内部触发输入时有效 注: 仅当通道关闭时(TIMx_CCER 中的 CC1E = 0),才可向 CC1S 位写入数据。 ## 3.2 捕获/比较使能寄存器CCER 我们要用到这个寄存器的最低 2 位, CC1E 和 CC1P。
- 位 15、11、7、3**CCxNP**:捕获 /比较x 输出极性 (Capture/Comparex output Polarity)。 - CCx 通道配置为输出: CCxNP 必须保持清零。 - CCx 通道配置为输入:此位与 CCxP 配合使用,用以定义 TI1FP1/TI2FP1 的极性。请参见 CCxP 说明。 - 位 14、10、6、2保留,必须保持复位值。 - 位 13、9、5、1**CCxP**:捕获 /比较x 输出极性 (Capture/Comparex output Polarity)。 - CCx 通道配置为**输出**: - 0:OCx 高电平有效 - 1:OCx低电平有效 - CCx 通道配置为**输入**: CCxNP/CCxP 位可针对触发或捕获操作选择 TI1FP1 和 TI2FP1 的极性。 - 00:非反相/上升沿触发 电路对 TIxFP1 上升沿敏感 (在复位模式、外部时钟模式或触发模式下执行捕获或触发操作), TIxFP1 未反相 (在门控模式或编码器模式下执行触发操作)。 - 01:反相/下降沿触发 电路对 TIxFP1 下降沿敏感 (在复位模式、外部时钟模式或触发模式下执行捕获或触发操作), TIxFP1 反相 (在门控模式或编码器模式下执行触发操作)。 - 10:保留,不使用此配置。 - 11:非反相/上升沿和下降沿均触发 电路对 TIxFP1 上升沿和下降沿都敏感(在复位模式、外部时钟模式或触发模式下执行捕获或触发操作),TIxFP1 未反相(在门控模式下执行触发操作)。编码器模式下不得使用此配置。 - 位 12、8、4、0**CCxE**:捕获 /比较 x 输出使能 (Capture/Comparex output enable)。 - CCx 通道配置为**输出**: - 0:关闭––OCx 未激活 - 1:开启––在相应输出引脚上输出 OCx信号 - CCx 通道配置为**输入**: 此位决定了是否可以实际将计数器值捕获到输入捕获/比较寄存器 1 (TIMx_CCR1) 中。 - 0:禁止捕获 - 1:使能捕获 ## 3.3 DMA/中断使能寄存器DIER 我们需要用到中断来处理捕获数据,所以必须开启通道 1 的捕获比较中断,即 **CC1IE **设置为 1 。
- 位 15、13、7、5 保留,必须保持复位值。 - 位 14 **TDE**:触发 DMA 请求使能 (Trigger DMA request enable) - 位 12~位9 **CCxDE**:捕获/比较x DMA 请求使能 (Capture/Compare 1 DMA request enable) - 位 8 **UDE**:更新 DMA 请求使能 (Update DMA request enable) - 位 6 **TIE**:触发信号(TRGI)中断使能 (Trigger interrupt enable) - 位 4~位1 **CCxIE**:捕获/比较x 中断使能 (Capture/Compare 1 interrupt enable) - 位 0 **UIE**:更新中断使能 (Update interrupt enable) # 4 编程 ## 4.1 定时器初始化 ### 4.1.1 GPIO初始化 这里用到的是定时器5的通道1,根据STM32F407的数据手册“3 Pinouts and pin description”中的“Table 9. Alternate function mapping”复用引脚说明表,可以看到定时器5通道1对应的引脚位A0,所以使用A0作为信号的输入引脚。
因此程序中对A0引脚可以这样配置,注意一定要**配置引脚的复用功能**: ```c GPIO_InitTypeDef GPIO_InitStructure; /*GPIO 结构体*/ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能PORTA时钟 /*输入信号的GPIO初始化*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //GPIOA0 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; /*复用功能*/ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; /*下拉*/ GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA0 GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM5); //PA0复用位定时器5 ``` ### 4.1.2 时基初始化 使用定时器,时基初始化是必不可少的,就是要设置一些计数的频率与溢出值(自动重装载值): ```c TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure; /*时基 结构体*/ /*时基初始化*/ TIM_TimeBaseStructure.TIM_Period=arr; /* 自动重装载值 */ TIM_TimeBaseStructure.TIM_Prescaler=psc;/* 定时器分频 */ TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式 TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure); ```
定时器的输入输出功能是必测项
谢谢分享
感谢分享~~希望分享更多关于电机的资料和经验
编码输入这么麻烦,唉,电机也不好搞
引用: ddllxxrr 发表于 2021-3-7 20:02 编码输入这么麻烦,唉,电机也不好搞
对于电机的正交编码器,定时器有专门的编码器模式,配置好后可以自动读取编码器的计数值,就不需要手动切换上下沿捕获了,下一篇文章会介绍编码器接口