This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

am335x ecap捕获中ecap1与ecap2互扰



各位好:

      使用AM335X芯片做ecap捕获,用到了全部三个ecap通道,ecap0用于时钟频率捕获,其中ecap1和ecap2用来捕获45HZ~55HZ方波,ecap1配置为APWM模式时,ecap2可以正常捕获到正确的周期,反之 ecap2设置为APWM模式时,ecap1也可以正常捕获到正确的周期。同时配置为ECAP_CAPTURE_MODE就都不能正常工作,求赐教。

int freq_init(void)
{
    void __iomem *p_REGS;

   /**************************配置时钟和设备地址映射****************************/
    p_REGS = ioremap(SOC_PWMSS1_REGS, SZ_8K);
    if(!p_REGS)
    {
        printk("%s:ioremap(%x) error\r\n", __func__, SOC_PWMSS1_REGS);
		
        return -1;
    }
    g_SOC_PWMSS1_REGS = (unsigned int)p_REGS;
    g_SOC_ECAP_1_REGS = g_SOC_PWMSS1_REGS + SOC_ECAP_REGS;
    g_aREGS[0] = g_SOC_ECAP_1_REGS;
    
    p_REGS = ioremap(SOC_PWMSS2_REGS, SZ_8K);
    if(!p_REGS)
    {
        printk("%s:ioremap(%x) error\r\n", __func__, SOC_PWMSS2_REGS);
        iounmap((void __iomem *)g_SOC_CONTROL_REGS);
        iounmap((void __iomem *)g_SOC_PWMSS1_REGS);
		
        return -1;
    }
    g_SOC_PWMSS2_REGS = (unsigned int)p_REGS;
    g_SOC_ECAP_2_REGS = g_SOC_PWMSS2_REGS + SOC_ECAP_REGS;	
    g_aREGS[1] = g_SOC_ECAP_2_REGS;
	
    /* Enable Clock */
    ECAPClockEnable(g_SOC_PWMSS1_REGS);
    while(ECAPClockEnableStatusGet(g_SOC_PWMSS1_REGS) == 0);     
    ECAPClockEnable(g_SOC_PWMSS2_REGS);
    while(ECAPClockEnableStatusGet(g_SOC_PWMSS2_REGS) == 0); 
	
	/***************************配置两个ecap的硬件管脚*****************************/
	p_REGS = ioremap(SOC_CONTROL_REGS, SZ_8K);
	if(!p_REGS)
	{
		printk("%s:ioremap(%x) error\r\n", __func__, SOC_CONTROL_REGS);
		
		return -1;
	}
	g_SOC_CONTROL_REGS = (unsigned int)p_REGS;

	/* eCAP1输入管脚 AM335X_ECAP1_IN I2C0_SCL C16 */
	HWREG(g_SOC_CONTROL_REGS + CONTROL_CONF_I2C0_SCL) =
		(CONTROL_CONF_PULLUPSEL |CONTROL_CONF_RXACTIVE	
		| CONTROL_CONF_MUXMODE(3));
	
	/* eCAP2输入管脚 eCAP2_in_PWM2_out模式 MCASP0_AHCLKR C12	*/
	HWREG(g_SOC_CONTROL_REGS + CONTROL_CONF_MCASP0_AHCLKR) =
		(CONTROL_CONF_PULLUPSEL |CONTROL_CONF_RXACTIVE	
		| CONTROL_CONF_MUXMODE(4));

	/****************************配置两个ecap的寄存器******************************/
	/* 捕捉模式 
	** ECCTL2[9] CAP_APWM CAP/APWM operating mode select
    ** 0h = ECAP module operates in capture mode. This mode forces the
    ** following configuration. (a) Inhibits TSCTR resets via PRDEQ event.
    ** (b) Inhibits shadow loads on CAP1 and 2 registers. (c) Permits user
    ** to enable CAP1-4 register load. (d) ECAPn/APWMn pin operates as
    ** a capture input.
    ** 1h = ECAP module operates in APWM mode. This mode forces the
    ** following configuration. (a) Resets TSCTR on PRDEQ event (period
    ** boundary). (b) Permits shadow loading on CAP1 and 2 registers. (c)
    ** Disables loading of time-stamps into CAP1-4 registers. (d)
    ** ECAPn/APWMn pin operates as a APWM output.
	*/
    ECAPOperatingModeSelect(g_SOC_ECAP_1_REGS, ECAP_CAPTURE_MODE);
    ECAPOperatingModeSelect(g_SOC_ECAP_2_REGS, ECAP_APWM_MODE);    /* 问题就在此处 ecap2设备APWM模式时 ecap1才能正常捕获,反之亦然 */
    
    /* 连续模式
	** ECCTL2[0] CONT_ONESHT  0h = Operate in continuous mode
    */
    ECAPContinousModeConfig(g_SOC_ECAP_1_REGS);
    ECAPContinousModeConfig(g_SOC_ECAP_2_REGS);

	/* 清除中断 
	** ECCLR[0:7] ECFLG&0xFF Writing a 1 clears the Int flag condition
	*/
    ECAPIntStatusClear(g_SOC_ECAP_1_REGS, 0xFF);
    ECAPIntStatusClear(g_SOC_ECAP_2_REGS, 0xFF);

    /* 这里的分频是指输入信号的分频,不是ECAP的时钟分频 
    ** ECCTL1[9:13] PRESCALE 0h = Divide by 1 (i.e,. no prescale, by-pass the prescaler)
	*/
    ECAPPrescaleConfig(g_SOC_ECAP_1_REGS, 0);
    ECAPPrescaleConfig(g_SOC_ECAP_2_REGS, 0);
	
    /* enables capture loading 
    ** ECCTL1[8] CAPLDEN 1h = Enable CAP1-4 register loads at capture event time.
	*/
    ECAPCaptureLoadingEnable(g_SOC_ECAP_1_REGS);
    ECAPCaptureLoadingEnable(g_SOC_ECAP_2_REGS);
	
    /* configures Capture Event polarity.上升沿捕捉 */
    ECAPCapeEvtPolarityConfig(g_SOC_ECAP_1_REGS, EC_RISING_EDGE, EC_RISING_EDGE, EC_RISING_EDGE, EC_RISING_EDGE);	
    ECAPCapeEvtPolarityConfig(g_SOC_ECAP_2_REGS, EC_RISING_EDGE, EC_RISING_EDGE, EC_RISING_EDGE, EC_RISING_EDGE);	
    
    /* enables reset of the counters upon Capture Events. */
    ECAPCaptureEvtCntrRstConfig(g_SOC_ECAP_1_REGS, EC_DELTA_MODE, EC_DELTA_MODE, EC_DELTA_MODE, EC_DELTA_MODE);
    ECAPCaptureEvtCntrRstConfig(g_SOC_ECAP_2_REGS, EC_DELTA_MODE, EC_DELTA_MODE, EC_DELTA_MODE, EC_DELTA_MODE);
	
	/* 0h = Stop after Capture Event 1 in one-shot mode. Wrap after
	   Capture Event 1 in continuous mode
	   0->0->0 CAP1 */
    //ECAPStopWrapConfig(g_SOC_ECAP_1_REGS, ECAP_CAPTURE_EVENT4_STOP);
    //ECAPStopWrapConfig(g_SOC_ECAP_2_REGS, ECAP_CAPTURE_EVENT1_STOP);
	
    /* 使能中断 */
    ECAPIntEnable(g_SOC_ECAP_1_REGS, ECAP_CEVT1_INT|ECAP_CEVT2_INT|ECAP_CEVT3_INT|ECAP_CEVT4_INT);
    ECAPIntEnable(g_SOC_ECAP_2_REGS, ECAP_CEVT1_INT|ECAP_CEVT2_INT|ECAP_CEVT3_INT|ECAP_CEVT4_INT);	

    /* Disables the sync out ,sync in. TI定义的宏ECAP_SYNC_OUT_DISABLE有问题,改用EC_SYNC_OUT_DISABLE 
    ** ECCTL2[5] SYNCI_EN  0h = Disable sync-in option
    ** ECCTL2[6:7] SYNCO_SEL  2h = Disable sync out signal
	*/
    ECAPSyncInOutSelect(g_SOC_ECAP_1_REGS, ECAP_SYNC_IN_DISABLE, EC_SYNC_OUT_DISABLE);
    ECAPSyncInOutSelect(g_SOC_ECAP_2_REGS, ECAP_SYNC_IN_DISABLE, EC_SYNC_OUT_DISABLE);
	
    /* Set Counter 
	** RSCTR[0:31] 0 Active 32 bit counter register that is used as the capture time-base
	*/
    ECAPCounterConfig(g_SOC_ECAP_1_REGS, 0);
    ECAPCounterConfig(g_SOC_ECAP_2_REGS, 0);
	
    /* 自由运行     ECCTL2[4] 1  TSCTRSTOP->TSCTR free-running 计数器停止位控制 计数器开始计数 */
    ECAPCounterControl(g_SOC_ECAP_1_REGS, ECAP_COUNTER_FREE_RUNNING);
    ECAPCounterControl(g_SOC_ECAP_2_REGS, ECAP_COUNTER_FREE_RUNNING);
	
    rt_request_irq(CFG_ECAP1INT, CFG_INT_LEVEL_ECAP, freq_isr0, "ecap1", 0);
    rt_request_irq(CFG_ECAP2INT, CFG_INT_LEVEL_ECAP, freq_isr1, "ecap2", 0);
    
    return 0;	
}


