s32k144w can fd Register help me

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

s32k144w can fd Register help me

Jump to solution
429 Views
Oido
Contributor I

Hello I want to use both CAN FD and motor drive using ADC with s32k144w at the same time.

Motor drive using ADC is currently possible and I'm trying to add CAN FD but it doesn't work.

CAN TX is PTE5 RX is PTE4 and ADC is using PTB0 and PTB1.
If both of them work at the same time, I think they'll be trapped in while and only one will work
I'm also thinking of getting the ADC to work as an interrupt, but it doesn't work.

I want to use CAN FD at 500K/2M, but I keep looking through the data sheet to see if I set the register incorrectly, but I couldn't find it.

I ask you to ask for help in a desperate way

I'm not good enough but I'll post the code I wrote.

The CANFD signal is sent to the CANO program.

I want pwm and timer to work at 8mhz and can fd to work at 48mhz.. please.

 

#include "S32K144W.h"
#include "sdk_project_config.h"
#include "core_cm4.h"
#include <stdint.h>
 
uint32_t ADC_Result_Channel4;
uint32_t ADC_Result_Channel5;
float ADC_Voltage;
float ADC_Current;
 
volatile int Direction=0;
volatile int Button=0;
 
uint8_t OverVoltage=13;
uint8_t UnderVoltage=11;
uint8_t OverCurrent=3;
 
void CW(void) //정방향 CW=1, CCW=0
{
PTB->PSOR = (1<<5);
PTB->PCOR = (1<<4);
FTM0->CONTROLS[6].CnV=300; //회전 속도(듀티비) CnV/400 > 80인경우 20%
}
 
void CCW(void) //역방향 CW=0, CCW=1
{
PTB->PSOR = (1<<4);
PTB->PCOR = (1<<5);
FTM0->CONTROLS[6].CnV=150; //회전 속도(듀티비) CnV/400 > 120인경우 30%
}
 
void ST(void) //정지 CW=0, CCW=0
{
PTB->PCOR = (1<<4);
PTB->PCOR = (1<<5);
FTM0->CONTROLS[6].CnV=0;
}
 
void SOSC_init_8MHz(void) // 클럭 설정을 위해 필요한 레지스터 **DIV, **CFG, **CSR
{
SCG->SOSCDIV = SCG_SOSCDIV_SOSCDIV1(1) | SCG_SOSCDIV_SOSCDIV2(1); //SOSCDIV1 & SOSCDIV2 =1: 분주비1
SCG->SOSCCFG  = SCG_SOSCCFG_EREFS_MASK|SCG_SOSCCFG_HGO(0)|SCG_SOSCCFG_RANGE(2); // 크리스탈 클럭 사용, LOW게인, 클럭 중간 범위 사용
 
while(SCG->SOSCCSR & SCG_SOSCCSR_LK_MASK); //SOSCCSR 잠금 해제(클리어)
 
SCG->SOSCCSR = SCG_SOSCCSR_SOSCEN_MASK; //오실레이터 오류감지 안됌, 잠금 해제, 크리스탈 활성화 > 오류감지시 인터럽트
 
while(!(SCG->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK)); //크리스탈 클럭 작동할 때 까지 대기
}
 
void FTM1_Ovf_Reload_IRQHandler(void) // 8Mhz 1KHz 1ms 타이머(오버플로우 인터럽트)
{
//if(11<ADC_Voltage && ADC_Voltage<13){ // 약 11V<전압<13V 내에서만 동작
if(PTA->PDIR & (1<<1)) // PORTA 에 스위치 입력이 들어오는 동안 타이머 작동
{
Button++;
if(Button==300) // 1당 1ms
{
Direction++;
}
if(Button==1000) // 1초간 누르고 있으면 정지
{
Direction=0;
}
}
else
{
Button=0;// 스위치 뗀 경우 0으로 초기화
}
//}
//else
//Direction=0;
if(Direction==3) // 정, 역만 왔다갔다 하게 0 = 정지, 1 = 정방향, 2 = 역방향
{
Direction=1;
}
FTM1->SC &= ~FTM_SC_TOF_MASK; // 오버플로우 플래그 클리어
}
 
