TIM

TIM

基于时间片轮询系统(仿RTOS)

回复

经验分享君莫笑 发起了问题 • 1 人关注 • 0 个回复 • 52 次浏览 • 2019-11-04 16:56 • 来自相关话题

设计一款基于STM32内部RTC的电子万年历,显示年月日 时分,可进行日期、时间调整

回复

新手交流慣性 发起了问题 • 1 人关注 • 0 个回复 • 58 次浏览 • 2019-10-18 08:51 • 来自相关话题

TIM中断callback总是不执行?

问题困惑admin 回复了问题 • 2 人关注 • 3 个回复 • 131 次浏览 • 2019-09-12 16:07 • 来自相关话题

怎么实现timer 触发DMA

回复

问题困惑lost_resister 发起了问题 • 1 人关注 • 0 个回复 • 112 次浏览 • 2019-09-08 10:13 • 来自相关话题

TIM1输入捕获模式测量脉冲宽度和频率 和 PWM输入模式的使用

软件教程陪你在坑里看动漫 回复了问题 • 17 人关注 • 8 个回复 • 21314 次浏览 • 2019-06-10 08:31 • 来自相关话题

STM32F429中Timer6使用问题

问题困惑STM32Cube_jack 回复了问题 • 2 人关注 • 2 个回复 • 620 次浏览 • 2019-05-04 19:13 • 来自相关话题

STM32F103定时器2外部时钟源超过150KHz后计数器不会自增加问题

回复

问题困惑frank1993 发起了问题 • 2 人关注 • 0 个回复 • 511 次浏览 • 2019-04-27 17:21 • 来自相关话题

关于串口接受9位字长的问题

问题困惑自带腹肌的西装 回复了问题 • 3 人关注 • 3 个回复 • 967 次浏览 • 2019-03-18 10:48 • 来自相关话题

关于定时器中断的相关问题

新手交流牙子男男 发表了文章 • 2 个评论 • 804 次浏览 • 2019-01-25 10:45 • 来自相关话题

新画了一个F334的板子,在CubeMX配置好定时中断,测试的时候发现定时中断进不去。纳了闷了,之前的板子定时中断很容易实现啊。。。刚开始担心晶振没起振,于是测了下晶振的波形。看着很完美,没问题。想了半天实在没想出来那儿没配置对。本来说好不找度娘的,,,艾玛,真香。发现在CubeMX配置好定时中断后,还需要在初始化中写入HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)这个函数,才能启动定时中断。加上这句话,中断就能进去啦,完美! 开贴记录程序设计过程中的各种坑 查看全部

新画了一个F334的板子,在CubeMX配置好定时中断,测试的时候发现定时中断进不去。纳了闷了,之前的板子定时中断很容易实现啊。。。刚开始担心晶振没起振,于是测了下晶振的波形。

TEK00000.PNG

看着很完美,没问题。

想了半天实在没想出来那儿没配置对。本来说好不找度娘的,,,艾玛,真香。

发现在CubeMX配置好定时中断后,还需要在初始化中写入HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)这个函数,才能启动定时中断。

image.png

加上这句话,中断就能进去啦,完美! 开贴记录程序设计过程中的各种坑

关于超声波等输入捕获实验

问题困惑乌龟也会飞 回复了问题 • 4 人关注 • 3 个回复 • 986 次浏览 • 2018-09-30 14:03 • 来自相关话题

如果使用SWD仿真,但是相应的引脚没有配置,会出现什么后果?

问题困惑谢~乾 回复了问题 • 4 人关注 • 4 个回复 • 1108 次浏览 • 2018-07-09 14:38 • 来自相关话题

(转)基于STM32Cube库的Timer捕获应用

软件教程admin 发表了文章 • 0 个评论 • 1757 次浏览 • 2018-06-14 09:19 • 来自相关话题

当使用Timer做捕获输入时,有时候需要将捕获得到的数据通过DMA方式写到定义好的数据或数组中,本文将详细介绍使用CubeMX配置PWM捕获功能,用户可以直接得到输入的PWM信号的频率以及占空比,Cube库可以很方便配置。实验过程中,当配置超过两个以上的Timer通道DMA时会遇到一些问题,本文也对其进行了说明并给出了解决方案。Timer2的PWM信号捕获功能√使用Timer的IC1,IC2两个捕获输入通道,两个通道的外部管脚输入配置为相同TI1通道;√两个通道的捕获输入极性,一个为Active,另外一个为Inactive;√其中一个TI1FP1作为触发输入,从模式配置为复位模式;√这样CCR1为PWM输入的频率值,CCR2为占空比值(正/负)。使用STM32CubeMX对外设进行初始化配置:Step1: TIM1的输出PWM波作为捕获输入的被测信号,输出管脚为PA8Step2: TIM2的输入管脚为PA5(CH1)Step3: 配置TIM2的输入捕获参数Step4: 捕获数据直接通过DMA方式保存到RAM变量Update_Value1和Update_Value2。Step5: 测试读取到的CCR1、CCR2的数据与Update_Value1、Update_Value2对应,PWM波的频率和占空比都可以捕获得到。实验过程要点提示在stm32f3xx_hal_tim.c库文件中的HAL_TIM_IC_Start_DMA函数中会将状态置忙。但在函数结尾配置完毕后没有将该状态位复位,如果客户在其用户程序中使用了这个函数,这会导致该状态位始终为忙,后续任何对该状态的判断配置都将无法执行:因此需要在函数的最后将状态复位:本文小结本文重点介绍利用STM32CubeMX初始化配置工具和STM32Cube库如何通过TIMER的捕获功能完成对频率、占空比的测试,同时我们对如何解决实验过程中遇到的一些问题,做了特别提示。我们知道STM32Cube库非常庞大,虽难尽善尽美,但一定会越来越强大、越来越完善。本文转自:https://mp.weixin.qq.com/s/e2M22gpqFmOKee36MFe9oQ感谢ST人的分享和付出! 查看全部

当使用Timer做捕获输入时,有时候需要将捕获得到的数据通过DMA方式写到定义好的数据或数组中,本文将详细介绍使用CubeMX配置PWM捕获功能,用户可以直接得到输入的PWM信号的频率以及占空比,Cube库可以很方便配置。

实验过程中,当配置超过两个以上的Timer通道DMA时会遇到一些问题,本文也对其进行了说明并给出了解决方案。

Timer2的PWM信号捕获功能


使用Timer的IC1,IC2两个捕获输入通道,两个通道的外部管脚输入配置为相同TI1通道;

两个通道的捕获输入极性,一个为Active,另外一个为Inactive;

其中一个TI1FP1作为触发输入,从模式配置为复位模式;

这样CCR1为PWM输入的频率值,CCR2为占空比值(正/负)。

webwxgetmsgimg.jpg


使用STM32CubeMX对外设进行初始化配置:


Step1: TIM1的输出PWM波作为捕获输入的被测信号,输出管脚为PA8

Step2: TIM2的输入管脚为PA5(CH1)

webwxgetmsgimg (1).jpg

Step3: 配置TIM2的输入捕获参数

webwxgetmsgimg (2).jpg

Step4: 捕获数据直接通过DMA方式保存到RAM变量Update_Value1和Update_Value2。

webwxgetmsgimg (3).jpg

Step5: 测试读取到的CCR1、CCR2的数据与Update_Value1、Update_Value2对应,PWM波的频率和占空比都可以捕获得到。


webwxgetmsgimg (4).jpg


实验过程要点提示


在stm32f3xx_hal_tim.c

库文件中的HAL_TIM_IC_Start_DMA函数中会将状态置忙。

webwxgetmsgimg (5).jpg

但在函数结尾配置完毕后没有将该状态位复位,如果客户在其用户程序中使用了这个函数,这会导致该状态位始终为忙,后续任何对该状态的判断配置都将无法执行:

webwxgetmsgimg (6).jpg

因此需要在函数的最后将状态复位:

webwxgetmsgimg (7).jpg

本文小结

本文重点介绍利用STM32CubeMX初始化配置工具和STM32Cube库如何通过TIMER的捕获功能完成对频率、占空比的测试,同时我们对如何解决实验过程中遇到的一些问题,做了特别提示。我们知道STM32Cube库非常庞大,虽难尽善尽美,但一定会越来越强大、越来越完善。



本文转自:https://mp.weixin.qq.com/s/e2M22gpqFmOKee36MFe9oQ


感谢ST人的分享和付出!

用GPIO及TIMER做出時序圖

问题困惑askod 回复了问题 • 2 人关注 • 2 个回复 • 833 次浏览 • 2018-02-08 19:47 • 来自相关话题

STM32CubeMX TIM16初始化失败

问题困惑XV 回复了问题 • 1 人关注 • 1 个回复 • 692 次浏览 • 2018-01-22 00:16 • 来自相关话题

关于编码器(encoder)模式的一个问题,如何实现正反转的检测

问题困惑admin 回复了问题 • 2 人关注 • 5 个回复 • 6734 次浏览 • 2017-06-09 11:42 • 来自相关话题

基于时间片轮询系统(仿RTOS)

回复

经验分享君莫笑 发起了问题 • 1 人关注 • 0 个回复 • 52 次浏览 • 2019-11-04 16:56 • 来自相关话题

设计一款基于STM32内部RTC的电子万年历,显示年月日 时分,可进行日期、时间调整

回复

新手交流慣性 发起了问题 • 1 人关注 • 0 个回复 • 58 次浏览 • 2019-10-18 08:51 • 来自相关话题

TIM中断callback总是不执行?

回复

问题困惑admin 回复了问题 • 2 人关注 • 3 个回复 • 131 次浏览 • 2019-09-12 16:07 • 来自相关话题

怎么实现timer 触发DMA

回复

问题困惑lost_resister 发起了问题 • 1 人关注 • 0 个回复 • 112 次浏览 • 2019-09-08 10:13 • 来自相关话题

TIM1输入捕获模式测量脉冲宽度和频率 和 PWM输入模式的使用

回复

软件教程陪你在坑里看动漫 回复了问题 • 17 人关注 • 8 个回复 • 21314 次浏览 • 2019-06-10 08:31 • 来自相关话题

STM32F429中Timer6使用问题

回复

问题困惑STM32Cube_jack 回复了问题 • 2 人关注 • 2 个回复 • 620 次浏览 • 2019-05-04 19:13 • 来自相关话题

STM32F103定时器2外部时钟源超过150KHz后计数器不会自增加问题

回复

问题困惑frank1993 发起了问题 • 2 人关注 • 0 个回复 • 511 次浏览 • 2019-04-27 17:21 • 来自相关话题

关于串口接受9位字长的问题

回复

问题困惑自带腹肌的西装 回复了问题 • 3 人关注 • 3 个回复 • 967 次浏览 • 2019-03-18 10:48 • 来自相关话题

关于超声波等输入捕获实验

回复

问题困惑乌龟也会飞 回复了问题 • 4 人关注 • 3 个回复 • 986 次浏览 • 2018-09-30 14:03 • 来自相关话题

如果使用SWD仿真,但是相应的引脚没有配置,会出现什么后果?

回复

问题困惑谢~乾 回复了问题 • 4 人关注 • 4 个回复 • 1108 次浏览 • 2018-07-09 14:38 • 来自相关话题

用GPIO及TIMER做出時序圖

回复

问题困惑askod 回复了问题 • 2 人关注 • 2 个回复 • 833 次浏览 • 2018-02-08 19:47 • 来自相关话题

STM32CubeMX TIM16初始化失败

回复