void freq_isr(int index) 
{
	unsigned int 	status, count = 0;
	float 	freq;

	/* 读取中断状态值 */
	status = ECAPIntStatus(g_aREGS[index], 0x3F);
	if(status & ECAP_CEVT1_INT)
	{
		count = ECAPTimeStampRead(g_aREGS[index], ECAP_CAPTURE_EVENT_1);
	}
	if(status & ECAP_CEVT2_INT)
	{
		count = ECAPTimeStampRead(g_aREGS[index], ECAP_CAPTURE_EVENT_2);    
	}
	if(status & ECAP_CEVT3_INT)
	{
		count = ECAPTimeStampRead(g_aREGS[index], ECAP_CAPTURE_EVENT_3);
	}
	if(status & ECAP_CEVT4_INT)
	{
		count = ECAPTimeStampRead(g_aREGS[index], ECAP_CAPTURE_EVENT_4);
	}	
	/* 清中断标志位 */
	ECAPIntStatusClear(g_aREGS[index], 0x3F);

	/* 换算成频率.不能除0 */
	if(count)
	{
		freq = (float)ECAP_CLK_FREQ/count;
	}
	else
	{
		freq = 0;
	}

	//将频率范围限定在45hz到55hz。
	if(freq>=44.0 && freq <= 56.0)
	{
		g_freqency[index] = freq;
	}
}

  • 各位安:

    使用AM335X芯片做ecap捕获,用到了全部三个ecap通道,ecap0用于时钟频率捕获,其中ecap1和ecap2用来捕获45HZ~55HZ方波,ecap1配置为APWM模式时,ecap2可以正常捕获到正确的周期,反之 ecap2设置为APWM模式时,ecap1也可以正常捕获到正确的周期。同时配置为ECAP_CAPTURE_MODE就都不能正常工作,求赐教。

    代码如下:

    int freq_init(void)
    {
        void __iomem *p_REGS;
    
       /**************************配置时钟和设备地址映射****************************/
        p_REGS = ioremap(SOC_PWMSS1_REGS, SZ_8K);
        if(!p_REGS)
        {
            printk("%s:ioremap(%x) error\r\n", __func__, SOC_PWMSS1_REGS);
    		
            return -1;
        }
        g_SOC_PWMSS1_REGS = (unsigned int)p_REGS;
        g_SOC_ECAP_1_REGS = g_SOC_PWMSS1_REGS + SOC_ECAP_REGS;
        g_aREGS[0] = g_SOC_ECAP_1_REGS;
        
        p_REGS = ioremap(SOC_PWMSS2_REGS, SZ_8K);
        if(!p_REGS)
        {
            printk("%s:ioremap(%x) error\r\n", __func__, SOC_PWMSS2_REGS);
            iounmap((void __iomem *)g_SOC_CONTROL_REGS);
            iounmap((void __iomem *)g_SOC_PWMSS1_REGS);
    		
            return -1;
        }
        g_SOC_PWMSS2_REGS = (unsigned int)p_REGS;
        g_SOC_ECAP_2_REGS = g_SOC_PWMSS2_REGS + SOC_ECAP_REGS;	
        g_aREGS[1] = g_SOC_ECAP_2_REGS;
    	
        /* Enable Clock */
        ECAPClockEnable(g_SOC_PWMSS1_REGS);
        while(ECAPClockEnableStatusGet(g_SOC_PWMSS1_REGS) == 0);     
        ECAPClockEnable(g_SOC_PWMSS2_REGS);
        while(ECAPClockEnableStatusGet(g_SOC_PWMSS2_REGS) == 0); 
    	
    	/***************************配置两个ecap的硬件管脚*****************************/
    	p_REGS = ioremap(SOC_CONTROL_REGS, SZ_8K);
    	if(!p_REGS)
    	{
    		printk("%s:ioremap(%x) error\r\n", __func__, SOC_CONTROL_REGS);
    		
    		return -1;
    	}
    	g_SOC_CONTROL_REGS = (unsigned int)p_REGS;
    
    	/* eCAP1输入管脚 AM335X_ECAP1_IN I2C0_SCL C16 */
    	HWREG(g_SOC_CONTROL_REGS + CONTROL_CONF_I2C0_SCL) =
    		(CONTROL_CONF_PULLUPSEL |CONTROL_CONF_RXACTIVE	
    		| CONTROL_CONF_MUXMODE(3));
    	
    	/* eCAP2输入管脚 eCAP2_in_PWM2_out模式 MCASP0_AHCLKR C12	*/
    	HWREG(g_SOC_CONTROL_REGS + CONTROL_CONF_MCASP0_AHCLKR) =
    		(CONTROL_CONF_PULLUPSEL |CONTROL_CONF_RXACTIVE	
    		| CONTROL_CONF_MUXMODE(4));
    
    	/****************************配置两个ecap的寄存器******************************/
    	/* 捕捉模式 
    	** ECCTL2[9] CAP_APWM CAP/APWM operating mode select
        ** 0h = ECAP module operates in capture mode. This mode forces the
        ** following configuration. (a) Inhibits TSCTR resets via PRDEQ event.
        ** (b) Inhibits shadow loads on CAP1 and 2 registers. (c) Permits user
        ** to enable CAP1-4 register load. (d) ECAPn/APWMn pin operates as
        ** a capture input.
        ** 1h = ECAP module operates in APWM mode. This mode forces the
        ** following configuration. (a) Resets TSCTR on PRDEQ event (period
        ** boundary). (b) Permits shadow loading on CAP1 and 2 registers. (c)
        ** Disables loading of time-stamps into CAP1-4 registers. (d)
        ** ECAPn/APWMn pin operates as a APWM output.
    	*/
        ECAPOperatingModeSelect(g_SOC_ECAP_1_REGS, ECAP_CAPTURE_MODE);
        ECAPOperatingModeSelect(g_SOC_ECAP_2_REGS, ECAP_APWM_MODE);    /* 问题就在此处 ecap2设备APWM模式时 ecap1才能正常捕获,反之亦然 */
        
        /* 连续模式
    	** ECCTL2[0] CONT_ONESHT  0h = Operate in continuous mode
        */
        ECAPContinousModeConfig(g_SOC_ECAP_1_REGS);
        ECAPContinousModeConfig(g_SOC_ECAP_2_REGS);
    
    	/* 清除中断 
    	** ECCLR[0:7] ECFLG&0xFF Writing a 1 clears the Int flag condition
    	*/
        ECAPIntStatusClear(g_SOC_ECAP_1_REGS, 0xFF);
        ECAPIntStatusClear(g_SOC_ECAP_2_REGS, 0xFF);
    
        /* 这里的分频是指输入信号的分频,不是ECAP的时钟分频 
        ** ECCTL1[9:13] PRESCALE 0h = Divide by 1 (i.e,. no prescale, by-pass the prescaler)
    	*/
        ECAPPrescaleConfig(g_SOC_ECAP_1_REGS, 0);
        ECAPPrescaleConfig(g_SOC_ECAP_2_REGS, 0);
    	
        /* enables capture loading 
        ** ECCTL1[8] CAPLDEN 1h = Enable CAP1-4 register loads at capture event time.
    	*/
        ECAPCaptureLoadingEnable(g_SOC_ECAP_1_REGS);
        ECAPCaptureLoadingEnable(g_SOC_ECAP_2_REGS);
    	
        /* configures Capture Event polarity.上升沿捕捉 */
        ECAPCapeEvtPolarityConfig(g_SOC_ECAP_1_REGS, EC_RISING_EDGE, EC_RISING_EDGE, EC_RISING_EDGE, EC_RISING_EDGE);	
        ECAPCapeEvtPolarityConfig(g_SOC_ECAP_2_REGS, EC_RISING_EDGE, EC_RISING_EDGE, EC_RISING_EDGE, EC_RISING_EDGE);	
        
        /* enables reset of the counters upon Capture Events. */
        ECAPCaptureEvtCntrRstConfig(g_SOC_ECAP_1_REGS, EC_DELTA_MODE, EC_DELTA_MODE, EC_DELTA_MODE, EC_DELTA_MODE);
        ECAPCaptureEvtCntrRstConfig(g_SOC_ECAP_2_REGS, EC_DELTA_MODE, EC_DELTA_MODE, EC_DELTA_MODE, EC_DELTA_MODE);
    	
    	/* 0h = Stop after Capture Event 1 in one-shot mode. Wrap after
    	   Capture Event 1 in continuous mode
    	   0->0->0 CAP1 */
        //ECAPStopWrapConfig(g_SOC_ECAP_1_REGS, ECAP_CAPTURE_EVENT4_STOP);
        //ECAPStopWrapConfig(g_SOC_ECAP_2_REGS, ECAP_CAPTURE_EVENT1_STOP);
    	
        /* 使能中断 */
        ECAPIntEnable(g_SOC_ECAP_1_REGS, ECAP_CEVT1_INT|ECAP_CEVT2_INT|ECAP_CEVT3_INT|ECAP_CEVT4_INT);
        ECAPIntEnable(g_SOC_ECAP_2_REGS, ECAP_CEVT1_INT|ECAP_CEVT2_INT|ECAP_CEVT3_INT|ECAP_CEVT4_INT);	
    
        /* Disables the sync out ,sync in. TI定义的宏ECAP_SYNC_OUT_DISABLE有问题,改用EC_SYNC_OUT_DISABLE 
        ** ECCTL2[5] SYNCI_EN  0h = Disable sync-in option
        ** ECCTL2[6:7] SYNCO_SEL  2h = Disable sync out signal
    	*/
        ECAPSyncInOutSelect(g_SOC_ECAP_1_REGS, ECAP_SYNC_IN_DISABLE, EC_SYNC_OUT_DISABLE);
        ECAPSyncInOutSelect(g_SOC_ECAP_2_REGS, ECAP_SYNC_IN_DISABLE, EC_SYNC_OUT_DISABLE);
    	
        /* Set Counter 
    	** RSCTR[0:31] 0 Active 32 bit counter register that is used as the capture time-base
    	*/
        ECAPCounterConfig(g_SOC_ECAP_1_REGS, 0);
        ECAPCounterConfig(g_SOC_ECAP_2_REGS, 0);
    	
        /* 自由运行     ECCTL2[4] 1  TSCTRSTOP->TSCTR free-running 计数器停止位控制 计数器开始计数 */
        ECAPCounterControl(g_SOC_ECAP_1_REGS, ECAP_COUNTER_FREE_RUNNING);
        ECAPCounterControl(g_SOC_ECAP_2_REGS, ECAP_COUNTER_FREE_RUNNING);
    	
        rt_request_irq(CFG_ECAP1INT, CFG_INT_LEVEL_ECAP, freq_isr0, "ecap1", 0);
        rt_request_irq(CFG_ECAP2INT, CFG_INT_LEVEL_ECAP, freq_isr1, "ecap2", 0);
        
        return 0;	
    }
    
    void freq_isr0(void *data) 
    {
    	freq_isr(0);
    }
    
    void freq_isr1(void *data) 
    {
    	freq_isr(1);
    }
    
    void freq_isr(int index) 
    {
    	unsigned int 	status, count = 0;
    	float 	freq;
    
    	/* 读取中断状态值 */
    	status = ECAPIntStatus(g_aREGS[index], 0x3F);
    	if(status & ECAP_CEVT1_INT)
    	{
    		count = ECAPTimeStampRead(g_aREGS[index], ECAP_CAPTURE_EVENT_1);
    	}
    	if(status & ECAP_CEVT2_INT)
    	{
    		count = ECAPTimeStampRead(g_aREGS[index], ECAP_CAPTURE_EVENT_2);    
    	}
    	if(status & ECAP_CEVT3_INT)
    	{
    		count = ECAPTimeStampRead(g_aREGS[index], ECAP_CAPTURE_EVENT_3);
    	}
    	if(status & ECAP_CEVT4_INT)
    	{
    		count = ECAPTimeStampRead(g_aREGS[index], ECAP_CAPTURE_EVENT_4);
    	}	
    	/* 清中断标志位 */
    	ECAPIntStatusClear(g_aREGS[index], 0x3F);
    
    	/* 换算成频率.不能除0 */
    	if(count)
    	{
    		freq = (float)ECAP_CLK_FREQ/count;
    	}
    	else
    	{
    		freq = 0;
    	}
    
    	//将频率范围限定在45hz到55hz。
    	if(freq>=44.0 && freq <= 56.0)
    	{
    		g_freqency[index] = freq;
    	}
    }
    

  • 好了,硬件问题,程序没问题
  • 楼主这是裸机代码?

  • linux下的代码