STM32正交编码器接口

发布者:BlissfulHiker最新更新时间:2018-07-19 来源: eefocus关键字:STM32  正交编码器接口 手机看文章 扫描二维码
随时随地手机看文章

一、主要内容

  1. 芯片型号、使用引脚及初始化程序源码

  2. TIM2端口重映射问题

  3. 与JTAG接口冲突时的现象及解决方法

二、芯片型号、使用引脚及初始化程序源码

芯片型号:STM32F103RET6 
使用定时器:TIM2、TIM3、TIM4、TIM5 
使用引脚: 
     TIM2—PA15、PB3(remap) 
     TIM3—PA6、PA7 
     TIM4—PB6、PB7 
     TIM5—PA0、PA1 
初始化程序源码: 
(其中TIM2的配置有特殊需要注意的地方,其他配置相同,调试时遇到的问题和解决方法见下文)

#include "stm32f10x.h"

#include "encoder.h"



void TIM2_Mode_Config(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    TIM_ICInitTypeDef TIM_ICInitStructure;      


    //PA15 ch1, PB3 ch2 

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);


    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);        // 关闭JTAG功能

    GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);            // 重映射TIM2的CH1、CH2到PA15和PB3

    GPIO_StructInit(&GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;         

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStructure);                           

    GPIO_StructInit(&GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;         

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOB, &GPIO_InitStructure);                           


    TIM_DeInit(TIM2);

    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

    TIM_TimeBaseStructure.TIM_Period = 50000;

    TIM_TimeBaseStructure.TIM_Prescaler = 0;

    TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1 ;

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);              


    TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_BothEdge ,TIM_ICPolarity_BothEdge);

    TIM_ICStructInit(&TIM_ICInitStructure);

    TIM_ICInitStructure.TIM_ICFilter = 6;

    TIM_ICInit(TIM2, &TIM_ICInitStructure);


    TIM_ClearFlag(TIM2, TIM_FLAG_Update);

    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

    //Reset counter

    TIM2->CNT = 0;


    TIM_Cmd(TIM2, ENABLE);

}



void TIM3_Mode_Config(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    TIM_ICInitTypeDef TIM_ICInitStructure;      


    //PA6 ch1, PA7 ch2 

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);


    GPIO_StructInit(&GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;         

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStructure);                           


    TIM_DeInit(TIM3);

    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

    TIM_TimeBaseStructure.TIM_Period = 50000;

    TIM_TimeBaseStructure.TIM_Prescaler = 0;

    TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1 ;

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);              


    TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_BothEdge ,TIM_ICPolarity_BothEdge);

    TIM_ICStructInit(&TIM_ICInitStructure);

    TIM_ICInitStructure.TIM_ICFilter = 6;

    TIM_ICInit(TIM3, &TIM_ICInitStructure);


    TIM_ClearFlag(TIM3, TIM_FLAG_Update);

    TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);

    //Reset counter

    TIM3->CNT = 0;


    TIM_Cmd(TIM3, ENABLE);

}



void TIM4_Mode_Config(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    TIM_ICInitTypeDef TIM_ICInitStructure;      


    //PB6 ch1, PB7 ch2 

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);


    GPIO_StructInit(&GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;         

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOB, &GPIO_InitStructure);                           


    TIM_DeInit(TIM4);

    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

    TIM_TimeBaseStructure.TIM_Period = 50000;

    TIM_TimeBaseStructure.TIM_Prescaler = 0;

    TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1;

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);              


    TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_BothEdge ,TIM_ICPolarity_BothEdge);

    TIM_ICStructInit(&TIM_ICInitStructure);

    TIM_ICInitStructure.TIM_ICFilter = 6;

    TIM_ICInit(TIM4, &TIM_ICInitStructure);


    TIM_ClearFlag(TIM4, TIM_FLAG_Update);

    TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);

    //Reset counter

    TIM4->CNT = 0;


    TIM_Cmd(TIM4, ENABLE);

}