void GPIO_Init(void)
{
PCC->PCCn[PCC_PORTA_INDEX] = PCC_PCCn_CGC_MASK; //포트A에 클럭 출력
PCC->PCCn[PCC_PORTB_INDEX] = PCC_PCCn_CGC_MASK; //포트B에 클럭 출력
PCC->PCCn[PCC_PORTD_INDEX] = PCC_PCCn_CGC_MASK; //포트D에 클럭 출력
PCC->PCCn[PCC_PORTE_INDEX] = PCC_PCCn_CGC_MASK; //포트E에 클럭 출력
 
PTA->PDDR = (0<<1); // GPIO DDR=0으로 PTA1 입력(스위치)
PTB->PDDR = (1<<2)|(1<<4)|(1<<5)|(1<<6)|(0<<7); // PTB2 출력 크리스탈 타이머 / PTB4 출력 CCW / PTB5 출력 CW/ PTB6 출력 크리스탈/ PTB7 입력 크리스탈
PTD->PDDR = (1<<15)|(1<<16); // GPIO PTD15 출력 mtr_sts A / PTD16 출력 mtr_sts B 게이트 드라이버 Enable
PTB->PCOR = (1<<5) | (1<<4); // CW, CCW 0으로 초기화
 
PORTE->PCR[8] = PORT_PCR_MUX(2); // PTE8번 PWM로 설정
PORTB->PCR[2] = PORT_PCR_MUX(1); // PTB2번 GPIO로 설정 (타이머)
PORTB->PCR[5] = PORT_PCR_MUX(1); // PTB5번 GPIO로 설정 (CW)
PORTB->PCR[4] = PORT_PCR_MUX(1); // PTB4번 GPIO로 설정 (CCW)
PORTA->PCR[1] = PORT_PCR_MUX(1); //PTA1번 GPIO로 설정 (스위치)
PORTE->PCR[5] = PORT_PCR_MUX(5); // PTE8번 PWM로 설정
PORTE->PCR[4] = PORT_PCR_MUX(5); // PTE8번 PWM로 설정
}
 
void PWM_Init(void) //FTM0 채널6 PWM사용
{
PCC->PCCn[PCC_FTM0_INDEX] = PCC_PCCn_PCS(1) | PCC_PCCn_CGC_MASK; //클럭활성화, FTM0 활성화
 
FTM0->MOD =400; // 카운터의 MAX값 400 20KHz
FTM0->CNTIN = 0; // 카운터의 현재값 0
FTM0->CONTROLS[6].CnSC = FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK; //PWM Edge 모드
FTM0->SC = FTM_SC_CLKS(3) | FTM_SC_PWMEN6_MASK; // 크리스탈 사용, FTM0 PWM채널6
FTM0->CONTROLS[6].CnV=0;
FTM0->CNT = 0; // 카운터의 초기 값
}
 
void TIMER_Init(void) //FTM1(8Mhz 크리스탈 타이머)
{
PCC->PCCn[PCC_FTM1_INDEX] = PCC_PCCn_PCS(1) | PCC_PCCn_CGC_MASK; //클럭활성화, FTM1 활성화
FTM1->MOD =8000; // 카운터의 MAX값 8000 8MHz 1KHz
FTM1->CNTIN = 0; // 카운터의 현재값
FTM1->SC = FTM_SC_CLKS(3)|FTM_SC_TOIE_MASK | FTM_SC_TOF_MASK; // 크리스탈 사용, FTM1 채널0, FTM1 오버플로우 인터럽트, 오버플로우 플래그 활성화
}
 
