每个模块都可被配置为独立工作,有三种工作方式:边沿触发捕捉、输出比较、8 位脉宽调 制。每个模块在系统控制器中都有属于自己的功能寄存器,这些寄存器用于配置模块的工作方 式和与模块交换数据。每组比较/捕获模块是由一个比较/捕获寄存器组(CCAPx)、1 个 16 位比 较器和各种逻辑门控制组成。寄存器组用来存储时间或次数,针对外部触发捕获条件,或内部 触发比较条件。在 PWM 模式下,寄存器(CCAPxL)用来控制输出波形的占空比。
每个模块都可 以独立编程的操作在任何以下模式:
⚫ 16 位捕获模式的上升沿,下降沿或任意沿触发。
⚫ 比较模式:16 位软件定时器,16 位高速输出或 8 位脉冲宽度调制。
⚫ 未启动。
比较/捕获模块模式寄存器(CCAPMx)确定相应的工作模式。对于比较/捕获模块进行编程时,他 们是基于共同的时间计数。定时器/计数器打开和关闭通过 CR.CR 位即可控制 PCA 定时/计数 227 / 447 器的运行。如果相应的使能位(CCAPMx.CCIE)被设置,当出现匹配或捕获时,比较/捕获标志 (CR.CCFx)被设置并产生 PCA 中断请求。CPU 可以在任何时候读写 CCAPx 寄存器。
CH3的通道起个啥CH0的名啊
测试代码
/**
******************************************************************************
* [url=home.php?mod=space&uid=1307177]@File[/url] main.c
* [url=home.php?mod=space&uid=1315547]@author[/url] MCU Software Team
* [url=home.php?mod=space&uid=252314]@version[/url] V1.0.0
* [url=home.php?mod=space&uid=311857]@date[/url] 21-Oct-2020
* [url=home.php?mod=space&uid=159083]@brief[/url] main function
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Public variables ---------------------------------------------------------*/
LPTIM_HandleTypeDef sLpTimHandle = {0};
PCA_HandleTypeDef sPcaHandle = {0};
PCA_IC_InitTypeDef sPcaIcInit = {0};
/* Private variables ---------------------------------------------------------*/
static uint32_t uiCaptureValue, uiCaptureValueOld, uiCaptureValueNew, uiFrequency;
static uint8_t ucCaptureCmpFlag;
static uint32_t uiCaptureValue_0, uiCaptureValueOld_0, uiCaptureValueNew_0, uiFrequency_0;
static uint8_t ucCaptureCmpFlag_0;
static uint32_t uiOverflowCnt;
/* Private function prototypes -----------------------------------------------*/
/* Private user code ---------------------------------------------------------*/
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock to HIRC 24MHz*/
SystemClock_Config();
/* Configure uart1 for printf */
LogInit();
printf("PCA input capture example.\n");
__HAL_RCC_LPTIMx_CLK_ENABLE();
/*********************** Configure Update frequency: LPTIMx_FREQ *******************************/
/* Initialize LPTIMx peripheral as follows:
+ Clock = PCLK
+ Period = 1ms(1KHz output frequency)
+ Toggle output
*/
sLpTimHandle.Instance = LPTIMx;
sLpTimHandle.Init.ClkSel = LPTIM_CLOCK_SOURCE_PCLK;
sLpTimHandle.Init.CntTimSel = LPTIM_TIMER_SELECT;
sLpTimHandle.Init.AutoReload = LPTIM_AUTORELOAD_ENABLE;
sLpTimHandle.Init.Period = LPTIMx_RELOADVALUE;
sLpTimHandle.Init.TogEnable = LPTIM_TOG_ENABLE;
HAL_LPTIM_Base_Init(&sLpTimHandle);
/* Start LPTIMx instance, output toggle signal */
HAL_LPTIM_Base_Start(&sLpTimHandle);
__HAL_RCC_PCA_CLK_ENABLE();
/*********************** Configure PCA clock source *******************************/
/* Initialize LPTIMx peripheral as follows:
+ Clock = PCLK/8 = 24M/8 = 3MHz
*/
sPcaHandle.Instance = PCAx;
sPcaHandle.Init.ClkSrcSel = PCA_CLOCK_SOURCE_PCLKDIV8;
sPcaHandle.Init.RunInIdleMode = PCA_IDLEMODE_DISABLE;
HAL_PCA_IC_Init(&sPcaHandle);
sPcaIcInit.ICPolarity = PCA_INPUT_POLARITY_FALLING;
HAL_PCA_IC_ConfigChannel(&sPcaHandle, &sPcaIcInit, PCA_CHANNEL_3);
HAL_PCA_IC_ConfigChannel(&sPcaHandle, &sPcaIcInit, PCA_CHANNEL_0);
HAL_PCA_Start_IT(&sPcaHandle, PCA_IT_CC3 | PCA_IT_OVERFLOW| PCA_IT_CC0);
HAL_NVIC_EnableIRQ(PCA_IRQn);
while (1)
{
if(ucCaptureCmpFlag == 1)
{
ucCaptureCmpFlag = 0;
uiCaptureValueNew = uiCaptureValue;
if(uiCaptureValueNew != uiCaptureValueOld)
{
if(uiCaptureValueNew > uiCaptureValueOld)
{
/* PCA clock source is PCLK/8 = 24M/8 = 3MHz */
uiFrequency = 3000000/(uiCaptureValueNew - uiCaptureValueOld);
}
}
uiCaptureValueOld = uiCaptureValueNew;
}
if(ucCaptureCmpFlag_0 == 1)
{
ucCaptureCmpFlag_0 = 0;
uiCaptureValueNew_0 = uiCaptureValue_0;
if(uiCaptureValueNew_0 != uiCaptureValueOld_0)
{
if(uiCaptureValueNew_0 > uiCaptureValueOld_0)
{
/* PCA clock source is PCLK/8 = 24M/8 = 3MHz */
uiFrequency_0 = 3000000/(uiCaptureValueNew_0 - uiCaptureValueOld_0);
}
}
uiCaptureValueOld_0 = uiCaptureValueNew_0;
}
/* print frequency every second */
if(uiOverflowCnt == 50)
{
uiOverflowCnt = 0;
printf("Frequecy is %d Hz. \n", uiFrequency);
printf("Frequecy is uiFrequency_0 %d Hz. \n", uiFrequency_0);
}
}
}
/**
* @brief Overflow callback in non blocking mode
* @param hpca : PCA handle
* @retval None
*/
void HAL_PCA_OverflowCallback(PCA_HandleTypeDef *hpca)
{
uiOverflowCnt++;
}
/**
* @brief Input capture callback in non blocking mode
* @param hpca : PCA handle
* @retval None
*/
void HAL_PCA_InputCaptureCallback(PCA_HandleTypeDef *hpca)
{
if(__HAL_PCA_GET_FLAG(hpca, PCA_FLAG_CC3) != RESET)
{
ucCaptureCmpFlag = 1;
uiCaptureValue = __HAL_PCA_GET_COMPARE(hpca, PCA_CHANNEL_3);
}
if(__HAL_PCA_GET_FLAG(hpca, PCA_FLAG_CC0) != RESET)
{
ucCaptureCmpFlag_0 = 1;
uiCaptureValue_0 = __HAL_PCA_GET_COMPARE(hpca, PCA_CHANNEL_0);
}
}
/**
* @brief Initializes the LPTIM Base MSP.
* @param hlptim : LPTIM handle
* @retval None
*/
void HAL_LPTIM_Base_MspInit(LPTIM_HandleTypeDef *hlptim)
{
GPIO_InitTypeDef sGpioInitConfig={0};
/* Enable the low power timer toggle gpio clock */
LPTIMx_TOGGLE_GPIO_CLK_ENABLE();
/* Configure the low power timer TOGGLE input pin */
sGpioInitConfig.Pin = LPTIMx_TOGGLE_PIN;
sGpioInitConfig.Mode = GPIO_MODE_AF;
sGpioInitConfig.Debounce.Enable = GPIO_DEBOUNCE_DISABLE;
sGpioInitConfig.SlewRate = GPIO_SLEW_RATE_HIGH;
sGpioInitConfig.DrvStrength = GPIO_DRV_STRENGTH_HIGH;
sGpioInitConfig.Pull = GPIO_PULLUP;
sGpioInitConfig.Alternate = LPTIMx_TOGGLE_AFn;
HAL_GPIO_Init(LPTIMx_TOGGLE_PORT, &sGpioInitConfig);
}
/**
* @brief Initializes the PCA Input Capture MSP.
* @param hpca : PCA handle
* @retval None
*/
void HAL_PCA_IC_MspInit(PCA_HandleTypeDef *hpca)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_PCAx_GPIO_CLK_ENABLE();
/**if PCAx is PCA
GPIO Configuration:
PC6 ------> PCA_CH3
*/
GPIO_InitStruct.Pin = PCAx_CH0_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF;
GPIO_InitStruct.OpenDrain = GPIO_PUSHPULL;
GPIO_InitStruct.Debounce.Enable = GPIO_DEBOUNCE_DISABLE;
GPIO_InitStruct.SlewRate = GPIO_SLEW_RATE_HIGH;
GPIO_InitStruct.DrvStrength = GPIO_DRV_STRENGTH_HIGH;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Alternate = PCAx_CH0_ALTERNATE_AFn;
HAL_GPIO_Init(PCAx_CH0_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Alternate = GPIO_AF2_PCA_CH0;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HIRC;
RCC_OscInitStruct.HIRCState = RCC_HIRC_ON;
// RCC_OscInitStruct.HIRCCalibrationValue = RCC_HIRCCALIBRATION_24M;
RCC_OscInitStruct.HIRCClockValue = HIRC_CLOCK_24M;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HIRC;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APBCLKDivider = RCC_PCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
/* USER CODE END Error_Handler_Debug */
}
#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)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/* Private function -------------------------------------------------------*/
中断函数这里改了,把清楚中断标志放到后面了
/**
* @brief This function handles PCA interrupts requests.
* @param hpca : PCA handle
* @retval None
*/
void HAL_PCA_IRQHandler(PCA_HandleTypeDef *hpca)
{
/* PCA input capture event */
if(__HAL_PCA_GET_FLAG(hpca, PCA_FLAG_CC0) != RESET)
{
if(__HAL_PCA_GET_IT_SOURCE(hpca, PCA_IT_CC0) !=RESET)
{
if((hpca->Instance->CCAPM0 & PCA_CCAPM0_ECOM) == PCA_CCAPM0_ECOM)
HAL_PCA_OutputCompareCallback(hpca);
else
HAL_PCA_InputCaptureCallback(hpca);
__HAL_PCA_CLEAR_IT(hpca, PCA_FLAG_CC0);
}
}
if(__HAL_PCA_GET_FLAG(hpca, PCA_FLAG_CC1) != RESET)
{
if(__HAL_PCA_GET_IT_SOURCE(hpca, PCA_IT_CC1) !=RESET)
{
__HAL_PCA_CLEAR_IT(hpca, PCA_FLAG_CC1);
if((hpca->Instance->CCAPM1 & PCA_CCAPM1_ECOM) == PCA_CCAPM1_ECOM)
HAL_PCA_OutputCompareCallback(hpca);
else
HAL_PCA_InputCaptureCallback(hpca);
}
}
if(__HAL_PCA_GET_FLAG(hpca, PCA_FLAG_CC2) != RESET)
{
if(__HAL_PCA_GET_IT_SOURCE(hpca, PCA_IT_CC2) !=RESET)
{
__HAL_PCA_CLEAR_IT(hpca, PCA_FLAG_CC2);
if((hpca->Instance->CCAPM2 & PCA_CCAPM2_ECOM) == PCA_CCAPM2_ECOM)
HAL_PCA_OutputCompareCallback(hpca);
else
HAL_PCA_InputCaptureCallback(hpca);
}
}
if(__HAL_PCA_GET_FLAG(hpca, PCA_FLAG_CC3) != RESET)
{
if(__HAL_PCA_GET_IT_SOURCE(hpca, PCA_IT_CC3) !=RESET)
{
if((hpca->Instance->CCAPM3 & PCA_CCAPM3_ECOM) == PCA_CCAPM3_ECOM)
HAL_PCA_OutputCompareCallback(hpca);
else
HAL_PCA_InputCaptureCallback(hpca);
__HAL_PCA_CLEAR_IT(hpca, PCA_FLAG_CC3);
}
}
if(__HAL_PCA_GET_FLAG(hpca, PCA_FLAG_CC4) != RESET)
{
if(__HAL_PCA_GET_IT_SOURCE(hpca, PCA_IT_CC4) !=RESET)
{
__HAL_PCA_CLEAR_IT(hpca, PCA_FLAG_CC4);
if((hpca->Instance->CCAPM4 & PCA_CCAPM4_ECOM) == PCA_CCAPM4_ECOM)
HAL_PCA_OutputCompareCallback(hpca);
else
HAL_PCA_InputCaptureCallback(hpca);
}
}
/* PCA overflow event */
if(__HAL_PCA_GET_FLAG(hpca, PCA_FLAG_OVERFLOW) != RESET)
{
if(__HAL_PCA_GET_IT_SOURCE(hpca, PCA_IT_OVERFLOW) !=RESET)
{
__HAL_PCA_CLEAR_IT(hpca, PCA_FLAG_OVERFLOW);
HAL_PCA_OverflowCallback(hpca);
}
}
}
测试现象
输入信号
输入1K HZ 信号