问题困惑XV 回复了问题 • 1 人关注 • 1 个回复 • 692 次浏览 • 2018-01-22 00:16 • 来自相关话题

关于编码器(encoder)模式的一个问题,如何实现正反转的检测

回复

问题困惑admin 回复了问题 • 2 人关注 • 5 个回复 • 6734 次浏览 • 2017-06-09 11:42 • 来自相关话题

请问怎么配置cube才能实现俩定时器级联(主从模式)?

回复

问题困惑Kurohard 发起了问题 • 1 人关注 • 0 个回复 • 1978 次浏览 • 2016-05-09 21:26 • 来自相关话题

定时器初始化过程探讨---初始化使得SR寄存器的UIF更新中断标志置1,导致开机即进入定时中断

回复

新手交流much_mouse 回复了问题 • 2 人关注 • 2 个回复 • 2552 次浏览 • 2016-01-18 14:42 • 来自相关话题

关于定时器中断的相关问题

新手交流牙子男男 发表了文章 • 2 个评论 • 804 次浏览 • 2019-01-25 10:45 • 来自相关话题

新画了一个F334的板子,在CubeMX配置好定时中断,测试的时候发现定时中断进不去。纳了闷了,之前的板子定时中断很容易实现啊。。。刚开始担心晶振没起振,于是测了下晶振的波形。看着很完美,没问题。想了半天实在没想出来那儿没配置对。本来说好不找度娘的,,,艾玛,真香。发现在CubeMX配置好定时中断后,还需要在初始化中写入HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)这个函数,才能启动定时中断。加上这句话,中断就能进去啦,完美! 开贴记录程序设计过程中的各种坑 查看全部

新画了一个F334的板子,在CubeMX配置好定时中断,测试的时候发现定时中断进不去。纳了闷了,之前的板子定时中断很容易实现啊。。。刚开始担心晶振没起振,于是测了下晶振的波形。

TEK00000.PNG

看着很完美,没问题。

想了半天实在没想出来那儿没配置对。本来说好不找度娘的,,,艾玛,真香。

发现在CubeMX配置好定时中断后,还需要在初始化中写入HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)这个函数,才能启动定时中断。

image.png

加上这句话,中断就能进去啦,完美! 开贴记录程序设计过程中的各种坑

(转)基于STM32Cube库的Timer捕获应用

软件教程admin 发表了文章 • 0 个评论 • 1757 次浏览 • 2018-06-14 09:19 • 来自相关话题

当使用Timer做捕获输入时,有时候需要将捕获得到的数据通过DMA方式写到定义好的数据或数组中,本文将详细介绍使用CubeMX配置PWM捕获功能,用户可以直接得到输入的PWM信号的频率以及占空比,Cube库可以很方便配置。实验过程中,当配置超过两个以上的Timer通道DMA时会遇到一些问题,本文也对其进行了说明并给出了解决方案。Timer2的PWM信号捕获功能√使用Timer的IC1,IC2两个捕获输入通道,两个通道的外部管脚输入配置为相同TI1通道;√两个通道的捕获输入极性,一个为Active,另外一个为Inactive;√其中一个TI1FP1作为触发输入,从模式配置为复位模式;√这样CCR1为PWM输入的频率值,CCR2为占空比值(正/负)。使用STM32CubeMX对外设进行初始化配置:Step1: TIM1的输出PWM波作为捕获输入的被测信号,输出管脚为PA8Step2: TIM2的输入管脚为PA5(CH1)Step3: 配置TIM2的输入捕获参数Step4: 捕获数据直接通过DMA方式保存到RAM变量Update_Value1和Update_Value2。Step5: 测试读取到的CCR1、CCR2的数据与Update_Value1、Update_Value2对应,PWM波的频率和占空比都可以捕获得到。实验过程要点提示在stm32f3xx_hal_tim.c库文件中的HAL_TIM_IC_Start_DMA函数中会将状态置忙。但在函数结尾配置完毕后没有将该状态位复位,如果客户在其用户程序中使用了这个函数,这会导致该状态位始终为忙,后续任何对该状态的判断配置都将无法执行:因此需要在函数的最后将状态复位:本文小结本文重点介绍利用STM32CubeMX初始化配置工具和STM32Cube库如何通过TIMER的捕获功能完成对频率、占空比的测试,同时我们对如何解决实验过程中遇到的一些问题,做了特别提示。我们知道STM32Cube库非常庞大,虽难尽善尽美,但一定会越来越强大、越来越完善。本文转自:https://mp.weixin.qq.com/s/e2M22gpqFmOKee36MFe9oQ感谢ST人的分享和付出! 查看全部

当使用Timer做捕获输入时,有时候需要将捕获得到的数据通过DMA方式写到定义好的数据或数组中,本文将详细介绍使用CubeMX配置PWM捕获功能,用户可以直接得到输入的PWM信号的频率以及占空比,Cube库可以很方便配置。

实验过程中,当配置超过两个以上的Timer通道DMA时会遇到一些问题,本文也对其进行了说明并给出了解决方案。

Timer2的PWM信号捕获功能


使用Timer的IC1,IC2两个捕获输入通道,两个通道的外部管脚输入配置为相同TI1通道;

两个通道的捕获输入极性,一个为Active,另外一个为Inactive;

其中一个TI1FP1作为触发输入,从模式配置为复位模式;

这样CCR1为PWM输入的频率值,CCR2为占空比值(正/负)。

webwxgetmsgimg.jpg


使用STM32CubeMX对外设进行初始化配置:


Step1: TIM1的输出PWM波作为捕获输入的被测信号,输出管脚为PA8

Step2: TIM2的输入管脚为PA5(CH1)

webwxgetmsgimg (1).jpg

Step3: 配置TIM2的输入捕获参数

webwxgetmsgimg (2).jpg

Step4: 捕获数据直接通过DMA方式保存到RAM变量Update_Value1和Update_Value2。

webwxgetmsgimg (3).jpg

Step5: 测试读取到的CCR1、CCR2的数据与Update_Value1、Update_Value2对应,PWM波的频率和占空比都可以捕获得到。


webwxgetmsgimg (4).jpg


实验过程要点提示


在stm32f3xx_hal_tim.c

库文件中的HAL_TIM_IC_Start_DMA函数中会将状态置忙。

webwxgetmsgimg (5).jpg

但在函数结尾配置完毕后没有将该状态位复位,如果客户在其用户程序中使用了这个函数,这会导致该状态位始终为忙,后续任何对该状态的判断配置都将无法执行:

webwxgetmsgimg (6).jpg

因此需要在函数的最后将状态复位:

webwxgetmsgimg (7).jpg

本文小结

本文重点介绍利用STM32CubeMX初始化配置工具和STM32Cube库如何通过TIMER的捕获功能完成对频率、占空比的测试,同时我们对如何解决实验过程中遇到的一些问题,做了特别提示。我们知道STM32Cube库非常庞大,虽难尽善尽美,但一定会越来越强大、越来越完善。



本文转自:https://mp.weixin.qq.com/s/e2M22gpqFmOKee36MFe9oQ


感谢ST人的分享和付出!

Encoder模式的分析方法和使用技巧(利用Tim1定时器encoder接口)

软件教程admin 发表了文章 • 5 个评论 • 5064 次浏览 • 2017-06-09 11:24 • 来自相关话题

测试工具:keil5 , stm32cubemx , stm32F407discovery板卡, 广数凯恩帝数控CNC电子手轮(5V六端子100脉冲)应为discovery板并没有内置手轮的差分式外部电路,所以手轮我只用到了vcc ,gnd ,A+,B+这四个端子分别接到了5V,0V,PE11,PE9这几个引脚上面,硬件未滤波,只是提供演示参考.以下是cubemx中的配置信息1,选中tim1的encoder模式2,根据discovery板设置时钟3,配置tim1的各种参数,这里我随意设置的,2分频,重载值为10000,各个io口是上升沿计数,这里我编码器模式使用的是TT1,因为我不想用那么复杂的多沿计数,只计数TT1的通道脉冲,这样方便程序的编写使用.滤波我设置的3模式,不知道效果如何.下面是TIM1的两个管脚的配置,PE9和PE11的,因为电子手轮输出的是高低电平,所以板卡就不需要上下拉了,直接用OD模式最好.4,编译生成代码,然后打开工程.在main.c文件中user0处添加两个变量,分别准备存储方向信号和脉冲信号/* USER CODE BEGIN 0 */
uint32_t uwDirection = 0;
uint32_t pulsecount = 0;
/* USER CODE END 0 */在main()函数中添加encoder的启动和初始化计数器值为0    /* USER CODE BEGIN 2 */
    HAL_TIM_Encoder_Start(&htim1,TIM_CHANNEL_ALL);
    //初始化计数器值为0
    __HAL_TIM_SetCounter(&htim1,0);
    /* USER CODE END 2 */然后在大循环while中添加获取方向信号和脉冲数量的代码    while (1)
    {
        /* USER CODE END WHILE */

        /* USER CODE BEGIN 3 */
        //获取转动方向,0正转,1反转
        uwDirection = __HAL_TIM_DIRECTION_STATUS(&htim1);

        //获取计数器计数值,即手轮脉冲计数
        pulsecount = __HAL_TIM_GetCounter(&htim1);

    }ok,代码编写完成了.编译烧写,然后点击keil的调试按钮调试这里我们分别在uwDirection和pulsecount上面点击右键,选择add 到 watch1中另外也添加htm1到观察1中然后点击左侧的全速运行,此时可以看到watch1观察口里是没有任何变化的,这时候你转动手轮,里面的值开始变化正转手轮pulsecount的计数开始从0一个一个增加,反转一下减少一个数值,同样的正转的时候direction一直是0,反转的时候就变成了1具体的操作可以看此贴顶部第一个动态图片.此次教程结束.具体到怎么去用这个encoder,还要考虑定时器的重载事件update,所以还要启用tim的update中断,在中断中记录中断的次数,然后结合你的autoreload数相乘得到实际的转动脉冲数.这里不再具体讲述. 查看全部

1496977140559287.png

GIF.gif

测试工具:

keil5 , stm32cubemx , stm32F407discovery板卡, 广数凯恩帝数控CNC电子手轮(5V六端子100脉冲)

blob.png

应为discovery板并没有内置手轮的差分式外部电路,所以手轮我只用到了vcc ,gnd ,A+,B+这四个端子

分别接到了5V,0V,PE11,PE9这几个引脚上面,硬件未滤波,只是提供演示参考.


以下是cubemx中的配置信息

1,选中tim1的encoder模式

blob.png

2,根据discovery板设置时钟

blob.png

3,配置tim1的各种参数,这里我随意设置的,2分频,重载值为10000,各个io口是上升沿计数,这里我编码器模式使用的是TT1,因为我不想用那么复杂的多沿计数,只计数TT1的通道脉冲,这样方便程序的编写使用.滤波我设置的3模式,不知道效果如何.

blob.png

下面是TIM1的两个管脚的配置,PE9和PE11的,因为电子手轮输出的是高低电平,所以板卡就不需要上下拉了,直接用OD模式最好.

blob.png

4,编译生成代码,然后打开工程.

在main.c文件中user0处添加两个变量,分别准备存储方向信号和脉冲信号

/* USER CODE BEGIN 0 */
uint32_t uwDirection = 0;
uint32_t pulsecount = 0;
/* USER CODE END 0 */

在main()函数中添加encoder的启动和初始化计数器值为0

    /* USER CODE BEGIN 2 */
    HAL_TIM_Encoder_Start(&htim1,TIM_CHANNEL_ALL);
    //初始化计数器值为0
    __HAL_TIM_SetCounter(&htim1,0);
    /* USER CODE END 2 */

