S32K144 Quadrature Decoder Configuration Issue

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

S32K144 Quadrature Decoder Configuration Issue

1,969 Views
cjf6221
Contributor I

Hello Everyone,

I would like to used FTM2_QD(PTD10, PTD11) to measure every rising or falling edge of A and B by using counter overflow interrupt and then calculate the motor position based on encoder. But I am troubled by the FTM2_QD configuration for a long time. 

Below is my configuration for FTM2_QD. Please provide some help. 

 

void FTM2_Quadrature_Decoder_Mode()
{
/* Enable clock for PORTD */
PCC->PCCn[PCC_PORTD_INDEX] = PCC_PCCn_CGC_MASK;
/* Select and enable clock for FTM2 */
PCC->PCCn[PCC_FLEXTMR2_INDEX] = PCC_PCCn_PCS(6) | PCC_PCCn_CGC_MASK;

PORTD->PCR[10] = PORT_PCR_MUX(3); // Set PTD10 for FTM2 - Phase B input
PORTD->PCR[11] = PORT_PCR_MUX(3); // Set PTD11 for FTM2 - Phase A input

FSL_NVIC->ISER[FTM2_IRQn / 32] |= (1 << (FTM2_IRQn % 32)); // Enable FTM2 counter overflow interrupt
// FSL_NVIC->ICPR[116/32] = 1 << (116% 32);
FSL_NVIC->ISER[116/32] = 1 << (116% 32);   // overflow interrupt number
// FSL_NVIC->IP[116] = 0;

FTM2->MODE = FTM_MODE_WPDIS_MASK | FTM_MODE_FTMEN_MASK;

//Enable FTM2 module (0x00000005): D2(WPDIS) and D0(FTMEN) are set.

 

FTM2->MOD = FTM_MOD_MOD(10); // overflow after totally 4096 rising/falling edges
FTM2->CNT = 0;  
FTM2->CNTIN = FTM_CNTIN_INIT(0);

FTM2->QDCTRL &= ~FTM_QDCTRL_QUADMODE_MASK; // Phase A and phase B encoding mode
FTM2->QDCTRL = FTM_QDCTRL_PHAFLTREN_MASK | FTM_QDCTRL_PHBFLTREN_MASK | FTM_QDCTRL_QUADEN_MASK; // Enable QD mode and input filter
FTM2->SC |= FTM_SC_CLKS(1) | FTM_SC_PS(2) | FTM_SC_CPWMS_MASK | FTM_SC_TOIE_MASK;

// FTM_SC_CLKS(1): select FTM as input timer.
// FTM_SC_PS(2): clock source FTM, prescaler 2^2, clock frequency = 112MHz/4 = 28MHz
// FTM_SC_TOIE_MASK: enable timer overflow interruption
// FTM_SC_CPWMS_MASK; D5(CPWMS) is set to enable up-down counting mode
}

 

Below is the overflow interrupt function.

void FTM2_Ovf_Reload_IRQHandler()  
{

if( FTM2->SC & FTM_SC_TOF_MASK ){   // there is overflow interrupt
    PTC->PTOR |= 1<<9; // Toggle PTC9 for scope display
    FTM2_ISR_Counter++;
    Temp_EncoderB = FTM2->CONTROLS[0].CnV; //store the captured C0V value (Counter's vaule)
    Temp_EncoderA = FTM2->CONTROLS[1].CnV; //store the captured C1V value (Counter's vaule)
    FTM2->CONTROLS[0].CnSC &= ~FTM_CnSC_CHF_MASK; //clear Ch0 flag D7(CHF) is required to be reset after reading
    FTM2->CONTROLS[1].CnSC &= ~FTM_CnSC_CHF_MASK; //clear Ch1 flag D7(CHF) is required to be reset after reading
    Count_Encoder = FTM2->CNT;
    FTM2->SC &= ~FTM_SC_TOF_MASK; // Clear timer overflow flag D9(TOF) after reading the captured C0V and C0V1 values.

}

}

I do not know why there is no output for Temp_EncoderB and Temp_EncoderA. It sounds like the overflow interrupt does not happen. Please provide some help if you know.

Thanks.

 

Best,

Jianfei Chen

0 Kudos
10 Replies

1,684 Views
dianabatrlova
NXP TechSupport
NXP TechSupport

Hello Rong,

The interrupt does not work because you are using old code/header file where is used FSL_NVIC write.

The S32_NVIC should be used instead of FSL_NVIC in the new projects. 

