PWDT是Pulse Width Detect Timer(脉冲宽度检测定时器)缩写。可作为测量脉冲宽度的工具或作为16位定时器。
功能
检测脉冲宽度
可编程起始测量触发沿
支持 3 个霍尔传感器的信号输入测量
支持来自模拟比较器的 3 个输入
定时器
在禁用定时器或在正常操作时,修改定时器加载值
功能框图
反电动势信号可推出霍尔信号?
PWDT 功能框图可知,ACMP 模块的输出可作为 PWDT 模块输入。该功能主要用于电机控制,无传感方案应用。
大致原理如下:由于电机自身特性,BLDC/PMSM 电机在运行时会产生反电动势(BLDC 为梯形波,PMSM 为正弦波)。通过反电动势采集电路,把采集到的电压输入给 ACMP 模块,ACMP 模块比较后输入给 PWDT,PWDT 根据三个输入值进行异或运算得到HALL 状态。
时钟配置
Pwdtclk 是由 PSC[2:0]从总线时钟分频得到。对于可测量脉冲宽度的范围,可通过设置 pwdtclk 进行调节。
在配置时钟分频时,有如下几点需注意:
1、输入信号的脉宽要在可捕获的范围内才行
2、脉冲宽度测量的精度
配置 PSC[2:0]以适当的值,以达到更准确的测量值。
一个基本原则是,使用较小的 PSC[2:0]可以获得更准确的测量值。显然,输入脉冲越窄,相对测量误差越大。
所以配备了滤波器功能:
模块中的滤波器设计用于滤除高或低电平小于本段中描述的特定宽度的噪声信号。
就像下面这个例子:
配置 FILTVAL = 15 及 FILT_PSC = 2 时,滤波器脉冲宽度为 60 bclk,小于 60 bclk 的脉冲被判断为噪声脉冲并将被过滤掉
单通道输入测量
对于基本测量,可以通过设置 PINSEL[1:0]来选择测量特定的通道输入,并可以根据实际应用通过设置 EDGE[1:0]来选择 4 种测量模式中的一种
三通道输入测量
对于霍尔测量,模块测量从 3 个通道输入的异或(XOR)得到的脉冲输入,设置 EDGE[1:0]= 2'b01。此外,内部 3 个通道比较器输入的配置类似于霍尔测量,只需把 CMPEN 同时配置为 1'b1。
对于霍尔测量或 3 个内部比较器输入,只需选择一种模式用于电机速度计算或换向,如下图所示。
实战测试
单通道
电路部分
产生一定频率与占空比的通道:
检测通道:PB8,对应PWDT_IN0,在Demo板子上是H_U接口
只需要在产生PWM的引脚引出一根杜邦线,连到PWDT检测通道上即可
软件部分
PWDT模块的初始化
/**
* PWDT_Initalize
*
* @param[in] none
*
* @return 0:Success
*
* @brief PWDT模块初始化
*/
void PWDT_Initalize(void)
{
PWDT_ConfigType pwdtConfig = {0};
///配置PWDT
pwdtConfig.overflowIntEn = 1; //使能溢出中断
pwdtConfig.readyIntEn = 1; //使能脉宽有效中断
pwdtConfig.pwdtIntEn = 1; //使能PWDT模块中断
pwdtConfig.pwdtEn = 1; //使能PWDT模块
pwdtConfig.edgeMode = RISING_START_CAPTURE_ALL; //上升沿开始捕获,双边沿捕获
pwdtConfig.clockPreScaler = PWDT_CLK_PRESCALER_8; //PWDT时钟源8分频
pwdtConfig.clockSource = PWDT_PCLKS_BUS; //PWDT时钟源为总线时钟
pwdtConfig.pwdtTimerEn = 0; //关闭PWDT timer
pwdtConfig.pwdtHallEn = 0; //关闭PWDT HALL功能
pwdtConfig.pinSelect = 0; //引脚选择 00/01/10/11分别选择pwdt_in0,pwdt_in1,pwdt_in2,internal_pwdtin
pwdtConfig.pwdtFilterEn = 1; //使能PWDT滤波,可滤掉小于pwdtFilterValue * (1 << pwdtFilterPsc)*bclk 的干扰信号
//Filter width = 1024 * 15 = 15360*bclk
pwdtConfig.pwdtFilterPsc = 10;//滤波器分频 1~12分别表示2/4/8.../4096
pwdtConfig.pwdtFilterValue = 15;//0~15表示滤波不同脉宽
PWDT_SetCallback(PWDT_Capture);//设置PWDT中断处理回调函数
PWDT_Init(&pwdtConfig);//设置PWDT
}
产生PWM信号
/**
* PWM2_GenerateFrequency
*
* @param[in] none
*
* @return 0:Success
*
* @brief 使用PWM2 CH0,CH2,CH4产生频率为100HZ,占空比为50%的信号,每组信号相移60度。
*/
void PWM2_GenerateFrequency(void)
{
//组合模式,高有效
PWM_PWMInit(PWM2, PWM_PWMMODE_COMBINE, PWM_PWM_HIGHTRUEPULSE);
//占空比 = (CH2n+1-CH2n)/(MOD+1) = (65-5)/(119+1) = 50%
PWM_SetChannelValue(PWM2, PWM_CHANNEL_CHANNEL0, 5);
PWM_SetChannelValue(PWM2, PWM_CHANNEL_CHANNEL1, 65);
//CH2,CH3PWM输出相位相对CH0,CH1相位delay60度
//(25-5)/(119+1) * 360度 = 60度
PWM_SetChannelValue(PWM2, PWM_CHANNEL_CHANNEL2, 25);
PWM_SetChannelValue(PWM2, PWM_CHANNEL_CHANNEL3, 85);
//CH4,CH5PWM输出相位相对CH2,CH3相位delay60度
PWM_SetChannelValue(PWM2, PWM_CHANNEL_CHANNEL4, 45);
PWM_SetChannelValue(PWM2, PWM_CHANNEL_CHANNEL5, 105);
PWM_SetModValue(PWM2, 119);
PWM_ClockSet(PWM2, PWM_CLOCK_SYSTEMCLOCK, 3999); //频率:48000000/(3999 + 1)/(119 + 1) = 100Hz
}
PWDT检测部分
/**
* PWDT_Capture
*
* @param[in] none
*
* @return none
*
* @brief PWDT Pulse Width Detection CallBack
*/
void PWDT_Capture(void)
{
if (PWDT_GetOverflowFlag())
{
//清PWDT溢出中断
PWDT_ClrOverflowFlag();
}
if (PWDT_GetReadyFlag())
{
//清脉宽有效中断
PWDT_ClrReadyFlag();
g_positvePulse = ((PWDT->INIT0 >> 16) & 0xFFFF); //获取正脉宽计数值
g_negativePulse = (PWDT->NPWCV & 0xFFFF); //获取负脉宽计数值
if (0 != (g_positvePulse + g_negativePulse))
{
/*
计算频率和占空比
频率 = PWDT时钟源 / PWDT时钟分频 / 正+负脉宽计数值
占空比 = 正脉宽计数值 / 正+负脉宽计数值
*/
g_freq = SYS_CLK / (PWDT_DIVIDER) / (g_positvePulse + 1 + g_negativePulse + 1);
g_duty = (float)((float)g_positvePulse / (float)(g_positvePulse +1 + g_negativePulse + 1));
printf("\ng_freq=%d, g_duty =%f.\r\n", g_freq, g_duty);
}
}
}
烧录测试
发现没有打印频率与占空比的结果
debug之后发现一直没有获取这个标志位
排除PWM产生功能原因
后来发现是电路的原因,R54焊盘被带掉了,而它正好是信号通道上的必经之路。
没办法,换通道了只能。
更换成,通道1,测试成功
使用霍尔信号捕获功能
霍尔两种安装方式的不同
因为HALL少了一个通道,所以暂时不进行此实验。