• 18.示例程序(编码器接口测速)


     STM32标准库开发-各章节笔记-查阅传送门_Archie_IT的博客-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_61712829/article/details/132434192?spm=1001.2014.3001.5501

    main.c

    这段代码主要作用是通过定时器定时执行 `TIM2_IRQHandler` 中断服务程序,在定时器中断处理函数中读取编码器的值,并将其存储在 `speed` 变量中,然后在主循环中利用 OLED 显示器显示速度值。

    值得注意的是,在 `main` 函数中需要调用 `OLED_Init()` 进行 OLED 显示器的初始化,并在使用 OLED 显示的地方调用 `OLED_ShowString` 和 `OLED_ShowSignedNum` 函数进行显示。

    除了这些代码片段外,程序的其他部分,例如 `OLED_Init`、`Timer_Init`、`Encoder_init` 等函数的定义以及头文件的包含内容,以及关于定时器和编码器的配置,也是非常重要的。

    1. #include "stm32f10x.h" // Device header
    2. #include "Delay.h"
    3. #include "OLED.h"
    4. #include "Timer.h"
    5. #include "Encoder.h"
    6. uint16_t speed;
    7. int main(void)
    8. {
    9. OLED_Init(); //初始化OLED
    10. Timer_Init(); //初始化定时器
    11. Encoder_init();
    12. OLED_ShowString(1,1,"speed:");
    13. while(1)
    14. {
    15. OLED_ShowSignedNum(1,7,speed,5);//每隔一段时间读取一次;用定时中断
    16. }
    17. }
    18. //定时器2中断函数放在使用中断的main.c文件中;在startup文件中;定时中断每隔1s执行一次
    19. void TIM2_IRQHandler(void) //当定时器产生更新中断时,这个函数就会自动被执行
    20. {
    21. //检查中断标志位
    22. if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
    23. {
    24. //执行相应的用户代码
    25. speed = Encoder_Get(); //定时器每隔1s读取一下速度,存在speed变量里
    26. TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除标志位
    27. }
    28. }

    Encoder.c

    这段代码是针对 STM32 微控制器的编码器初始化和测速函数的实现,用于读取编码器的旋转位置和速度。以下是对代码的简要说明:

    1. `Encoder_init` 函数是编码器的初始化函数,主要包括了以下几个步骤:
       - 开启时钟,选择内部时钟,以及初始化 GPIO 接口。
       - 配置时基单元 TIM3,设置预分频器、计数器模式和周期等参数。
       - 配置输入捕获单元(通道)TIM_ICInit,设置滤波器和极性。
       - 最后调用 `TIM_EncoderInterfaceConfig` 函数配置编码器接口。
       - 启动定时器 TIM3。

    2. `Encoder_Get` 函数是用于测速的函数,主要实现了在固定的时间间隔内读取一次计数器的值,并清零计数器。函数返回了测量得到的编码器的变化值,即速度信息。

    1. #include "stm32f10x.h" // Device header
    2. //编码器旋转控制CNT自增自减
    3. //编码器初始化函数,编码器电路初始化后,CNT就会随着编码器旋转而自增自减;直接读出CNT值就能测量编码器的位置;测量编码器的速度和方向就需要每隔一段固定的闸门时间取出一次CNT然后再把CNT清零这就是测频法测量速度了
    4. /*
    5. 第一步,RCC开启时钟,开启GPIO和定时器的时钟
    6. 第二步,配置GPIO,需将PA6和PA7配置成输入模式
    7. 第三步,配置时基单元,预分频器一般选择不分频,ARR一般给最大值655535,只需要CNT执行计数就行了
    8. 第四步,配置输入捕获单元,这里只有滤波器和极性两个参数有用,后面的参数没有用到,与编码器无关
    9. 第五步,配置编码器接口模式,直接调用一个库函数
    10. 最后,调用TIM_Cmd,启动定时器
    11. */
    12. void Encoder_init(void)
    13. {
    14. //1.打开时钟,选择内部时钟
    15. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    16. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    17. //2.初始化GPIO
    18. GPIO_InitTypeDef GPIO_InitStructure;
    19. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入,与外部模块保持默认电平一致(上拉与下拉的选择原则);一般来说是默认高电平,所以一般上拉输入用的比较多;若不确定外部模块输出的默认状态或外部信号输出功率非常小,这时就尽量选择浮空输入(浮空输入:没有上拉和下拉电阻去影响外部信号,缺点是当引脚悬空,没有默认的电平了,输入就会受噪声干扰,来回不断地跳变)
    20. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    21. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    22. GPIO_Init(GPIOA,&GPIO_InitStructure);
    23. //不需要初始化时基单元下面这个内部时钟函数,因为编码器接口会托管时钟,编码器接口就是一个带方向控制的外部时钟,所以内部时钟就不用了
    24. //TIM_InternalClockConfig(TIM3);
    25. //3.配置时基单元
    26. /*
    27. 公式:
    28. PWM 频 率:Freq = CK_PSC / (PSC + 1) / (ARR + 1)
    29. PWM占空比:Duty = CCR / (ARR + 1)
    30. PWM分辨率:Reso = 1 / (ARR + 1)
    31. */
    32. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    33. TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //指定时钟分频
    34. TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,这个参数也是没有作用的,计数方向也是被编码器接口托管的
    35. TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; //ARR 周期 ,满量程计数,这样计数的范围是最大的而且方便换算成负数
    36. TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1; //PSC 预分频器,不分频,编码器的时钟直接驱动计数器
    37. TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器的值
    38. TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure); //初始化TIM3
    39. //4.配置输入捕获单元(通道),编码器接口只使用了通道12的滤波器和极性选择
    40. //首先定义结构体变量,然后StructInit给结构体赋一个初始值,再部分修改我们想要的参数,调用ICInit配置一遍电路,结构体变量的配置在调用ICInit函数之后就写入到硬件的寄存器了,所以ICInit之后这个结构体我们可以换个值继续使用、不需要重新定义新的结构体
    41. TIM_ICInitTypeDef TIM_ICInitStructure;
    42. TIM_ICStructInit(&TIM_ICInitStructure);//结构体初始化,防止结构体中出现不确定值可能造成问题,最好用StructInit给结构体赋一个初始值
    43. TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //通道1
    44. TIM_ICInitStructure.TIM_ICFilter = 0xF; //滤波器为0xF
    45. //TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //电平极性为上升沿,这里的上升沿参数代表的是高低电平极性不反转;等会配置编码器接口的时候也有极性配置,属于重复配置,这个其实可以删掉;这里的上升沿并不代表上升沿有效,因为编码器接口始终都是上升沿、下降沿都有效
    46. TIM_ICInit(TIM3, &TIM_ICInitStructure);
    47. TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; //通道2
    48. TIM_ICInitStructure.TIM_ICFilter = 0xF; //滤波器为0xF
    49. //TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //电平极性为上升沿,这里的上升沿参数代表的是高低电平极性不反转;等会配置编码器接口的时候也有极性配置,属于重复配置,这个其实可以删掉;这里的上升沿并不代表上升沿有效,因为编码器接口始终都是上升沿、下降沿都有效
    50. TIM_ICInit(TIM3, &TIM_ICInitStructure);
    51. //5.配置编码器接口,只需调用一个函数就行了;;需保证TIM_EncoderInterfaceConfig在TIM_ICInit函数之后,否则TIM_ICInit覆盖TIM_EncoderInterfaceConfig函数的配置
    52. TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);//选择Rising是通道不反相,选择Falling是通道反相;重复配置TIM_ICPolarity_Rising,后面的参数会覆盖前面的参数配置
    53. //6.启动定时器
    54. TIM_Cmd(TIM3,ENABLE);
    55. }
    56. int16_t Encoder_Get(void)
    57. {
    58. //测速,在固定的匝门时间读一次CNT然后把CNT清零
    59. int16_t temp;//因为要先读取CNT再清零,所以要用temp缓存一下
    60. temp = TIM_GetCounter(TIM3);//读取CNT
    61. TIM_SetCounter(TIM3,0);//CNT清零
    62. return temp;
    63. }

    Encoder.h

    这段代码是编码器模块的头文件 "Encoder.h" 的内容。它使用了条件编译指令,防止头文件的重复包含。

    在头文件中,声明了两个函数的原型:
    - `Encoder_init`:编码器的初始化函数。
    - `Encoder_Get`:获取编码器的值(位置或速度)的函数。

    同时,使用了预处理指令 `#ifndef`、`#define`、`#endif`,确保头文件只包含一次,以避免重复定义的错误。

    通过包含这个头文件,其他源文件就可以使用 `Encoder_init` 和 `Encoder_Get` 函数进行编码器的初始化和获取编码器的值。

    1. #ifndef __ENCODER_H
    2. #define __ENCODER_H
    3. void Encoder_init(void);
    4. int16_t Encoder_Get(void);
    5. #endif
  • 相关阅读:
    【王道】操作系统OS第三章存储系统(三)
    Linux下通过yum安装nginx【详细步骤】
    Golang高级数据结构
    Java spring boot 全解Camunda 7,从 0 到 1 构建工作流平台——第一节:各个开源框架对比
    xshell终端下tmux显示异常,显示多个状态栏
    用户注册场景
    Android 平板、手机: 忘记密码处理及刷机处理技术贴(以三星为例)
    java计算机毕业设计农村养老保险信息管理系统源码+系统+mysql数据库+lw文档
    STC15单片机-无线通讯(WIFI模块)
    AutoJs学习-实现区域截图+文字识别+摇一摇截图+截图查看器
  • 原文地址:https://blog.csdn.net/m0_61712829/article/details/133499078