当前位置:首页 >> 编程语言 >> 【STC15库函数上手笔记】7、PCA与PWM,联想a66t怎么样

【STC15库函数上手笔记】7、PCA与PWM,联想a66t怎么样

cpugpu芯片开发光刻机 编程语言 1
文件名:【STC15库函数上手笔记】7、PCA与PWM,联想a66t怎么样 【STC15库函数上手笔记】7、PCA与PWM

目录硬知识硬件知识CCP/PWM/PCA模块的结构软件知识PCA初始化函数PWM更新占空比函数测试程序PWM模式产生PWM信号main.c实验现象16位软件定时器模式模式产生PWM信号main.c实验现象捕获模式测量周期长度main.c实验现象

STC实验箱4 IAP15W4K58S4 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0


硬知识 硬件知识

       摘自《STC15系列单片机器件手册》        STC15系列部分单片机集成了3路可编程计数器阵列(CCP/PCA)模块(STC15W4K32S4系列单片机只有两路CCP/PCA),可用于软件定时器、外部脉冲的捕捉、高速脉冲输出以及脉宽调制(PWM)输出。        下表总结了STC15系列单片机内部集成了CCP/PCA/PM功能的单片机型号:        上表中√表示对应的系列有相应的功能。

CCP/PWM/PCA模块的结构

       STC15系列部分单片机有3路可编程计数器阵列CCP/PCA/PWM(通过AUXR1/P_SW1寄存器可以设置CCP/PCA/PWM从P1口切换到P2口切换到P3口)。        PCA含有一个特殊的16位定时器,有3个16位的捕获/比较模块与之相连,如下图所示。        每个模块可编程工作在4种模式下:上升/下降沿捕获、软件定时器、高速脉冲输出或可调制脉冲输出。        16位PCA定时器/计数器是3个模块的公共时间基准,其结构如下图所示。

软件知识

       摘自《STC库函数使用参考》

PCA初始化函数

PCA_Init PCA_id:选择要初始化的PCA通道: PCA_InitTypeDef的定义见于文件"PCA.H".

typedef struct{u8 PCA_IoUse;u8 PCA_Clock; u8 PCA_Mode; u8 PCA_PWM_Wide;u8 PCA_Interrupt_Mode; u8 PCA_Polity;u16 PCA_Value;} PCA_InitTypeDef;

PCA_IoUse:选择PCA使用的IO:初始化PCA_Counter时的取值,初始化PCA0~PCA2时忽略 PCA_Clock:选择PCA使用的时钟:初始化PCA_Counter时的取值,初始化PCA0~PCA2时忽略 PCA_Mode:设置PCA通道的工作模式:初始化PCA0~PCA2时的取值,初始化PCA_Counter时忽略 PCA_PWM_Wide:设置PCA通道工作于PWM模式时的PWM宽度:初始化PCA0~PCA2工作于PWM模式时的取值,初始化PCA_Counter时或PCA通道其它模式时忽略 PCA_Interrupt_Mode:中断允许或禁止:初始化PCA0~PCA2时的取值,初始化PCA_Counter时忽略 注意:上面的参数可以做如下组合:

PCA_InitStructure.PCA_Interrupt_Mode = PCA_Fall_Active | ENABLE; //下降沿中断,允许中断。PCA_InitStructure.PCA_Interrupt_Mode = PCA_Rise_Active | ENABLE; //上升沿中断,允许中断。PCA_InitStructure.PCA_Interrupt_Mode = PCA_Rise_Active | PCA_Fall_Active | ENABLE; //上升沿、下降沿中断,允许中断。

如果后面使用了| DISABLE,则中断被禁止。

PCA_Polity:中断的优先级:初始化PCA_Counter时的取值,初始化PCA0~PCA2时忽略 PCA_Value:设置PCA通道的初值。初始化PCA0~PCA2时的取值,初始化PCA_Counter时忽略

PWM更新占空比函数

UpdatePwm

测试程序 PWM模式产生PWM信号

PCA.c里的UpdatePwm函数默认是被注释掉的,需要解除注释:

