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

📄 main.c

📁 AT91SAM9261相关源程序
💻 C
字号:
/* ----------------------------------------------------------------------------
 *         ATMEL Microcontroller Software Support  -  ROUSSET  -
 * ----------------------------------------------------------------------------
 * Copyright (c) 2006, Atmel Corporation
 *
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the disclaiimer below.
 * 
 * - Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the disclaimer below in the documentation and/or
 * other materials provided with the distribution. 
 * 
 * Atmel's name may not be used to endorse or promote products derived from
 * this software without specific prior written permission. 
 * 
 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * ----------------------------------------------------------------------------
 */
/*-----------------------------------------------------------------------------
 *  File Name           : main.c
 *  Object              : main file
 *  Creation            : FDy   10-Nov-2006
 *-----------------------------------------------------------------------------
 */

/* Include Standard files */
#include "project.h"

/* Global variables */
#define LED_A    AT91B_LED1
#define LED_B    AT91B_LED2 
#define BUTTON_A AT91B_BP3
#define BUTTON_B AT91B_BP4

/* The following global variables, control the LED blinking */
unsigned long led_a_active = 1;
unsigned long led_b_active = 1;
volatile unsigned long jiffies = 0;


/*-----------------------------------------------------------------------------
 * Function Name       : pitc_handler
 * Object              : Handler for PITC interrupt
 *-----------------------------------------------------------------------------*/
void pitc_handler(void)
{
  volatile unsigned long pivr = 0;
  volatile unsigned long pisr = 0;

  /* Read the PISR */
  pisr = AT91C_BASE_PITC->PITC_PISR & AT91C_PITC_PITS;
  if (pisr != 0) {
    /* Read the PIVR. It acknowledges the IT */
    pivr = AT91C_BASE_PITC->PITC_PIVR;  

    /* Add to jiffies PICNT: the number of occurrences of periodic intervals  */
    /* since the last read of PIT_PIVR */
    jiffies += (pivr >> 20);
  }
}


/*-----------------------------------------------------------------------------
 * Function Name       : configure_pit
 * Object              : Configure priodic interval timer 
 *-----------------------------------------------------------------------------*/
static void configure_pit(void)
{
  volatile unsigned long pimr = 0;

  /* Configure a resolution of 1 ms */
  AT91C_BASE_PITC->PITC_PIMR = AT91B_MCK / (16 * 1000) - 1;

  /* Enable interrupts */
  /* Disable the interrupt on the interrupt controller */
  AT91C_BASE_AIC->AIC_IDCR = (1 << AT91C_ID_SYS);

  /* Save the interrupt handler routine pointer and the interrupt priority */
  AT91C_BASE_AIC->AIC_SVR[AT91C_ID_SYS] = (unsigned long) pitc_handler;
  /* Store the Source Mode Register */
  AT91C_BASE_AIC->AIC_SMR[AT91C_ID_SYS] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | AT91C_AIC_PRIOR_LOWEST;
  /* Clear the interrupt on the interrupt controller */
  AT91C_BASE_AIC->AIC_ICCR = (1 << AT91C_ID_SYS);

  /* Enable the interrupt on the interrupt controller */
  AT91C_BASE_AIC->AIC_IECR = (1 << AT91C_ID_SYS);

  /* Enable the interrupt on the pit */
  pimr = AT91C_BASE_PITC->PITC_PIMR;
  AT91C_BASE_PITC->PITC_PIMR = pimr | AT91C_PITC_PITIEN;

  /* Enable the pit */
  pimr = AT91C_BASE_PITC->PITC_PIMR;
  AT91C_BASE_PITC->PITC_PIMR = pimr | AT91C_PITC_PITEN;
}


/*-----------------------------------------------------------------------------
 * Function Name       : button_handler
 * Object              : Button Interrupt Service Routine (PIO A)
 *-----------------------------------------------------------------------------*/
void button_handler(void)
{
  /* Read the Interrupt Status register (It acknowledge the IT)  */
  volatile unsigned long pio_isr = AT91C_BASE_PIOA->PIO_ISR;
  volatile unsigned long pio_pdsr = AT91C_BASE_PIOA->PIO_PDSR;
   
  /* If the BUTTON_A has been pushed or released */
  if (pio_isr & BUTTON_A) {
    /* Enable/disable the LED A blinking when BUTTON_A is released */
    if (pio_pdsr & BUTTON_A)
      led_a_active = !led_a_active;
  }
  /* If the BUTTON_B has been pushed or released */
  else if (pio_isr & BUTTON_B) {
    /* Enable/disable the LED B blinking when BUTTON_B is pushed */
    if ( !(pio_pdsr & BUTTON_B) ) {
      if (led_b_active) {
        /* Disable the clock */
        AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
      } else {
        /* Clock is started */
        AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN;
        /* Counter is reset and the clock is started */
        AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
      }
      led_b_active = !led_b_active;
    }
  }
  
  /* The else should not be executed since no other PIO are enabled  */
  else { }
}


