PCA(可编程计数器阵列 Programmable Counter Array)支持最多 5 个 16 位的捕获/比较模块。该定时/计数器可用作为一个通用的时钟计数/事件计数器的捕获/比较功能。PCA 的每个模块都可以进行独立编程,以提供输入捕捉、输出比较或脉冲宽度调制。另外模块 4 有额外的看门狗定时器模式。
每个模块都可被配置为独立工作,有三种工作方式:边沿触发捕捉、输出比较、8 位脉宽调制。每个模块在系统控制器中都有属于自己的功能寄存器,这些寄存器用于配置模块的工作方式和与模块交换数据。
PCA 8 位脉宽调制功能
脉宽调制是一种使用程序来控制波形占空比,周期,相位的技术。5 个 PCA 模块都可以被独立地用于在对应PCA 的 CAP/CMP[x] 引脚产生脉宽调制(PWM)输出,脉冲宽度为 8 位分辨率。
pca_cap例程
本样例对展示PCA对外部上升/下降沿的捕获功能,捕获到沿时产生中断。用跳线连接P33(CAP1)与P32(沿输出),在main函数while(1)处设置断点。运行。程序到断点处停止,此时观察"u8TestFlag"的值,若为'0'则功能正常。
- en_result_t PcaCapTest(void)
- {
- stc_pca_config_t stcConfig;
- stc_pca_capmodconfig_t stcModConfig;
- en_result_t enResult = Error;
- uint16_t u16InitCntData = 0;
- uint16_t u16Cnt = 0;
-
- // GPIO CFG
- Gpio_SetFunc_PCA_CH1_P33(1);
- Gpio_InitIO(3, 2, GpioDirOut);
- Gpio_SetIO(3, 2, TRUE);
-
- stcConfig.enCIDL = IdleGoon; //休眠模式PCA工作
- stcConfig.enWDTE = PCAWDTDisable; // wdt功能关闭
- stcConfig.enCPS = PCAPCLKDiv8;
-
- stcConfig.pfnPcaCb = PcaInt;
-
- stcModConfig.enECOM = ECOMDisable; //比较器功能禁止
- stcModConfig.enCAPP = CAPPEnable; //上升沿捕获
- stcModConfig.enCAPN = CAPNEnable; //下降沿捕获
- stcModConfig.enMAT = MATDisable; //禁止匹配
- stcModConfig.enTOG = TOGDisable;
- stcModConfig.enPWM = PCAPWMDisable;
-
- if (Ok != Pca_Init(&stcConfig)) {
- enResult = Error;
- }
- if (Ok != Pca_CapModConfig(Module1, &stcModConfig)) {
- enResult = Error;
- }
-
- // PCA中断使能
- Pca_ClearIntFlag(Module1);
- Pca_EnableIrq(Module1);
- EnableNvic(PCA_IRQn, 3, TRUE);
-
- Pca_Cnt16Set(u16InitCntData);
- Pca_Run();
-
- u16Cnt = 0x100;
- while (u16Cnt--)
- ;
- Gpio_SetIO(3, 2, FALSE); //内部输出低,外接P24产生下降沿中断
-
- //进入中断……
- while (1) {
- //发生下降沿捕获
- if (0x02 == (u32PcaTestFlag & 0x02)) {
- u32PcaTestFlag = (u32PcaTestFlag & (~0x02));
- u16CcapData[0] = Pca_CapData16Get(Module1);
- enResult = Ok;
- break;
- }
- }
-
- u16Cnt = 0x100;
- while (u16Cnt--)
- ;
- Gpio_SetIO(3, 2, TRUE); //内部输出高,外接P24产生上升沿中断
- //进入中断……
- while (1) {
- //发生上升沿捕获
- if (0x02 == (u32PcaTestFlag & 0x02)) {
- u32PcaTestFlag = (u32PcaTestFlag & (~0x02));
- u16CcapData[1] = Pca_CapData16Get(Module1);
- enResult = Ok;
- break;
- }
- }
-
- Pca_Stop();
-
- return enResult;
- }
通过普通IO P32的拉高拉低模拟出上升下降沿,触发PCA边沿捕捉。
pca_cmp_cnt例程
本样例对展示PCA的比较计数功能,当计数值达到设定的比较值时,产生中断,停止计数。
在main函数while(1)处设置断点。运行。程序到断点处停止,此时观察"u8TestFlag"的值,若为'0'则功能正常。
- en_result_t PcaCmpCntTest(void)
- {
- stc_pca_config_t stcConfig;
- stc_pca_capmodconfig_t stcModConfig;
- en_result_t enResult = Error;
- uint16_t u16InitCntData = 0;
- uint16_t u16CcapData = 0xC0;
-
- // INT ENABLE
- EnableNvic(PCA_IRQn, 3, TRUE);
- Pca_EnableIrq(Module2);
-
- stcConfig.enCIDL = IdleGoon;
- stcConfig.enWDTE = PCAWDTDisable;
- stcConfig.enCPS = PCAPCLKDiv3;
-
- stcConfig.pfnPcaCb = PcaInt;
-
- stcModConfig.enECOM = ECOMEnable; //允许比较功能
- stcModConfig.enCAPP = CAPPDisable;
- stcModConfig.enCAPN = CAPNDisable;
- stcModConfig.enMAT = MATEnable; //允许匹配
- stcModConfig.enTOG = TOGDisable;
- stcModConfig.enPWM = PCAPWMDisable;
-
- if (Ok != Pca_Init(&stcConfig)) {
- enResult = Error;
- }
- if (Ok != Pca_CapModConfig(Module2, &stcModConfig)) {
- enResult = Error;
- }
-
- Pca_CapData16Set(Module2, u16CcapData); //比较捕获寄存器设置
- Pca_Cnt16Set(u16InitCntData);
- Pca_Run();
-
- //进入中断……
- while (1) {
- //比较值匹配
- if (0x04 == (u32PcaTestFlag & 0x04)) {
- u32PcaTestFlag = (u32PcaTestFlag & (~0x04));
- Pca_Stop();
- enResult = Ok;
- break;
- }
- }
-
- return enResult;
- }
当捕获计数值与设置的计数值相同的时候就会触发中断,程序继续向下运行。
pca_pwm例程
本样例展示PCA的PWM功能。用示波器观察P34(CMP0),在main函数while(1)处设置断点。运行,观察波形,持续一段时间后停止。程序到断点处停止,此时观察"u8TestFlag"的值,若为'0'则功能正常。
- en_result_t PcaPwmTest(void)
- {
- stc_pca_config_t stcConfig;
- stc_pca_capmodconfig_t stcModConfig;
- en_result_t enResult = Ok;
- uint8_t u8CcaplData = 0x20;
- uint8_t u8CcaphData = 0x40;
- uint32_t u32Cnt;
-
- Gpio_SetFunc_PCA_CH0_P34(0);
-
- stcConfig.enCIDL = IdleGoon;
- stcConfig.enWDTE = PCAWDTDisable;
- stcConfig.enCPS = PCAPCLKDiv32;
-
- stcConfig.pfnPcaCb = PcaInt;
-
- stcModConfig.enECOM = ECOMEnable;
- stcModConfig.enCAPP = CAPPDisable;
- stcModConfig.enCAPN = CAPNDisable;
- stcModConfig.enMAT = MATDisable;
- stcModConfig.enTOG = TOGDisable;
- stcModConfig.enPWM = PCAPWMEnable;
-
- if (Ok != Pca_Init(&stcConfig)) {
- enResult = Error;
- }
- if (Ok != Pca_CapModConfig(Module0, &stcModConfig)) {
- enResult = Error;
- }
-
- Pca_CapDataLSet(Module0, u8CcaplData);
- Pca_CapDataHSet(Module0, u8CcaphData);
- Pca_Run();
-
- // PWM波形输出……
- u32Cnt = 0x80000;
- while (u32Cnt--) {
- ;
- }
-
- return enResult;
- }
通过Pca_CapDataLSet和Pca_CapDataHSet设置计数周期和低电平周期。输出pwm非常方便。
pca_wdt例程
本样例展示PCA的WDT功能,在达到定时值时如果没有及时设定比较值(喂狗),则发生系统复位,反之则系统正常运行。
- en_result_t PcaWdtTest(void)
- {
- stc_pca_config_t stcConfig;
- stc_pca_capmodconfig_t stcModConfig;
- en_result_t enResult = Ok;
- uint16_t u16CntData = 0;
- uint16_t u16CcapData0 = 0x8000;
- uint16_t u16CcapData1 = 0x6000;
-
- stcConfig.enCIDL = IdleGoon;
- stcConfig.enWDTE = PCAWDTEnable;
- stcConfig.enCPS = PCAPCLKDiv32;
-
- stcConfig.pfnPcaCb = PcaInt;
-
- stcModConfig.enECOM = ECOMEnable;
- stcModConfig.enCAPP = CAPPDisable;
- stcModConfig.enCAPN = CAPNDisable;
- stcModConfig.enMAT = MATEnable;
- stcModConfig.enTOG = TOGDisable;
- stcModConfig.enPWM = PCAPWMDisable;
-
- Pca_Cnt16Set(u16CntData);
- Pca_CapData16Set(Module4, u16CcapData0);
-
- if (Ok != Pca_CapModConfig(Module4, &stcModConfig)) {
- enResult = Error;
- return enResult;
- }
- if (Ok != Pca_Init(&stcConfig)) {
- enResult = Error;
- return enResult;
- }
-
- Pca_Run();
-
- // WDT:修改为while(1),则不断更新比较值,保持运行;否则复位。
- while (1) {
- if (0x7000 > Pca_Cnt16Get()) {
- Pca_CapData16Set(Module4, u16CcapData0);
- } else {
- Pca_CapData16Set(Module4, u16CcapData1);
- }
- }
- return enResult;
- }
这个代码按照注释测试就行了,就是个喂狗的一种方式。