然后在大循环while中添加获取方向信号和脉冲数量的代码

    while (1)
    {
        /* USER CODE END WHILE */

        /* USER CODE BEGIN 3 */
        //获取转动方向,0正转,1反转
        uwDirection = __HAL_TIM_DIRECTION_STATUS(&htim1);

        //获取计数器计数值,即手轮脉冲计数
        pulsecount = __HAL_TIM_GetCounter(&htim1);

    }

ok,代码编写完成了.

编译烧写,然后点击keil的调试按钮调试

blob.png

这里我们分别在uwDirection和pulsecount上面点击右键,选择add 到 watch1中

另外也添加htm1到观察1中

blob.png

然后点击左侧的全速运行,

此时可以看到watch1观察口里是没有任何变化的,这时候你转动手轮,里面的值开始变化

正转手轮pulsecount的计数开始从0一个一个增加,反转一下减少一个数值,同样的正转的时候direction一直是0,反转的时候就变成了1


具体的操作可以看此贴顶部第一个动态图片.


此次教程结束.

具体到怎么去用这个encoder,还要考虑定时器的重载事件update,所以还要启用tim的update中断,在中断中记录中断的次数,然后结合你的autoreload数相乘得到实际的转动脉冲数.这里不再具体讲述.


(转)TIM3 Output Compare on the STM32 Family

其他分享admin 发表了文章 • 0 个评论 • 2818 次浏览 • 2016-03-13 23:34 • 来自相关话题

好久没时间继续更新stm32cube的程序了.
先转一些歪果仁对stm32的分析文章
TIM3 is a general purpose timer found on all the STM32 family processors. Among other features, it has four capture compare channels that can be used to generate regular interrupts. In this article I will show you how to set up simple interrupt events based on these features.

This is part of a series of articles about the TIM3 general purpose timer. In the preceding parts I introduced the TIM3 timer features and showed you how to identify the timer clock and set up the prescaler and reload register.You can see all the STM32 TIM3 posts here. Code is written using the Standard Peripheral Library for the STM32F4Discovery board. Timer related portions should run directly on other STM32 family members since they all have a TIM3

In this part, I will explain the basic configuration of the capture compare registers, describe how they can be used to generate regular interrupts and give you sample code to demonstrate the facility.
 
Capture Compare Registers
Here is a modified view of the TIM3 timer taken from the reference manual RM0090.





 
You can see that there are four registers associated with the timer TIM3. These are referred to as CCR1, CCR2, CCR3 and CCR4 or CCRx in general. Each channel is actually a pretty complex affair I am only going to concern myself with its behaviour in output compare modes. The reference manual RM0090 has this diagram of the output configuration:





 A look at the reference manual reveals that in basic Output Compare mode, I can program the output mode controller to one of four different states on a match. It can be:
frozen – that is, nothing happensset active (forced high)set inactive (forced low)toggled 
Other results are possible in other modes such as PWM.

In this article though, I just want to look at triggering an interrupt event. Although there are four Output Compare channels, and each can generate its own interrupt, they all get handled by the same Interrupt Service Routine (ISR). That means a series of tests will be needed in the ISR to determine exactly which channel caused the interrupt. I will just use two channels to illustrate how all this works.

Example Problem Statement

For this example, I want to set up two Output Compare channels on TIM3. Each channel will simply generate an interrupt. The ISR for that channel will toggle an LED on the target board. Each channel gets its own LED. Channel 1 will look after the blue LED and flash it  4 times per second. Channel 2 will look after the orange LED and flash it 2 times a second. These are simple numbers and the interrupt rate is quite low so that it is easy to see what is happening. Adapt the code for your needs.

Set up the Timer Prescale and Auto Reload

As with most timer problems, the first task is to set up the basic counter activity. This problem needs counts that are some handy but fairly small fraction of a second. Since the problem statement mentions numbers like 4 times per second and 8 times per second, it seems reasonable to try and arrange the counting frequency to be a convenient power of 2. Something like 256Hz or 128kHz of 3200Hz. Whatever, some number that lets me easily get binary fractions.

I have already established that the input frequency to the prescaler is 72MHz. This is an inconvenient value since there are no divisors that give me the kind of counter frequency that I was looking for. After a bit of fiddling with some of the factors of 72,000,000 I discovered that if I divide it by 28,125 I get 2560. Now that is a handy value for the counter since I can easily get many multiples of 2 and 5 out of it. Multiples of 3 would be more tricky but that is not part of my problem. The actual frequency for the counter is not critical in this case so long as it is high enough to give me the resolution I require.

Note that it is not sufficient to just pick a frequency. You must choose an value that divides exactly into the clock frequency if the results are to be accurate. the TIM3 counter frequency gets stored in a variable so that we can use it when calculating the intervals for the CCRx registers.
uint32_t TIM3COUNTER_Frequency = 2560;Now I need to set the prescaler to (28125-1) = 28124 so that my counter will increment at 2560Hz. The prescaler value is calculated from the timer input clock frequency (TIM3CLK_Frequency) and the desired TIM3COUNTER_Frequency.

When using the Output Compare channels, I need the CNT register to wrap around completely for reasons that should be clear shortly. To do this, I need to load the ARR register with 65535.

The update event interrupt is not needed so basic timer configuration looks like this:
void timer_init (void)
{
uint32_t TIM3CLK_Frequency = get_timer_clock_frequency();
uint16_t prescaler = (TIM3CLK_Frequency / TIM3COUNTER_Frequency) - 1;
/* allow the timer to wrap around naturally */
uint16_t reload = 65535;

/* make sure the peripheral is clocked */
RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/* set everything back to default values */
TIM_TimeBaseStructInit (&TIM_TimeBaseStructure);
/* only changes from the defaults are needed */
TIM_TimeBaseStructure.TIM_Period = reload;
TIM_TimeBaseStructure.TIM_Prescaler = prescaler;
TIM_TimeBaseInit (TIM3, &TIM_TimeBaseStructure);
}Once the timer is started, it will free run at the specified frequency and then I have to think about how to configure the Output Compare registers.

Configure the Output Compare Function

Along with all the other configuration, I have to tell the timer to use the CCRx registers in output compare mode. The Standard Peripheral Library makes all this super easy:
void timer_ccr_init (void)
{
TIM_OCInitTypeDef TIM_OCInitStructure;
/* always initialise local variables before use */
TIM_OCStructInit (&TIM_OCInitStructure);
/* just use basic Output Compare Mode*/
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Active;
/* set the initial match interval for CC1 */
TIM_OCInitStructure.TIM_Pulse = CCR1_Interval;
TIM_OC1Init (TIM3, &TIM_OCInitStructure);
/* and then for CC2 */
TIM_OCInitStructure.TIM_Pulse = CCR2_Interval;
TIM_OC2Init (TIM3, &TIM_OCInitStructure);
}Each channel is configured separately and I need only configure the channels I need. They are completely independent. The initial interval must be loaded into the register when using the library code but that value is only good for the first match and assumes that the CNT register starts at zero. When a match between CNT and the CCRx register is made, the CNT register carries on counting. That leaves me with the problem of how to update the CCRx registers after each match. The value used for the interval will be the number of CNT counts between interrupts. That gets calculated depending on the problem requirements.

Updating the Output Compare Registers

There is nothing in the Output Compare that will reset the CNT register. Even if there was, it would be no good to me because I want to use the CNT register contents to match against up to four CCRx registers. So, how can I get recurring intervals?

The CNT register, by default, will just count upwards at a fixed rate, wrapping around to zero again when it gets to the end. I just made sure of that in the timer setup. Each CCRx register is just compared with CNT for equality – it does not care what the actual value is. Every time the ISR runs then, I just need to add a fixed interval to the CCRx register. When the CNT value catches up with the CCRx again another interrupt will be generated. Overflows will not matter since both registers overflow in the same way and a match must eventually occur. Updating the CCR is now very simple. This code fragment deals with channel 1. The other channels are similar:

uint16_t CCR1_Current = TIM_GetCapture1 (TIM3);
TIM_SetCompare1 (TIM3, CCR1_Current + CCR1_Interval);In the problem statement, I wanted the blue LED to flash 4 times a second using channel 1 and the orange LED to flash 2 times a second using channel 2. To get two flashes per second, I set the interval to a quarter second since, at each interrupt, I will toggle the LED pin. Similarly, I use 8 ticks per second for the blue LED
uint16_t CCR1_Interval = TIM3COUNTER_Frequency / 8; // blue LED
uint16_t CCR2_Interval = TIM3COUNTER_Frequency / 4; // orange LEDVariable Update Intervals

There is no reason why the same interval has to be used each time the interrupt fires. If I want to drive stepper motors, I can arrange to have a steadily diminishing interval as the motor accelerates. The values could be calculated or looked up in a table. Because I can have four channels and each is independent, I could easily drive four stepper motors from the same timer and have different motion profiles on each one.

Servicing the Output Compare Interrupt

Recall that several channels are all sharing the same ISR so in there I must poll each of the possible interrupt sources, act on any that are active and reset their flags ready for the next time. The entire ISR for my two channel problem looks like this.
void TIM3_IRQHandler (void)
{
/* run through the interrupt sources looking for a hit */
if (TIM_GetITStatus (TIM3, TIM_IT_CC1) != RESET) {
GPIO_ToggleBits (BLUE_LED);

uint16_t CCR1_Current = TIM_GetCapture1 (TIM3);
TIM_SetCompare1 (TIM3, CCR1_Current + CCR1_Interval);

TIM_ClearITPendingBit (TIM3, TIM_IT_CC1);
}
if (TIM_GetITStatus (TIM3, TIM_IT_CC2) != RESET) {
GPIO_ToggleBits (ORANGE_LED);

uint16_t CCR2_Current = TIM_GetCapture2 (TIM3);
TIM_SetCompare2 (TIM3, CCR2_Current + CCR2_Interval);

TIM_ClearITPendingBit (TIM3, TIM_IT_CC2);
}
}The action associated with each channel here is just toggling an LED on and off. It could just as easily be setting the pattern of bits needed to drive the phases of a stepper motor. Just try to keep the ISR code as short and simple as you can. All that remains is to enable the interrupt and let it loose.

Enabling the Output Compare Interrupt

Although all the Output Compare channels share an ISR, each has its own interrupt enable flag so they can be turned on and off individually. Again, the Standard Peripheral Library makes this easy:
void timer_interrupt_enable (void)
{
/*
* It is important to clear any pending interrupt flags since the timer
* has been free-running since we last used it and that may generate
* interrupts on match even though the associated interrupt event has
* not been enabled.
*/
TIM_ClearITPendingBit (TIM3, TIM_IT_CC1 | TIM_IT_CC2);
/* put the counter into a known state */
TIM_SetCounter (TIM3, 0);
/* enable the interrupt for CC1 and CC2 only */
TIM_ITConfig (TIM3, TIM_IT_CC1 | TIM_IT_CC2, ENABLE);
}Once the timer is started, my ISR should run and the LEDs will flash in the required way.

Putting it Together

Here is a complete code listing demonstrating how to do all these things with the STM32F4 Discovery
#include "stm32f4xx.h"
#include "systick.h"

#define MHz 1000000L
#define KHz 1000L


// The LED indicators on the STM32F4Discovery board
#define LED_PORT GPIOD
#define LED_PORT_CLOCK RCC_AHB1Periph_GPIOD
#define GREEN_PIN GPIO_Pin_12
#define ORANGE_PIN GPIO_Pin_13
#define RED_PIN GPIO_Pin_14
#define BLUE_PIN GPIO_Pin_15
#define ALL_LED_PINS GREEN_PIN | ORANGE_PIN | RED_PIN | BLUE_PIN
#define GREEN_LED LED_PORT,GREEN_PIN
#define ORANGE_LED LED_PORT,ORANGE_PIN
#define RED_LED LED_PORT,RED_PIN
#define BLUE_LED LED_PORT,BLUE_PIN
#define ALL_LEDS LED_PORT,ALL_LED_PINS

/* unfortunate globals because they get used in the ISR */
uint32_t TIM3COUNTER_Frequency = 2560;
/* determine the correct counter intervals */
uint16_t CCR1_Interval = TIM3COUNTER_Frequency / 8; // blue LED
uint16_t CCR2_Interval = TIM3COUNTER_Frequency / 4; // orange LED


void timer_interrupt_init (void)
{
NVIC_InitTypeDef NVIC_InitStructure;
RCC_ClocksTypeDef RCC_Clocks;
/* Enable the timer global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init (&NVIC_InitStructure);
}

uint32_t get_timer_clock_frequency (void)
{
RCC_ClocksTypeDef RCC_Clocks;
RCC_GetClocksFreq (&RCC_Clocks);
uint32_t multiplier;
if (RCC_Clocks.PCLK1_Frequency == RCC_Clocks.SYSCLK_Frequency) {
multiplier = 1;
} else {
multiplier = 2;
}
return multiplier * RCC_Clocks.PCLK1_Frequency;
}

void timer_clock_init (void)
{
uint32_t TIM3CLK_Frequency = get_timer_clock_frequency();
uint16_t prescaler = (TIM3CLK_Frequency / TIM3COUNTER_Frequency) - 1;
/* allow the timer to wrap around naturally */
uint16_t reload = 65535;

/* make sure the peripheral is clocked */
RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/* set everything back to default values */
TIM_TimeBaseStructInit (&TIM_TimeBaseStructure);
/* only changes from the defaults are needed */
TIM_TimeBaseStructure.TIM_Period = reload;
TIM_TimeBaseStructure.TIM_Prescaler = prescaler;
TIM_TimeBaseInit (TIM3, &TIM_TimeBaseStructure);
}

void timer_start (void)
{
TIM_Cmd (TIM3, ENABLE);
}

void timer_stop (void)
{
TIM_Cmd (TIM3, DISABLE);
}

void timer_interrupt_enable (void)
{
/*
* It is important to clear any pending interrupt flags since the timer
* has been free-running since we last used it and that may generate
* interrups on overflow even though the associated interrupt event has
* not been enabled.
*/
TIM_ClearITPendingBit (TIM3, TIM_IT_CC1 | TIM_IT_CC2);
/* put the counter into a known state */
//TIM_SetCounter (TIM3, 0);
/* enable the interrupt for CC1 and CC2 only */
TIM_ITConfig (TIM3, TIM_IT_CC1 | TIM_IT_CC2, ENABLE);
}

// for C++ ensure the interrupt handler is linked as a C function
#ifdef __cplusplus
extern "C" {
#endif

void TIM3_IRQHandler (void)
{
/* run through the interrupt sources looking for a hit */
if (TIM_GetITStatus (TIM3, TIM_IT_CC1) != RESET) {
GPIO_ToggleBits (BLUE_LED);

uint16_t CCR1_Current = TIM_GetCapture1 (TIM3);
TIM_SetCompare1 (TIM3, CCR1_Current + CCR1_Interval);

TIM_ClearITPendingBit (TIM3, TIM_IT_CC1);
}
if (TIM_GetITStatus (TIM3, TIM_IT_CC2) != RESET) {
GPIO_ToggleBits (ORANGE_LED);

uint16_t CCR2_Current = TIM_GetCapture2 (TIM3);
TIM_SetCompare2 (TIM3, CCR2_Current + CCR2_Interval);

TIM_ClearITPendingBit (TIM3, TIM_IT_CC2);
}
}

#ifdef __cplusplus
}
#endif

void timer_ccr_init (void)
{
TIM_OCInitTypeDef TIM_OCInitStructure;
/* always initialise local variables before use */
TIM_OCStructInit (&TIM_OCInitStructure);
/* just use basic Output Compare Mode*/
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Active;
/* set the initial match interval for CC1 */
TIM_OCInitStructure.TIM_Pulse = CCR1_Interval;
TIM_OC1Init (TIM3, &TIM_OCInitStructure);
/* and then for CC2 */
TIM_OCInitStructure.TIM_Pulse = CCR2_Interval;
TIM_OC2Init (TIM3, &TIM_OCInitStructure);
}


// these are the LEDs on the STM32F4Discovery
void board_leds_init (void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// always do this with an auto structure as it is undefined
GPIO_StructInit (&GPIO_InitStructure);
RCC_AHB1PeriphClockCmd (LED_PORT_CLOCK, ENABLE);
GPIO_StructInit (&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = RED_PIN + GREEN_PIN + BLUE_PIN + ORANGE_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init (LED_PORT, &GPIO_InitStructure);
GPIO_ResetBits (LED_PORT, RED_PIN + GREEN_PIN + BLUE_PIN + ORANGE_PIN);
}

void flash_green_led_forever (void)
{
while (1) {
GPIO_ToggleBits (GREEN_LED);
delay_ms (500);
}
}

int main (void)
{
systickInit (1000);
board_leds_init();
timer_clock_init();
timer_ccr_init();
timer_interrupt_init();
timer_interrupt_enable();
timer_start();
flash_green_led_forever();
return 0; // there is no going back but keep the compiler happy
}

Happy Coding
 
本文引用自:
http://www.micromouseonline.co ... mily/ 查看全部
好久没时间继续更新stm32cube的程序了.
先转一些歪果仁对stm32的分析文章
TIM3 is a general purpose timer found on all the STM32 family processors. Among other features, it has four capture compare channels that can be used to generate regular interrupts. In this article I will show you how to set up simple interrupt events based on these features.

This is part of a series of articles about the TIM3 general purpose timer. In the preceding parts I introduced the TIM3 timer features and showed you how to identify the timer clock and set up the prescaler and reload register.You can see all the STM32 TIM3 posts here. Code is written using the Standard Peripheral Library for the STM32F4Discovery board. Timer related portions should run directly on other STM32 family members since they all have a TIM3

In this part, I will explain the basic configuration of the capture compare registers, describe how they can be used to generate regular interrupts and give you sample code to demonstrate the facility.
 
Capture Compare Registers
Here is a modified view of the TIM3 timer taken from the reference manual RM0090.

TIM3-diagram-Fig119-RM0090-1187x1200.png

 
You can see that there are four registers associated with the timer TIM3. These are referred to as CCR1, CCR2, CCR3 and CCR4 or CCRx in general. Each channel is actually a pretty complex affair I am only going to concern myself with its behaviour in output compare modes. The reference manual RM0090 has this diagram of the output configuration:

STM32F4-TIM3-capture-compare-output.png

 A look at the reference manual reveals that in basic Output Compare mode, I can program the output mode controller to one of four different states on a match. It can be:
  • frozen – that is, nothing happensset active (forced high)set inactive (forced low)toggled
  •  

Other results are possible in other modes such as PWM.

In this article though, I just want to look at triggering an interrupt event. Although there are four Output Compare channels, and each can generate its own interrupt, they all get handled by the same Interrupt Service Routine (ISR). That means a series of tests will be needed in the ISR to determine exactly which channel caused the interrupt. I will just use two channels to illustrate how all this works.

Example Problem Statement

For this example, I want to set up two Output Compare channels on TIM3. Each channel will simply generate an interrupt. The ISR for that channel will toggle an LED on the target board. Each channel gets its own LED. Channel 1 will look after the blue LED and flash it  4 times per second. Channel 2 will look after the orange LED and flash it 2 times a second. These are simple numbers and the interrupt rate is quite low so that it is easy to see what is happening. Adapt the code for your needs.

Set up the Timer Prescale and Auto Reload

As with most timer problems, the first task is to set up the basic counter activity. This problem needs counts that are some handy but fairly small fraction of a second. Since the problem statement mentions numbers like 4 times per second and 8 times per second, it seems reasonable to try and arrange the counting frequency to be a convenient power of 2. Something like 256Hz or 128kHz of 3200Hz. Whatever, some number that lets me easily get binary fractions.

I have already established that the input frequency to the prescaler is 72MHz. This is an inconvenient value since there are no divisors that give me the kind of counter frequency that I was looking for. After a bit of fiddling with some of the factors of 72,000,000 I discovered that if I divide it by 28,125 I get 2560. Now that is a handy value for the counter since I can easily get many multiples of 2 and 5 out of it. Multiples of 3 would be more tricky but that is not part of my problem. The actual frequency for the counter is not critical in this case so long as it is high enough to give me the resolution I require.

Note that it is not sufficient to just pick a frequency. You must choose an value that divides exactly into the clock frequency if the results are to be accurate. the TIM3 counter frequency gets stored in a variable so that we can use it when calculating the intervals for the CCRx registers.
uint32_t TIM3COUNTER_Frequency =  2560;
Now I need to set the prescaler to (28125-1) = 28124 so that my counter will increment at 2560Hz. The prescaler value is calculated from the timer input clock frequency (TIM3CLK_Frequency) and the desired TIM3COUNTER_Frequency.

When using the Output Compare channels, I need the CNT register to wrap around completely for reasons that should be clear shortly. To do this, I need to load the ARR register with 65535.

The update event interrupt is not needed so basic timer configuration looks like this:
void timer_init (void)
{
uint32_t TIM3CLK_Frequency = get_timer_clock_frequency();
uint16_t prescaler = (TIM3CLK_Frequency / TIM3COUNTER_Frequency) - 1;
/* allow the timer to wrap around naturally */
uint16_t reload = 65535;

/* make sure the peripheral is clocked */
RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/* set everything back to default values */
TIM_TimeBaseStructInit (&TIM_TimeBaseStructure);
/* only changes from the defaults are needed */
TIM_TimeBaseStructure.TIM_Period = reload;
TIM_TimeBaseStructure.TIM_Prescaler = prescaler;
TIM_TimeBaseInit (TIM3, &TIM_TimeBaseStructure);
}
Once the timer is started, it will free run at the specified frequency and then I have to think about how to configure the Output Compare registers.

Configure the Output Compare Function

Along with all the other configuration, I have to tell the timer to use the CCRx registers in output compare mode. The Standard Peripheral Library makes all this super easy:
void timer_ccr_init (void)
{
TIM_OCInitTypeDef TIM_OCInitStructure;
/* always initialise local variables before use */
TIM_OCStructInit (&TIM_OCInitStructure);
/* just use basic Output Compare Mode*/
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Active;
/* set the initial match interval for CC1 */
TIM_OCInitStructure.TIM_Pulse = CCR1_Interval;
TIM_OC1Init (TIM3, &TIM_OCInitStructure);
/* and then for CC2 */
TIM_OCInitStructure.TIM_Pulse = CCR2_Interval;
TIM_OC2Init (TIM3, &TIM_OCInitStructure);
}
Each channel is configured separately and I need only configure the channels I need. They are completely independent. The initial interval must be loaded into the register when using the library code but that value is only good for the first match and assumes that the CNT register starts at zero. When a match between CNT and the CCRx register is made, the CNT register carries on counting. That leaves me with the problem of how to update the CCRx registers after each match. The value used for the interval will be the number of CNT counts between interrupts. That gets calculated depending on the problem requirements.

Updating the Output Compare Registers

There is nothing in the Output Compare that will reset the CNT register. Even if there was, it would be no good to me because I want to use the CNT register contents to match against up to four CCRx registers. So, how can I get recurring intervals?

The CNT register, by default, will just count upwards at a fixed rate, wrapping around to zero again when it gets to the end. I just made sure of that in the timer setup. Each CCRx register is just compared with CNT for equality – it does not care what the actual value is. Every time the ISR runs then, I just need to add a fixed interval to the CCRx register. When the CNT value catches up with the CCRx again another interrupt will be generated. Overflows will not matter since both registers overflow in the same way and a match must eventually occur. Updating the CCR is now very simple. This code fragment deals with channel 1. The other channels are similar:

uint16_t CCR1_Current = TIM_GetCapture1 (TIM3);
TIM_SetCompare1 (TIM3, CCR1_Current + CCR1_Interval);
In the problem statement, I wanted the blue LED to flash 4 times a second using channel 1 and the orange LED to flash 2 times a second using channel 2. To get two flashes per second, I set the interval to a quarter second since, at each interrupt, I will toggle the LED pin. Similarly, I use 8 ticks per second for the blue LED
uint16_t CCR1_Interval = TIM3COUNTER_Frequency / 8; // blue LED
uint16_t CCR2_Interval = TIM3COUNTER_Frequency / 4; // orange LED
Variable Update Intervals

There is no reason why the same interval has to be used each time the interrupt fires. If I want to drive stepper motors, I can arrange to have a steadily diminishing interval as the motor accelerates. The values could be calculated or looked up in a table. Because I can have four channels and each is independent, I could easily drive four stepper motors from the same timer and have different motion profiles on each one.

Servicing the Output Compare Interrupt

Recall that several channels are all sharing the same ISR so in there I must poll each of the possible interrupt sources, act on any that are active and reset their flags ready for the next time. The entire ISR for my two channel problem looks like this.
void TIM3_IRQHandler (void)
{
/* run through the interrupt sources looking for a hit */
if (TIM_GetITStatus (TIM3, TIM_IT_CC1) != RESET) {
GPIO_ToggleBits (BLUE_LED);

uint16_t CCR1_Current = TIM_GetCapture1 (TIM3);
TIM_SetCompare1 (TIM3, CCR1_Current + CCR1_Interval);

TIM_ClearITPendingBit (TIM3, TIM_IT_CC1);
}
if (TIM_GetITStatus (TIM3, TIM_IT_CC2) != RESET) {
GPIO_ToggleBits (ORANGE_LED);

uint16_t CCR2_Current = TIM_GetCapture2 (TIM3);
TIM_SetCompare2 (TIM3, CCR2_Current + CCR2_Interval);

TIM_ClearITPendingBit (TIM3, TIM_IT_CC2);
}
}
The action associated with each channel here is just toggling an LED on and off. It could just as easily be setting the pattern of bits needed to drive the phases of a stepper motor. Just try to keep the ISR code as short and simple as you can. All that remains is to enable the interrupt and let it loose.

Enabling the Output Compare Interrupt

Although all the Output Compare channels share an ISR, each has its own interrupt enable flag so they can be turned on and off individually. Again, the Standard Peripheral Library makes this easy:
void timer_interrupt_enable (void)
{
/*
* It is important to clear any pending interrupt flags since the timer
* has been free-running since we last used it and that may generate
* interrupts on match even though the associated interrupt event has
* not been enabled.
*/
TIM_ClearITPendingBit (TIM3, TIM_IT_CC1 | TIM_IT_CC2);
/* put the counter into a known state */
TIM_SetCounter (TIM3, 0);
/* enable the interrupt for CC1 and CC2 only */
TIM_ITConfig (TIM3, TIM_IT_CC1 | TIM_IT_CC2, ENABLE);
}
Once the timer is started, my ISR should run and the LEDs will flash in the required way.

Putting it Together

Here is a complete code listing demonstrating how to do all these things with the STM32F4 Discovery
#include "stm32f4xx.h"
#include "systick.h"

#define MHz 1000000L
#define KHz 1000L


// The LED indicators on the STM32F4Discovery board
#define LED_PORT GPIOD
#define LED_PORT_CLOCK RCC_AHB1Periph_GPIOD
#define GREEN_PIN GPIO_Pin_12
#define ORANGE_PIN GPIO_Pin_13
#define RED_PIN GPIO_Pin_14
#define BLUE_PIN GPIO_Pin_15
#define ALL_LED_PINS GREEN_PIN | ORANGE_PIN | RED_PIN | BLUE_PIN
#define GREEN_LED LED_PORT,GREEN_PIN
#define ORANGE_LED LED_PORT,ORANGE_PIN
#define RED_LED LED_PORT,RED_PIN
#define BLUE_LED LED_PORT,BLUE_PIN
#define ALL_LEDS LED_PORT,ALL_LED_PINS

/* unfortunate globals because they get used in the ISR */
uint32_t TIM3COUNTER_Frequency = 2560;
/* determine the correct counter intervals */
uint16_t CCR1_Interval = TIM3COUNTER_Frequency / 8; // blue LED
uint16_t CCR2_Interval = TIM3COUNTER_Frequency / 4; // orange LED


void timer_interrupt_init (void)
{
NVIC_InitTypeDef NVIC_InitStructure;
RCC_ClocksTypeDef RCC_Clocks;
/* Enable the timer global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init (&NVIC_InitStructure);
}

uint32_t get_timer_clock_frequency (void)
{
RCC_ClocksTypeDef RCC_Clocks;
RCC_GetClocksFreq (&RCC_Clocks);
uint32_t multiplier;
if (RCC_Clocks.PCLK1_Frequency == RCC_Clocks.SYSCLK_Frequency) {
multiplier = 1;
} else {
multiplier = 2;
}
return multiplier * RCC_Clocks.PCLK1_Frequency;
}

void timer_clock_init (void)
{
uint32_t TIM3CLK_Frequency = get_timer_clock_frequency();
uint16_t prescaler = (TIM3CLK_Frequency / TIM3COUNTER_Frequency) - 1;
/* allow the timer to wrap around naturally */
uint16_t reload = 65535;

/* make sure the peripheral is clocked */
RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/* set everything back to default values */
TIM_TimeBaseStructInit (&TIM_TimeBaseStructure);
/* only changes from the defaults are needed */
TIM_TimeBaseStructure.TIM_Period = reload;
TIM_TimeBaseStructure.TIM_Prescaler = prescaler;
TIM_TimeBaseInit (TIM3, &TIM_TimeBaseStructure);
}

void timer_start (void)
{
TIM_Cmd (TIM3, ENABLE);
}

void timer_stop (void)
{
TIM_Cmd (TIM3, DISABLE);
}

void timer_interrupt_enable (void)
{
/*
* It is important to clear any pending interrupt flags since the timer
* has been free-running since we last used it and that may generate
* interrups on overflow even though the associated interrupt event has
* not been enabled.
*/
TIM_ClearITPendingBit (TIM3, TIM_IT_CC1 | TIM_IT_CC2);
/* put the counter into a known state */
//TIM_SetCounter (TIM3, 0);
/* enable the interrupt for CC1 and CC2 only */
TIM_ITConfig (TIM3, TIM_IT_CC1 | TIM_IT_CC2, ENABLE);
}

// for C++ ensure the interrupt handler is linked as a C function
#ifdef __cplusplus
extern "C" {
#endif

void TIM3_IRQHandler (void)
{
/* run through the interrupt sources looking for a hit */
if (TIM_GetITStatus (TIM3, TIM_IT_CC1) != RESET) {
GPIO_ToggleBits (BLUE_LED);

uint16_t CCR1_Current = TIM_GetCapture1 (TIM3);
TIM_SetCompare1 (TIM3, CCR1_Current + CCR1_Interval);

TIM_ClearITPendingBit (TIM3, TIM_IT_CC1);
}
if (TIM_GetITStatus (TIM3, TIM_IT_CC2) != RESET) {
GPIO_ToggleBits (ORANGE_LED);

uint16_t CCR2_Current = TIM_GetCapture2 (TIM3);
TIM_SetCompare2 (TIM3, CCR2_Current + CCR2_Interval);

TIM_ClearITPendingBit (TIM3, TIM_IT_CC2);
}
}

#ifdef __cplusplus
}
#endif

void timer_ccr_init (void)
{
TIM_OCInitTypeDef TIM_OCInitStructure;
/* always initialise local variables before use */
TIM_OCStructInit (&TIM_OCInitStructure);
/* just use basic Output Compare Mode*/
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Active;
/* set the initial match interval for CC1 */
TIM_OCInitStructure.TIM_Pulse = CCR1_Interval;
TIM_OC1Init (TIM3, &TIM_OCInitStructure);
/* and then for CC2 */
TIM_OCInitStructure.TIM_Pulse = CCR2_Interval;
TIM_OC2Init (TIM3, &TIM_OCInitStructure);
}


// these are the LEDs on the STM32F4Discovery
void board_leds_init (void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// always do this with an auto structure as it is undefined
GPIO_StructInit (&GPIO_InitStructure);
RCC_AHB1PeriphClockCmd (LED_PORT_CLOCK, ENABLE);
GPIO_StructInit (&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = RED_PIN + GREEN_PIN + BLUE_PIN + ORANGE_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init (LED_PORT, &GPIO_InitStructure);
GPIO_ResetBits (LED_PORT, RED_PIN + GREEN_PIN + BLUE_PIN + ORANGE_PIN);
}

void flash_green_led_forever (void)
{
while (1) {
GPIO_ToggleBits (GREEN_LED);
delay_ms (500);
}
}

int main (void)
{
systickInit (1000);
board_leds_init();
timer_clock_init();
timer_ccr_init();
timer_interrupt_init();
timer_interrupt_enable();
timer_start();
flash_green_led_forever();
return 0; // there is no going back but keep the compiler happy
}

Happy Coding
 
本文引用自:
http://www.micromouseonline.co ... mily/

利用STM32CubeMX 和定时器htim1实现编码器Encoder正反旋转脉冲检测

经验分享admin 发表了文章 • 9 个评论 • 12360 次浏览 • 2016-03-02 09:48 • 来自相关话题

利用STM32CubeMX 和定时器htim1实现编码器Encoder正反旋转脉冲检测 
点开TIM1, Combined Channels 中选择 Encoder Mode,这时,PA8和PA9被分配。单击PA10 选择GPIO_EXTI10,配置为中断口,用于连接编码器的Z相信号。
添加外部中断代码,我是添加在main.c文件中,USER CODE BEGIN 4 和 USER CODE END 4,自己添加的代码一定要在BEGIN x和END x之间,要不然下次更新时会被覆盖掉。这段代码的作用是编码器经过0点的时候,将计数器的值清0.

























 






在main.c中增加
 int16_t Angle;
  char TmpArray[10];
开启 HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_ALL);
while中增加
Angle = (int16_t)(__HAL_TIM_GET_COUNTER(&htim1));//获取定时器的值,因为在配置的时候做了分频处理,所以这边角度直接等于COUNTER的值。这里做了一下强制转换,因为用到了负角度。
 sprintf(TmpArray, "%4d", Angle);//
下面是中断回调void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
switch(GPIO_Pin)
{
case GPIO_PIN_10:
{
__HAL_TIM_SET_COUNTER(&htim1, 0);
}break;
}
} 查看全部
利用STM32CubeMX 和定时器htim1实现编码器Encoder正反旋转脉冲检测 
点开TIM1, Combined Channels 中选择 Encoder Mode,这时,PA8和PA9被分配。单击PA10 选择GPIO_EXTI10,配置为中断口,用于连接编码器的Z相信号。
添加外部中断代码,我是添加在main.c文件中,USER CODE BEGIN 4 和 USER CODE END 4,自己添加的代码一定要在BEGIN x和END x之间,要不然下次更新时会被覆盖掉。这段代码的作用是编码器经过0点的时候,将计数器的值清0.

1.png


2.png


3.png


4.png


5.png

 
QQ图片20160302095855.jpg



在main.c中增加
 int16_t Angle;
  char TmpArray[10];
开启 HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_ALL);
while中增加
Angle = (int16_t)(__HAL_TIM_GET_COUNTER(&htim1));//获取定时器的值,因为在配置的时候做了分频处理,所以这边角度直接等于COUNTER的值。这里做了一下强制转换,因为用到了负角度。
 sprintf(TmpArray, "%4d", Angle);//
下面是中断回调
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
switch(GPIO_Pin)
{
case GPIO_PIN_10:
{
__HAL_TIM_SET_COUNTER(&htim1, 0);
}break;
}
}








TIM定时器再次研究,其实一直都是只知道用,不知道道理,导致后面出了好多问题,烦

经验分享admin 发表了文章 • 12 个评论 • 21550 次浏览 • 2014-10-20 09:59 • 来自相关话题

只研究stm32cube生成的代码里面的TIM定时器的用法.
这次务必搞懂,不留后遗症,一直知道怎么用,但是还是不了解为什么,导致问题多多,以此借鉴!






1: 生成了一个定时一秒的代码,如下:
/ TIM3 init function /
void MX_TIM3_Init(void)
{

TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;

htim3.Instance = TIM3;
htim3.Init.Prescaler = 8399;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 9999;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&htim3);

sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig);

sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig);

}
为什么呢?以前是按照我总结的写的,这次原理要弄懂.tnnd
htim3.Init.Prescaler = 8399; 这个是分频数,就是将时钟分频使频率降低,额,我是这样理解的
上面用的定时器3,连接的是APB1时钟,而我的时钟是:





所以当前的频率是:时钟频率/(分频数+1)=84000000/8400=10000HZ
即每次定时器自加1时间为1/10000=0.0001s
htim3.Init.Period = 9999; 这个意思是:自动重载值,可以理解为当从0开始加到这个值的时候,定时器中断一次
所以从0加到9999共10000次,所需时间=10000*0.0001=1s
定时时间1s.
好了,2楼回复中继续研究定时器其他参数. 查看全部
只研究stm32cube生成的代码里面的TIM定时器的用法.
这次务必搞懂,不留后遗症,一直知道怎么用,但是还是不了解为什么,导致问题多多,以此借鉴!

1345217050_8286.JPG


1: 生成了一个定时一秒的代码,如下:
/ TIM3 init function /
void MX_TIM3_Init(void)
{

TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;

htim3.Instance = TIM3;
htim3.Init.Prescaler = 8399;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 9999;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&htim3);

sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig);

sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig);

}
为什么呢?以前是按照我总结的写的,这次原理要弄懂.tnnd
htim3.Init.Prescaler = 8399; 这个是分频数,就是将时钟分频使频率降低,额,我是这样理解的
上面用的定时器3,连接的是APB1时钟,而我的时钟是:

QQ图片20141020095418.jpg

所以当前的频率是:时钟频率/(分频数+1)=84000000/8400=10000HZ
即每次定时器自加1时间为1/10000=0.0001s
htim3.Init.Period = 9999; 这个意思是:自动重载值,可以理解为当从0开始加到这个值的时候,定时器中断一次
所以从0加到9999共10000次,所需时间=10000*0.0001=1s
定时时间1s.
好了,2楼回复中继续研究定时器其他参数.

stm32定时器深入研究:在定时中途修改此定时器的定时时间,会立即更改定时时间还是等待这次定时结束才更改?

经验分享admin 发表了文章 • 1 个评论 • 2428 次浏览 • 2014-10-14 00:20 • 来自相关话题

今天遇到这样的问题?

就是比如定时器tim1初始化的定时时间是6s,表现为一个LED反转。
那么,如果我在定时途中修改这个定时器的定时时间参数,定时器是即时反应还是定时结束后统一更新?

比如现在定时为6s,然而我在定时途中2.5s的时候修改定时时间为2s,那么是在第4.5s就立马定时中断,还是继续上次的6s定时后进行呢?

于是我做了实验。

就是上面我提到的定时参数一样。

结果是:程序在2.5s更改参数后,立即以2s的定时开始运行,也就是紧接着执行了定时2s的中断,于是我得出,定时器修改参数后会立即转到新的参数进行运行!

希望大家共勉!实验才是硬道理啊。哈哈
好吧,2楼实验程序也贴出来,程序用的stm32cubemx自动生成。 查看全部
今天遇到这样的问题?

就是比如定时器tim1初始化的定时时间是6s,表现为一个LED反转。
那么,如果我在定时途中修改这个定时器的定时时间参数,定时器是即时反应还是定时结束后统一更新?

比如现在定时为6s,然而我在定时途中2.5s的时候修改定时时间为2s,那么是在第4.5s就立马定时中断,还是继续上次的6s定时后进行呢?

于是我做了实验。

就是上面我提到的定时参数一样。

结果是:程序在2.5s更改参数后,立即以2s的定时开始运行,也就是紧接着执行了定时2s的中断,于是我得出,定时器修改参数后会立即转到新的参数进行运行!

希望大家共勉!实验才是硬道理啊。哈哈
好吧,2楼实验程序也贴出来,程序用的stm32cubemx自动生成。

stm32cube中文教程:TIM3定时,TIM1双通道计数器的实现

软件教程admin 发表了文章 • 0 个评论 • 5757 次浏览 • 2014-10-14 00:16 • 来自相关话题

本次利用了,stm32cubemx生成代码,稍微在main中添加得到
打开cubemx,先设置pinout选项卡。
rcc选择crystal。外部时钟
TIM1中选择Channel1的Input Capture direct mode
TIM1中选择Channel2的Input Capture direct mode

TIM3中Clock Source选择Internal Clock
Usart1中MOde选择Asynchronous

其他所有的默认即可。
TIM1用于计数,两个通道同时计数。
TIM3用于定时,并且生成一个脉冲信号
usart用于输出计数结果

Clock configuration选项卡中
时钟我用的25M晶振,系统时钟设为168MHz
APB1 Prescaler 选4,APB2 Prescaler选2

Configuration选项卡中,
usart设置不再讲述,可以去看网站里面的帖子
NVIC按钮打开后,TIM1 Capture Compare interrupt 设为0,2
TIM3 gloable interrupt 设置 0,1
并且以上开启使能
TIM1设置页打开后 counter period (autoreload register-16bits value) 设为65535,up,其他不变,tim1的gpio都设为Pull-up,high
Tim3设置页 prescaler (psc-16 bits value) 为8399
紧接着up,继续9999
最后update event。

好了,设置结束,生成代码,
main.c中的代码:其他的文件没变啊,自己对比添加了哪些吧,懒得一个个写


/[i] Includes ------------------------------------------------------------------[/i]/
#include "stm32f4xx_hal.h"

/[i] Private variables ---------------------------------------------------------[/i]/
TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim3;

UART_HandleTypeDef huart1;

/[i] USER CODE BEGIN 0 [/i]/
#include "stdio.h"
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /[i] __GNUC__ [/i]/

/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/[i] Place your implementation of fputc here [/i]/
/[i] e.g. write a character to the EVAL_COM1 and Loop until the end of transmission [/i]/
HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
uint32_t cont_value1 = 0;
uint32_t cont_value2 = 0;
uint32_t v_value1 = 0;
uint32_t v_value2 = 0;
static void Error_Handler(void);
/[i] USER CODE END 0 [/i]/

/[i] Private function prototypes -----------------------------------------------[/i]/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM1_Init(void);
static void MX_TIM3_Init(void);
static void MX_USART1_UART_Init(void);

int main(void)
{

/[i] USER CODE BEGIN 1 [/i]/

/[i] USER CODE END 1 [/i]/

/[i] MCU Configuration----------------------------------------------------------[/i]/

/[i] Reset of all peripherals, Initializes the Flash interface and the Systick. [/i]/
HAL_Init();

/[i] Configure the system clock [/i]/
SystemClock_Config();

/[i] System interrupt init[/i]/
/[i] Sets the priority grouping field [/i]/
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);

/[i] Initialize all configured peripherals [/i]/
MX_GPIO_Init();
MX_TIM1_Init();
MX_TIM3_Init();
MX_USART1_UART_Init();

/[i] USER CODE BEGIN 2 [/i]/
HAL_TIM_Base_Start_IT (&htim3 );
if(HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_2) != HAL_OK)
{
/[i] Starting Error [/i]/
Error_Handler();
}
if(HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1) != HAL_OK)
{
/[i] Starting Error [/i]/
Error_Handler();
}
/[i] USER CODE END 2 [/i]/

/[i] USER CODE BEGIN 3 [/i]/
/[i] Infinite loop [/i]/
while (1)
{
// HAL_Delay(1000);

// printf ("hello ,my world!");
HAL_Delay(1000);
printf ("%d , %d \r\n",v_value1, v_value2);
cont_value1= 0;cont_value2= 0;

}
/[i] USER CODE END 3 [/i]/

}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;

__PWR_CLK_ENABLE();

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);

}

/[i] TIM1 init function [/i]/
void MX_TIM1_Init(void)
{

TIM_IC_InitTypeDef sConfigIC;
TIM_MasterConfigTypeDef sMasterConfig;

htim1.Instance = TIM1;
htim1.Init.Prescaler = 0;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 65535;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
HAL_TIM_IC_Init(&htim1);

sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0;
HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_1);

HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_2);

sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);

}

/[i] TIM3 init function [/i]/
void MX_TIM3_Init(void)
{

TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;

htim3.Instance = TIM3;
htim3.Init.Prescaler = 8399;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 99;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&htim3);

sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig);

sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig);

}

/[i] USART1 init function [/i]/
void MX_USART1_UART_Init(void)
{

huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart1);

}

/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
void MX_GPIO_Init(void)
{

GPIO_InitTypeDef GPIO_InitStruct;

/[i] GPIO Ports Clock Enable [/i]/
__GPIOF_CLK_ENABLE();
__GPIOH_CLK_ENABLE();
__GPIOE_CLK_ENABLE();
__GPIOB_CLK_ENABLE();

/[i]Configure GPIO pin : PF6 [/i]/
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

}

/[i] USER CODE BEGIN 4 [/i]/
static void Error_Handler(void)
{
/[i] Turn LED3 on [/i]/
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
while(1)
{
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* NOTE : This function Should not be modified, when the callback is needed,
the __HAL_TIM_PeriodElapsedCallback could be implemented in the user file
*/
v_value1 = cont_value1;v_value2 = cont_value2;
// cont_value = 0;
HAL_GPIO_TogglePin (GPIOF,GPIO_PIN_6);

}
/**
* @brief Conversion complete callback in non blocking mode
* @param htim : hadc handle
* @retval None
*/
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{

/[i] Get the 1st Input Capture value [/i]/
cont_value1 ++;

}
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{

/[i] Get the 1st Input Capture value [/i]/
cont_value2 ++;

}
}
/[i] USER CODE END 4 [/i]/

#ifdef USE_FULL_ASSERT

/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/[i] USER CODE BEGIN 6 [/i]/
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/[i] USER CODE END 6 [/i]/

}

#endif 查看全部
本次利用了,stm32cubemx生成代码,稍微在main中添加得到
打开cubemx,先设置pinout选项卡。
rcc选择crystal。外部时钟
TIM1中选择Channel1的Input Capture direct mode
TIM1中选择Channel2的Input Capture direct mode

TIM3中Clock Source选择Internal Clock
Usart1中MOde选择Asynchronous

其他所有的默认即可。
TIM1用于计数,两个通道同时计数。
TIM3用于定时,并且生成一个脉冲信号
usart用于输出计数结果

Clock configuration选项卡中
时钟我用的25M晶振,系统时钟设为168MHz
APB1 Prescaler 选4,APB2 Prescaler选2

Configuration选项卡中,
usart设置不再讲述,可以去看网站里面的帖子
NVIC按钮打开后,TIM1 Capture Compare interrupt 设为0,2
TIM3 gloable interrupt 设置 0,1
并且以上开启使能
TIM1设置页打开后 counter period (autoreload register-16bits value) 设为65535,up,其他不变,tim1的gpio都设为Pull-up,high
Tim3设置页 prescaler (psc-16 bits value) 为8399
紧接着up,继续9999
最后update event。

好了,设置结束,生成代码,
main.c中的代码:其他的文件没变啊,自己对比添加了哪些吧,懒得一个个写


/[i] Includes ------------------------------------------------------------------[/i]/
#include "stm32f4xx_hal.h"

/[i] Private variables ---------------------------------------------------------[/i]/
TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim3;

UART_HandleTypeDef huart1;

/[i] USER CODE BEGIN 0 [/i]/
#include "stdio.h"
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /[i] __GNUC__ [/i]/

/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/[i] Place your implementation of fputc here [/i]/
/[i] e.g. write a character to the EVAL_COM1 and Loop until the end of transmission [/i]/
HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
uint32_t cont_value1 = 0;
uint32_t cont_value2 = 0;
uint32_t v_value1 = 0;
uint32_t v_value2 = 0;
static void Error_Handler(void);
/[i] USER CODE END 0 [/i]/

/[i] Private function prototypes -----------------------------------------------[/i]/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM1_Init(void);
static void MX_TIM3_Init(void);
static void MX_USART1_UART_Init(void);

int main(void)
{

/[i] USER CODE BEGIN 1 [/i]/

/[i] USER CODE END 1 [/i]/

/[i] MCU Configuration----------------------------------------------------------[/i]/

/[i] Reset of all peripherals, Initializes the Flash interface and the Systick. [/i]/
HAL_Init();

/[i] Configure the system clock [/i]/
SystemClock_Config();

/[i] System interrupt init[/i]/
/[i] Sets the priority grouping field [/i]/
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);

/[i] Initialize all configured peripherals [/i]/
MX_GPIO_Init();
MX_TIM1_Init();
MX_TIM3_Init();
MX_USART1_UART_Init();

/[i] USER CODE BEGIN 2 [/i]/
HAL_TIM_Base_Start_IT (&htim3 );
if(HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_2) != HAL_OK)
{
/[i] Starting Error [/i]/
Error_Handler();
}
if(HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1) != HAL_OK)
{
/[i] Starting Error [/i]/
Error_Handler();
}
/[i] USER CODE END 2 [/i]/

/[i] USER CODE BEGIN 3 [/i]/
/[i] Infinite loop [/i]/
while (1)
{
// HAL_Delay(1000);

// printf ("hello ,my world!");
HAL_Delay(1000);
printf ("%d , %d \r\n",v_value1, v_value2);
cont_value1= 0;cont_value2= 0;

}
/[i] USER CODE END 3 [/i]/

}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;

__PWR_CLK_ENABLE();

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);

}

/[i] TIM1 init function [/i]/
void MX_TIM1_Init(void)
{

TIM_IC_InitTypeDef sConfigIC;
TIM_MasterConfigTypeDef sMasterConfig;

htim1.Instance = TIM1;
htim1.Init.Prescaler = 0;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 65535;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
HAL_TIM_IC_Init(&htim1);

sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0;
HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_1);

HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_2);

sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);

}

/[i] TIM3 init function [/i]/
void MX_TIM3_Init(void)
{

TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;

htim3.Instance = TIM3;
htim3.Init.Prescaler = 8399;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 99;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&htim3);

sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig);

sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig);

}

/[i] USART1 init function [/i]/
void MX_USART1_UART_Init(void)
{

huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart1);

}

/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
void MX_GPIO_Init(void)
{

GPIO_InitTypeDef GPIO_InitStruct;

/[i] GPIO Ports Clock Enable [/i]/
__GPIOF_CLK_ENABLE();
__GPIOH_CLK_ENABLE();
__GPIOE_CLK_ENABLE();
__GPIOB_CLK_ENABLE();

/[i]Configure GPIO pin : PF6 [/i]/
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

}

/[i] USER CODE BEGIN 4 [/i]/
static void Error_Handler(void)
{
/[i] Turn LED3 on [/i]/
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
while(1)
{
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* NOTE : This function Should not be modified, when the callback is needed,
the __HAL_TIM_PeriodElapsedCallback could be implemented in the user file
*/
v_value1 = cont_value1;v_value2 = cont_value2;
// cont_value = 0;
HAL_GPIO_TogglePin (GPIOF,GPIO_PIN_6);

}
/**
* @brief Conversion complete callback in non blocking mode
* @param htim : hadc handle
* @retval None
*/
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{

/[i] Get the 1st Input Capture value [/i]/
cont_value1 ++;

}
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{

/[i] Get the 1st Input Capture value [/i]/
cont_value2 ++;

}
}
/[i] USER CODE END 4 [/i]/

#ifdef USE_FULL_ASSERT

/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/[i] USER CODE BEGIN 6 [/i]/
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/[i] USER CODE END 6 [/i]/

}

#endif

stm32cube中文教程:运行中修改TIM定时时间的例子将1s定时运行中改成200ms定时

软件教程admin 发表了文章 • 0 个评论 • 3658 次浏览 • 2014-10-14 00:14 • 来自相关话题

本实验用stm32cubemx生成定时器4的1s定时,然后准备在运行过程中更改定时时间
考虑程序中初始化后定时修改时再次init初始化,应该就可以了。
关于用stm32cube生成定时的方法,请找本论坛文章。
本程序只在原来定时中断中增加了再次初始化代码。
运行正常,测试通过。
代码如下:

其他代码不给出了,只贴出修改了的代码:
在main文件中的定时中断函数中增加:


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* NOTE : This function Should not be modified, when the callback is needed,
the __HAL_TIM_PeriodElapsedCallback could be implemented in the user file
*/
flag++;
HAL_GPIO_TogglePin (GPIOD,GPIO_PIN_14);
if(flag==20)
{
htim4.Init.Period = 1999;
HAL_TIM_Base_Init(&htim4);
}
}

其中flag是计数标示,用来记进入了几次中断,程序中断20次后,修改Period ,然后固化,
之后程序开始以200ms开始闪烁。灯是PD14. 查看全部
本实验用stm32cubemx生成定时器4的1s定时,然后准备在运行过程中更改定时时间
考虑程序中初始化后定时修改时再次init初始化,应该就可以了。
关于用stm32cube生成定时的方法,请找本论坛文章。
本程序只在原来定时中断中增加了再次初始化代码。
运行正常,测试通过。
代码如下:

其他代码不给出了,只贴出修改了的代码:
在main文件中的定时中断函数中增加:


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* NOTE : This function Should not be modified, when the callback is needed,
the __HAL_TIM_PeriodElapsedCallback could be implemented in the user file
*/
flag++;
HAL_GPIO_TogglePin (GPIOD,GPIO_PIN_14);
if(flag==20)
{
htim4.Init.Period = 1999;
HAL_TIM_Base_Init(&htim4);
}
}

其中flag是计数标示,用来记进入了几次中断,程序中断20次后,修改Period ,然后固化,
之后程序开始以200ms开始闪烁。灯是PD14.

stm32cube中文教程:AD用TIM8定时采集,uart3输出

软件教程admin 发表了文章 • 15 个评论 • 5139 次浏览 • 2014-10-13 23:45 • 来自相关话题

stm32cube中文教程:AD用TIM8定时采集,uart3输出
arm片子stm32f407ZGT,用ADC1,TIM8,UART3,。
ad脚PB0,uart脚PB10和11,PF6输出led灯。
晶振25M,时钟168M。
stm32cubemx软件设置:
uart9600,8,0,1,不使能uart中断,TX:PULL_up,fast。RX:NO PULL_UP,fast
DMA不使能。
ADC设置:修改了continuous conversion mode:enable;end of conversion selection :Eoc flag signle channel

External Trigger conversion Edge : Trigger detection on the rising edge
External Trigger Conversion Source : Time 8 Trigger Out event
其余的默认即可。
ADC中断不使能。
TIme8定时设置:
Prescaler(psc - 16 bits value) : 0
counter mode : UP
counter Period(autoreload register - 16 bits value) : 60
internal clock division (CDK) : NO Division
Repetition counter(RCR - 8bits value) : 0
slave mode controller : trigger mode
master/slave mode : Disable
trigger event selection : Update enent
不使能任何TIM中断,DMA不使能。
----------------------------------------------------------
以上软件配置结束,自动生成代码即可。
main文件中添加:


#include "stdio.h"
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /[i] __GNUC__ [/i]/

/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/[i] Place your implementation of fputc here [/i]/
/[i] e.g. write a character to the EVAL_COM1 and Loop until the end of transmission [/i]/
HAL_UART_Transmit(&huart3 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}

---------------------------------------为了能使用printf。
main()函数中添加:


/[i] USER CODE BEGIN 2 [/i]/
/[i][size=16]-3- Start the conversion process and enable interrupt [/size]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[/i]/ [/size][/size][/size][/size][/size]
if(HAL_ADC_Start_IT(&hadc1) != HAL_OK)
{
/[i] Start Conversation Error [/i]/
// Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}
if(HAL_TIM_Base_Start(&htim8) != HAL_OK)
{
/[i] Counter Enable Error [/i]/
//Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}

/[i] USER CODE END 2 [/i]/

/[i] USER CODE BEGIN 3 [/i]/
/[i] Infinite loop [/i]/
while (1)
{

HAL_Delay (1000);
HAL_GPIO_TogglePin (GPIOF,GPIO_PIN_6);
printf ("%d",s_value);
// HAL_ADC_Start_IT(&hadc1);
}
/[i] USER CODE END 3 [/i]/

-------------------------------------------------开启AD和TIM
底部添加:


/[i] USER CODE BEGIN 4 [/i]/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
/[i] Get the converted value of regular channel [/i]/
uhADCxConvertedValue = HAL_ADC_GetValue(AdcHandle);
v_value += uhADCxConvertedValue;
count++;
if(count>=500) { s_value = v_value/500; v_value = 0; count=0; }
}

/[i] USER CODE END 4 [/i]/

---------------------------------------AD采集完成数据处理调用

其他文件不要变动。

下面是完整的main文件代码:


/[i] Includes ------------------------------------------------------------------[/i]/
#include "stm32f4xx_hal.h"

/[i] Private variables ---------------------------------------------------------[/i]/
ADC_HandleTypeDef hadc1;

TIM_HandleTypeDef htim8;

UART_HandleTypeDef huart3;

/[i] USER CODE BEGIN 0 [/i]/
#include "stdio.h"
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /[i] __GNUC__ [/i]/

/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/[i] Place your implementation of fputc here [/i]/
/[i] e.g. write a character to the EVAL_COM1 and Loop until the end of transmission [/i]/
HAL_UART_Transmit(&huart3 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/[i] Variable used to get converted value [/i]/
__IO uint16_t uhADCxConvertedValue = 0;
int32_t v_value;
int32_t s_value;
uint16_t count=0;
/[i] USER CODE END 0 [/i]/

/[i] Private function prototypes -----------------------------------------------[/i]/
static void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM8_Init(void);
static void MX_USART3_UART_Init(void);

int main(void)
{

/[i] USER CODE BEGIN 1 [/i]/

/[i] USER CODE END 1 [/i]/

/[i] MCU Configuration----------------------------------------------------------[/i]/

/[i] Reset of all peripherals, Initializes the Flash interface and the Systick. [/i]/
HAL_Init();

/[i] Configure the system clock [/i]/
SystemClock_Config();

/[i] Initialize all configured peripherals [/i]/
MX_GPIO_Init();
MX_ADC1_Init();
MX_TIM8_Init();
MX_USART3_UART_Init();

/[i] USER CODE BEGIN 2 [/i]/
/[i][size=16]-3- Start the conversion process and enable interrupt [/size]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[/i]/ [/size][/size][/size][/size][/size]
if(HAL_ADC_Start_IT(&hadc1) != HAL_OK)
{
/[i] Start Conversation Error [/i]/
// Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}
if(HAL_TIM_Base_Start(&htim8) != HAL_OK)
{
/[i] Counter Enable Error [/i]/
//Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}

/[i] USER CODE END 2 [/i]/

/[i] USER CODE BEGIN 3 [/i]/
/[i] Infinite loop [/i]/
while (1)
{

HAL_Delay (1000);
HAL_GPIO_TogglePin (GPIOF,GPIO_PIN_6);
printf ("%d",s_value);
// HAL_ADC_Start_IT(&hadc1);
}
/[i] USER CODE END 3 [/i]/

}
/** System Clock Configuration
*/
static void SystemClock_Config(void)
{

RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;

__PWR_CLK_ENABLE();

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);

}

/[i] ADC1 init function [/i]/
void MX_ADC1_Init(void)
{

ADC_ChannelConfTypeDef sConfig;
ADC_MultiModeTypeDef multimode;

/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION12b;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.NbrOfDiscConversion = 1;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T8_TRGO;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = EOC_SINGLE_CONV;
HAL_ADC_Init(&hadc1);

/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);

/**Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES;
HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode);

}

/[i] TIM8 init function [/i]/
void MX_TIM8_Init(void)
{

TIM_SlaveConfigTypeDef sSlaveConfig;
TIM_MasterConfigTypeDef sMasterConfig;

htim8.Instance = TIM8;
htim8.Init.Prescaler = 0;
htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
htim8.Init.Period = 60;
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim8.Init.RepetitionCounter = 0;
HAL_TIM_Base_Init(&htim8);

sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;
sSlaveConfig.InputTrigger = TIM_TS_ITR0;
HAL_TIM_SlaveConfigSynchronization(&htim8, &sSlaveConfig);

sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig);

}

/[i] USART3 init function [/i]/
void MX_USART3_UART_Init(void)
{

huart3.Instance = USART3;
huart3.Init.BaudRate = 9600;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart3);

}

/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
void MX_GPIO_Init(void)
{

GPIO_InitTypeDef GPIO_InitStruct;

/[i] GPIO Ports Clock Enable [/i]/
__GPIOF_CLK_ENABLE();
__GPIOH_CLK_ENABLE();
__GPIOB_CLK_ENABLE();

/[i]Configure GPIO pin : PF6 [/i]/
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

}

/[i] USER CODE BEGIN 4 [/i]/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
/[i] Get the converted value of regular channel [/i]/
uhADCxConvertedValue = HAL_ADC_GetValue(AdcHandle);
v_value += uhADCxConvertedValue;
count++;
if(count>=500) { s_value = v_value/500; v_value = 0; count=0; }
}

/[i] USER CODE END 4 [/i]/ 查看全部
stm32cube中文教程:AD用TIM8定时采集,uart3输出
arm片子stm32f407ZGT,用ADC1,TIM8,UART3,。
ad脚PB0,uart脚PB10和11,PF6输出led灯。
晶振25M,时钟168M。
stm32cubemx软件设置:
uart9600,8,0,1,不使能uart中断,TX:PULL_up,fast。RX:NO PULL_UP,fast
DMA不使能。
ADC设置:修改了continuous conversion mode:enable;end of conversion selection :Eoc flag signle channel

External Trigger conversion Edge : Trigger detection on the rising edge
External Trigger Conversion Source : Time 8 Trigger Out event
其余的默认即可。
ADC中断不使能。
TIme8定时设置:
Prescaler(psc - 16 bits value) : 0
counter mode : UP
counter Period(autoreload register - 16 bits value) : 60
internal clock division (CDK) : NO Division
Repetition counter(RCR - 8bits value) : 0
slave mode controller : trigger mode
master/slave mode : Disable
trigger event selection : Update enent
不使能任何TIM中断,DMA不使能。
----------------------------------------------------------
以上软件配置结束,自动生成代码即可。
main文件中添加:


#include "stdio.h"
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /[i] __GNUC__ [/i]/

/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/[i] Place your implementation of fputc here [/i]/
/[i] e.g. write a character to the EVAL_COM1 and Loop until the end of transmission [/i]/
HAL_UART_Transmit(&huart3 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}

---------------------------------------为了能使用printf。
main()函数中添加:


/[i] USER CODE BEGIN 2 [/i]/
/[i][size=16]-3- Start the conversion process and enable interrupt [/size]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[/i]/ [/size][/size][/size][/size][/size]
if(HAL_ADC_Start_IT(&hadc1) != HAL_OK)
{
/[i] Start Conversation Error [/i]/
// Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}
if(HAL_TIM_Base_Start(&htim8) != HAL_OK)
{
/[i] Counter Enable Error [/i]/
//Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}

/[i] USER CODE END 2 [/i]/

/[i] USER CODE BEGIN 3 [/i]/
/[i] Infinite loop [/i]/
while (1)
{

HAL_Delay (1000);
HAL_GPIO_TogglePin (GPIOF,GPIO_PIN_6);
printf ("%d",s_value);
// HAL_ADC_Start_IT(&hadc1);
}
/[i] USER CODE END 3 [/i]/

-------------------------------------------------开启AD和TIM
底部添加:


/[i] USER CODE BEGIN 4 [/i]/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
/[i] Get the converted value of regular channel [/i]/
uhADCxConvertedValue = HAL_ADC_GetValue(AdcHandle);
v_value += uhADCxConvertedValue;
count++;
if(count>=500) { s_value = v_value/500; v_value = 0; count=0; }
}

/[i] USER CODE END 4 [/i]/

---------------------------------------AD采集完成数据处理调用

其他文件不要变动。

下面是完整的main文件代码:


/[i] Includes ------------------------------------------------------------------[/i]/
#include "stm32f4xx_hal.h"

/[i] Private variables ---------------------------------------------------------[/i]/
ADC_HandleTypeDef hadc1;

TIM_HandleTypeDef htim8;

UART_HandleTypeDef huart3;

/[i] USER CODE BEGIN 0 [/i]/
#include "stdio.h"
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /[i] __GNUC__ [/i]/

/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/[i] Place your implementation of fputc here [/i]/
/[i] e.g. write a character to the EVAL_COM1 and Loop until the end of transmission [/i]/
HAL_UART_Transmit(&huart3 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/[i] Variable used to get converted value [/i]/
__IO uint16_t uhADCxConvertedValue = 0;
int32_t v_value;
int32_t s_value;
uint16_t count=0;
/[i] USER CODE END 0 [/i]/

/[i] Private function prototypes -----------------------------------------------[/i]/
static void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM8_Init(void);
static void MX_USART3_UART_Init(void);

int main(void)
{

/[i] USER CODE BEGIN 1 [/i]/

/[i] USER CODE END 1 [/i]/

/[i] MCU Configuration----------------------------------------------------------[/i]/

/[i] Reset of all peripherals, Initializes the Flash interface and the Systick. [/i]/
HAL_Init();

/[i] Configure the system clock [/i]/
SystemClock_Config();

/[i] Initialize all configured peripherals [/i]/
MX_GPIO_Init();
MX_ADC1_Init();
MX_TIM8_Init();
MX_USART3_UART_Init();

/[i] USER CODE BEGIN 2 [/i]/
/[i][size=16]-3- Start the conversion process and enable interrupt [/size]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[/i]/ [/size][/size][/size][/size][/size]
if(HAL_ADC_Start_IT(&hadc1) != HAL_OK)
{
/[i] Start Conversation Error [/i]/
// Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}
if(HAL_TIM_Base_Start(&htim8) != HAL_OK)
{
/[i] Counter Enable Error [/i]/
//Error_Handler();
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET );
HAL_Delay (5000);
}

/[i] USER CODE END 2 [/i]/

/[i] USER CODE BEGIN 3 [/i]/
/[i] Infinite loop [/i]/
while (1)
{

HAL_Delay (1000);
HAL_GPIO_TogglePin (GPIOF,GPIO_PIN_6);
printf ("%d",s_value);
// HAL_ADC_Start_IT(&hadc1);
}
/[i] USER CODE END 3 [/i]/

}
/** System Clock Configuration
*/
static void SystemClock_Config(void)
{

RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;

__PWR_CLK_ENABLE();

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);

}

/[i] ADC1 init function [/i]/
void MX_ADC1_Init(void)
{

ADC_ChannelConfTypeDef sConfig;
ADC_MultiModeTypeDef multimode;

/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION12b;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.NbrOfDiscConversion = 1;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T8_TRGO;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = EOC_SINGLE_CONV;
HAL_ADC_Init(&hadc1);

/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);

/**Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES;
HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode);

}

/[i] TIM8 init function [/i]/
void MX_TIM8_Init(void)
{

TIM_SlaveConfigTypeDef sSlaveConfig;
TIM_MasterConfigTypeDef sMasterConfig;

htim8.Instance = TIM8;
htim8.Init.Prescaler = 0;
htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
htim8.Init.Period = 60;
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim8.Init.RepetitionCounter = 0;
HAL_TIM_Base_Init(&htim8);

sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;
sSlaveConfig.InputTrigger = TIM_TS_ITR0;
HAL_TIM_SlaveConfigSynchronization(&htim8, &sSlaveConfig);

sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig);

}

/[i] USART3 init function [/i]/
void MX_USART3_UART_Init(void)
{

huart3.Instance = USART3;
huart3.Init.BaudRate = 9600;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart3);

}

/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
void MX_GPIO_Init(void)
{

GPIO_InitTypeDef GPIO_InitStruct;

/[i] GPIO Ports Clock Enable [/i]/
__GPIOF_CLK_ENABLE();
__GPIOH_CLK_ENABLE();
__GPIOB_CLK_ENABLE();

/[i]Configure GPIO pin : PF6 [/i]/
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

}

/[i] USER CODE BEGIN 4 [/i]/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
/[i] Get the converted value of regular channel [/i]/
uhADCxConvertedValue = HAL_ADC_GetValue(AdcHandle);
v_value += uhADCxConvertedValue;
count++;
if(count>=500) { s_value = v_value/500; v_value = 0; count=0; }
}

/[i] USER CODE END 4 [/i]/