/*-----------------------------------------------------------------------------
 * Function Name       : configure_buttons
 * Object              : Configure pios to capture buttons state 
 *-----------------------------------------------------------------------------*/
static void configure_buttons(void)
{   
  /* Enable the periph clock for the PIO controller */
  /* This is mandatory when PIO are configured as input */
  AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOA);

  /* Set the PIO line in input */
  AT91C_BASE_PIOA->PIO_ODR = (BUTTON_A | BUTTON_B);
  
  /* Set the PIO controller in PIO mode instead of peripheral mode */
  AT91C_BASE_PIOA->PIO_PER = (BUTTON_A | BUTTON_B);

  /* Disable the interrupt on the interrupt controller */
  AT91C_BASE_AIC->AIC_IDCR = (1 << AT91C_ID_PIOA);
  
  /* Save the interrupt handler routine pointer and the interrupt priority */
  AT91C_BASE_AIC->AIC_SVR[AT91C_ID_PIOA] = (unsigned long) button_handler;
  
  /* Store the Source Mode Register */
  AT91C_BASE_AIC->AIC_SMR[AT91C_ID_PIOA] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | AT91C_AIC_PRIOR_LOWEST;
  
  /* Clear the interrupt on the interrupt controller */
  AT91C_BASE_AIC->AIC_ICCR = (1 << AT91C_ID_PIOA);

  /* Enable button interrupts generation through the PIO controller */
  AT91C_BASE_PIOA->PIO_IER = (BUTTON_A | BUTTON_B);

  /* Enable PIO interrupt in the interrupt controller */
  AT91C_BASE_AIC->AIC_IECR = (1 << AT91C_ID_PIOA);
}


/*-----------------------------------------------------------------------------
 * Function Name       : configure_leds
 * Object              : Configure pios to control led states
 *-----------------------------------------------------------------------------*/
static void configure_leds(void)
{
  /* Configure the pin in output */
  AT91C_BASE_PIOA->PIO_OER = (LED_A | LED_B);
  /* Set the PIO controller in PIO mode instead of peripheral mode */
  AT91C_BASE_PIOA->PIO_PER = (LED_A | LED_B);
  /* Disable pull-up */
  AT91C_BASE_PIOA->PIO_PPUDR = (LED_A | LED_B);

  /* Set the default state for the led */
  if (led_a_active)
    AT91C_BASE_PIOA->PIO_SODR = LED_A;
  else
    AT91C_BASE_PIOA->PIO_CODR = LED_A;

  if (led_b_active)
    AT91C_BASE_PIOA->PIO_SODR = LED_B;
  else
    AT91C_BASE_PIOA->PIO_CODR = LED_B;
}


/*-----------------------------------------------------------------------------
 * Function Name       : timer_handler
 * Object              : Handler for TC interrupt
 *-----------------------------------------------------------------------------*/
void timer_handler(void)
{
  volatile unsigned long dummy;
  /* Clear status bit */
  dummy = AT91C_BASE_TC0->TC_SR;
  
  /* Toggle LED state */
  if (AT91C_BASE_PIOA->PIO_ODSR & LED_B) {
    AT91C_BASE_PIOA->PIO_CODR = LED_B;
  } else {
    AT91C_BASE_PIOA->PIO_SODR = LED_B;
  }
}


/*-----------------------------------------------------------------------------
 * Function Name       : configure_tc
 * Object              : Configure TC
 *-----------------------------------------------------------------------------*/
