Discussion in "ARM Development" started by    pravin_35    Jan 13, 2014.
Mon Jan 13 2014, 12:10 pm
#1
hi guys,

i am using Arduino Due with Atmel Studio .
SAM3X8E ARM cortex m3 Processor.
Atmel Studio 6.1IDE.
SAMICE Debugger.


i am trying to read Analog Signal in the internal ADC & trigger of ADC is External Which i have given 1mhz.
i am trying to read 128 Samples in for loop .but i am getting only 2 or 3 Sample Which iam printing in Serial Port.
Kindly see the code i have attached full code in notepad file..
below is the While loop.....
 while (1) {

			
			start_adc();
			
		/* Check if ADC sample is done. */
for (i =0 ;i<127;i++)
{
		if (g_adc_sample_data.us_done == ADC_DONE_MASK) {
			for (i = 0; i < NUM_CHANNELS; i++) {
				printf("CH%02d: %04d mv.    ",
						(int)g_adc_sample_data.uc_ch_num[i],
						(int)(g_adc_sample_data.
								us_value[i] ));
			}
}
			puts("\r");
			g_adc_sample_data.us_done = 0;
		}
	}
}




[ Edited Fri Jan 17 2014, 09:50 am ]
Fri Jan 17 2014, 09:53 am
#2
is this flag indicates all the ADC channel samples are ready? "g_adc_sample_data.us_done"

instead of if loop you should be waiting for it to be done. i.e.
while (g_adc_sample_data.us_done != ADC_DONE_MASK);
 pravin_35 like this.
Fri Jan 17 2014, 03:51 pm
#3
Thanks Ajay,,,
I tried with
(g_adc_sample_data.us_done != ADC_DONE_MASK);
Still iam missing the data.

i try to make you clear what i am trying for !!
i have CCD sensor Which has a output pattern (Refer pic1).The output of ccd is analog and the rate of 1msps.
I am connected the analog output to the SAM3X8E (Arduino Due). Adc configured as Ext trigger (Rising Edge) given 1mhz clock(same camera clock which ccd Triggered). Start and stop connected to port pin edge trigger . whenever 1 interrupt (start adc, Read ccd data) stop when 2 interrupt.(Refer : SI the clock mentioned in pic1).

Between start and stop there are 128 clocks (ccd will out 120 pixel analog output).. i need to read this 128 pixel in adc and load the data to 1d Array... please help how to make this logic ..

The above code is the example code . i will upload the real code that made for the mentioned logic..
expected is 128 data in buffer .

ajay please let me know some more details required.



Thanks
Pravin


[ Edited Fri Jan 17 2014, 03:58 pm ]
Fri Jan 17 2014, 09:10 pm
#4
hi ajay

This is the actual code for above mentioned logic
#include <string.h>

#include "asf.h"
#include "conf_board.h"
#include <stdint-gcc.h>

#include "sysclk.h"
#include "conf_clock.h"
//#include "conf_example3.h"
#include "genclk.h"


 


/** IRQ priority for PIO (The lower the value, the greater the priority) */
#define IRQ_PRIOR_PIO    0

/** LED0 blinking control. */
volatile bool g_b_led0_active = false;

#if  SAM3XA
/* Tracking Time*/
#define  TRACKING_TIME            1
/* Transfer Period */
#define  TRANSFER_PERIOD       1 
#endif

/** Total number of ADC channels in use */
#if SAM3XA 
#define NUM_CHANNELS    (1)
#endif
/** ADC convention done mask. */
#define ADC_DONE_MASK   ( (1<<NUM_CHANNELS) - 1 )

/** Size of the receive buffer and transmit buffer. */
#define BUFFER_SIZE     NUM_CHANNELS

/** Reference voltage for ADC, in mv. */
#define VOLT_REF        (3300)

#if  SAM3XA
/** The maximal digital value */
#define MAX_DIGITAL     (4095)
#endif

/** ADC channel for potentiometer */
//#if  SAM3N 
//#define ADC_CHANNEL_POTENTIOMETER  ADC_CHANNEL_5
#if SAM3XA
#define ADC_CHANNEL_POTENTIOMETER  ADC_CHANNEL_1
//#elif SAM3U
//#define ADC_CHANNEL_POTENTIOMETER  ADC_CHANNEL_3
#endif

