⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c~

📁 atmel at91SAM7a3 ADC sample
💻 C~
字号:
//*----------------------------------------------------------------------------
//* AT91SAM7S example application "gamma" (SWI, stdio, remapping...)
//*----------------------------------------------------------------------------
//* The software is delivered "AS IS" without warranty or condition of any
//* kind, either express, implied or statutory. This includes without
//* limitation any warranty or condition with respect to merchantability or
//* fitness for any particular purpose, or against the infringements of
//* intellectual property rights of others.
//*----------------------------------------------------------------------------
//* 
//* by Martin Thomas, Kaiserslautern, Germany
//*    http://www.siwawi.arubi.uni-kl.de/avr_projects
//*
//* partly based on free code from Atmel Rousset, Keil/ARM and others
//*
//*----------------------------------------------------------------------------

/* 
   20070211 : defining CUSTOM_PCB disables switches
			  -mods made to makefile, and renaming of files for SAM7A3
   20060902 : PIT ISR-Handler in RAM (__ramfunc),
*/

#include <stdint.h>
#include <stdio.h>

#include "Board.h"
#include "dbgu.h"
#include "swi.h"

/* Global variables */
#define SPEED 		(MCKKHz/10)
const int led_mask[8]= {LED1, LED2, LED3};

unsigned int LedSpeed = SPEED *50 ;



#define	SAMPLE			16


#define RTTC_INTERRUPT_LEVEL   0
#define PIV_200_MS             600000  //* 200 ms for 48 MHz

#define SWDEBOUNCE 2
volatile int sw1cnt, sw2cnt;
volatile unsigned long systick;



#define PWM_PRESCALE 1

// 5khz period for channel 0
#define PERIOD_CH0 1/5000

// 25% duty cycle for CH0
#define DUTY_CH0 1/4

// 10 kHz period for channel 1
#define PERIOD_CH1 1/10000

// 60% duty cycle for CH1
#define DUTY_CH1 6/10 

//*----------------------------------------------------------------------------
//* Function Name       : Periodic_Interval_Timer_handler
//* Object              : C handler interrupt function called by the interrupts
//*                       assembling routine
//*----------------------------------------------------------------------------
__ramfunc void Periodic_Interval_Timer_handler(void) 
{
	volatile uint32_t status;
	//volatile uint32_t ledOnCount;
	
	// Interrupt Acknowledge
	status = AT91C_BASE_PITC->PITC_PIVR;
	// status = status;
	
	systick++;
	
	//PRE_INJ2
	if ((AT91F_PIO_GetInput(AT91C_BASE_PIOB) & PRE_INJ2 ) == PRE_INJ2 ) {
		AT91F_PIO_ClearOutput( AT91C_BASE_PIOB, PRE_INJ2 );
	}
	else  { 
		AT91F_PIO_SetOutput( AT91C_BASE_PIOB, PRE_INJ2 );
	}
	#ifndef CUSTOM_PCB
	// detect switch-states
	if ( (AT91F_PIO_GetInput(AT91C_BASE_PIOA) & SW1_MASK ) != SW1_MASK ) {
		sw1cnt++;
	}
	else {
		sw1cnt=0;
	}
	if ( (AT91F_PIO_GetInput(AT91C_BASE_PIOA) & SW2_MASK ) != SW2_MASK ) {
		sw2cnt++;
	}
	else {
		sw2cnt=0;
	}
	#endif //CUSTOM_PCB
	
}

static void device_init(void)
{
	// Enable User Reset and set its minimal assertion to 960 us
	AT91C_BASE_RSTC->RSTC_RMR = AT91C_RSTC_URSTEN | (0x4<<8) | (unsigned int)(0xA5<<24);

	// Set-up the PIO
	// First, enable the clock of the PIO and set the LEDs in output
	AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, (1 << AT91C_ID_PIOA) | (1 << AT91C_ID_PIOB)) ;

	// then, we configure the PIO Lines corresponding to LED1 to LED4
	// to be outputs. No need to set these pins to be driven by the PIO because it is GPIO pins only.
	AT91F_PIO_CfgOutput( AT91C_BASE_PIOA, LED_MASK ) ;
	AT91F_PIO_CfgOutput( AT91C_BASE_PIOB, PIOB_MASK ) ;
	
	AT91F_PIO_SetOutput( AT91C_BASE_PIOA, LED_MASK ) ;

	AT91F_PIO_ClearOutput( AT91C_BASE_PIOB, PIOB_MASK ) ;


/////////////////PWM
AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1<<AT91C_ID_PWMC ); // Enable clock to peripheral
AT91F_PIO_CfgPeriph( AT91C_BASE_PIOA, AT91C_PA19_PWM1, 0); // Assign PIOs to PA0 and PA1
AT91F_PIO_CfgPeriph( AT91C_BASE_PIOA, AT91C_PA22_PWM4, 0);

AT91C_BASE_PWMC->PWMC_CH[4].PWMC_CMR = ( AT91C_PWMC_CALG | AT91C_PWMC_CPOL | \
PWM_PRESCALE ); // Center align, start high, CUPD=duty, prescale = 2
AT91C_BASE_PWMC->PWMC_CH[4].PWMC_CDTYR = ((MCK * PERIOD_CH0) / (2 * PWM_PRESCALE)) * DUTY_CH0;
AT91C_BASE_PWMC->PWMC_CH[4].PWMC_CPRDR = (MCK * PERIOD_CH0) / (2 * PWM_PRESCALE);

AT91C_BASE_PWMC->PWMC_CH[1].PWMC_CMR = ( AT91C_PWMC_CALG | AT91C_PWMC_CPOL | \
AT91C_PWMC_CPD | PWM_PRESCALE ); // Center align, start high, CUPD=period, prescale = 2
AT91C_BASE_PWMC->PWMC_CH[1].PWMC_CDTYR = ((MCK * PERIOD_CH1) / (2 * PWM_PRESCALE)) * DUTY_CH1;
AT91C_BASE_PWMC->PWMC_CH[1].PWMC_CPRDR = (MCK * PERIOD_CH1) / (2 * PWM_PRESCALE);

AT91C_BASE_PWMC->PWMC_ENA = AT91C_PWMC_CHID4;
AT91C_BASE_PWMC->PWMC_ENA = AT91C_PWMC_CHID1; 

	
//////////////////





	#ifndef CUSTOM_PCB
	// define switch SW1 and SW2 at PIO input
	AT91F_PIO_CfgInput(AT91C_BASE_PIOA, SW1_MASK|SW2_MASK);
	#endif //CUSTOM_PCB


	// Set-up PIT interrupt
	// AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_SYS, RTTC_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE, Periodic_Interval_Timer_handler);
	AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_SYS, RTTC_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE, (void*)Periodic_Interval_Timer_handler);
	AT91C_BASE_PITC->PITC_PIMR = AT91C_PITC_PITEN | AT91C_PITC_PITIEN | PIV_200_MS;  //  IRQ enable CPC
	AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_SYS);

	// Set-up DBGU Usart ("UART2")
	AT91F_DBGU_Init();
}

static void dump_mem(unsigned long startaddress, int n)
{
	volatile unsigned long *p;
	
	p = (unsigned long*)startaddress;
	int i;
	
	for (i=0; i<n; i++) {
		iprintf("Addr:0x%08lx = 0x%08lx (0x%04x:0x%04x)\n", 
			p, *p, (*p)>>16, (*p)&0xffff);
		p++;
	}
}

static void dump_interrupt_state(void)
{
	unsigned long cpsr;
	const unsigned long I_Bit = 0x80;
	const unsigned long F_Bit	= 0x40;
	
	cpsr = IntGetCPSR();
	
	iprintf("State : stat-reg 0x%08x -> ", cpsr);
	
	if ( cpsr & I_Bit ) {
		iprintf("IRQ disabled, ");
	}
	else {
		iprintf("IRQ enabled, ");
	}
	
	if ( cpsr & F_Bit ) {
		iprintf("FIQ disabled\n");
	}
	else {
		iprintf("FIQ enabled\n");
	}
}

static void showsp(void)
{
	unsigned long mysp;
	asm volatile ("mov %0, r13" : "=r" (mysp) );
	iprintf("SP = 0x%08lx\n", mysp);
}

static unsigned long gettick()
{
	unsigned long state, res;
	
	state = IntDisable();
	res = systick;
	IntRestore(state);
	
	return res;
}

static void test_tick(void)
{
	iprintf("Current systick %lu\n", gettick() );
}

//*--------------------------------------------------------------------------------------
//* Function Name       : wait
//* Object              : Software waiting loop
//* Input Parameters    : none. Waiting time is defined by the global variable LedSpeed.
//* Output Parameters   : none
//*--------------------------------------------------------------------------------------
static void wait ( void )
{//* Begin
    volatile unsigned int waiting_time ;
    for(waiting_time = 0; waiting_time < LedSpeed; waiting_time++) ;
}//* End

#define VREF  3                          /* number of records                     */
#define AT91C_ADC_PRESCAL_SHIFT 8        /* ADC Prescaler bit offset              */

AT91S_ADC * pADC = AT91C_BASE_ADC0;       /* Global Pointer to ADC                 */


int main(void)
{
	const int MAXMSG = 80;
	char message[MAXMSG];
	int drawmenu;
	unsigned long stored_int;
	unsigned long val;
	unsigned int  choice;


    unsigned int led_index ;
    char value;
	
	device_init(); // init interrupts and peripherals
	
	// example "puts" with dbgu.c-function
	AT91F_DBGU_Printk("\r\n\r\nAT91SAM7-Demo for the GNU-Toolchain\r\n");
	
	// example "puts" with siprintf formated string, the integer versions
	// of the newlib's printf need less memory but do not offer floating-
	// point support
	siprintf(message,"MCK clock frequency: %d Hz \r\n",MCK );
	AT91F_DBGU_Printk(message);
	
	stored_int = IntGetCPSR(); // save initial-state
	IntEnable();
	
	// example printf with "newlib" - the write-routine is
	// bound to the dbug-interface (see syscalls.c) so
	// (i)printf output goes to DBGU (uart2)
	iprintf("Demo created by Martin Thomas, Kaiserslautern, Germany\n\n");
	
	drawmenu = 1;

	// main-loop
        

	unsigned int adval;
	
	/* Enable peripheral clocks */
	*AT91C_PMC_PCER = (1<<AT91C_ID_ADC0);  /* enable ADC,                           */
		
	
	/* Setup the A/D converter */
	pADC->ADC_CR = AT91C_ADC_SWRST;        /* reset ADC                             */
	pADC->ADC_CHER = AT91C_ADC_CH0 | 
					AT91C_ADC_CH1
					|AT91C_ADC_CH2        /* enable ADC channels 0..3              */
					|AT91C_ADC_CH3;        /* enable ADC channels 0..3              */
	pADC->ADC_MR = AT91C_ADC_LOWRES_10_BIT |
			(9<<AT91C_ADC_PRESCAL_SHIFT); /* set 10-bit res., prescale = 9    */
	
	while (1)  {                                     /* loop forever                */
		
		pADC->ADC_CR = AT91C_ADC_START;                /* start ADC0 conversion       */
		//while ((pADC->ADC_SR & AT91C_ADC_EOC0) == 0);  /* wait for ADC0 conversion    */
		
		/* Read result of ADC conversion   */
		//AT91C_BASE_PWMC->PWMC_CH[4].PWMC_CDTYR = ((MCK * PERIOD_CH0) / (2 * PWM_PRESCALE)) * adval;

		if ( drawmenu ) {
			iprintf("** Test Menu **\n");
			iprintf("(1) Read ADC0\n");
			iprintf("(2) Read ADC1\n");
			iprintf("(3) Read ADC2\n");
			iprintf("(4) Read ADC3\n");
			iprintf("(5) Flash leds\n");
			iprintf("(6) ADC0->PWM4\n");
			iprintf("(7) PWM4->75%%\n");
			iprintf("(8) PWM4->25%%\n");
			iprintf("Select > ");
			drawmenu = 0;
		}
		else {
			iprintf("Select (0 shows menu) > ");
		}
		fflush(stdout);
		AT91F_DBGU_scanf("%i", &choice);
		iprintf("Selected %i\n\r", choice);

		switch (choice) {
		case 0 :
			drawmenu = 1;
			break;
		case 1 :
			/* Output 0-1023 AD0 value without using floating-point */
			while ((pADC->ADC_SR & AT91C_ADC_EOC0) == 0);
			adval = (unsigned int) pADC->ADC_CDR0 & AT91C_ADC_DATA;
			iprintf ("\n\rAD0 Output Value %4u = %01u.%04u Volts\n\r",
			(unsigned) adval,
			(unsigned) (adval * VREF) >> 10,                          /* Output Integer Portion */
			(unsigned) ((adval * VREF * 10000UL) >> 10UL) % 10000);   /* Output Decimal Portion */
			break;
		case 2 :
			while ((pADC->ADC_SR & AT91C_ADC_EOC1) == 0);
			adval = (unsigned int) pADC->ADC_CDR1 & AT91C_ADC_DATA;
			iprintf ("\n\rAD1 Output Value %4u = %01u.%04u Volts\n\r",
			(unsigned) adval,
			(unsigned) (adval * VREF) >> 10,                          /* Output Integer Portion */
			(unsigned) ((adval * VREF * 10000UL) >> 10UL) % 10000);   /* Output Decimal Portion */
			break;
		case 3 :
			while ((pADC->ADC_SR & AT91C_ADC_EOC2) == 0);
			adval = (unsigned int) pADC->ADC_CDR2 & AT91C_ADC_DATA;
			iprintf ("\n\rAD2 Output Value %4u = %01u.%04u Volts\n\r",
			(unsigned) adval,
			(unsigned) (adval * VREF) >> 10,                          /* Output Integer Portion */
			(unsigned) ((adval * VREF * 10000UL) >> 10UL) % 10000);   /* Output Decimal Portion */
			break;
		case 4 :
			while ((pADC->ADC_SR & AT91C_ADC_EOC3) == 0);
			adval = (unsigned int) pADC->ADC_CDR3 & AT91C_ADC_DATA;
			iprintf ("\n\rAD3 Output Value %4u = %01u.%04u Volts\n\r",
			(unsigned) adval,
			(unsigned) (adval * VREF) >> 10,                          /* Output Integer Portion */
			(unsigned) ((adval * VREF * 10000UL) >> 10UL) % 10000);   /* Output Decimal Portion */
			break;
		case 5 :
			// Once a Shot on each led		
			for ( int i=0 ; i < 3 ; i++ )
			{
				AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, led_mask[i]) ;
				wait();
				AT91F_PIO_SetOutput( AT91C_BASE_PIOA, led_mask[i] ) ;
				wait();
			}// End for
			// Once a Shot on each led
			for ( int i=(3-1) ; i >= 0 ; i-- )
			{
				AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, led_mask[i]) ;
				wait();
				AT91F_PIO_SetOutput( AT91C_BASE_PIOA, led_mask[i] ) ;
				wait();
			}
			break;
		case 6 :
			adval = (unsigned int) pADC->ADC_CDR0 & AT91C_ADC_DATA;
			iprintf ("\n\rAD0 Output Value %4u = %01u.%04u Volts\n\r",
			(unsigned) adval,
			(unsigned) (adval * VREF) >> 10,                          /* Output Integer Portion */
			(unsigned) ((adval * VREF * 10000UL) >> 10UL) % 10000);   /* Output Decimal Portion */

			AT91F_PWMC_StopChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID4);  // Disable PWM on channel 2 (PWM2 = PA25 = buzzer)
			while(AT91C_BASE_PWMC->PWMC_SR & AT91C_PWMC_CHID4); //wait for disabled
			AT91C_BASE_PWMC_CH4->PWMC_CPRDR = (MCK * PERIOD_CH0) / (2 * PWM_PRESCALE);                // Re-configure period
			AT91C_BASE_PWMC_CH4->PWMC_CDTYR = ((MCK * PERIOD_CH0) / (2 * PWM_PRESCALE)) * (adval/1024.0);             // Re-configure duty cycle
			AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID4); // Re-enable PWM on channel 2 (PWM2 = PA25 = 

			break;	
		case 7 :

			AT91F_PWMC_StopChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID4);  // Disable PWM on channel 2 (PWM2 = PA25 = buzzer)
			while(AT91C_BASE_PWMC->PWMC_SR & AT91C_PWMC_CHID4); //wait for disabled
			AT91C_BASE_PWMC_CH4->PWMC_CPRDR = (MCK * PERIOD_CH0) / (2 * PWM_PRESCALE);                // Re-configure period
			AT91C_BASE_PWMC_CH4->PWMC_CDTYR = ((MCK * PERIOD_CH0) / (2 * PWM_PRESCALE)) * 0.85;             // Re-configure duty cycle
			AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID4); // Re-enable PWM on channel 2 (PWM2 = PA25 = 

			break;
		case 8 :
			AT91F_PWMC_StopChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID4);  // Disable PWM on channel 2 (PWM2 = PA25 = buzzer)
			while(AT91C_BASE_PWMC->PWMC_SR & AT91C_PWMC_CHID4); //wait for disabled

			AT91C_BASE_PWMC_CH4->PWMC_CPRDR = (MCK * PERIOD_CH0) / (2 * PWM_PRESCALE);                // Re-configure period
			AT91C_BASE_PWMC_CH4->PWMC_CDTYR = ((MCK * PERIOD_CH0) / (2 * PWM_PRESCALE)) * 0.25;             // Re-configure duty cycle
			AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, AT91C_PWMC_CHID4); // Re-enable PWM on channel 2 (PWM2 = PA25 = buzzer)			
			break;
		default:
			iprintf("Invalid Choice\n\r");
			break;
		}	
	}
	return 0; /* never reached */
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -