四路输入捕获(占空比和周期)

本贴最后更新于 515 天前,其中的信息可能已经物是人非

手册

  在输入捕获模式下,当检测到 ICi 信号上相应的边沿后,计数器的当前值被锁存到捕获/比较寄存器(PWMA_CCRx)中。当发生捕获事件时,相应的 CCiIF 标志(PWMA_SR 寄存器)被置 1。
如果 PWMA_IER 寄存器的 CCiIE 位被置位,也就是使能了中断,则将产生中断请求。如果发生捕获
事件时 CCiIF 标志已经为高,那么重复捕获标志 CCiOF(PWMA_SR2 寄存器)被置 1。写 CCiIF=0 或
读取存储在 PWMA_CCRiL 寄存器中的捕获数据都可清除 CCiIF。写 CCiOF=0 可清除 CCiOF。

PWM 输入信号上升沿时捕获

  
以下例子说明如何在 TI1 输入的上升沿时捕获计数器的值到 PWMA_CCR1 寄存器中,步骤如下:

  1. 选择有效输入端:例如 PWMA_CCR1 连接到 TI1 输入,所以写入 PWMA_CCR1 寄存器中的 CC1S=01,此时通道被配置为输入,并且 PWMA_CCR1 寄存器变为只读。
  2. 根据输入信号 TIi 的特点,==可通过配置 PWMA_CCMRi 寄存器中的 ICiF 位来设置相应的输入滤波器的滤波时间。==假设输入信号在最多 5 个时钟周期的时间内抖动,我们须配置滤波器的带宽长于 5 个时钟周期;因此我们可以连续采样 8 次,以确认在 TI1 上一次真实的边沿变换, 即在 TIMi_CCMR1 寄存器中写入 IC1F=0011,此时,只有连续采样到 8 个相同的 TI1 信号,信号才为有效(采样频率为 fMASTER)。
  3. 选择 TI1 通道的有效转换边沿,在 PWMA_CCER1 寄存器中写入 CC1P=0(上升沿)。
  4. 配置输入预分频器。在本例中,我们希望捕获发生在每一个有效的电平转换时刻,因此预分频器被禁止(写 PWMA_CCMR1 寄存器的 IC1PS=00)。
  5. 设置 PWMA_CCER1 寄存器的 CC1E=1,允许捕获计数器的值到捕获寄存器中。
  6. 如果需要,通过设置 PWMA_IER 寄存器中的 CC1IE 位允许相关中断请求。
    当发生一个输入捕获时:
     当产生有效的电平转换时,计数器的值被传送到 PWMA_CCR1 寄存器。
     CC1IF 标志被设置。当发生至少 2 个连续的捕获时,而 CC1IF 未曾被清除时,CC1OF 也被置 1。
     如设置了 CC1IE 位,则会产生一个中断。
    为了处理捕获溢出事件(CC1OF 位),建议在读出重复捕获标志之前读取数据,这是为了避免丢失在读出捕获溢出标志之后和读取数据之前可能产生的重复捕获信息。
    注意:设置 PWMA_EGR 寄存器中相应的 CCiG 位,可以通过软件产生输入捕获中断。

  ‍

PWM 输入信号测量

  
该模式是输入捕获模式的一个特例,除下列区别外,操作与输入捕获模式相同:
 两个 ICi 信号被映射至同一个 TIi 输入。
 这两个 ICi 信号的有效边沿的极性相反。
 其中一个 TIiFP 信号被作为触发输入信号,而触发模式控制器被配置成复位触发模式。

  ‍

程序

  ​imageimage​​