main.c #include "./Drivers/config.h"#include "./Drivers/delay.h"#include "./Drivers/GPIO.h"#include "./Drivers/PCA.h"void GPIO_config(void){GPIO_InitTypeDef GPIO_InitStructure;//结构定义GPIO_InitStructure.Mode = GPIO_OUT_PP;//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PPGPIO_InitStructure.Pin = GPIO_Pin_5 | GPIO_Pin_6;//指定要初始化的IO, 或操作GPIO_Inilize(GPIO_P2, &GPIO_InitStructure);//P2.5、P2.6初始化为推挽输出}void PCA_config(void){PCA_InitTypeDef PCA_InitStructure;PCA_InitStructure.PCA_Mode = PCA_Mode_PWM;//PCA_Mode_PWM, PCA_Mode_Capture, PCA_Mode_SoftTimer, PCA_Mode_HighPulseOutputPCA_InitStructure.PCA_PWM_Wide = PCA_PWM_8bit;//PCA_PWM_8bit, PCA_PWM_7bit, PCA_PWM_6bitPCA_InitStructure.PCA_Interrupt_Mode = DISABLE;//PCA_Rise_Active, PCA_Fall_Active, ENABLE, DISABLEPCA_InitStructure.PCA_Value = (u16)((1 << 8) * (1 - 0.5));//对于软件定时, 为匹配比较值PCA_Init(PCA0,&PCA_InitStructure);PCA_InitStructure.PCA_Mode = PCA_Mode_PWM;//PCA_Mode_PWM, PCA_Mode_Capture, PCA_Mode_SoftTimer, PCA_Mode_HighPulseOutputPCA_InitStructure.PCA_PWM_Wide = PCA_PWM_7bit;//PCA_PWM_8bit, PCA_PWM_7bit, PCA_PWM_6bitPCA_InitStructure.PCA_Interrupt_Mode = DISABLE;//PCA_Rise_Active, PCA_Fall_Active, ENABLE, DISABLEPCA_InitStructure.PCA_Value = (u16)((1 << 7) * (1 - 0.5));//对于软件定时, 为匹配比较值PCA_Init(PCA1,&PCA_InitStructure);PCA_InitStructure.PCA_Clock = PCA_Clock_1T;//PCA_Clock_1T, PCA_Clock_2T, PCA_Clock_4T, PCA_Clock_6T, PCA_Clock_8T, PCA_Clock_12T, PCA_Clock_Timer0_OF, PCA_Clock_ECIPCA_InitStructure.PCA_IoUse = PCA_P24_P25_P26_P27;//PCA_P12_P11_P10_P37, PCA_P34_P35_P36_P37, PCA_P24_P25_P26_P27PCA_InitStructure.PCA_Interrupt_Mode = DISABLE;//ENABLE, DISABLEPCA_InitStructure.PCA_Polity = PolityHigh;//优先级设置PolityHigh,PolityLowPCA_Init(PCA_Counter,&PCA_InitStructure);}void main(void){GPIO_config();PCA_config();UpdatePwm(PCA0, (1 << 8) * (1 - 0.75));UpdatePwm(PCA1, (1 << 7) * (1 - 0.25));while(1){}} 实验现象

PWM频率 = PCA时钟频率 / 2PWM位数2^{PWM位数}2PWM 30MHz/1/28=117187.5Hz30MHz / 1 / 2^8 = 117187.5 Hz30MHz/1/28=117187.5Hz 30MHz/1/27=234375Hz30MHz / 1 / 2^7 = 234375 Hz30MHz/1/27=234375Hz

16位软件定时器模式模式产生PWM信号

PWM频率 = PCA时钟频率 / PWMx_DUTY

修改PCA.h中的PWMx_DUTY 修改PCA_Handler内的对应引脚