void ADC_Init(void)
{
PCC->PCCn[PCC_ADC0_INDEX] = PCC_PCCn_PCS(1) | PCC_PCCn_CGC_MASK; // ADC0에 출력
ADC0->SC1[0] = ADC_SC1_ADCH(4)|ADC_SC1_ADCH(5)|ADC_SC1_AIEN_MASK;; //채널4,5 활성화
ADC0->SC2 = ADC_SC2_ADTRG(0); //소프트웨어 트리거 (중요!! 하드웨어 또는 소프트웨어 트리거 설정해줘야함)
ADC0->CFG1 =  ADC_CFG1_ADIV(1)|ADC_CFG1_MODE(1);// 분주비2, 12비트
ADC0->CFG2 = ADC_CFG2_SMPLTS(255); // SAMPLE TIME 2~255
}
void CAN_Init(void)
{
PCC->PCCn[PCC_FlexCAN0_INDEX] = PCC_PCCn_CGC_MASK; // CAN0 출력
PTD->PSOR = (1<<1);
CAN0->MCR |= CAN_MCR_MDIS(0)|CAN_MCR_FDEN_MASK;
CAN0->CBT |= CAN_CBT_EPRESDIV(0)|CAN_CBT_ERJW(1)|CAN_CBT_EPROPSEG(7)|CAN_CBT_EPSEG1(4)|CAN_CBT_EPSEG2(1);
CAN0->CTRL1 |= CAN_CTRL1_CLKSRC_MASK;
CAN0->FDCTRL |= CAN_FDCTRL_FDRATE_MASK|CAN_FDCTRL_MBDSR0(3);
CAN0->FDCBT |= CAN_FDCBT_FPRESDIV(0)|CAN_FDCBT_FRJW(1)|CAN_FDCBT_FPROPSEG(17)|CAN_FDCBT_FPSEG1(2)|CAN_FDCBT_FPSEG2(2);
}
 
 
int main(void)
{
SOSC_init_8MHz(); // SOSC 8Mhz 초기화
GPIO_Init();
PWM_Init(); // 초기화
TIMER_Init();
ADC_Init();
CAN_Init();
NVIC_EnableIRQ(FTM1_Ovf_Reload_IRQn); // 오버플로우 인터럽트 활성화
 
while (1)
{
ADC0->SC1[0] = ADC_SC1_ADCH(4); // ADC0 채널4번 활성화
while(((ADC0->SC1[0] & ADC_SC1_COCO_MASK)>>ADC_SC1_COCO_SHIFT) == 0); // 변환이 완료되어 SC1_COCO가 1로 설정 될 때 까지 대기
ADC_Result_Channel4 = ADC0->R[0]; // ADC0 R(A)의 값을 저장
 
ADC0->SC1[0] = ADC_SC1_ADCH(5); // ADC0 채널5번 활성화
while(((ADC0->SC1[0] & ADC_SC1_COCO_MASK)>>ADC_SC1_COCO_SHIFT) == 0); // 변환이 완료되어 SC1_COCO가 1로 설정 될 때 까지 대기
ADC_Result_Channel5 = ADC0->R[0]; // ADC0 R(A)의 값을 저장
 
ADC_Current = ((float)ADC_Result_Channel4/140); // 게이트 드라이버 전류센서 140mV / 1A
ADC_Voltage = (((float)ADC_Result_Channel5 * 5) / 4095)*4+0.6;
//0~5V 값으로 변환한 값을 서플라이와 대략적으로 일치시켜 읽기 편하게 조정 정확하게 12V가 들어오지 않기 때문
 
  if(ADC_Current<=OverCurrent){ // 0~3A 이하일 때 동작
  if(UnderVoltage<=ADC_Voltage && ADC_Voltage<=OverVoltage){ // 약 11V<전압<13V 내에서만 동작 수치 조정 가능
  if(Direction==0){ // 정지
  ST();
  }
  if(Direction==1){ // 정방향
  CW();
  }
  if(Direction==2){ // 역방향
  CCW();
  }
  }
  else
  {
  ST();//전압 범위에서 벗어날 경우 정지
  }
  }
  else
  {
  ST();//전류 범위에서 벗어날 경우 정지
  }
}
}

 

 

0 Kudos
1 Solution
379 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

does it mean that even if you implemented a code from cookbook, modify it for your need, still you are not able to communicate properly? Your code does not include mentioned one.
Generally, if having issue still, check if any error is detected within module, read ECR/ESR1 registers.
Do you see any signal generated on CAN H/L lines?

BR, Petr

View solution in original post

0 Kudos
3 Replies
408 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

you can refer to S32K1 cookbook for a FlexCAN FD baremetal code;
https://www.nxp.com/docs/en/application-note/AN5413.pdf (chapter 2.10)
Your CAN init code is little bit insufficient.

BR, Petr

0 Kudos
399 Views
Oido
Contributor I

HELLO

Thanks but I learned how to use ADC and PWM through COOKBOOK but CAN FD failed.
But I am grateful to you.

0 Kudos
380 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

does it mean that even if you implemented a code from cookbook, modify it for your need, still you are not able to communicate properly? Your code does not include mentioned one.
Generally, if having issue still, check if any error is detected within module, read ECR/ESR1 registers.
Do you see any signal generated on CAN H/L lines?

BR, Petr

0 Kudos