📄 main.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 + -