#define STRING_EOL    "\r"
#define STRING_HEADER "-- CCD Capture Data/Designed by :Pravin --\r\n" \
		"-- "BOARD_NAME" --\r\n" \
		"-- Compiled: "__DATE__" "__TIME__" --"STRING_EOL
#define MENU_HEADER "\n\r" \
		"===================================================\n\r" \
		"Menu: press a key to change the configuration.\n\r" \
		"---------------------------------------------------------\n\r"
						
/** ADC test mode structure */
struct {
	uint8_t uc_trigger_mode;
	uint8_t uc_pdc_en;
	uint8_t uc_sequence_en;
	uint8_t uc_gain_en;
	uint8_t uc_offset_en;
#if SAM3N 
	uint8_t uc_power_save_en;
#endif
} g_adc_test_mode;

/** ADC trigger modes */
enum {
	TRIGGER_MODE_SOFTWARE = 0,
	TRIGGER_MODE_ADTRG,
	TRIGGER_MODE_TIMER,
#if SAM3S || SAM3U || SAM3XA || SAM4S
	TRIGGER_MODE_PWM,
#endif
#if SAM3S || SAM3N || SAM3XA || SAM4S
	TRIGGER_MODE_FREERUN
#endif
} e_trigger_mode;

/** ADC sample data */
struct {
	uint8_t uc_ch_num[NUM_CHANNELS];
	uint16_t us_value[1];
	uint16_t us_done;
} g_adc_sample_data;

#if SAM3S || SAM3XA || SAM3N || SAM4S
/**Channel list for sequence*/
enum adc_channel_num_t ch_list[1] = {
	//ADC_TEMPERATURE_SENSOR,
	ADC_CHANNEL_POTENTIOMETER
};
#endif


/** Global timestamp in milliseconds since start of application */
static volatile uint32_t gs_ul_ms_ticks = 0;


/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
	#endif
	/**INDENT-ON**/
	/// @endcond




#if SAM3XA 
static uint32_t adc_read_buffer(Adc * p_adc, uint16_t * p_s_buffer, uint32_t ul_size)
{
	/* Check if the first PDC bank is free. */
	if ((p_adc->
ADC_RCR == 0) && (p_adc->
ADC_RNCR == 0)) {
		p_adc->
ADC_RPR = (uint32_t) p_s_buffer;
		p_adc->
ADC_RCR = ul_size;
		p_adc->
ADC_PTCR = ADC_PTCR_RXTEN;

		return 1;
	} else {	/* Check if the second PDC bank is free. */
		if (p_adc->
ADC_RNCR == 0) {
			p_adc->
ADC_RNPR = (uint32_t) p_s_buffer;
			p_adc->
ADC_RNCR = ul_size;

			return 1;
		} else {
			return 0;
		}
	}
}

#endif

/**
 * \brief Start ADC sample.
 * Initialize ADC, set clock and timing, and set ADC to given mode.
 */
static void start_adc(void)
{
	/* Enable peripheral clock. */
#if  SAM3XA
	//uint32_t i;
	pmc_enable_periph_clk(ID_ADC);
#endif

	/* Initialize ADC. */
	/*
	 * Formula: ADCClock = MCK / ( (PRESCAL+1) * 2 )
	 * For example, MCK = 64MHZ, PRESCAL = 4, then:
	 * ADCClock = 64 / ((4+1) * 2) = 6.4MHz;
	 */
#if SAM3XA 
	/* Formula:
	 *     Startup  Time = startup value / ADCClock
	 *     Startup time = 64 / 6.4MHz = 10 us
	 */
	adc_init(ADC, sysclk_get_cpu_hz(), 6400000, ADC_STARTUP_TIME_4);

#endif

	memset((void *)&g_adc_sample_data, 0, sizeof(g_adc_sample_data));

	/* Set ADC timing. */
#if SAM3XA 
	/* Formula:
	 *     Transfer Time = (TRANSFER * 2 + 3) / ADCClock
	 *     Tracking Time = (TRACKTIM + 1) / ADCClock
	 *     Settling Time = settling value / ADCClock
	 *
	 *     Transfer Time = (1 * 2 + 3) / 6.4MHz = 781 ns
	 *     Tracking Time = (1 + 1) / 6.4MHz = 312 ns
	 *     Settling Time = 3 / 6.4MHz = 469 ns
	 */
	adc_configure_timing(ADC, TRACKING_TIME, ADC_SETTLING_TIME_3, TRANSFER_PERIOD);

#endif

#if SAM3XA
	/* Enable channel number tag. */
	adc_enable_tag(ADC);
	/* Enable/disable sequencer. */
	//if (g_adc_test_mode.uc_sequence_en) {
		/* Set user defined channel sequence. */
		//adc_configure_sequence(ADC, ch_list, 2);

		/* Enable sequencer. */
		//adc_start_sequencer(ADC);

		/* Enable channels. */
		//for (i = 0; i < 1; i++) {
		//	adc_enable_channel(ADC, (enum adc_channel_num_t)i);
		//}
		/* Update channel number. */
		g_adc_sample_data.uc_ch_num[0] = ch_list[0];
		g_adc_sample_data.uc_ch_num[1] = ch_list[1];
	//} else {
		/* Disable sequencer. */
		//adc_stop_sequencer(ADC);

		/* Enable channels. */
		adc_enable_channel(ADC, ADC_CHANNEL_POTENTIOMETER);
// #if SAM3XA
// 		adc_enable_channel(ADC, ADC_TEMPERATURE_SENSOR);
// #endif
		/* Update channel number. */
		g_adc_sample_data.uc_ch_num[0] = ADC_CHANNEL_POTENTIOMETER;
// #if SAM3XA
// 		g_adc_sample_data.uc_ch_num[1] = ADC_TEMPERATURE_SENSOR;
// #else
// 		g_adc_sample_data.uc_ch_num[1] = ADC_CHANNEL_POTENTIOMETER;
 #endif
	//}

// #if SAM3XA 
// 	/* Enable the temperature sensor (CH15). */
// 	//adc_enable_ts(ADC);
// #endif
// 	/* Set gain and offset (only single ended mode used here). */
// #if SAM3XA
// 	adc_disable_anch(ADC);	/* Disable analog change. */
// #endif
	if (g_adc_test_mode.uc_gain_en) {
#if SAM3XA
		adc_enable_anch(ADC);
		/* gain = 2 */
		adc_set_channel_input_gain(ADC, ADC_CHANNEL_POTENTIOMETER, ADC_GAINVALUE_2);
#endif
// 	} else {
// #if SAM3S || SAM3XA || SAM4S
// 		/* gain = 1 */
// 		adc_set_channel_input_gain(ADC, ADC_CHANNEL_POTENTIOMETER, ADC_GAINVALUE_0);
// #elif SAM3U
// #ifdef ADC_12B
// 		adc12b_set_input_gain(ADC12B, ADC_GAINVALUE_0);
// #endif
//#endif
	}

	if (g_adc_test_mode.uc_offset_en) {
#if SAM3XA
		adc_enable_anch(ADC);
		adc_enable_channel_input_offset(ADC, ADC_CHANNEL_POTENTIOMETER);

#endif
	} else {
#if  SAM3XA
		adc_disable_channel_input_offset(ADC, ADC_CHANNEL_POTENTIOMETER);
#endif
	}
	

#if SAM3XA 
	/* Transfer with/without PDC. */
	if (g_adc_test_mode.uc_pdc_en) {
		adc_read_buffer(ADC, g_adc_sample_data.us_value, BUFFER_SIZE);
		/* Enable PDC channel interrupt. */
		adc_enable_interrupt(ADC, ADC_IER_RXBUFF);
	} else {
		/* Enable Data ready interrupt. */
		adc_enable_interrupt(ADC, ADC_IER_DRDY);
	}
	/* Enable ADC interrupt. */
	NVIC_EnableIRQ(ADC_IRQn);
	/*NVIC_SetPriority(ADC_IRQn,0);*/

#endif


	/* Configure trigger mode and start convention. */
	switch (g_adc_test_mode.uc_trigger_mode) {
	case TRIGGER_MODE_SOFTWARE:
#if SAM3XA 
         adc_configure_trigger(ADC, ADC_TRIG_SW, 0);	/* Disable hardware trigger. */

#endif
		break;
// 
	case TRIGGER_MODE_ADTRG:
#if SAM3XA
		gpio_configure_pin(PINS_ADC_TRIG, PINS_ADC_TRIG_FLAG);
		adc_configure_trigger(ADC, ADC_TRIG_EXT, 0);
#endif
		break;

#if SAM3XA 
	case TRIGGER_MODE_FREERUN:
		adc_configure_trigger(ADC, ADC_TRIG_SW, 1);
		break;
#endif
	default:
		break;
	}
}

/**
 * \brief Systick handler.
 */
void SysTick_Handler(void)
{
	gs_ul_ms_ticks++;
}

static void ProcessButtonEvt(uint8_t uc_button)
{
	if (uc_button == 0) {
		ioport_set_pin_level(LED0_GPIO, IOPORT_PIN_LEVEL_HIGH);
		g_b_led0_active = true;
		if (g_b_led0_active == true) {
			
			ioport_set_pin_level(LED0_GPIO, IOPORT_PIN_LEVEL_HIGH);
		}
	}
	
// 	else {
// 	
// 	g_b_led0_active = true;
// 	//if (g_b_led0_active == true) {
// 		
// 		//ioport_set_pin_level(LED0_GPIO, IOPORT_PIN_LEVEL_LOW);
//   }
 }

static void Button2_Handler(uint32_t id, uint32_t mask)
{
	if (PIN_PUSHBUTTON_2_ID == id && PIN_PUSHBUTTON_2_MASK == mask) {
	ProcessButtonEvt(0);
	g_b_led0_active = true;
	ioport_set_pin_level(LED0_GPIO, IOPORT_PIN_LEVEL_LOW);
	}
}

// static void Button1_Handler(uint32_t id, uint32_t mask)
// {
// 	if (PIN_PUSHBUTTON_1_ID == id && PIN_PUSHBUTTON_1_MASK == mask) {
// 		ProcessButtonEvt(1);
// 		//g_b_led0_active = true;
// 		//ioport_set_pin_level(LED0_GPIO, IOPORT_PIN_LEVEL_HIGH);
// 	}
// }

#if  SAM3XA 
/**
 * \brief Interrupt handler for the ADC.
 */
void ADC_Handler(void)
{
	uint32_t i;
	//uint32_t ul_temp;
	//uint8_t uc_ch_num;
   ioport_set_pin_level(LED1_GPIO, IOPORT_PIN_LEVEL_LOW);
    
 	/* With PDC transfer */
 	if (g_adc_test_mode.uc_pdc_en) {
 		
 		if ((adc_get_status(ADC) & ADC_ISR_RXBUFF) ==
 				ADC_ISR_RXBUFF) {
 			g_adc_sample_data.us_done = ADC_DONE_MASK;
 			adc_read_buffer(ADC, g_adc_sample_data.us_value, BUFFER_SIZE);
 			/* Only keep sample value, and discard channel number. */
 			for (i = 0; i < NUM_CHANNELS; i++) {
 				g_adc_sample_data.us_value[i] &= ADC_LCDR_LDATA_Msk;
 			}
 		}
 	} 
 
 ioport_set_pin_level(LED1_GPIO, IOPORT_PIN_LEVEL_HIGH);
}


#endif
/**
 *  Configure UART console.
 */
static void configure_console(void)
{
	const usart_serial_options_t uart_serial_options = {
		.baudrate = CONF_UART_BAUDRATE,
		.paritytype = CONF_UART_PARITY
	};

	/* Configure console UART. */
	sysclk_enable_peripheral_clock(CONSOLE_UART_ID);
	stdio_serial_init(CONF_UART, &uart_serial_options);
}



static void configure_buttons(void)
{
	
// 		/* Configure Pushbutton 1 */
// 			pmc_enable_periph_clk(PIN_PUSHBUTTON_1_ID);
// 			pio_set_debounce_filter(PIN_PUSHBUTTON_1_PIO, PIN_PUSHBUTTON_1_MASK, 10);
// 			/* Interrupt on rising edge  */
// 			pio_handler_set(PIN_PUSHBUTTON_1_PIO, PIN_PUSHBUTTON_1_ID,
// 			PIN_PUSHBUTTON_1_MASK, PIN_PUSHBUTTON_1_ATTR, Button1_Handler);
// 			NVIC_EnableIRQ((IRQn_Type) PIN_PUSHBUTTON_1_ID);
// 			pio_handler_set_priority(PIN_PUSHBUTTON_1_PIO,
// 			(IRQn_Type) PIN_PUSHBUTTON_1_ID, IRQ_PRIOR_PIO);
// 			pio_enable_interrupt(PIN_PUSHBUTTON_1_PIO, PIN_PUSHBUTTON_1_MASK);
		
	#ifndef BOARD_NO_PUSHBUTTON_2
	
			/* Configure Pushbutton 2 */
		pmc_enable_periph_clk(PIN_PUSHBUTTON_2_ID);
		pio_set_debounce_filter(PIN_PUSHBUTTON_2_PIO, PIN_PUSHBUTTON_2_MASK, 10);
			// 	/* Interrupt on falling edge */
			pio_handler_set(PIN_PUSHBUTTON_2_PIO, PIN_PUSHBUTTON_2_ID,
			PIN_PUSHBUTTON_2_MASK, PIN_PUSHBUTTON_2_ATTR, Button2_Handler);
			NVIC_EnableIRQ((IRQn_Type) PIN_PUSHBUTTON_2_ID);
		//NVIC_SetPriority((IRQn_Type) PIN_PUSHBUTTON_2_ID,1);
		pio_handler_set_priority(PIN_PUSHBUTTON_2_PIO,
		(IRQn_Type) PIN_PUSHBUTTON_2_ID, IRQ_PRIOR_PIO);
		pio_enable_interrupt(PIN_PUSHBUTTON_2_PIO, PIN_PUSHBUTTON_2_MASK);
		 #endif
}


/**
 *  Wait for the given number of milliseconds (using the dwTimeStamp generated
 *  by the SAM microcontrollers' system tick).
 *  \param ul_dly_ticks  Delay to wait for, in milliseconds.
 */
static void mdelay(uint32_t ul_dly_ticks)
{
	uint32_t ul_cur_ticks;
    ul_cur_ticks = gs_ul_ms_ticks;
	while ((gs_ul_ms_ticks - ul_cur_ticks) < ul_dly_ticks);
}


/**
 *  \brief adc12 Application entry point.
 *
 *  \return Unused (ANSI-C compatibility).
 */
int main(void)
{
	    uint8_t key;
		uint32_t bufcnt,col;
		uint32_t buffer[1][127];
		uint32_t i;	
				
		//struct genclk_config gcfg;
	
		/* Initialize the SAM system. */
		sysclk_init();
		board_init();

		WDT->
WDT_MR = WDT_MR_WDDIS;

		configure_console();
		
		/* Output example information. */
		puts(STRING_HEADER);

		puts("Configure system tick to get 1ms tick period.\r");
		if (SysTick_Config(sysclk_get_cpu_hz() / 1000)) {
			puts("-F- Systick configuration error\r");
			while (1);
		}

	
	/* Set default ADC test mode. */
	memset((void *)&g_adc_test_mode, 0, sizeof(g_adc_test_mode));
	
	/*set default Analog_DataBuffer.*/ 
	memset(buffer, 0, sizeof(buffer[1][127]) * 1 * 127);
	
	g_adc_test_mode.uc_trigger_mode = TRIGGER_MODE_ADTRG;
	//g_adc_test_mode.uc_trigger_mode = TRIGGER_MODE_FREERUN;
	g_adc_test_mode.uc_pdc_en = 1;
	g_adc_test_mode.uc_sequence_en = 0;
	g_adc_test_mode.uc_gain_en = 0;
	g_adc_test_mode.uc_offset_en = 0;
	
	
	configure_buttons();
    //adc_start(ADC);
   start_adc();
	printf("Analog to digital conversion Function Started.\r");	
	
 	while (1) { 
			
// scanf("%c", (char *)&key);
// 
//     if(key == 'h')
// 	{
		    
 	   //Wait till the Stick Rising Edge//
 	   while (g_b_led0_active == false);		
 	     if (g_b_led0_active == true) {
	          pio_disable_interrupt(PIN_PUSHBUTTON_2_PIO, PIN_PUSHBUTTON_2_MASK);
		 	  	
		 	   
         for(col = 0;col<1;col++){
 		 	for(bufcnt = 0; bufcnt < 127 ; bufcnt++){
	 		 	
	 		 if(g_adc_sample_data.us_done == ADC_DONE_MASK){ 
		 	buffer[col][bufcnt] = g_adc_sample_data.us_value[i];
	 		 	}
				
				g_adc_sample_data.us_done = 0;
	 		 }
	       }
		 		//Clear the bit //
		 		g_b_led0_active = false;
		 	adc_stop(ADC);
		 	//pio_enable_interrupt(PIN_PUSHBUTTON_2_PIO, PIN_PUSHBUTTON_2_MASK);
		   }
	/*	key = 0;   */
		
    printf("Digital data of Ccd :\r");
  for(col = 0;col<1;col++){
    for (bufcnt = 0; bufcnt < 127 ; bufcnt++) {
	    printf("buf[%d]= %d ",(int)bufcnt,(int)buffer[col][bufcnt]);
    }
  }
    printf("\n");
	
    }
 }



