SAMD20, Trying to get fan tacho signal recognized

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all!

 

I'm trying to get fan tacho signal recognized and cant get a reading on evsys edge detection. My problem is mainly with the initialization. What am I missing? Here is my code:

 

GCLK->CLKCTRL.reg =                    GCLK_CLKCTRL_ID(EIC_GCLK_ID)|
                                                      GCLK_CLKCTRL_GEN(0)|
                                                      GCLK_CLKCTRL_CLKEN;
    
    /*********************|
    |  PIN CONFIGURATION  |
    **********************/
    
    /* Pin PB08 input direction enable and pinmux enable */
    PORT->Group[1].PINCFG[8].reg  =        PORT_PINCFG_INEN |
                                                                 PORT_PINCFG_PMUXEN;
                                        
                                        
    PORT->Group[1].PMUX[4].bit.PMUXE = 0;
                                        
    /* Enable pin function A (EXTINT) for pin PB08 */
    PORT->Group[1].PMUX[4].reg =           PORT_PMUX_PMUXE_A;
    
        
    /**********************|
    |  EIC INITIALIZATION  |
    ***********************/
    
    /* EIC APB Clock Enable */
    PM->APBAMASK.reg |=                    PM_APBAMASK_EIC;
        
    /* External interrupt 8 event output enable */
    REG_EIC_INTENSET =                    EIC_EVCTRL_EXTINTEO8;
    
    /* Enable filtering and to detect rising edge */
    REG_EIC_CONFIG1 |=                    EIC_CONFIG_FILTEN0 |
                                                          EIC_CONFIG_SENSE0_RISE;
    
    /* Clear the interrupt */
    EIC->INTFLAG.reg =                    EIC_INTFLAG_EXTINT8;
    
    /* Enable EIC-peripheral */
    REG_EIC_CTRL |=                        EIC_CTRL_ENABLE;
    
    /* enable EIC interrupts */
    NVIC_EnableIRQ(EIC_IRQn);
    
                                                        
    /**********************|
    |  TC4 INITIALIZATION  |
    ***********************/
    
    /* set 16-bit counter mode, set prescaler to divide by 1 (no division) and
    set prescaler synchronization to reload or reset counter on next GCLK */
        
    PM->APBCMASK.reg  |=                PM_APBCMASK_TC4;
    
    TC4->COUNT16.CTRLA.reg =            TC_CTRLA_MODE_COUNT16 |                    
                                                             TC_CTRLA_PRESCALER_DIV1 |                
                                                             TC_CTRLA_PRESCSYNC_GCLK;                
    
    /* Enable TC event input and set it to count on event */
    TC4->COUNT16.EVCTRL.reg =            TC_EVCTRL_TCEI |
                                                              TC_EVCTRL_EVACT_COUNT;
                                        
    TC4->COUNT16.COUNT.reg =            0;
                                        
    /* Enable the timer counter peripheral TC4 */
    TC4->COUNT16.CTRLA.reg |=            TC_CTRLA_ENABLE;
    
    
    /*******************************|
    |  EVENT SYSTEM INITIALIZATION  |
    ********************************/
    
    EVSYS->USER.reg =    EVSYS_USER_CHANNEL(1) |
                                       EVSYS_USER_USER(EVSYS_ID_USER_TC4_EVU);
                        
    EVSYS->CHANNEL.reg = EVSYS_CHANNEL_EDGSEL_RISING_EDGE |
                                          EVSYS_CHANNEL_PATH_ASYNCHRONOUS |
                                          EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_8) |
                                          EVSYS_CHANNEL_CHANNEL(0);

 

void EIC_Handler(void){
    EIC->INTFLAG.reg =    0xFFFF;
}  

 

to read the value and 0 the register every second with a software timer:

    rpmValue = TC4->COUNT16.COUNT.reg;
    TC4->COUNT16.COUNT.reg = 0; 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Bits 27:26 – EDGSEL[1:0]

Edge Detection Selection These bits set the type of edge detection to be used on the channel. These bits must be written to zero when using the asynchronous path.

Looks like a problem with the  EVSYS->CHANNEL.reg  setting.
And TC4 has no clock?

/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the reply!

 

Made the suggested changes, but still no values at:

 

TC4->COUNT16.CTRLA.reg

TC4->COUNT16.CC[0].reg;
TC4->COUNT16.CC[1].reg;

 

Here is my modified initialization code:

 