void PWM_INIT(void)
{
    PWMA_CCER1 = 0x00;
    PWMA_CCMR1 = 0x01; //CC1 为输入模式,且映射到 TI1FP1 上
    PWMA_CCMR2 = 0x02; //CC2 为输入模式,且映射到 TI1FP2 上
    PWMA_CCER1 = 0x11; //使能 CC1 上的捕获功能,使能 CC2 上的捕获功能
    PWMA_CCER1 |= 0x00; //设置捕获极性为 CC1 的上升沿
    PWMA_CCER1 |= 0x20; //设置捕获极性为 CC2 的下降沿

    PWMA_CCER2 = 0x00;
    PWMA_CCMR3 = 0x01; //CC3 为输入模式,且映射到 TI3FP3 上
    PWMA_CCMR4 = 0x02; //CC4 为输入模式,且映射到 TI3FP4 上
    PWMA_CCER2 = 0x11; //使能 CC3 上的捕获功能,使能 CC4 上的捕获功能
    PWMA_CCER2 |= 0x00; //设置捕获极性为 CC3 的上升沿
    PWMA_CCER2 |= 0x20; //设置捕获极性为 CC4 的下降沿
    PWMA_CR1 = 0x01;

    PWMA_IER = 0x1e; //使能 CC1/CC2/CC3/CC4 捕获中断

    PWMB_CCER1 = 0x00;
    PWMB_CCMR1 = 0x01; //CC5 为输入模式,且映射到 TI5FP5 上
    PWMB_CCMR2 = 0x02; //CC6 为输入模式,且映射到 TI5FP6 上

    PWMB_CCER1 = 0x11; //使能 CC5 上的捕获功能,使能 CC6 上的捕获功能
    PWMB_CCER1 |= 0x00; //设置捕获极性为 CC5 的上升沿
    PWMB_CCER1 |= 0x20; //设置捕获极性为 CC6 的下降沿

    PWMB_CCER2 = 0x00;
    PWMB_CCMR3 = 0x01; //CC7 为输入模式,且映射到 TI7FP8 上
    PWMB_CCMR4 = 0x02; //CC8 为输入模式,且映射到 TI7FP8 上
    PWMB_CCER2 = 0x11; //使能 CC7 上的捕获功能,使能 CC8 上的捕获功能
    PWMB_CCER2 |= 0x00; //设置捕获极性为 CC7 的上升沿
    PWMB_CCER2 |= 0x20; //设置捕获极性为 CC8 的下降沿
    PWMB_CR1 = 0x01;

    PWMB_IER = 0x1e; //使能 CC5/CC6/CC7/CC8 捕获中断

}

void PWMA_ISR() interrupt PWMA_VECTOR
{
    unsigned int ccr;

    if (PWMA_SR1 & 0x02) //CC1 捕获中断
    {
        PWMA_SR1 &= ~0x02;

        ccr = (PWMA_CCR1H << 8) + PWMA_CCR1L; //读取捕获值
        cycle1 = ccr - ccr1; //计算周期
        ccr1 = ccr; //保存当前捕获值
        f1 = 1; //波形 1 的周期和占空比捕获完成,触发串口发送
    }
    if (PWMA_SR1 & 0x04) //CC2 捕获中断
    {
        PWMA_SR1 &= ~0x04;

        ccr = (PWMA_CCR2H << 8) + PWMA_CCR2L; //读取捕获值
        duty1 = ccr - ccr1; //计算占空比
    }

    if (PWMA_SR1 & 0x08) //CC3 捕获中断
    {
        PWMA_SR1 &= ~0x08;

        ccr = (PWMA_CCR3H << 8) + PWMA_CCR3L; //读取捕获值
        cycle2 = ccr - ccr3; //计算周期
        ccr3 = ccr; //保存当前捕获值
        f2 = 1; //波形 2 的周期和占空比捕获完成,触发串口发送
    }
    if (PWMA_SR1 & 0x10) //CC4 捕获中断
    {
        PWMA_SR1 &= ~0x10;

        ccr = (PWMA_CCR4H << 8) + PWMA_CCR4L; //读取捕获值
        duty2 = ccr - ccr3; //计算占空比
    }
}