//========================================================================// 函数: voidPCA_Handler (void) interrupt PCA_VECTOR// 描述: PCA中断处理程序.// 参数: None// 返回: none.// 版本: V1.0, 2012-11-22//========================================================================voidPCA_Handler (void) interrupt PCA_VECTOR{if(CCF0)//PCA模块0中断{CCF0 = 0;//清PCA模块0中断标志if(P25)CCAP0_tmp += PCA_Timer0;//输出为高电平,则给影射寄存器装载高电平时间长度elseCCAP0_tmp += PWM0_low;//输出为低电平,则给影射寄存器装载低电平时间长度CCAP0L = (u8)CCAP0_tmp;//将影射寄存器写入捕获寄存器,先写CCAP0LCCAP0H = (u8)(CCAP0_tmp >> 8);//后写CCAP0H}if(CCF1)//PCA模块1中断{CCF1 = 0;//清PCA模块1中断标志if(P26)CCAP1_tmp += PCA_Timer1;//输出为高电平,则给影射寄存器装载高电平时间长度elseCCAP1_tmp += PWM1_low;//输出为低电平,则给影射寄存器装载低电平时间长度CCAP1L = (u8)CCAP1_tmp;//将影射寄存器写入捕获寄存器,先写CCAP0LCCAP1H = (u8)(CCAP1_tmp >> 8);//后写CCAP0H}if(CCF2)//PCA模块2中断{CCF2 = 0;//清PCA模块1中断标志if(P27)CCAP2_tmp += PCA_Timer2;//输出为高电平,则给影射寄存器装载高电平时间长度elseCCAP2_tmp += PWM2_low;//输出为低电平,则给影射寄存器装载低电平时间长度CCAP2L = (u8)CCAP2_tmp;//将影射寄存器写入捕获寄存器,先写CCAP0LCCAP2H = (u8)(CCAP2_tmp >> 8);//后写CCAP0H}if(CF)//PCA溢出中断{CF = 0;//清PCA溢出中断标志}} main.c #include "./Drivers/config.h"#include "./Drivers/delay.h"#include "./Drivers/GPIO.h"#include "./Drivers/PCA.h"void GPIO_config(void){GPIO_InitTypeDef GPIO_InitStructure;//结构定义GPIO_InitStructure.Mode = GPIO_OUT_PP;//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PPGPIO_InitStructure.Pin = GPIO_Pin_5 | GPIO_Pin_6;//指定要初始化的IO, 或操作GPIO_Inilize(GPIO_P2, &GPIO_InitStructure);//P2.5、P2.6初始化为推挽输出}void PCA_config(void){PCA_InitTypeDef PCA_InitStructure;PCA_InitStructure.PCA_Mode = PCA_Mode_HighPulseOutput;//PCA_Mode_PWM, PCA_Mode_Capture, PCA_Mode_SoftTimer, PCA_Mode_HighPulseOutputPCA_InitStructure.PCA_PWM_Wide = 0;//PCA_PWM_8bit, PCA_PWM_7bit, PCA_PWM_6bitPCA_InitStructure.PCA_Interrupt_Mode = ENABLE;//PCA_Rise_Active, PCA_Fall_Active, ENABLE, DISABLEPCA_InitStructure.PCA_Value = 65535;//对于软件定时, 为匹配比较值PCA_Init(PCA0,&PCA_InitStructure);PCA_InitStructure.PCA_Mode = PCA_Mode_HighPulseOutput;//PCA_Mode_PWM, PCA_Mode_Capture, PCA_Mode_SoftTimer, PCA_Mode_HighPulseOutputPCA_InitStructure.PCA_PWM_Wide = 0;//PCA_PWM_8bit, PCA_PWM_7bit, PCA_PWM_6bitPCA_InitStructure.PCA_Interrupt_Mode = ENABLE;//PCA_Rise_Active, PCA_Fall_Active, ENABLE, DISABLEPCA_InitStructure.PCA_Value = 65535;//对于软件定时, 为匹配比较值PCA_Init(PCA1,&PCA_InitStructure);PCA_InitStructure.PCA_Clock = PCA_Clock_12T;//PCA_Clock_1T, PCA_Clock_2T, PCA_Clock_4T, PCA_Clock_6T, PCA_Clock_8T, PCA_Clock_12T, PCA_Clock_Timer0_OF, PCA_Clock_ECIPCA_InitStructure.PCA_IoUse = PCA_P24_P25_P26_P27;//PCA_P12_P11_P10_P37, PCA_P34_P35_P36_P37, PCA_P24_P25_P26_P27PCA_InitStructure.PCA_Interrupt_Mode = DISABLE;//ENABLE, DISABLEPCA_InitStructure.PCA_Polity = PolityHigh;//优先级设置PolityHigh,PolityLowPCA_Init(PCA_Counter, &PCA_InitStructure);}void main(void){GPIO_config();PCA_config();PWMn_Update(PCA0, (u16)(PWM0_DUTY * 0.75));PWMn_Update(PCA1, (u16)(PWM1_DUTY * 0.25));EA = 1;while(1){}} 实验现象

30MHz/12/50000=50Hz30MHz / 12 / 50000 = 50 Hz30MHz/12/50000=50Hz

捕获模式测量周期长度

修改PCA.c内的PCA_Handler