void rpm_init(void){
    
    // Enable GCLK for TC4
    PM->APBCMASK.reg |=                    PM_APBCMASK_TC4;
    
    GCLK->CLKCTRL.reg =                    GCLK_CLKCTRL_CLKEN |
                                                  GCLK_CLKCTRL_GEN_GCLK0 |
                                    GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_TC4_TC5_Val);
    
    // Enable GCLK for EVSYS
    PM->APBCMASK.reg |=                    PM_APBCMASK_EVSYS;
    
    GCLK->CLKCTRL.reg =                    GCLK_CLKCTRL_CLKEN |
                                                  GCLK_CLKCTRL_GEN_GCLK0 |
                        GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_EVSYS_CHANNEL_0_Val);
        
    // Enable GCLK EIC
    PM->APBAMASK.reg |=                    PM_APBAMASK_EIC;
    
    GCLK->CLKCTRL.reg =                    GCLK_CLKCTRL_CLKEN |
                                                 GCLK_CLKCTRL_GEN_GCLK0 |
                                                 GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_EIC_Val);
        
                                            
    /*********************|
    |  PIN CONFIGURATION  |
    **********************/
    
    PORT->Group[1].DIR.reg =            (0 << 8);
    
    /* Pin PB08 input direction enable and pinmux enable */
    PORT->Group[1].PINCFG[8].reg  =        PORT_PINCFG_INEN |
                                                                 PORT_PINCFG_PMUXEN;
                                            
    /* Enable pin function A (EXTINT) for pin PB08 */
    PORT->Group[1].PMUX[4].reg =        PORT_PMUX_PMUXE_A;
    
    
    /**********************|
    |  TC4 INITIALIZATION  |
    ***********************/
    
    /* set 16-bit counter mode, set prescaler to divide by 1 (no division) and
    set prescaler synchronization to reload or reset counter on next GCLK */
    TC4->COUNT16.CTRLA.reg =            TC_CTRLA_MODE_COUNT16 |
                                                             TC_CTRLA_PRESCALER_DIV1;
                
    TC4->COUNT16.CTRLC.reg |=            TC_CTRLC_CPTEN0;
            
    /* Enable TC event input and set it to count on event */
    TC4->COUNT16.EVCTRL.reg =            TC_EVCTRL_TCEI |
                                                              TC_EVCTRL_EVACT_COUNT |
                                                              TC_EVCTRL_EVACT_PPW;
                                        
    //TC4->COUNT16.COUNT.reg =            0;
    
    TC4->COUNT16.INTENSET.reg |=        TC_INTENSET_MC0;
    
    /* Enable the timer counter peripheral TC4 */
    TC4->COUNT16.CTRLA.reg |=            TC_CTRLA_ENABLE;
    
    
    /**********************|
    |  EIC INITIALIZATION           |
    ***********************/
            
    /* External interrupt 8 event output enable */
    EIC->EVCTRL.reg |=                    EIC_EVCTRL_EXTINTEO8;
    
    /* Enable filtering and to detect rising edge */
    EIC->CONFIG[1].reg =                EIC_CONFIG_FILTEN0 |
                                                       EIC_CONFIG_SENSE0_RISE;
    
    /* Clear the interrupt */
    EIC->INTFLAG.reg =                    EIC_INTFLAG_EXTINT8;
    
    /* Enable EIC-peripheral */
    EIC->CTRL.reg |=                         EIC_CTRL_ENABLE;
    
        
    /*******************************|
    |  EVENT SYSTEM INITIALIZATION            |
    ********************************/
    
    EVSYS->USER.reg =                                EVSYS_USER_CHANNEL(1) |
                                                  EVSYS_USER_USER(EVSYS_ID_USER_TC4_EVU);
                        
    EVSYS->CHANNEL.reg =               EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT |  
                                                        EVSYS_CHANNEL_PATH_ASYNCHRONOUS |
                                            EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_8) |
                                                  EVSYS_CHANNEL_CHANNEL(0);
                                          
                                                              
    /* interrupts config */
    NVIC_DisableIRQ(EIC_IRQn);
    NVIC_ClearPendingIRQ(EIC_IRQn);
    NVIC_SetPriority(EIC_IRQn, 0);
    NVIC_EnableIRQ(EIC_IRQn);                                      
}

 

/Sam

 

Last Edited: Tue. Jun 14, 2022 - 12:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Looks like input capture now, but
 

    TC4->COUNT16.EVCTRL.reg = TC_EVCTRL_TCEI |
                              TC_EVCTRL_EVACT_COUNT |
                              TC_EVCTRL_EVACT_PPW;

you can't enable both COUNT and PPW.

Here is some example code for PPW:

https://www.avrfreaks.net/forum/...
/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
    PM->APBCMASK.reg |= PM_APBCMASK_EVSYS;

is missing.

/Lars