static void configure_tc(void)
{
    volatile unsigned long dummy;

    /* Enable periph clock for the PIO controller */
    AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0);

    /* Enable the periph */
    /* Disable the clock and the interrupts */
    AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
    AT91C_BASE_TC0->TC_IDR = 0xFFFFFFFF;

    /* Clear status bit */
    dummy = AT91C_BASE_TC0->TC_SR;

    /* Set the Mode of the Timer Counter */
    AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV5_CLOCK | AT91C_TC_CPCTRG;
    AT91C_BASE_TC0->TC_RC = AT91B_SLOW_CLOCK >> 2;  /* SLOW_CLOCK divided by 4 */

    /* Enable interrupts */
    /* Disable the interrupt on the interrupt controller */
    AT91C_BASE_AIC->AIC_IDCR = (1 << AT91C_ID_TC0);
    /* Save the interrupt handler routine pointer and the interrupt priority */
    AT91C_BASE_AIC->AIC_SVR[AT91C_ID_TC0] = (unsigned long) timer_handler;
    /* Store the Source Mode Register */
    AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC0] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | AT91C_AIC_PRIOR_LOWEST;
    /* Clear the interrupt on the interrupt controller */
    AT91C_BASE_AIC->AIC_ICCR = (1 << AT91C_ID_TC0);

    AT91C_BASE_TC0->TC_IER = AT91C_TC_CPCS;

    /* Enable the interrupt on the interrupt controller */
    AT91C_BASE_AIC->AIC_IECR = (1 << AT91C_ID_TC0);
}


/*----------------------------------------------------------------------------
 * Function Name       : dbgu_printk
 * Object              : This function is used to send a string through the
 *                       DBGU channel (Very low level debugging)
 *----------------------------------------------------------------------------*/
void dbgu_printk(char *buffer)
{
    while (*buffer != '\0') {
        while (!(AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXRDY));
	AT91C_BASE_DBGU->DBGU_THR = (*buffer++ & 0x1FF);
    }
}


/*-----------------------------------------------------------------------------
 * Function Name       : dbgu_init
 * Object              : Configure DBGU
 *-----------------------------------------------------------------------------*/
static void dbgu_init (void)
{
    /* Reset and disable receiver */
    AT91C_BASE_DBGU->DBGU_CR = AT91C_US_RSTRX | AT91C_US_RSTTX;

    /* Disable interrupts */
    AT91C_BASE_DBGU->DBGU_IDR = 0xFFFFFFFF;

    /* Configure PIOs for DBGU */
    AT91C_BASE_PIOA->PIO_ASR = AT91C_PA9_DRXD | AT91C_PA10_DTXD;
    AT91C_BASE_PIOA->PIO_BSR = 0;
    AT91C_BASE_PIOA->PIO_PDR = AT91C_PA9_DRXD | AT91C_PA10_DTXD;

    /* === Configure serial link === */
    /* Define the baud rate divisor register [BRGR = MCK / (115200 * 16)] */
    AT91C_BASE_DBGU->DBGU_BRGR = 54;
    /* Define the USART mode */
    AT91C_BASE_DBGU->DBGU_MR = AT91C_US_CHMODE_NORMAL;

    /* Disable the RX and TX PDC transfer requests */
    AT91C_BASE_DBGU->DBGU_PTCR = AT91C_PDC_RXTDIS;
    AT91C_BASE_DBGU->DBGU_PTCR = AT91C_PDC_TXTDIS;

    /* Enable transmitter */
    AT91C_BASE_DBGU->DBGU_CR = AT91C_US_TXEN;
}

/*-----------------------------------------------------------------------------
 * Function Name       : wait
 * Object              : Tempo using jiffies (updated by PITC)
 *-----------------------------------------------------------------------------*/
void wait (unsigned long ms)
{
  volatile unsigned long current_time = jiffies;
  volatile unsigned long prev_jiffies;
  volatile unsigned long target_time = current_time + ms;

  // Handle the counter overflow
  if (target_time < current_time) {
    prev_jiffies = current_time;
    while (prev_jiffies <= jiffies)
      prev_jiffies = jiffies;
  }
  // Loop until the target time is reached
  while (jiffies < target_time);
}


/*-----------------------------------------------------------------------------
 * Function Name       : Main
 * Object              : Software entry point
 *-----------------------------------------------------------------------------*/
int main()
{
  /* ==== PITC configuration ==== */
  configure_pit();

  /* ==== TIMER configuration ==== */
  configure_tc();

  /* === BUTTON configuration === */
  configure_buttons();

  /* === LED configuration === */
  configure_leds();

  /* ==== DBGU configuration ==== */
  dbgu_init();

  dbgu_printk("AT91SAM9261 Getting Started program launched ...\n\r");

  while (1) {    
    if (led_a_active) {
      /* Switch on the led */
      wait(500);
      AT91C_BASE_PIOA->PIO_CODR = LED_A;

       /* Switch off the led */
      wait(500);
      AT91C_BASE_PIOA->PIO_SODR = LED_A;
    }
  }
}

⌨️ 快捷键说明

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