/// @cond 0
/**INDENT-OFF**/
#ifdef  __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond
Fri Jan 17 2014, 10:10 pm
#5
This code is too complicated to spot a bug (for me anyway ).
Can you write, test and post a complete code that takes one sample and prints it.
We can go from there.

 pravin_35 like this.
Fri Jan 17 2014, 10:44 pm
#6


This code is too complicated to spot a bug (for me anyway ).
Can you write, test and post a complete code that takes one sample and prints it.
We can go from there.

ExperimenterUK



Thanks for your Reply Experiment UK..
Actually i have edited the code as for my application.... the above code i took from Examples Which has been done Effectively..

i have already tested the above code is not printing the any value Except buf[0][0] .. The above code is single Sample ... which every time i press Reset button to Execute and print in serial port...
please check the output below... image





Sun Jan 19 2014, 11:22 am
#7
ok the basic question, is ADC faster enough to take samples back to back. and Can you share sensor datasheet? coz by just looking at that timing diagram its hard to understand the operation. also I suggest you to use freerun mode of ADC and trigger via software by monitoring SI pin. It will be much better control.
Sun Jan 19 2014, 09:25 pm
#8


ok the basic question, is ADC faster enough to take samples back to back. and Can you share sensor datasheet? coz by just looking at that timing diagram its hard to understand the operation. also I suggest you to use freerun mode of ADC and trigger via software by monitoring SI pin. It will be much better control.

Ajay Bhargav



PFA of datasheet ,..

ajay does freerun works for this logic . i need to take all 128 sample between SI with reference to clock ..and load it to the buffer.
Sun Jan 19 2014, 09:25 pm
#9


ok the basic question, is ADC faster enough to take samples back to back. and Can you share sensor datasheet? coz by just looking at that timing diagram its hard to understand the operation. also I suggest you to use freerun mode of ADC and trigger via software by monitoring SI pin. It will be much better control.

Ajay Bhargav



i know what i required but still i am struggling with code implementation!!
i think processor is sufficient acquire data and process..


[ Edited Mon Jan 20 2014, 11:05 am ]
Tue Jan 21 2014, 11:28 pm
#10
Now things are more clear..
1. How you are supplying clock, processor or external?
2. What is clock frequency?
3. ADC tested?

If you have tested your ADC then it will be much easier to do this.

PS: using it for finger print scanning?

Get Social

Information

Powered by e107 Forum System

Downloads

Comments

carpinteyrowrl
Fri Apr 19 2024, 02:51 pm
DonaldJAX
Fri Apr 19 2024, 01:08 pm
Lewisuhakeply
Thu Apr 18 2024, 06:00 pm
Darrellciz
Thu Apr 18 2024, 11:07 am
Charlessber
Thu Apr 18 2024, 09:29 am
BartonSem
Thu Apr 18 2024, 04:56 am
DonaldKnown
Thu Apr 18 2024, 12:24 am
utaletxcyw
Wed Apr 17 2024, 10:21 am