本帖最后由 assman 于 2022-5-20 08:56 编辑
各位大大安安,我在学习NUC240 BSP中Smpl_Basic01_PWM_Capture范例,输入的PWM频率范围在0~100Hz区间,量测周期结果不是输入的PWM频率,是否该设定PWM_ConfigCaptureChannel中的参数才能正确量测?
- /**
- * @brief Configure PWM capture and get the nearest unit time.
- * @param[in] pwm The pointer of the specified PWM module
- * @param[in] u32ChannelNum PWM channel number. Valid values are between 0~3
- * @param[in] u32UnitTimeNsec The unit time of counter
- * @param[in] u32CaptureEdge The condition to latch the counter. This parameter is not used
- * @return The nearest unit time in nano second.
- * @details This function is used to configure PWM capture and get the nearest unit time.
- */
- uint32_t PWM_ConfigCaptureChannel(PWM_T *pwm,
- uint32_t u32ChannelNum,
- uint32_t u32UnitTimeNsec,
- uint32_t u32CaptureEdge)
- {
- uint32_t u32Src;
- uint32_t u32PWMClockSrc;
- uint32_t u32PWMClkTbl[8] = {__HXT, __LXT, NULL, __HIRC, NULL, NULL, NULL, __LIRC};
- uint32_t u32NearestUnitTimeNsec;
- uint8_t u8Divider = 1;
- /* this table is mapping divider value to register configuration */
- uint32_t u32PWMDividerToRegTbl[17] = {NULL, 4, 0, NULL, 1, NULL, NULL, NULL, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3};
- uint16_t u16Prescale = 2;
- uint16_t u16CNR = 0xFFFF;
- if(pwm == PWMA)
- {
- if(u32ChannelNum < 2)/* channel 0 and channel 1 */
- u32Src = ((CLK->CLKSEL2 & (CLK_CLKSEL2_PWM01_S_EXT_Msk)) >> (CLK_CLKSEL2_PWM01_S_EXT_Pos - 2)) | (CLK->CLKSEL1 & (CLK_CLKSEL1_PWM01_S_Msk)) >> (CLK_CLKSEL1_PWM01_S_Pos);
- else /* channel 2 and channel 3 */
- u32Src = ((CLK->CLKSEL2 & (CLK_CLKSEL2_PWM23_S_EXT_Msk)) >> (CLK_CLKSEL2_PWM23_S_EXT_Pos - 2)) | (CLK->CLKSEL1 & (CLK_CLKSEL1_PWM23_S_Msk)) >> (CLK_CLKSEL1_PWM23_S_Pos);
- }
- else /*pwm == PWMB*/
- {
- if(u32ChannelNum < 2)/* channel 0 and channel 1 */
- u32Src = ((CLK->CLKSEL2 & (CLK_CLKSEL2_PWM45_S_EXT_Msk)) >> (CLK_CLKSEL2_PWM45_S_EXT_Pos - 2)) | (CLK->CLKSEL2 & (CLK_CLKSEL2_PWM45_S_Msk)) >> (CLK_CLKSEL2_PWM45_S_Pos);
- else /* channel 2 and channel 3 */
- u32Src = ((CLK->CLKSEL2 & (CLK_CLKSEL2_PWM67_S_EXT_Msk)) >> (CLK_CLKSEL2_PWM67_S_EXT_Pos - 2)) | (CLK->CLKSEL2 & (CLK_CLKSEL2_PWM67_S_Msk)) >> (CLK_CLKSEL2_PWM67_S_Pos);
- }
- if(u32Src == 2)
- {
- SystemCoreClockUpdate();
- u32PWMClockSrc = SystemCoreClock;
- }
- else
- {
- u32PWMClockSrc = u32PWMClkTbl[u32Src];
- }
- u32PWMClockSrc /= 1000;
- for(; u16Prescale <= 0x100; u16Prescale++)
- {
- u32NearestUnitTimeNsec = (1000000 * u16Prescale * u8Divider) / u32PWMClockSrc;
- if(u32NearestUnitTimeNsec < u32UnitTimeNsec)
- {
- if((u16Prescale == 0x100) && (u8Divider == 16)) //limit to the maximum unit time(nano second)
- break;
- if(u16Prescale == 0x100)
- {
- u16Prescale = 2;
- u8Divider <<= 1; // clk divider could only be 1, 2, 4, 8, 16
- continue;
- }
- if(!((1000000 * ((u16Prescale * u8Divider) + 1)) > (u32NearestUnitTimeNsec * u32PWMClockSrc)))
- break;
- continue;
- }
- break;
- }
- // Store return value here 'cos we're gonna change u8Divider & u16Prescale & u16CNR to the real value to fill into register
- u16Prescale -= 1;
- // convert to real register value
- u8Divider = u32PWMDividerToRegTbl[u8Divider];
- // every two channels share a prescaler
- (pwm)->PPR = ((pwm)->PPR & ~(PWM_PPR_CP01_Msk << ((u32ChannelNum >> 1) * 8))) | (u16Prescale << ((u32ChannelNum >> 1) * 8));
- (pwm)->CSR = ((pwm)->CSR & ~(PWM_CSR_CSR0_Msk << (4 * u32ChannelNum))) | (u8Divider << (4 * u32ChannelNum));
- // set PWM to edge aligned type
- (pwm)->PCR &= ~(PWM_PCR_PWM01TYPE_Msk << (u32ChannelNum >> 1));
- (pwm)->PCR |= PWM_PCR_CH0MOD_Msk << (8 * u32ChannelNum);
- *((__IO uint32_t *)((((uint32_t) & ((pwm)->CNR0)) + (u32ChannelNum) * 12))) = u16CNR;
- return (u32NearestUnitTimeNsec);
- }
复制代码
实际输入PWM频率100Hz,量测得到Total Period = 60399,利用下面公式计算频率=12000000/2/60399=99.36Hz
假设输入PWM频率为50Hz,(CNR+1)=120000000/2/50=120000 大于65536,所以必须增大prescaler值,请问该如何调整prescaler值?
|
|