void PWMB_ISR() interrupt PWMB_VECTOR
{
    unsigned int ccr;

    if (PWMB_SR1 & 0x02) //CC5 捕获中断
    {
        PWMB_SR1 &= ~0x02;

        ccr = (PWMB_CCR5H << 8) + PWMB_CCR5L; //读取捕获值
        cycle3 = ccr - ccr5; //计算周期
        ccr5 = ccr; //保存当前捕获值
        f3 = 1; //波形 3 的周期和占空比捕获完成,触发串口发送
    }
    if (PWMB_SR1 & 0x04) //CC6 捕获中断
    {
        PWMB_SR1 &= ~0x04;

        ccr = (PWMB_CCR6H << 8) + PWMB_CCR6L; //读取捕获值
        duty3 = ccr - ccr5; //计算占空比
    }

    if (PWMB_SR1 & 0x08) //CC7 捕获中断
    {
        PWMB_SR1 &= ~0x08;

        ccr = (PWMB_CCR7H << 8) + PWMB_CCR7L; //读取捕获值
        cycle4 = ccr - ccr7; //计算周期
        ccr7 = ccr; //保存当前捕获值
        f4 = 1; //波形 4 的周期和占空比捕获完成,触发串口发送
    }
    if (PWMB_SR1 & 0x10) //CC8 捕获中断
    {
        PWMB_SR1 &= ~0x10;

        ccr = (PWMB_CCR8H << 8) + PWMB_CCR8L; //读取捕获值
        duty4 = ccr - ccr7; //计算占空比
    }
}
/***************	功能说明	****************

大彩驱动程序
下载时, 选择时钟 24MHz (可以在配置文件"config.h"中修改).

******************************************/

/*************	头文件声明	**************/
#include  "peripheralInit.h"
#include "isr.h"

//大彩头文件
#include    "hmi_driver.h"					//大彩驱动文件-API
#include    "cmd_queue.h"					//队列操作
#include    "cmd_process.h"					//指令处理

#include    "stdio.h"

/*************	本地常量声明	**************/


/*************	本地变量声明	**************/

float freq = 0 ,duty = 0 ,tmp = 0;

/*************	本地函数声明	**************/
float get_voltage(u16 ad);
void drawACurve(void);

/*************  外部函数和变量声明 *****************/

void main(void)
{
    SYSTEM_INIT();
    GPIO_config();
    UART_config();
    Hmi_Init();
    PWM_INIT();
    EA = 1;

    while(1)
    {
        instructionProcessing();									//大彩的指令处理和解析

		if (f1) 
		  { 
		   f1 = 0; 
		   printf("cycle1 = %04x duty1 = %04x\n", cycle1, duty1); 
		  } 
		  if (f2) 
		  { 
		   f2 = 0; 
		   printf("cycle2 = %04x duty2 = %04x\n", cycle2, duty2); 
		  } 
		  if (f3) 
		  { 
		   f3 = 0; 
		   printf("cycle3 = %04x duty3 = %04x\n", cycle3, duty3); 
		  } 
		  if (f4) 
		  { 
		   f4 = 0; 
			  tmp = cycle4 * 1.0;
			  freq = 1.0 / ( 1.0 / MAIN_Fosc * tmp);
			  tmp = duty4 * 1.0;
			  duty = tmp / cycle4 * 100.0;
			  printf("cycle4 = %.3f duty4 = %.3f\n", freq, duty); 
		  }
//        // SetBuzzer(100);
//        delay_ms(100);
    }
}



/********************* 绘制曲线************************/
void drawACurve()
{
    u16 i;
    u8 tmp;
    GraphChannelDataClear(1,1,0);							//清除原有数据
    GraphChannelDataRetraction(1,1,0,500,0,100);			//曲线放缩、位移

    for(i=0; i<ad_max; i++)
    {
        //SetTextFloat(0,11,wave_Data[ad_cnt],3,1);
        tmp = wave_Data[i]/16;
        GraphChannelDataAdd(1,1,0,&tmp,1);					//添加点
        delay_ms(1);
    }
}

/********************* AD值转电压值************************/
float get_voltage(u16 ad)
{
    float voltage=0;
    voltage = ad*5.0/4096;
    return voltage;
}
1 操作
linyiii 在 2023-07-22 17:10:18 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...