void TIM5_Mode_Config(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    TIM_ICInitTypeDef TIM_ICInitStructure;      


    //PA0 ch1 A,PA1 ch2 

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);


    GPIO_StructInit(&GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;         

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOB, &GPIO_InitStructure);                           


    TIM_DeInit(TIM5);

    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

    TIM_TimeBaseStructure.TIM_Period = 50000;

    TIM_TimeBaseStructure.TIM_Prescaler = 0;

    TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1;

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);              


    TIM_EncoderInterfaceConfig(TIM5, TIM_EncoderMode_TI12, TIM_ICPolarity_BothEdge ,TIM_ICPolarity_BothEdge);

    TIM_ICStructInit(&TIM_ICInitStructure);

    TIM_ICInitStructure.TIM_ICFilter = 6;

    TIM_ICInit(TIM5, &TIM_ICInitStructure);


    TIM_ClearFlag(TIM5, TIM_FLAG_Update);

    TIM_ITConfig(TIM5, TIM_IT_Update, ENABLE);

    //Reset counter

    TIM5->CNT = 0;


    TIM_Cmd(TIM5, ENABLE);

}

在使用时,读取TIMx->CNT寄存器中的数据即可。

三、 TIM2端口重映射问题

问题描述

在一开始调试的时候,TIM2的初始化程序和其他定时器的相同,这时旋转TIM2连接的编码器,计数没有变化,旋转TIM5连接的编码器时,TIM2和TIM5的计数同时变化并且数值相同。

解决方法

引脚定义 
引脚定义 
引脚定义

从手册中可以看出PA15和PB3的TIM2功能需要进行重映射,否则在PA0和PA1上编码器信号既进入TIM2,又进入TIM5,因此会导致TIM2和TIM5的计数相同。

在PA15和PB3作为TIM2编码器信号输入引脚时,需要进行IO重映射:

GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);            // 重映射TIM2的CH1、CH2到PA15和PB31

四、与JTAG接口冲突时的现象及解决方法

问题描述

在TIM2进行IO重映射后,仍不能正常使用,无论如何旋转编码器,计数器的值只有0、1、MAX三个值(在0上+1或-1)

解决方法

编码器模式中计数器样例 
从手册中编码器模式下的计数器变化过程中可以看出,当两相编码器的一个信号不变,另一个信号变化时,计数器计数值会在某个数值上下波动,和上述问题情况类似,因此猜测是因为编码器其中一相的信号没有捕获到。 
引脚定义 
引脚定义 
再次查阅手册发现PA15和PB3引脚的默认功能为JTAG功能,需要关闭后才能正确使用,否则JTDO为输出引脚,无法捕获到编码器信号,所以会出现计数值只有0,1,MAX三个值的现象。这里仅关闭JTAG功能,保留SWD以便调试使用:

    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);        // 关闭JTAG功能12

五、参考链接

http://blog.csdn.net/wang328452854/article/details/50579832 
http://www.openedv.com/posts/list/54017.htm 
http://www.openedv.com/posts/list/0/57077.htm


关键字:STM32  正交编码器接口 引用地址:STM32正交编码器接口

上一篇:深度解析stm32编码器模式(一)
下一篇:stm32的通用计数器用于编码器的脉冲计数

推荐阅读最新更新时间:2024-03-16 16:09