I recommend you to create a new project. After that, the header file will be correct and you can use, for example, code below for initialization of the interrupt:

S32_NVIC->ICPR[3] = 1 << (116 % 32);
S32_NVIC->ISER[3] = 1 << (116 % 32);
S32_NVIC->IP[116] = 0x00;

I hope it helps.

Best Regards,

Diana

0 Kudos

1,684 Views
cjf6221
Contributor I

Hello Diana,

Thanks so much.

According to your suggest, I creat a new project in S32 Design Studio but it showed there is no "S32_NVIC". What is the problem ? Is it a must to replace FSL_NVIC by S32_NVIC ?

Best,

Jianfei

0 Kudos

1,684 Views
dianabatrlova
NXP TechSupport
NXP TechSupport

Hello Rong,

Which version of S32 Design Studio do you use?

Please, use the newest version S32 Design Studio for Arm 2018.R1:

https://www.nxp.com/webapp/swlicensing/sso/downloadSoftware.sp?catid=S32-DS-ARM_v2018  

Best Regards,

Diana

0 Kudos

1,684 Views
cjf6221
Contributor I

Maybe the problem is caused by the interruption type. I used overflow interruption, which maybe not suitable for quadrature encoder mode. What do you think ?

Best,

Jianfei

0 Kudos

1,684 Views
dianabatrlova
NXP TechSupport
NXP TechSupport

Hello Jianfei,

I really recommend you to install the newest version of the S32DS - S32 Design Studio for Arm 2018.R1 – Windows/Linux(REV 2018-R1), after that, it should work:

S32 Design Studio IDE for Arm® based MCUs | NXP 

Have you seen the maskset when you select the device in v1.3? I'm asking because the v1.3 generates the old header file where the FSL_NVIC is implemented.

Best Regards,

Diana

0 Kudos

1,684 Views
cjf6221
Contributor I

Hello Diana,

According to your suggestion, I have installed the newest version of S32DS. Below is the code built in S32-Arm2018.R1.


#include "S32K144.h" /* include peripheral declarations S32K144 */

void FTM2_Quadrature_Decoder_Mode();
uint16_t Temp_EncoderA; //Port D11
uint16_t Temp_EncoderB; //Port D10
uint16_t FTM2_ISR_Counter=0;
uint16_t Count_Encoder = 0;
uint16_t Pre_Count_Encoder = 0;
uint16_t Count_Overflow,k;
uint8_t Motor_TOFDIR_Encoder, Motor_TOF_Encoder; // Timer overflow direction

int main(void)
{
int counter = 0;
FTM2_Quadrature_Decoder_Mode();

// for(;;) {
// }

/* to avoid the warning message for GHS and IAR: statement is unreachable*/
#if defined (__ghs__)
#pragma ghs nowarning 111
#endif
#if defined (__ICCARM__)
#pragma diag_suppress=Pe111
#endif
return 0;
}

void FTM2_Quadrature_Decoder_Mode()
{
/* Enable clock for PORTD */
PCC->PCCn[PCC_PORTD_INDEX] = PCC_PCCn_CGC_MASK; // clock enabled
/* Select and enable clock for FTM2 */
PCC->PCCn[58] |= PCC_PCCn_PCS(6) | PCC_PCCn_CGC_MASK;
// PORTD->PCR[4] |= PORT_PCR_MUX(1) | PORT_PCR_IRQC(9);

PORTD->PCR[10] |= PORT_PCR_MUX(3); // Set PTD10 for FTM2 - Phase B input
PORTD->PCR[11] |= PORT_PCR_MUX(3); // Set PTD11 for FTM2 - Phase A input

// S32_NVIC->ISER[3] |= (1 << (FTM2_IRQn % 32)); // Enable FTM2 interrupt FTM2_IRQn
S32_NVIC->ICPR[3] = (1<<(116%32)); //116/32=3 /* clr any pending IRQ*/
S32_NVIC->ISER[3] = (1<<(116%32)); //116/32=3 /* enable IRQ */
S32_NVIC->IP[116] = 0x00;

/* Input capture mode sensitive on both rising and falling edges to measure duty cycle of tested signal */

FTM2->MODE |= FTM_MODE_WPDIS_MASK | FTM_MODE_FTMEN_MASK; // Enable write the FTM CnV register (0x00000004): D2(WPDIS)
// Enable FTM2 module (0x00000001): D0(FTMEN) are set.FTM_MODE_INIT_MASK
//enable the counter to run in the BDM mode
//FTM2->CONF = FTM_CONF_BDMMODE(3);
/* Encoder simulation with totally 144 rising/falling edges */
FTM2->MOD = FTM_MOD_MOD(10);
/* Reset counter */
FTM2->CNTIN = FTM_CNTIN_INIT(0); // initial value of FTM2 counter
FTM2->QDCTRL &= ~FTM_QDCTRL_QUADMODE_MASK; // Phase A and phase B encoding mode
FTM2->QDCTRL |= FTM_QDCTRL_QUADEN_MASK; // Enable QD mode.
FTM2->QDCTRL &= ~FTM_QDCTRL_TOFDIR_MASK;
FTM2->CNT = 0;
/* Select clock */
FTM2->SC |= FTM_SC_CLKS(1) | FTM_SC_PS(4) | FTM_SC_TOIE_MASK;
// FTM_SC_CLKS(1) selects FTM as input timer.
// FTM_SC_PS(2); clock source FTM, prescaler 2^2, clock frequency = 112MHz/4 = 28MHz
// FTM_SC_TOIE_MASK enables timer overflow interruption
// FTM_SC_CPWMS_MASK; D5(CPWMS) is set to enable up-down counting mode FTM_SC_CPWMS_MASK
}

