menu
AMENG
Carpe Diem and Do what I like.
调试STM32F207编码器时遇到的问题

access_time
brush 934个字
whatshot 69 ℃

一个项目需要对电机闭环控制,采用的霍尔编码电机。

QQ截图20211223163338.jpg

本来用的STM32F103ZET6,然后不知道咋回事芯片发热烧坏了,然后正好有一批STM32F207ZET6,对比了下IO口发现一样,就直接干上去了,干上去后发现3.3和GND处于短路状态,开始怀疑是3.3V电压出问题了,就把3.3V供电部分全部拆除了,发现还是短路,就又把芯片引脚仔细对了一遍,发现供电引脚有几个对不上。如下图

image.png

image.png

由于VSS和VDD芯片能不是相连的,所以少一路供电应该问题不大,就直接把这几个引脚掰断干上去了,烧下测试代码,成功运行,至此换芯片结束。

代码部分直接换库文件,移植过程还算简单。

但当调到编码器时,一直没有读数。一度怀疑是不是掰断那几个引脚引起的问题,无奈之下用STM32CubeMX生成的代码测试一下,发现可以正常读数,遂排除了硬件问题。然后对比发现了问题

调整前的代码
GPIO_PinAFConfig(GPIOA,
GPIO_Pin_9,GPIO_AF_4);
GPIO_PinAFConfig(GPIOA,
GPIO_Pin_10,GPIO_AF_4);

调整后的代码
GPIO_PinAFConfig(GPIOA,
GPIO_PinSource9,GPIO_AF_4);
GPIO_PinAFConfig(GPIOA,
GPIO_PinSource10,GPIO_AF_4);


不难看出,调整的就是上面红色参数部分。一个是GPIO_Pin_N,一个是GPIO_PinSourceN,其实这2个参数是不一样的。

GPIO_Pin_n可以理解为某端口脚在整个端口的位置。比方某GPIO口的第6管脚位置编码GPIO_Pin_6 被定义为 ((uint16_t)0x0040) ,在对相应GPIO管脚做基本属性配置时会用到,如配置输入输出模式、模拟输入模式的选择等。有兴趣的话,可以点击GPIO_Init( )进去看看。

GPIO_PinSourceN一般是在对某GPIO口相应pin脚的复用功能进行选择配置才会用到。它是根据端口各脚位的位置按顺序从0开始依次递增编号,可以理解为该管脚在该端口的序号。比方某GPIO口的第6号复用功能脚的序号GPIO_PinSource6 被定义为 ((uint8_t)0x06) 。有兴趣的话,也可以打开GPIO_PinAFConfig( )函数看看。显然,GPIO_PinSource6跟上面的GPIO_Pin_6的值相差甚远。


下面是ST官方库代码中有关GPIO_Pin_N的定义:

#define GPIO_Pin_0 ((uint16_t)0x0001)

#define GPIO_Pin_1 ((uint16_t)0x0002)

#define GPIO_Pin_2 ((uint16_t)0x0004)

#define GPIO_Pin_3 ((uint16_t)0x0008)

#define GPIO_Pin_4 ((uint16_t)0x0010)

#define GPIO_Pin_5 ((uint16_t)0x0020)

#define GPIO_Pin_6 ((uint16_t)0x0040)

#define GPIO_Pin_7 ((uint16_t)0x0080)

#define GPIO_Pin_8 ((uint16_t)0x0100)

#define GPIO_Pin_9 ((uint16_t)0x0200)

#define GPIO_Pin_10 ((uint16_t)0x0400)

。。。。。。

#define GPIO_Pin_15 ((uint16_t)0x8000)

#define GPIO_Pin_All ((uint16_t)0xFFFF)

下面是有关GPIO_PinSourceN的定义:

#define GPIO_PinSource0 ((uint8_t)0x00)

#define GPIO_PinSource1 ((uint8_t)0x01)

#define GPIO_PinSource2 ((uint8_t)0x02)

#define GPIO_PinSource3 ((uint8_t)0x03)

#define GPIO_PinSource4 ((uint8_t)0x04)

#define GPIO_PinSource5 ((uint8_t)0x05)

#define GPIO_PinSource6 ((uint8_t)0x06)

#define GPIO_PinSource7 ((uint8_t)0x07)

#define GPIO_PinSource8 ((uint8_t)0x08)

#define GPIO_PinSource9 ((uint8_t)0x09)

#define GPIO_PinSource10 ((uint8_t)0x0A)

。。。。。。

#define GPIO_PinSource15 ((uint8_t)0x0F)


贴出编码器驱动代码


void Encoder3_Init(void)
{    
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_ICInitTypeDef   TIM_ICInitStructure;
    GPIO_StructInit(&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = TIM3_CH1_PIN | TIM3_CH2_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用模式
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(TIM3_CH1_GPIO, &GPIO_InitStructure);
    //引脚映射
    GPIO_PinAFConfig(TIM3_CH1_GPIO, GPIO_PinSource6, GPIO_AF_TIM3);    
    GPIO_PinAFConfig(TIM3_CH1_GPIO, GPIO_PinSource7, GPIO_AF_TIM3);
    //定时器设置
    TIM_DeInit(TIM3);
    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
    TIM_TimeBaseStructure.TIM_Prescaler = 0;           //时钟分频
    TIM_TimeBaseStructure.TIM_Period = 65535;//计数器最大值
    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_Rising , TIM_ICPolarity_Rising );
    TIM_ICStructInit(&TIM_ICInitStructure);
    TIM_ICInitStructure.TIM_ICFilter = 15;
    TIM_ICInit(TIM3, &TIM_ICInitStructure);
    TIM_SetCounter(TIM3,0);
    TIM_Cmd(TIM3, ENABLE);
}


方向读取

encoder_1 = (TIM3->CR1 & 0X10)>>4;

数据读取

num = TIM3->CNT;

读取后清零

TIM3->CNT = 0;






#如无特别声明,该文章均为 AMENG 原创,转载请遵循 署名-非商业性使用 4.0 国际(CC BY-NC 4.0) 协议,即转载请注明文章来源。
#最后编辑时间为: 2021 年 12 月 25 日


create 添加新评论


account_circle
email
language
textsms