Hello Community,
i am new to Cortex-programming, and i wanted to test the 16-bit ADC of te freedom kl25z board. And I am using IAR to develop and debug it.
The setup is 16 bit, continuous-Conversion-Mode, BUS-clock, Clock frequency divided by 8, hardware-averaging enabled with 32 sampels, and differential mode.
Now, i ve got a few problems,
1. COCO-flag (conversion complete) is permanently set
-> i can not "manually" check whether conversion is finished or not
2. conversion complete interrupt does not fire, too
-> i don't know how to enable them, "asm("CPSIE i");" does not seem to work
-> void adc0_isr is built to read the ADC0_RA (result) register
#include "common.h"
#include "smc.h"
#include "adc16.h"
#include "isr.h"
#define ADC
#define EnableInterrupts asm(" CPSIE i");
void init_ADC16(void);
tADC_Config Master_Adc_Config;
uint32 result0A = 0;
/********************************************************************/
int main (void)
{
EnableInterrupts;
//adc (diff-mode, continuous conversion, 16 bit)
init_ADC16();
while(1){
/*
* custom code here
*/
}
}
/********************************************************************/
/*
* custom function here
*/
/********************************************************************/
//also mentioned in isr.h
//as: extern void adc0_isr(void);
void adc0_isr(void){
result0A = ADC0_RA;
};
/********************************************************************/
void init_ADC16(void){
// Turn on the ADC0 clock as well as the PDB clocks to test ADC triggered by PDB
SIM_SCGC6 |= (SIM_SCGC6_ADC0_MASK );
PMC_REGSC |= PMC_REGSC_BGBE_MASK ;
// setup the initial ADC default configuration
Master_Adc_Config.CONFIG1 =0xFC; //ADLPC_NORMAL //Config Reg.1
//| (11<<5) //ADC_CFG1_ADIV(ADIV_8)
//| (1<<4) //ADLSMP_LONG
//| (11<<2) //ADC_CFG1_MODE(MODE_16)
//| (00<<0); //ADC_CFG1_ADICLK(ADICLK_BUS);
Master_Adc_Config.CONFIG2 = 0x00; //MUXSEL_ADCA //Config Reg.2
//| (0<<3) //ADACKEN_DISABLED
//| (0<<2) //ADHSC_NORMAL
//| (00<<0); //ADC_CFG2_ADLSTS(ADLSTS_20) ;
//Status Register
Master_Adc_Config.STATUS1A = 0x60; //AIEN_ON //Status Reg SC1A
//| (1<<5) //DIFF_ENABLED
//| (0x00); //Analog chanel 0
Master_Adc_Config.STATUS2 = 0x00; //ADTRG_SW //Status Reg SC2
//| (0<<5) //ACFE_DISABLED
//| (0<<4) //ACFGT_DISABLED
//| (0<<3) //ACREN_DISABLED
//| (0<<2) //DMA_DISABLED
//| (00<<0);//ADC_SC2_REFSEL(REFSEL_EXT);
Master_Adc_Config.STATUS3 = 0x0F; //CAL_OFF //Status Reg SC3
//| (0<<3) //ADCO_CONTINUOUS
//| (1<<2) //AVGE_ENABLED
//| (11<<0); //ADC_SC3_AVGS(AVGS_32);
ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc_Config); // config ADC
ADC_Cal(ADC0_BASE_PTR); // do the calibration
// The structure still has the desired configuration. So restore it.
// The calibration makes some adjustments to the
// configuration of the ADC. The are now undone:
// config the ADC again to desired conditions
ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc_Config);
}
I hope that someone can help me,
Regards
marius
Hi,
Please refer attached KL25 ADC example code about how to use ADC interrupt mode.
Wish it helps.
Have a great day,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Ma Hui,
The ISR function in this code is incorrect. I used it for a software trigger and it caused me problems. I assume that this will cause problems if you use a continuous scan.
//File:TPM_ADC_Alternative_Trigger.c void adc0_isr(void) { if(((ADC0_SC1A & ADC_SC1_COCO_MASK) >> ADC_SC1_COCO_SHIFT) == 0x1) { adc0_a_value = ADC0_RA; ADC0_SC1A |= ADC_SC1_COCO_MASK; printf("ADC0_RA = 0x%x\n\r", adc0_a_value); } if(((ADC0_SC1B & ADC_SC1_COCO_MASK) >> ADC_SC1_COCO_SHIFT) == 0x1) { adc0_b_value = ADC0_RB; ADC0_SC1B |= ADC_SC1_COCO_MASK; printf("ADC0_RB = 0x%x\n\r", adc0_b_value); } }
The problem:
ADC0_SC1A |= ADC_SC1_COCO_MASK;
This attempts to set a read only flag of the register. The very flag of the register you are trying to check to see if the conversion is complete.
This triggered a conversion interrupt. Which in my case, caused me to read ADC Channel X instead of ADC Channel Y or vice versa frequently.
The manual states that it is read only, but debugging has shown otherwise. Reading the appropriate ADC Data Result Register (ADC0_RA OR ADC0_RB) will automatically clear that flag.
Best Regards,
Jason Philippi
Hi
You are quite right.
The ADCx_SC1n[COCO] bit is read-only bit. That code try to write this bit is incorrect.
As you mentioned, this bit could be cleared when the respective SC1n register is written or when the respective Rn register is read.
Thank you for the direction.
Have a great day,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------