void FTM2_Ovf_Reload_IRQHandler()//this interrupt is FTM2
//void FTM2_Ch0_Ch1_IRQHandler()//this interrupt is FTM2
{
PTA->PTOR |= 0x0800; //PTA11 is set
if(FTM2->SC & FTM_SC_TOF_MASK ){
Motor_TOFDIR_Encoder = ((FTM2->QDCTRL)>>1)&0x1; // the QUADIR bit in the FTM_QDCTRL register indicates Timer overflow direction in QD mode
Motor_TOF_Encoder = ((FTM2->SC)>>9)&0x1; // Timer overflow flag
if(Motor_TOFDIR_Encoder){
Count_Overflow++;
}else{
Count_Overflow--;
}
Pre_Count_Encoder = Count_Encoder;
Count_Encoder = Count_Encoder*10 + FTM2->CNT;
FTM2->SC &= ~FTM_SC_TOF_MASK; // Clear timer overflow flag D9(TOF) is reset
}
PTA->PTOR &= 0x7FFF; //PTA11 is reset
}

I debuged it in Debug_RAM mode and found it cannot enter the overflow interrupt. So FTM2->CNT has no change. I also tried another interrupt FTM2_Ch0_Ch1_IRQHandler() but still cannot enter the interrupt. I was troubled by this issue for so long time. 

Best,

Jianfei

0 Kudos

1,684 Views
dianabatrlova
NXP TechSupport
NXP TechSupport

Hello Rong,

I have attached a very simple test code. I'm using S32K144EVB.

There I verify that after the FTM counter reach number 36 (0x24) the interrupt is generated.

pastedImage_1.png

I hope it helps.

Best Regards,

Diana

0 Kudos

1,684 Views
cjf6221
Contributor I

Hi Diana,

Thanks for your patience and kind help. Finally I figured it out and found the FTM2 should be configured to work under debug mode as I would like to debug it under the debug_RAM mode. So the following code must be added.

 FTM2->CONF = FTM_CONF_BDMMODE(3); 

 

Under this way, the overflow interrrupt is set as follows:

pastedImage_1.png

Then, quadrature decoder works well and there is the same result as you attached. FTM2->CNT successfully changes.

pastedImage_3.png

But here I have one more question. I used overflowed interrupt (TOF) but you suggested reload interrupt (RF) with the code as follows:

pastedImage_2.png

 

Interestingly, the output results are the same. Can you explain why this happen ?

0 Kudos

1,684 Views
dianabatrlova
NXP TechSupport
NXP TechSupport

Hi Rong, 

I'm very sorry for the delay. I'm glad that it works.

Actually I'm using TOIE - overflowed interrupt in this code. I'm using this code as a test code (it is not an official example) so, the clearing reload flag RF it's unnecessary. It should not be there. I'm sorry I confused you. There should be clearing TOF.

If you have the interest to know more about reload interrupt I recommend you to read sections in the RM rev 11:

45.5.29 Reload Points and 45.5.29.1 Reload Opportunities

Best Regards,

Diana

0 Kudos

1,684 Views
cjf6221
Contributor I

Hello Diana,

Thanks so much. The version I used is Arm V1.3. As you said, quadrature encoder is not availablel in Arm V1.3 ?

Best,

Jianfei

0 Kudos