//========================================================================// 函数: voidPCA_Handler (void) interrupt PCA_VECTOR// 描述: PCA中断处理程序.// 参数: None// 返回: none.// 版本: V1.0, 2012-11-22//========================================================================voidPCA_Handler (void) interrupt PCA_VECTOR{if(CCF0)//PCA模块0中断{CCF0 = 0;//清PCA模块0中断标志if(P25)CCAP0_tmp += PCA_Timer0;//输出为高电平,则给影射寄存器装载高电平时间长度elseCCAP0_tmp += PWM0_low;//输出为低电平,则给影射寄存器装载低电平时间长度CCAP0L = (u8)CCAP0_tmp;//将影射寄存器写入捕获寄存器,先写CCAP0LCCAP0H = (u8)(CCAP0_tmp >> 8);//后写CCAP0H}if(CCF1)//PCA模块1中断{CCF1 = 0;//清PCA模块1中断标志if(PCA1_mode >= PCA_Mode_SoftTimer)//PCA_Mode_SoftTimer and PCA_Mode_HighPulseOutput{CCAP1_tmp += PCA_Timer1;CCAP1L = (u8)CCAP1_tmp;//将影射寄存器写入捕获寄存器,先写CCAP0LCCAP1H = (u8)(CCAP1_tmp >> 8);//后写CCAP0H}else if(PCA1_mode == PCA_Mode_Capture){CCAP1_tmp = CCAP1H;//读CCAP1HCCAP1_tmp = (CCAP1_tmp << 8) + CCAP1L;B_Capture1 = 1;}}if(CCF2)//PCA模块2中断{CCF2 = 0;//清PCA模块1中断标志if(P27)CCAP2_tmp += PCA_Timer2;//输出为高电平,则给影射寄存器装载高电平时间长度elseCCAP2_tmp += PWM2_low;//输出为低电平,则给影射寄存器装载低电平时间长度CCAP2L = (u8)CCAP2_tmp;//将影射寄存器写入捕获寄存器,先写CCAP0LCCAP2H = (u8)(CCAP2_tmp >> 8);//后写CCAP0H}if(CF)//PCA溢出中断{CF = 0;//清PCA溢出中断标志}} main.c #include "./Drivers/config.h"#include "./Drivers/delay.h"#include "./Drivers/GPIO.h"#include "./Drivers/PCA.h"#include "./Drivers/soft_UART.h"#include <stdio.h>char putchar(char Char){TxSend(Char);return Char;}void GPIO_config(void){GPIO_InitTypeDef GPIO_InitStructure;//结构定义GPIO_InitStructure.Mode = GPIO_OUT_PP;//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PPGPIO_InitStructure.Pin = GPIO_Pin_5;//指定要初始化的IO, 或操作GPIO_Inilize(GPIO_P2, &GPIO_InitStructure);//P2.5初始化为推挽输出}void PCA_config(void){PCA_InitTypeDef PCA_InitStructure;PCA_InitStructure.PCA_Mode = PCA_Mode_HighPulseOutput;//PCA_Mode_PWM, PCA_Mode_Capture, PCA_Mode_SoftTimer, PCA_Mode_HighPulseOutputPCA_InitStructure.PCA_PWM_Wide = 0;//PCA_PWM_8bit, PCA_PWM_7bit, PCA_PWM_6bitPCA_InitStructure.PCA_Interrupt_Mode = ENABLE;//PCA_Rise_Active, PCA_Fall_Active, ENABLE, DISABLEPCA_InitStructure.PCA_Value = 65535;//对于软件定时, 为匹配比较值PCA_Init(PCA0,&PCA_InitStructure);PCA_InitStructure.PCA_Mode = PCA_Mode_Capture;//PCA_Mode_PWM, PCA_Mode_Capture, PCA_Mode_SoftTimer, PCA_Mode_HighPulseOutputPCA_InitStructure.PCA_PWM_Wide = 0;//PCA_PWM_8bit, PCA_PWM_7bit, PCA_PWM_6bitPCA_InitStructure.PCA_Interrupt_Mode = PCA_Fall_Active | ENABLE;//(PCA_Rise_Active, PCA_Fall_Active) or (ENABLE, DISABLE)PCA_InitStructure.PCA_Value = 0;//对于捕捉, 这个值没意义PCA_Init(PCA1,&PCA_InitStructure);PCA_InitStructure.PCA_Clock = PCA_Clock_12T;//PCA_Clock_1T, PCA_Clock_2T, PCA_Clock_4T, PCA_Clock_6T, PCA_Clock_8T, PCA_Clock_12T, PCA_Clock_Timer0_OF, PCA_Clock_ECIPCA_InitStructure.PCA_IoUse = PCA_P24_P25_P26_P27;//PCA_P12_P11_P10_P37, PCA_P34_P35_P36_P37, PCA_P24_P25_P26_P27PCA_InitStructure.PCA_Interrupt_Mode = DISABLE;//ENABLE, DISABLEPCA_InitStructure.PCA_Polity = PolityHigh;//优先级设置PolityHigh,PolityLowPCA_Init(PCA_Counter, &PCA_InitStructure);}u16Cap_time;//上一次捕捉时间void main(void){u16 j;Cap_time = 0;GPIO_config();PCA_config();PWMn_Update(PCA0, (u16)(PWM0_DUTY * 0.75));EA = 1;while(1){if(B_Capture1){B_Capture1 = 0;j = CCAP1_tmp - Cap_time;//计算时间差Cap_time = CCAP1_tmp;printf("%d us\r\n", (int)(j * 12. / 30));}delay_ms(1);}} 实验现象

协助本站SEO优化一下,谢谢!
关键词不能为空
同类推荐
«    2025年12月    »
1234567
891011121314
15161718192021
22232425262728
293031
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
搜索
最新留言
文章归档
网站收藏
友情链接