STM32 GPIO 配置
固件库 V3.5 IAR /******************************************************************************* * 函数名称: GPIO_Configuration * 函数功能: 设置各GPIO端口功能 * 参数变量: NONE * 全局变量: NONE * 调用函数: * 修改时间: * 版 本: V1.0 * 状 态:调试完成 *******************************************************************************/ void GPIO_Configuration(voi
[单片机]
基于VS1003B的语音通信方法研究
简介:在通指装备模拟训练器材研发中,经常会遇到需要模拟实现语音通话功能的情况。常规的解决方案是在计算机上通过高级语言编程实现对声音的采集和播放,并通过局域网进行传输。考虑到语音通信的模块化和可控性,文中以STM32F107VCT6作为核心处理器,采用VS1003B作为语音采集和播放器件,通过CAN总线实现语音和信令传输,设计实现了一种低成本、高质量的语音通信方法。 1 VS1003B解码芯片介绍 VS1003B是由芬兰VLSI公司出品的一款单芯片的MP3/WMA/MIDI音频解码和ADPCM编码芯片,其内部电路如图1所示。由图可见,VS1003B包含一个高性能、具有自主产权的低功耗DSP处理器内核VSDSP,工作数据存储器
[单片机]
基于VS1003B的语音通信方法研究
STM32初学笔记2之Systick
前面花了近一周的时间完成了STM32中关于复位与系统时钟的学习,终于,现在可以开始下一个任务了:SysTick。也不知道接着学这个对不对,但是感觉全都是跟时钟有关的东东,就放一起来学学,应该没什么问题吧。 好吧,我不得不承认自己水平还不够,在第一个板子(金牛STM32F107VCT6)上跑了一个程序,但是没能成功,继续找原因吧。 接下来,我还是不死心,在另外一块板子(ALIENTEK STM32F103RBT6)上面写了一个使用SysTick定时的代码,结果运行成功,在这里分享出来,以作以后复习只用。 ////////////////////////////////////////////////////////
[单片机]
14. 独立看门狗实验
一。 看门狗概述 1. 为什么要用看门狗 2. 看门狗要解决的问题 STM32有两个看门狗 独立看门狗 窗口看门狗 3. 独立看门狗的功能描述 键值寄存器 KR (1)往KR中写入0xCCCC的时候,开始启动看门狗。 (2)计数器开始从其复位值0xFFF递减,当计数到0的时候会产生一个复位信号RESET。 (3)如果在某个时候往KR寄存器中写入0xAAAA(喂狗),自动重装载寄存器RLR的值就会重新加载到计数器中,从而避免看门狗复位。 如果能够及时喂狗,计数器的值就无法到0,从而程序可以正常运行。 在由单片机构成的微型计算机系统中,由于单片机的工作常常会受到来自外界电磁场的干扰, 造成程序跑
[单片机]
14. 独立看门狗实验
如何使用STM32_V3.5版本固件库建立工程模板
准备工作如下: 1:下载STM32_V3.5的固件库 去论坛上找,很多 2:准备Keil uVision4 软件,并安装到电脑上。 3:不要带板凳了,带上你的脑袋就行,因为板凳不会思考。 开始: 1:首先解压缩下载的固件库(保留一个备份,你懂的) 里面有, _htmresc : ST的 logo完全无用,不用理会, Libraries: 比较重要的文件 包含STM32的系统文件和大量头文件,也就是库文件了。 Project: 包含大量外设的例程,和各个软件版本的评估版工程模板。 KEIL对应的就是 MDK-ARM 文件下的工程模板。你也可以利用这
[单片机]
如何使用STM32_V3.5版本固件库建立工程模板
CC1101接口STM32
【目的】 移植原来TI对于CC1101与MSP430接口库到STM32平台,参考原TI库应用笔记 MSP430 Interface to CC1100/2500 Code Library ,做到尽量保持所有函数名不改变,以方便以前基于MSP430的程序向STM32移植。 【要求】 1.编程要求:改写原来基于MSP430的程序,使用于STM32,尽量保持所有函数名不改变,以方便以前基于MSP430的程序向STM32移植。 2.实现功能:STM32与CC1101通过SPI接口正常传输数据,不同节点的CC1101可以正常传输数据。 3.实验现象:STM32与CC1101连接后,可以与另一个节点通信
[单片机]
CC1101<font color='red'>接口</font>与<font color='red'>STM32</font>
STM32学习笔记3——stm32系统时钟树
①HSI 是内部高速时钟, RC 振荡器, 频率为 8MHz。 可作为系统时钟或 PLL 锁相环的输入。 ②HSE 是外部高速时钟。 可通过外接一个频率范围是 4-16MHz 的时钟或者晶振。 HSE 可以作为系统时钟和 PLL 锁相环输入, 还可以经过 128 分频后输入给 RTC。 ③LSI 是内部低速时钟, RC 振荡器, 频率大约为 40K, 可供独立看门狗和 RTC 使用, 并且独立看门狗只能使用 LSI 时钟。 ④LSE 是外部低速时钟,芯片上有相应的外部低速时钟管脚。 通常在此管脚上外接一个 32.768KHz 的晶振, 供 RTC使用。 ⑤PLL 是锁相环, 用于倍频输出。
[单片机]
<font color='red'>STM32</font>学习笔记3——<font color='red'>stm32</font>系统时钟树
STM32 串口通讯 发送 接收
STM32的使用有利有弊,种类多---但是种类有太多,资料也是比较乱的,还有就是库的调用,经常忘记一些函数的使用------比如最常用的串口------ ------------------------------------------------------------------------------USART ----设置------------------------------- void USART1_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure;
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved