打印
[应用相关]

为什么用单脉冲模式和RCR寄存器控制定时器发出指定频率和数目的PWM脉冲时,当频率上升...

[复制链接]
879|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
需要产生频率[50, 200k]Hz,数目[1, 2000]的PWM脉冲来驱动步进电机。目前已经尝试了三种方法。
1. 直接使用定时器中断计数和停止脉冲
2. 设置一个门模式从定时器计数和停止脉冲
3. 使用高级定时器的单脉冲和重复计数器(RCR)计数和停止脉冲

个人认为第三种方法最简单、最可靠。毕竟所有的控制都是硬件完成的。但是当频率上升到200kHz时,三种方法均无法产生数目准确的PWM脉冲。并且脉冲数目总是小于预期值。

下面是我计时器的设置和代码。



  • #define CLK_FREQ 144000   /* CLK_INT / 1000 */
  • #define DT 1                       /* dt in millisecond */
  • #include "tim.h"
  • #include "gpio.h"
  • #include "math.h"
  • void motorMove(uint8_t xdir,uint16_t xsteps, uint8_t ydir,uint16_t ysteps)
  • {
  •     uint16_t psc = 0;
  •     uint16_t arr = 0;
  •     uint16_t ccr = 0;
  •     xdirOut(xdir);
  •     getFreq(xsteps, DT, &psc, &arr, &ccr);
  •     xpwmOut(psc, arr, ccr, xsteps);
  •     ydirOut(ydir);
  •     getFreq(ysteps, DT, &psc, &arr, &ccr);
  •     ypwmOut(psc, arr, ccr, ysteps);
  • }
  • void xpwmOut(uint16_t psc,uint16_t arr,uint16_t ccr,uint16_t stp)
  • {
  •     htim1.Init.Prescaler = psc;
  •     htim1.Init.Period = arr;
  •     __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, ccr);
  •     htim1.Init.RepetitionCounter = stp - 1;
  •     HAL_TIM_Base_Init(&htim1);
  •     HAL_TIM_PWM_Start_IT(&htim1, TIM_CHANNEL_1);
  • }
  • void ypwmOut(uint16_t psc,uint16_t arr,uint16_t ccr,uint16_t stp)
  • {
  •     htim8.Init.Prescaler = psc;
  •     htim8.Init.Period = arr;
  •     __HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_1, ccr);
  •     htim8.Init.RepetitionCounter = stp - 1;
  •     HAL_TIM_Base_Init(&htim8);
  •     HAL_TIM_PWM_Start_IT(&htim8, TIM_CHANNEL_1);
  • }
  • void xdirOut(uint8_t dir)
  • {
  •     if(dir)
  •     {
  •         HAL_GPIO_WritePin(X_DIR_GPIO_Port, X_DIR_Pin, GPIO_PIN_RESET);
  •     }
  •     else
  •     {
  •     HAL_GPIO_WritePin(X_DIR_GPIO_Port, X_DIR_Pin, GPIO_PIN_SET);
  •     }
  • }
  • void ydirOut(uint8_t dir)
  • {
  •     if(dir)

复制代码



使用特权

评论回复
沙发
flycamelaaa|  楼主 | 2022-11-17 10:23 | 只看该作者
  • void ydirOut(uint8_t dir)
  • {
  •     if(dir)
  •     {
  •         HAL_GPIO_WritePin(Y_DIR_GPIO_Port, Y_DIR_Pin, GPIO_PIN_RESET);
  •     }
  •     else
  •     {
  •         HAL_GPIO_WritePin(Y_DIR_GPIO_Port, Y_DIR_Pin, GPIO_PIN_SET);
  •     }
  • }
  • void getFreq(uint16_t steps, const uint16_t dt, uint16_t* psc, uint16_t* arr, uint16_t* ccr)
  • {
  •     double temp;
  •     temp = CLK_FREQ * dt / steps;
  •     temp = sqrt(temp);
  •     *(psc) = ((uint16_t) temp) - 1;
  •     *(arr) = *(psc);
  •     *(ccr) = *(arr) / 2;
  • }

复制代码

上面代码好像没显示全

使用特权

评论回复
板凳
OKAKAKO| | 2024-6-25 15:58 | 只看该作者
PWM脉冲时,当频率上升会有问题吗?

使用特权

评论回复
地板
童雨竹| | 2024-12-1 07:02 | 只看该作者

这些引线越窄越好

使用特权

评论回复
5
Wordsworth| | 2024-12-1 08:05 | 只看该作者

图像由前景和背景组成,在灰度直方图上,前景和背景会形成高峰,在双峰之间的最低谷处就是阈值。

使用特权

评论回复
6
Clyde011| | 2024-12-1 09:08 | 只看该作者

要将多余空间去除。对于第一个字符从第一行开始向下扫描,把那些一行中所有的点的灰度值全为0的点去掉,直到扫描到有一行不全为0时为止。

使用特权

评论回复
7
公羊子丹| | 2024-12-1 10:01 | 只看该作者

输入滤波电容的公共端应作为其他交流电流地的唯一接点

使用特权

评论回复
8
万图| | 2024-12-1 11:04 | 只看该作者

根据色彩的变化记录每一行的颜色跳变点,由此识别出车牌区域。

使用特权

评论回复
9
Uriah| | 2024-12-1 12:07 | 只看该作者

切割完了第四个字符之后,再依次扫描剩下的空间,直到所扫描的这一竖上的所有点的灰度值不全为0时,认为是字符的开始并依次扫描直到所扫描的这一竖上的所有点的灰度值全为0时认为是字符的结束。

使用特权

评论回复
10
Bblythe| | 2024-12-1 15:06 | 只看该作者

在内存中开辟七个长为车牌长的七分之一和宽为车牌宽的区域

使用特权

评论回复
11
周半梅| | 2024-12-1 17:02 | 只看该作者

把纹波电流分摊到每个电容上

使用特权

评论回复
12
Pulitzer| | 2024-12-1 18:05 | 只看该作者

分别记录车牌区域的上下高度。然后通过RGB-HSV颜色转换

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

688

主题

3273

帖子

0

粉丝