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

[复制链接]
1062|13
 楼主| flycamelaaa 发表于 2022-11-17 10:22 | 显示全部楼层 |阅读模式
需要产生频率[50, 200k]Hz,数目[1, 2000]的PWM脉冲来驱动步进电机。目前已经尝试了三种方法。
1. 直接使用定时器中断计数和停止脉冲
2. 设置一个门模式从定时器计数和停止脉冲
3. 使用高级定时器的单脉冲和重复计数器(RCR)计数和停止脉冲

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

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

182205zq463abbshh8z2s8.png
182228s42zxxzlp24xhk6k.png
  • #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 | 显示全部楼层

这些引线越窄越好
Wordsworth 发表于 2024-12-1 08:05 | 显示全部楼层

图像由前景和背景组成,在灰度直方图上,前景和背景会形成高峰,在双峰之间的最低谷处就是阈值。
Clyde011 发表于 2024-12-1 09:08 | 显示全部楼层

要将多余空间去除。对于第一个字符从第一行开始向下扫描,把那些一行中所有的点的灰度值全为0的点去掉,直到扫描到有一行不全为0时为止。
公羊子丹 发表于 2024-12-1 10:01 | 显示全部楼层

输入滤波电容的公共端应作为其他交流电流地的唯一接点
万图 发表于 2024-12-1 11:04 | 显示全部楼层

根据色彩的变化记录每一行的颜色跳变点,由此识别出车牌区域。
Uriah 发表于 2024-12-1 12:07 | 显示全部楼层

切割完了第四个字符之后,再依次扫描剩下的空间,直到所扫描的这一竖上的所有点的灰度值不全为0时,认为是字符的开始并依次扫描直到所扫描的这一竖上的所有点的灰度值全为0时认为是字符的结束。
Bblythe 发表于 2024-12-1 15:06 | 显示全部楼层

在内存中开辟七个长为车牌长的七分之一和宽为车牌宽的区域
周半梅 发表于 2024-12-1 17:02 | 显示全部楼层

把纹波电流分摊到每个电容上
Pulitzer 发表于 2024-12-1 18:05 | 显示全部楼层

分别记录车牌区域的上下高度。然后通过RGB-HSV颜色转换
您需要登录后才可以回帖 登录 | 注册

本版积分规则

837

主题

4432

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部