Hi,
I have tested on my TWR-KV31 board, I can enter ADC ISR multiple times, so it is okay.
For your issue, you do not set the ADCx_SC2[]ADTRG] bit, because you set it, then clear it with the two lines.
ADC0->SC2 = ADC_SC2_ADTRG(1); // hardware triggered
ADC0->SC2= ADC_SC2_ADACT(1);//conversion start
Pls use the following code, I run it, it works fine.
BR
XiangJun Rong
void FTM_TrigAdc(void)
{
SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK | SIM_SCGC6_FTM0_MASK;
SIM->SCGC5 |= 0x3E00; // enable port A/B/C/D/E clock
PORTC->PCR[1] = PORT_PCR_MUX(4);
GPIOC->PDDR |= 0x40; // PTC direction register, PTD6 is in output mode
#if 0
FTM0->SC = 0x00;
FTM0->CONF = FTM_CONF_BDMMODE(3);
FTM0->FMS = 0x00;
FTM0->MODE |= FTM_MODE_WPDIS_MASK | FTM_MODE_FAULTM(0x05);
FTM0->MOD = 19999;
FTM0->CONTROLS[0].CnSC = FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK;
//FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK;
FTM0->CONTROLS[0].CnV = 9999;
FTM0->COMBINE = FTM_COMBINE_COMBINE2_MASK;
FTM0->COMBINE |= FTM_COMBINE_DTEN1_MASK;
FTM0->DEADTIME = FTM_DEADTIME_DTVAL(31); // dead time is 31 system clock cycles
FTM0->CNTIN = 0x00;
FTM0->SC = FTM_SC_CLKS(0x01) |FTM_SC_CPWMS(0);
asm("nop");
FTM0->EXTTRIG |= FTM_EXTTRIG_CH0TRIG_MASK ;
//FTM0->EXTTRIG |= FTM_EXTTRIG_INITTRIGEN_MASK;
FTM0->CONF |= FTM_CONF_GTBEEN_MASK; // Enable global time base
FTM0->CONF |= FTM_CONF_GTBEOUT_MASK;
#endif
FTM0->SC=0x00;
FTM0->CONF=0xC0; //set up BDM in 11
FTM0->FMS=0x00; //clear the WPEN so that WPDIS is set in FTM0->_MODE register
FTM0->MODE|=0x05; //enable write the FTM CnV register
FTM0->MOD=1000;
FTM0->CONTROLS[0].CnSC=0x28; //High_Low_high for center-alignment
FTM0->CONTROLS[1].CnSC=0x28;
FTM0->CONTROLS[2].CnSC=0x28;
FTM0->CONTROLS[3].CnSC=0x28;
FTM0->CONTROLS[4].CnSC=0x28;
FTM0->CONTROLS[5].CnSC=0x28;
FTM0->CONTROLS[6].CnSC=0x28;
FTM0->COMBINE=0x020202; //complementary mode for CH0&CH1, CH2&CH3 of FTM0->
FTM0->COMBINE|=0x101010; // dead timer insertion enabled in complementary mode //for CH0&CH1 of FTM0->
FTM0->DEADTIME=0x1F; //dead time is 31 system clock cycles
FTM0->CNTIN=0x00;
FTM0->CONTROLS[1].CnV=500; //in complementary, C0V/C2V/C4V are used to control duty cycle.
FTM0->CONTROLS[0].CnV=500; //in complementary mode, C1V/C3V/C5V are not used.
FTM0->CONTROLS[2].CnV=500;
FTM0->CONTROLS[3].CnV=500;
FTM0->CONTROLS[4].CnV=500;
FTM0->CONTROLS[5].CnV=1000;
//triggering ADC at the center point of PWM signal while PWM is set up in //center alignment mode
FTM0->SC=0x28; //PWM center alignment, system clock driving, dividing by 1
asm("nop");
//set that FTM0_C5V to trigger ADC, in complementary, C5V is not used to //control duty cycle
FTM0->EXTTRIG|=0x08;
//NVIC->ISER[1] |= (1 << 7);
//NVIC->ICPR[0] |= (1 << 7);
//FTM0->SC |= FTM_SC_TOIE_MASK;
}
void FTM0_IRQHandler(void)
{
if (FTM0->STATUS & FTM_STATUS_CH0F_MASK)
{
FTM0->STATUS &= ~FTM_STATUS_CH0F_MASK; // Clear the channel flag
//ADC0->SC1[0] = ADC_SC1_AIEN_MASK | ADC_SC1_ADCH(8); // Start ADC conversion on channel 8
}
}
void AdcInit(void)
{
SIM->SCGC5 |= 0x3E00; // enable port A/B/C/D/E clock
SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK; // enable ADC0 clock
ADC0->CFG1 = ADC_CFG1_ADIV(4) | ADC_CFG1_MODE(1) | ADC_CFG1_ADICLK(0); // ADC clock is bus clock/2, bus clock is 20M, ADC clock is 10MHz
ADC0->CFG2 = 0x00;
ADC0->SC2 = ADC_SC2_ADTRG(1); // hardware triggered
ADC0->SC2|= ADC_SC2_ADACT(1);//conversion start
ADC0->SC3 = 0x00;
ADC0->SC1[0] = ADC_SC1_AIEN_MASK | ADC_SC1_ADCH(8);
SIM->SOPT7 = SIM_SOPT7_ADC0TRGSEL(0x08)| SIM_SOPT7_ADC0ALTTRGEN_MASK;
NVIC_EnableIRQ(ADC0_IRQn);
__ASM("CPSIE I");
}
uint32_t sample[10];
void ADC0_IRQHandler(void)
{
if (ADC0->SC1[0] & ADC_SC1_COCO_MASK)
{
// ADC0->SC1[0] = ADC_SC1_AIEN_MASK | ADC_SC1_ADCH(8);
GPIOC->PTOR = 0x40; // Toggle indicator
sample[0] = ADC0->R[0];
}
}
Hi,
If you want to use hardware triggering mode, you have to configure:
1)set the ADCx_SC2[ADTRG] bit, it means that the ADC will be triggered by the hardware instead of software
2)configure the SIM_SOPT7 register, it defines the triggering source of ADC. For detailed inf, pls refer to section 3.7.1.7 ADC triggers in the RM of KV31
For example, if you select PIT trigger 0, you have to configure the PIT channel0 so that PIT channel0 can generate triggering signal, while configure SIM_SOPT7[ADCxTRGSEL]=4;
Hope it can help you
BR
XiangJun Rong
hi,
xiangjun_rong,
ADC inject trigger with PWM Ontime duty trigger register level code or function level code guide me how to configure step by step
#include "board.h"
#include "fsl_debug_console.h"
#include "fsl_adc16.h"
#include "fsl_ftm.h"
#include "fsl_common.h"
#include "pin_mux.h"
#include"fsl_port.h"
//#include"pin_mux.c"
#include <stdio.h>
#include "peripherals.h"
#define DEMO_ADC16_BASE ADC0
#define DEMO_ADC16_CHANNEL_GROUP 0U
#define DEMO_ADC16_USER_CHANNEL 8U
#define DEMO_PWM_BASE FTM0
#define DEMO_PWM_CHANNEL 0U
volatile uint32_t pwmDutyCyclePercent = 0;
uint32_t result = 0;
adc16_channel_config_t adc16ChannelConfigStruct;
//volatile uint32_t read = *((uint32_t*)0x00080000);
void BOARD_InitPWM(void) {
ftm_config_t ftmInfo;
FTM_GetDefaultConfig(&ftmInfo);
/* Initialize FTM module */
FTM_Init(DEMO_PWM_BASE, &ftmInfo);
/* Set the PWM period */
FTM_SetTimerPeriod(DEMO_PWM_BASE, kFTM_SystemClock);
/* Configure the PWM channel */
ftm_chnl_pwm_signal_param_t ftmParam;
ftmParam.chnlNumber = DEMO_PWM_CHANNEL;
ftmParam.level = kFTM_HighTrue;
ftmParam.dutyCyclePercent = 30;
ftmParam.firstEdgeDelayPercent = 0;
// PORT_SetPinMux(BOARD_FTM0_CH0_PORT, BOARD_FTM0_CH0_PIN, kPORT_MuxAlt4);
FTM_SetupPwm(DEMO_PWM_BASE, &ftmParam, 1U, kFTM_EdgeAlignedPwm, 25000U, kFTM_SystemClock);
//PORT_SetPinMux(BOARD_FTM0_CH0_PORT, BOARD_FTM0_CH0_PIN, kPORT_MuxAlt4);
//PORT_SetPinMux(PORTE,1,1);
//PORT_SetPinMux(BOARD_FTM0_CH0_PORT, BOARD_FTM0_CH0_PIN, kPORT_MuxAlt4);
/* Start the PWM */
FTM_StartTimer(DEMO_PWM_BASE, kFTM_SystemClock);
}
void BOARD_InitADC(void) {
adc16_config_t adc16ConfigStruct;
ADC16_GetDefaultConfig(&adc16ConfigStruct);
adc16ConfigStruct.resolution = kADC16_ResolutionSE12Bit; // Change as needed
ADC16_Init(DEMO_ADC16_BASE, &adc16ConfigStruct);
/* Configure ADC channel */
adc16ChannelConfigStruct.channelNumber = DEMO_ADC16_USER_CHANNEL;
adc16ChannelConfigStruct.enableInterruptOnConversionCompleted = false;
adc16ChannelConfigStruct.enableDifferentialConversion = false;
ADC16_SetChannelConfig(DEMO_ADC16_BASE, DEMO_ADC16_CHANNEL_GROUP, &adc16ChannelConfigStruct);
/* Enable the Injected Conversion */
// ADC16_EnableHardwareTrigger(DEMO_ADC16_BASE, true);
ADC16_EnableHardwareTrigger(DEMO_ADC16_BASE , false);
//ADC16_EnableInjectedSequences(DEMO_ADC16_BASE , false);
}
void FTM0_IRQHandler(void) {
/* Clear interrupt flag */
FTM_ClearStatusFlags(DEMO_PWM_BASE, kFTM_Chnl0Flag);
/* Update PWM duty cycle based on some condition */
pwmDutyCyclePercent = (result * 100U) / 4095U;
FTM_UpdatePwmDutycycle(DEMO_PWM_BASE, DEMO_PWM_CHANNEL, kFTM_EdgeAlignedPwm, pwmDutyCyclePercent);
}
/*void HardFault_Handler(void){
while(1){
}
}*/
int main(void) {
BOARD_InitPWM();
BOARD_InitADC();
/* Enable FTM0 interrupt */
EnableIRQ(FTM0_IRQn);
FTM_EnableInterrupts(DEMO_PWM_BASE, kFTM_Chnl0InterruptEnable);
NVIC_SetPriority(FTM0_IRQn, 0);
while (1) {
/* Start an injected conversion with software trigger */
ADC16_SetChannelConfig(DEMO_ADC16_BASE, DEMO_ADC16_CHANNEL_GROUP, &adc16ChannelConfigStruct);
//ADC16_DoSoftwareTrigger(DEMO_ADC16_BASE);
//PORT_SetPinMux(BOARD_FTM0_CH0_PORT, BOARD_FTM0_CH0_PIN, kPORT_MuxAlt4);
/* Wait for the conversion to complete */
while (0U == (kADC16_ChannelConversionDoneFlag & ADC16_GetChannelStatusFlags(DEMO_ADC16_BASE, DEMO_ADC16_CHANNEL_GROUP)))
{
}
/* Read ADC result */
result = ADC16_GetChannelConversionValue(DEMO_ADC16_BASE, DEMO_ADC16_CHANNEL_GROUP);
/* Print the result or use it as needed */
PRINTF("ADC Result: %d\r\n", result);
/* Delay for a while */
SDK_DelayAtLeastUs(1000000U, SystemCoreClock);
}
return 0;
}
this program adc inject trigger method if any changes let me know
BR
PANDI
Hi,
Pls refer to the attached an5142.pdf, in the section 3.7. FTM triggering ADC, the FTM triggering ADC is discussed and the code is given.
But You use both the FTM diver and ADC driver instead of writing register.
anyway, you have to write the following registers:
1)set the ADCx_SC2[ADTRG] bit, it means that the ADC will be triggered by the hardware instead of software
2)configure the SIM_SOPT7 register to select the triggering source
3)write the FTM0_EXTTRIG to select which CVx register can generate the triggering signal.
I suppose that you can use the code directly.
Hope it can help you
BR
XiangJun Rong
void FTM_TrigAdc(void)
{
SIM_SCGC6|=0x03000000; //enable FTM0 and FTM0 module clock
SIM_SCGC5=SIM_SCGC5|0x3E00; //enable port A/B/C/D/E clock
PORTC_PCR7=0x100; //PTC7 in GPIO mode
GPIOC_PDDR=0x80; //PTC direction register, PTC7 is in output mode
FTM0_SC=0x00;
FTM0_CONF=0xC0; //set up BDM in 11
FTM0_FMS=0x00; //clear the WPEN so that WPDIS is set in FTM0_MODE register
FTM0_MODE|=0x05; //enable write the FTM CnV register
FTM0_MOD=1000;
FTM0_C0SC=0x28; //High_Low_high for center-alignment
FTM0_C1SC=0x28;
FTM0_C2SC=0x28;
FTM0_C3SC=0x28;
FTM0_C4SC=0x28;
FTM0_C5SC=0x28;
FTM0_C6SC=0x28;
FTM0_COMBINE=0x020202; //complementary mode for CH0&CH1, CH2&CH3 of FTM0
FTM0_COMBINE|=0x101010; // dead timer insertion enabled in complementary mode //for CH0&CH1 of FTM0
FTM0_DEADTIME=0x1F; //dead time is 31 system clock cycles
FTM0_CNTIN=0x00;
FTM0_C1V=500; //in complementary, C0V/C2V/C4V are used to control duty cycle.
FTM0_C0V=500; //in complementary mode, C1V/C3V/C5V are not used.
FTM0_C2V=500;
FTM0_C3V=500;
FTM0_C4V=500;
FTM0_C5V=1000;
//triggering ADC at the center point of PWM signal while PWM is set up in //center alignment mode
FTM0_SC=0x28; //PWM center alignment, system clock driving, dividing by 1
asm("nop");
//set that FTM0_C5V to trigger ADC, in complementary, C5V is not used to //control duty cycle
FTM0_EXTTRIG|=0x08;
}
unsigned int sample[8];
void AdcInit(void)
{
SIM_SCGC5=SIM_SCGC5|0x3E00; //enable port A/B/C/D/E clock
SIM_SCGC3|=0x08000000; //enable ADC1 clock
ADC1_CFG1=0x44; //adc clock is bus clock/2, busclock is 20M, ADC clock is 10MHz
ADC1_CFG2=0x00;
ADC1_SC2=0x40; //hardware triggered,
ADC1_SC3=0x00; //not continuous conversion
ADC1_SC1A=0x54; //interrupt enable and select ADC1_DM1 channel
//set that FTM0 to trigger ADC1
SIM_SOPT7=0x8800; //FTM0 trigger ADC1, alternative triggering, only ADC1_SC1A //conversion is valid
NVICIP58=0x30; //setting interrupt of ADC1
PWM Features
Features of the FlexTimer Module, Rev. 0, 06/2015
Freescale Semiconductor, Inc. 13
NVICICPR1|=1<<26; //clear the pending register of interrupt source 58
NVICISER1|=1<<26; //set the interrupt source of ADC1
asm("cpsie i"); //interrupt enable
}
void ADC_ISR(void)
{
GPIOC_PTOR=0x80; //toggle indicator
sample[0]=ADC1_RA;
asm("nop");
//ADC1_SC1A=0x14; //interrupt enable and select ADC1_DM1 channel
}
hi
I`m changing to register level program but ADC value not reading please guide me
void FTM_TrigAdc(void) {
// Enable clock for ADC0 and FTM0
SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK | SIM_SCGC6_FTM0_MASK;
// Enable clock for port B and E
SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK | SIM_SCGC5_PORTE_MASK;
// Configure pin multiplexing for FTM0 channels
PORTB->PCR[18] = PORT_PCR_MUX(3); // FTM0_CH1, PTB18
PORTB->PCR[19] = PORT_PCR_MUX(3); // FTM0_CH0, PTB19
PORTE->PCR[1] = PORT_PCR_MUX(3); // FTM0_CH2, PTE1
// Configure FTM0 for PWM
FTM0->SC = 0x00;
FTM0->CONF = FTM_CONF_BDMMODE(3);
FTM0->FMS = 0x00;
FTM0->MODE |= FTM_MODE_WPDIS_MASK | FTM_MODE_FAULTM(0x05);
FTM0->MOD = 1000;
// Configure channels for complementary mode
for (int i = 0; i < 7; ++i) {
FTM0->CONTROLS[i].CnSC = FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK;
FTM0->CONTROLS[i].CnV = 500;
}
// Enable dead time insertion
FTM0->COMBINE = FTM_COMBINE_COMBINE0_MASK | FTM_COMBINE_COMBINE1_MASK | FTM_COMBINE_COMBINE2_MASK |
FTM_COMBINE_COMBINE3_MASK;
FTM0->COMBINE |= FTM_COMBINE_DTEN0_MASK | FTM_COMBINE_DTEN1_MASK | FTM_COMBINE_DTEN2_MASK |
FTM_COMBINE_DTEN3_MASK;
FTM0->DEADTIME = FTM_DEADTIME_DTVAL(31);
// Configure FTM0 for PWM center alignment, system clock driving, dividing by 1
FTM0->SC = FTM_SC_CLKS(1) | FTM_SC_PS(0x00);
// Set FTM0_C5V to trigger ADC
FTM0->EXTTRIG |= FTM_EXTTRIG_CH5TRIG_MASK;
// Set FTM0_C5SC to PWM
FTM0->CONTROLS[5].CnSC = FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK;
__NOP();
}
void AdcInit(void)
{
//SIM->SCGC5 |= 0x3E00;
SIM->SCGC5 |= 0x3E00;//enable port A/B/C/D/E clock
SIM->SCGC6|= SIM_SCGC6_ADC1_MASK; //enable ADC1 clock
ADC1->CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_MODE(1) | ADC_CFG1_ADICLK(0); // adc clock is bus clock/2, bus clock is 20M, ADC clock is 10MHz
ADC1->CFG2 = 0x00;
ADC1->SC2 = ADC_SC2_ADTRG_MASK; //hardware triggered,
ADC1->SC3 = 0x00; //not continuous conversion
ADC1->SC1[0] = ADC_SC1_AIEN_MASK | ADC_SC1_ADCH(4); //interrupt enable and select ADC1_DM1 channel
//set that FTM0 to trigger ADC1
SIM->SOPT7 = SIM_SOPT7_ADC1TRGSEL(0x09) | SIM_SOPT7_ADC1ALTTRGEN_MASK;//FTM0 trigger ADC1, alternative triggering, only ADC1_SC1A //conversion is valid
NVIC->ISER[1] |= (1 << 26);//setting interrupt of ADC1
__ASM("CPSIE I"); //interrupt enable
}
void ADC_ISR(void)
{
GPIOC->PTOR = 0x80; // toggle indicator
sample[1] = ADC1->R[0];
//sample[1]=ADC1->R[1];
__NOP();
//ADC1_SC1A=0x14; //interrupt enable and select ADC1_DM1 channel
}
BR
PANDI
Hi,
For KV31, the ADC1 interrupt vector is 73.
NVIC->ISER[2] |= (1 << 9); //setting interrupt of ADC1
//NVIC->ICPR[2] |= (1 << 9); //clear interrupt pending bit
Pls check if you can enter ADC1 ISR.
Hope it can help you
BR
XiangJun Rong
hi
This code ADC inject trigger. Correct
or not if not means which line in change to program please guide me
void FTM_TrigAdc(void)
{
SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK | SIM_SCGC6_FTM0_MASK;
SIM->SCGC5 |= 0x3E00; // enable port A/B/C/D/E clock
//PORTD->PCR[6] = PORT_PCR_MUX(3);
PORTC->PCR[1] = PORT_PCR_MUX(4);// PDC6 as FTM0_CH6
GPIOC->PDDR |= 0x40; // PTC direction register, PTD6 is in output mode
FTM0->SC = 0x00;
FTM0->CONF = FTM_CONF_BDMMODE(3);
FTM0->FMS = 0x00;
FTM0->MODE |= FTM_MODE_WPDIS_MASK | FTM_MODE_FAULTM(0x05);
FTM0->MOD = 699-1;
FTM0->CONTROLS[0].CnSC = FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK; // High_Low_high for center-alignment
FTM0->CONTROLS[0].CnV = 349; // in complementary, C6V is used to control duty cycle
FTM0->COMBINE = FTM_COMBINE_COMBINE2_MASK;
FTM0->COMBINE |= FTM_COMBINE_DTEN1_MASK;
FTM0->DEADTIME = FTM_DEADTIME_DTVAL(31); // dead time is 31 system clock cycles
FTM0->CNTIN = 0x00;
// triggering ADC at the center point of PWM signal while PWM is set up in center alignment mode
FTM0->SC = FTM_SC_CLKS(1) | FTM_SC_PS(0x00); // PWM center alignment, system clock driving, dividing by 1
asm("nop");
FTM0->EXTTRIG |= FTM_EXTTRIG_CH5TRIG_MASK;
//FTM0->EXTTRIG |= FTM_EXTTRIG_CH6TRIG_MASK;
NVIC->ISER[0] |= (1 << 9);
FTM0->SC |= FTM_SC_TOIE_MASK;
}
void FTM0_IRQHandler(void)
{
GPIOC->PTOR = 0x40; // Toggle indicator
sample[0] = ADC0->R[0]; // Store ADC sample value
__NOP();
FTM0->SC &= ~FTM_SC_TOF_MASK; // Clear Timer Overflow Flag
}
void AdcInit(void)
{
SIM->SCGC5 |= 0x3E00; // enable port A/B/C/D/E clock
SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK; // enable ADC0 clock
ADC0->CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_MODE(1) | ADC_CFG1_ADICLK(0); // ADC clock is bus clock/2, bus clock is 20M, ADC clock is 10MHz
ADC0->CFG2 = 0x00;
ADC0->SC2 = ADC_SC2_ADTRG_MASK; // hardware triggered
ADC0->SC2= ADC_SC2_ADACT_MASK ;//conversion start
ADC0->SC3 = 0x00;
ADC0->SC1[0] = ADC_SC1_AIEN_MASK | ADC_SC1_ADCH(8); // interrupt enable and select ADC0_SE8 channel
// set FTM0 to trigger ADC0
SIM->SOPT7 = SIM_SOPT7_ADC0TRGSEL(0x0A) | SIM_SOPT7_ADC0ALTTRGEN_MASK; // FTM0 trigger ADC0
// Enable ADC0 interrupt in NVIC
NVIC_EnableIRQ(ADC0_IRQn);
__ASM("CPSIE I");
}
void ADC0_IRQHandler(void)
{
GPIOC->PTOR = 0x40; // toggle indicator
sample[0] = ADC0->R[0];
__NOP();
}
int main(void)
{
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitBootPeripherals();
AdcInit();
FTM_TrigAdc();
SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK | SIM_SCGC6_FTM0_MASK;
#ifndef BOARD_INIT_DEBUG_CONSOLE_PERIPHERAL
BOARD_InitDebugConsole();
#endif
//PRINTF("Hello World\r\n");
//PRINTF("Hello World\r\n");
PRINTF("%d",sample[0]);
volatile static int i = 0;
while(1)
{
i++;
//GETCHAR();
//sample[0] = ADC0->R[0];
__asm volatile ("nop");
}
return 0;
}
BR
PANDI
Hi,
1)As I attached the ADC triggering source, the FTM0 index is 4b'1000 or 8, so you have to use the line:
SIM->SOPT7 = SIM_SOPT7_ADC0TRGSEL(0x08) | SIM_SOPT7_ADC0ALTTRGEN_MASK; // FTM0 trigger ADC0
2)For the ADC0 interrupt vector is 39, so you have to write the line:
NVIC->ISER[1] |= (1 << 7); //39-32=7
3)The FTM0 triggers ADC0 and the ADC0 generates interrupt after conversion is over, so it is unnecessary to have FTM generate interrupt. pls comment the line:
//FTM0->SC |= FTM_SC_TOIE_MASK;
4)I suppose that you know the mechanism of the FTM0 triggering ADC0, if you set the line:
FTM0->EXTTRIG |= FTM_EXTTRIG_CH5TRIG_MASK;
SIM->SOPT7 = SIM_SOPT7_ADC0TRGSEL(0x08) | SIM_SOPT7_ADC0ALTTRGEN_MASK; // FTM0 trigger ADC0
when the FTM0 counter reaches up to the value of FTM0_C5V, the FTM0 triggering event will happen, because the SIM->SOPT7 = SIM_SOPT7_ADC0TRGSEL(0x08); the FTM0 triggering event will route to ADC0, because the ADC0 is configured as hardware triggering, the analog channel in ADC0_SC1[0] will be converted with FTM0 triggering event.
So you have to initialize the FTM0_C5V and the ADC0_SC1[0]
I suggest you use the original code in the AN, because the code is based on K40, you use KV31, so you have to change the code to adapt to KV31.
Hope it can help you
BR
XiangJun Rong
hi
I`m configuration all peripheral but inject trigger not working if anything missing you have to guide me
void AdcInit(void)
{
SIM->SCGC5 |= 0x3E00; // enable port A/B/C/D/E clock
SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK; // enable ADC0 clock
ADC0->CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_MODE(1) | ADC_CFG1_ADICLK(0); // ADC clock is bus clock/2, bus clock is 20M, ADC clock is 10MHz
ADC0->CFG2 = 0x00;
ADC0->SC2 = ADC_SC2_ADTRG(1); // hardware triggered
ADC0->SC2= ADC_SC2_ADACT(1);//conversion start
ADC0->SC3 = 0x00;
ADC0->SC1[0] = ADC_SC1_AIEN_MASK | ADC_SC1_ADCH(8);
SIM->SOPT7 = SIM_SOPT7_ADC0TRGSEL(0x08)| SIM_SOPT7_ADC0ALTTRGEN_MASK;
NVIC_EnableIRQ(ADC0_IRQn);
__ASM("CPSIE I");
}
void FTM_TrigAdc(void)
{
SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK | SIM_SCGC6_FTM0_MASK;
SIM->SCGC5 |= 0x3E00; // enable port A/B/C/D/E clock
//PORTD->PCR[6] = PORT_PCR_MUX(3);
PORTC->PCR[1] = PORT_PCR_MUX(4);
GPIOC->PDDR |= 0x40; // PTC direction register, PTD6 is in output mode
FTM0->SC = 0x00;
FTM0->CONF = FTM_CONF_BDMMODE(3);
FTM0->FMS = 0x00;
FTM0->MODE |= FTM_MODE_WPDIS_MASK | FTM_MODE_FAULTM(0x05);
FTM0->MOD = 19999;
FTM0->CONTROLS[0].CnSC = FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK;
//FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK;
//FTM0->SC = FTM_CnSC_ELSB(1) | FTM_CnSC_ELSA(0);
FTM0->CONTROLS[0].CnV = 9999;
FTM0->COMBINE = FTM_COMBINE_COMBINE2_MASK;
FTM0->COMBINE |= FTM_COMBINE_DTEN1_MASK;
FTM0->DEADTIME = FTM_DEADTIME_DTVAL(31); // dead time is 31 system clock cycles
FTM0->CNTIN = 0x00;
FTM0->SC = FTM_SC_CLKS(0x01) |FTM_SC_CPWMS(0);
asm("nop");
//FTM0->EXTTRIG |= FTM_EXTTRIG_CH0TRIG_MASK ;
FTM0->EXTTRIG |= FTM_EXTTRIG_INITTRIGEN_MASK;
FTM0->CONF |= FTM_CONF_GTBEEN_MASK; // Enable global time base
FTM0->CONF |= FTM_CONF_GTBEOUT_MASK;
NVIC->ISER[1] |= (1 << 7);
//NVIC->ICPR[0] |= (1 << 7);
//FTM0->SC |= FTM_SC_TOIE_MASK;
}
void FTM0_IRQHandler(void)
{
if (FTM0->STATUS & FTM_STATUS_CH0F_MASK)
{
FTM0->STATUS &= ~FTM_STATUS_CH0F_MASK; // Clear the channel flag
ADC0->SC1[0] = ADC_SC1_AIEN_MASK | ADC_SC1_ADCH(8); // Start ADC conversion on channel 8
}
}
void ADC0_IRQHandler(void)
{
if (ADC0->SC1[0] & ADC_SC1_COCO_MASK)
{
GPIOC->PTOR = 0x40; // Toggle indicator
sample[0] = ADC0->R[0];
}
}
BR
PANDI
Hi
This program inject ADC trigger or not if inject trigger not means please you guide me i`m configure all peripheral in the program please check it . if any other changes you have guide me
void FTM_TrigAdc(void)
{
SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK | SIM_SCGC6_FTM0_MASK;
SIM->SCGC5 |= 0x3E00; // enable port A/B/C/D/E clock
PORTC->PCR[1] = PORT_PCR_MUX(4);
GPIOC->PDDR |= 0x40; // PTC direction register, PTD6 is in output mode
FTM0->SC = 0x00;
FTM0->CONF = FTM_CONF_BDMMODE(3);
FTM0->FMS = 0x00;
FTM0->MODE |= FTM_MODE_WPDIS_MASK | FTM_MODE_FAULTM(0x05);
FTM0->MOD = 19999;
FTM0->CONTROLS[0].CnSC = FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK;
//FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK;
FTM0->CONTROLS[0].CnV = 9999;
FTM0->COMBINE = FTM_COMBINE_COMBINE2_MASK;
FTM0->COMBINE |= FTM_COMBINE_DTEN1_MASK;
FTM0->DEADTIME = FTM_DEADTIME_DTVAL(31); // dead time is 31 system clock cycles
FTM0->CNTIN = 0x00;
FTM0->SC = FTM_SC_CLKS(0x01) |FTM_SC_CPWMS(0);
asm("nop");
FTM0->EXTTRIG |= FTM_EXTTRIG_CH0TRIG_MASK ;
//FTM0->EXTTRIG |= FTM_EXTTRIG_INITTRIGEN_MASK;
FTM0->CONF |= FTM_CONF_GTBEEN_MASK; // Enable global time base
FTM0->CONF |= FTM_CONF_GTBEOUT_MASK;
NVIC->ISER[1] |= (1 << 7);
//NVIC->ICPR[0] |= (1 << 7);
//FTM0->SC |= FTM_SC_TOIE_MASK;
}
void FTM0_IRQHandler(void)
{
if (FTM0->STATUS & FTM_STATUS_CH0F_MASK)
{
FTM0->STATUS &= ~FTM_STATUS_CH0F_MASK; // Clear the channel flag
ADC0->SC1[0] = ADC_SC1_AIEN_MASK | ADC_SC1_ADCH(8); // Start ADC conversion on channel 8
}
}
void AdcInit(void)
{
SIM->SCGC5 |= 0x3E00; // enable port A/B/C/D/E clock
SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK; // enable ADC0 clock
ADC0->CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_MODE(1) | ADC_CFG1_ADICLK(0); // ADC clock is bus clock/2, bus clock is 20M, ADC clock is 10MHz
ADC0->CFG2 = 0x00;
ADC0->SC2 = ADC_SC2_ADTRG(1); // hardware triggered
ADC0->SC2= ADC_SC2_ADACT(1);//conversion start
ADC0->SC3 = 0x00;
ADC0->SC1[0] = ADC_SC1_AIEN_MASK | ADC_SC1_ADCH(8);
SIM->SOPT7 = SIM_SOPT7_ADC0TRGSEL(0x08)| SIM_SOPT7_ADC0ALTTRGEN_MASK;
NVIC_EnableIRQ(ADC0_IRQn);
__ASM("CPSIE I");
}
void ADC0_IRQHandler(void)
{
if (ADC0->SC1[0] & ADC_SC1_COCO_MASK)
{
GPIOC->PTOR = 0x40; // Toggle indicator
sample[0] = ADC0->R[0];
}
}
BR
PANDI
Hi,
I have tested on my TWR-KV31 board, I can enter ADC ISR multiple times, so it is okay.
For your issue, you do not set the ADCx_SC2[]ADTRG] bit, because you set it, then clear it with the two lines.
ADC0->SC2 = ADC_SC2_ADTRG(1); // hardware triggered
ADC0->SC2= ADC_SC2_ADACT(1);//conversion start
Pls use the following code, I run it, it works fine.
BR
XiangJun Rong
void FTM_TrigAdc(void)
{
SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK | SIM_SCGC6_FTM0_MASK;
SIM->SCGC5 |= 0x3E00; // enable port A/B/C/D/E clock
PORTC->PCR[1] = PORT_PCR_MUX(4);
GPIOC->PDDR |= 0x40; // PTC direction register, PTD6 is in output mode
#if 0
FTM0->SC = 0x00;
FTM0->CONF = FTM_CONF_BDMMODE(3);
FTM0->FMS = 0x00;
FTM0->MODE |= FTM_MODE_WPDIS_MASK | FTM_MODE_FAULTM(0x05);
FTM0->MOD = 19999;
FTM0->CONTROLS[0].CnSC = FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK;
//FTM_CnSC_MSB_MASK | FTM_CnSC_ELSB_MASK;
FTM0->CONTROLS[0].CnV = 9999;
FTM0->COMBINE = FTM_COMBINE_COMBINE2_MASK;
FTM0->COMBINE |= FTM_COMBINE_DTEN1_MASK;
FTM0->DEADTIME = FTM_DEADTIME_DTVAL(31); // dead time is 31 system clock cycles
FTM0->CNTIN = 0x00;
FTM0->SC = FTM_SC_CLKS(0x01) |FTM_SC_CPWMS(0);
asm("nop");
FTM0->EXTTRIG |= FTM_EXTTRIG_CH0TRIG_MASK ;
//FTM0->EXTTRIG |= FTM_EXTTRIG_INITTRIGEN_MASK;
FTM0->CONF |= FTM_CONF_GTBEEN_MASK; // Enable global time base
FTM0->CONF |= FTM_CONF_GTBEOUT_MASK;
#endif
FTM0->SC=0x00;
FTM0->CONF=0xC0; //set up BDM in 11
FTM0->FMS=0x00; //clear the WPEN so that WPDIS is set in FTM0->_MODE register
FTM0->MODE|=0x05; //enable write the FTM CnV register
FTM0->MOD=1000;
FTM0->CONTROLS[0].CnSC=0x28; //High_Low_high for center-alignment
FTM0->CONTROLS[1].CnSC=0x28;
FTM0->CONTROLS[2].CnSC=0x28;
FTM0->CONTROLS[3].CnSC=0x28;
FTM0->CONTROLS[4].CnSC=0x28;
FTM0->CONTROLS[5].CnSC=0x28;
FTM0->CONTROLS[6].CnSC=0x28;
FTM0->COMBINE=0x020202; //complementary mode for CH0&CH1, CH2&CH3 of FTM0->
FTM0->COMBINE|=0x101010; // dead timer insertion enabled in complementary mode //for CH0&CH1 of FTM0->
FTM0->DEADTIME=0x1F; //dead time is 31 system clock cycles
FTM0->CNTIN=0x00;
FTM0->CONTROLS[1].CnV=500; //in complementary, C0V/C2V/C4V are used to control duty cycle.
FTM0->CONTROLS[0].CnV=500; //in complementary mode, C1V/C3V/C5V are not used.
FTM0->CONTROLS[2].CnV=500;
FTM0->CONTROLS[3].CnV=500;
FTM0->CONTROLS[4].CnV=500;
FTM0->CONTROLS[5].CnV=1000;
//triggering ADC at the center point of PWM signal while PWM is set up in //center alignment mode
FTM0->SC=0x28; //PWM center alignment, system clock driving, dividing by 1
asm("nop");
//set that FTM0_C5V to trigger ADC, in complementary, C5V is not used to //control duty cycle
FTM0->EXTTRIG|=0x08;
//NVIC->ISER[1] |= (1 << 7);
//NVIC->ICPR[0] |= (1 << 7);
//FTM0->SC |= FTM_SC_TOIE_MASK;
}
void FTM0_IRQHandler(void)
{
if (FTM0->STATUS & FTM_STATUS_CH0F_MASK)
{
FTM0->STATUS &= ~FTM_STATUS_CH0F_MASK; // Clear the channel flag
//ADC0->SC1[0] = ADC_SC1_AIEN_MASK | ADC_SC1_ADCH(8); // Start ADC conversion on channel 8
}
}
void AdcInit(void)
{
SIM->SCGC5 |= 0x3E00; // enable port A/B/C/D/E clock
SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK; // enable ADC0 clock
ADC0->CFG1 = ADC_CFG1_ADIV(4) | ADC_CFG1_MODE(1) | ADC_CFG1_ADICLK(0); // ADC clock is bus clock/2, bus clock is 20M, ADC clock is 10MHz
ADC0->CFG2 = 0x00;
ADC0->SC2 = ADC_SC2_ADTRG(1); // hardware triggered
ADC0->SC2|= ADC_SC2_ADACT(1);//conversion start
ADC0->SC3 = 0x00;
ADC0->SC1[0] = ADC_SC1_AIEN_MASK | ADC_SC1_ADCH(8);
SIM->SOPT7 = SIM_SOPT7_ADC0TRGSEL(0x08)| SIM_SOPT7_ADC0ALTTRGEN_MASK;
NVIC_EnableIRQ(ADC0_IRQn);
__ASM("CPSIE I");
}
uint32_t sample[10];
void ADC0_IRQHandler(void)
{
if (ADC0->SC1[0] & ADC_SC1_COCO_MASK)
{
// ADC0->SC1[0] = ADC_SC1_AIEN_MASK | ADC_SC1_ADCH(8);
GPIOC->PTOR = 0x40; // Toggle indicator
sample[0] = ADC0->R[0];
}
}
Hi,
It is okay to sample 4 ADC channel synchronized.
The KV31 has 2 ADC modules, ADC0 and ADC1, each ADC has two converters: SC1A and SC1B, so it is okay, but the PDB module must be involved.
This is the solution.
FTM triggers PDB, the PDB generates timing to trigger both ADC0 and ADC1.
Pls refer to the ticket and check if it is helpful.
https://community.nxp.com/t5/Kinetis-Microcontrollers/KV56-Trigger-HSADC-with-PDB/m-p/1473870#M63331
BR
XiangJun Rong
Hi,
I means that the FTM0 trigger 4 ADC channel via PDB.
Pls refer to the an:
https://www.nxp.com.cn/docs/en/application-note/AN4822.pdf
Hope it can help you
BR
XiangJun Rong
Hi,
You set the line:
DC0->CFG1 = ADC_CFG1_ADIV(4) | ADC_CFG1_MODE(1) | ADC_CFG1_ADICLK(0);
Mode bits is 01 in binary, so the ADC resolution is 12 bits.
The 3.3V full range is 0xFFF or 4095. The tested voltage on ADC channel is (950/4095)*3.3V=0.76V.
Hope it can help you
BR
XiangJun Rong