AT91SAM7X-EK Port I/O

From Nutwiki
Revision as of 17:02, 27 October 2016 by Harald (Talk | contribs) (1 revision imported)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Switching LED 1 On and Off

LED 1 is connected to Bit 19 on Port B. To switch the LED on, we must configure this port bit for output and then set the output to low.

<source lang="c"> void Led1On(void) {

   outr(PIOB_OER, _BV(19));
   outr(PIOB_CODR, _BV(19));

} </source>

Setting bit 19 at Port B to high will switch off the LED.

<source lang="c"> void Led1Off(void) {

   outr(PIOB_OER, _BV(19));
   outr(PIOB_SODR, _BV(19));

} </source>

Blinking LED 1

We can use the routines Led1On() and Led1Off with the NutSleep() API to implement a blinking LED.

<source lang="c">

  1. include <sys/timer.h>

int main(void) {

   int i;
   for (;;) {
       Led1On();
       NutSleep(500);
       Led1Off();
       NutSleep(500);
   }

} </source>

Switching LEDs 2, 3 and 4

Here are the routines for the remaining LEDs 2 to 4:

<source lang="c"> void Led2On(void) {

   outr(PIOB_OER, _BV(20));
   outr(PIOB_CODR, _BV(20));

}

void Led2Off(void) {

   outr(PIOB_OER, _BV(20));
   outr(PIOB_SODR, _BV(20));

}

void Led3On(void) {

   outr(PIOB_OER, _BV(21));
   outr(PIOB_CODR, _BV(21));

}

void Led3Off(void) {

   outr(PIOB_OER, _BV(21));
   outr(PIOB_SODR, _BV(21));

}

void Led4On(void) {

   outr(PIOB_OER, _BV(22));
   outr(PIOB_CODR, _BV(22));

}

void Led4Off(void) {

   outr(PIOB_OER, _BV(22));
   outr(PIOB_SODR, _BV(22));

} </source>

Reading the Joystick

The joystick is connected to bits 21 to 25 at Port A. When using a port for input, it is required to enable the clock for this port.

When a joystick contact is closed, it will connect the related port bit to ground. Otherwise the port bit will be floating. We can avoid the floating status by enabling the internal pull-up resistor.

<source lang="c"> void JoystickInit(void) {

   outr(PMC_PCER, _BV(PIOA_ID));
   outr(PIOA_ODR, _BV(21) | _BV(22) | _BV(23) | _BV(24) | _BV(25));
   outr(PIOA_PUER, _BV(21) | _BV(22) | _BV(23) | _BV(24) | _BV(25));

} </source>

The following routine will return zero, if the joystick is in idle state. Otherwise 1, 2, 3, 4 or 5 is returned, depending on the contact that is currently closed.

<source lang="c"> int JoystickRead(void) {

   int rc;
   u_int pin;
   pin = inr(PIOA_PDSR);
   if ((pin & _BV(21)) == 0) {
       rc = 1;
   }
   else if ((pin & _BV(22)) == 0) {
       rc = 2;
   }
   else if ((pin & _BV(23)) == 0) {
       rc = 3;
   }
   else if ((pin & _BV(24)) == 0) {
       rc = 4;
   }
   else if ((pin & _BV(25)) == 0) {
       rc = 5;
   }
   else {
       rc = 0;
   }
   return rc;

} </source>

LED Control via Joystick

The following application connects the four LEDs with the four joystick directions:

<source lang="c">

  1. include <compiler.h>

int main(void) {

   int s;
   for (;;) {
       s = JoystickRead();
       if (s == 1) {
           Led1On();
       }
       else if (s == 2) {
           Led2On();
       }
       else if (s == 3) {
           Led3On();
       }
       else if (s == 4) {
           Led4On();
       }
       else if (s == 5) {
           Led1On();
           Led2On();
           Led3On();
           Led4On();
       }
       else {
           Led1Off();
           Led2Off();
           Led3Off();
           Led4Off();
       }
   }

} </source>

Joystick Interrupts

Enabling joystick interrupts.

<source lang="c">

  1. include <dev/irqreg.h>

void JoystickIsrEnable(void) {

   NutRegisterIrqHandler(&sig_PIOA, JoystickIsr, NULL);
   outr(PIOA_IER, _BV(21) | _BV(22) | _BV(23) | _BV(24) | _BV(25));
   NutIrqEnable(&sig_PIOA);

} </source>

Joystick interrupt service routine.

<source lang="c"> void JoystickIsr(void *arg) {

   u_int s = inr(PIOA_ISR);
   if (s & _BV(21)) {
       Led1On();
   }
   if (s & _BV(22)) {
       Led2On();
   }
   if (s & _BV(23)) {
       Led3On();
   }
   if (s & _BV(24)) {
       Led4On();
   }
   if (s & _BV(25)) {
       Led1Off();
       Led2Off();
       Led3Off();
       Led4Off();
   }

} </source>

Upto Nut/OS 4.5.4 there is a bug in the configuration files. The "Interrupt Handler (SAM7X)" lists the wrong PIO interrupt handler. Replace the following part in conf/arch/arm.nut and rebuild Nut/OS.

<source lang="lua">

   {
       name = "nutarch_arm_irqat91sam7x",
       brief = "Interrupt Handler (SAM7X)",
       requires = { "HW_MCU_AT91SAM7X" },
       provides = { "DEV_IRQ_AT91" },
       sources =
       {
           "arm/dev/ih_at91fiq.c",
           "arm/dev/ih_at91sys.c",
           "arm/dev/ih_at91irq0.c",
           "arm/dev/ih_at91irq1.c",
           "arm/dev/ih_at91irq2.c",
           "arm/dev/ih_at91pioa.c",
           "arm/dev/ih_at91piob.c",
           "arm/dev/ih_at91pioc.c",
           "arm/dev/ih_at91spi0.c",
           "arm/dev/ih_at91spi1.c",
           "arm/dev/ih_at91ssc.c",
           "arm/dev/ih_at91swirq.c",
           "arm/dev/ih_at91tc0.c",
           "arm/dev/ih_at91tc1.c",
           "arm/dev/ih_at91tc2.c",
           "arm/dev/ih_at91adc.c",
           "arm/dev/ih_at91twi.c",
           "arm/dev/ih_at91uart0.c",
           "arm/dev/ih_at91uart1.c",
           "arm/dev/ih_at91emac.c",
           "arm/dev/ih_at91wdi.c",
       },
   },

</source>


Complete Application Code

Here is a full application. It will first blink LED 1 for 10 times. Then the joystick is polled and the related LEDs are switched on and off until you push the joystick. Finally it will demonstrate joystick interrupt handling.

<source lang="c">

  1. include <dev/irqreg.h>
  2. include <sys/timer.h>

void Led1On(void) {

   outr(PIOB_OER, _BV(19));
   outr(PIOB_CODR, _BV(19));

}

void Led1Off(void) {

   outr(PIOB_OER, _BV(19));
   outr(PIOB_SODR, _BV(19));

}

void Led2On(void) {

   outr(PIOB_OER, _BV(20));
   outr(PIOB_CODR, _BV(20));

}

void Led2Off(void) {

   outr(PIOB_OER, _BV(20));
   outr(PIOB_SODR, _BV(20));

}

void Led3On(void) {

   outr(PIOB_OER, _BV(21));
   outr(PIOB_CODR, _BV(21));

}

void Led3Off(void) {

   outr(PIOB_OER, _BV(21));
   outr(PIOB_SODR, _BV(21));

}

void Led4On(void) {

   outr(PIOB_OER, _BV(22));
   outr(PIOB_CODR, _BV(22));

}

void Led4Off(void) {

   outr(PIOB_OER, _BV(22));
   outr(PIOB_SODR, _BV(22));

}

void JoystickInit(void) {

   outr(PMC_PCER, _BV(PIOA_ID));
   outr(PIOA_ODR, _BV(21) | _BV(22) | _BV(23) | _BV(24) | _BV(25));
   outr(PIOA_PUER, _BV(21) | _BV(22) | _BV(23) | _BV(24) | _BV(25));

}

int JoystickRead(void) {

   int rc;
   u_int pin;
   pin = inr(PIOA_PDSR);
   if ((pin & _BV(21)) == 0) {
       rc = 1;
   }
   else if ((pin & _BV(22)) == 0) {
       rc = 2;
   }
   else if ((pin & _BV(23)) == 0) {
       rc = 3;
   }
   else if ((pin & _BV(24)) == 0) {
       rc = 4;
   }
   else if ((pin & _BV(25)) == 0) {
       rc = 5;
   }
   else {
       rc = 0;
   }
   return rc;

}

void BlinkLed1(int n) {

   int i;
   for (i = 0; i < n; i++) {
       Led1On();
       NutSleep(500);
       Led1Off();
       NutSleep(500);
   }

}

void JoystickPolling(void) {

   int s;
   for (;;) {
       s = JoystickRead();
       if (s == 1) {
           Led1On();
       }
       else if (s == 2) {
           Led2On();
       }
       else if (s == 3) {
           Led3On();
       }
       else if (s == 4) {
           Led4On();
       }
       else if (s == 5) {
           Led1On();
           Led2On();
           Led3On();
           Led4On();
           break;
       }
       else {
           Led1Off();
           Led2Off();
           Led3Off();
           Led4Off();
       }
   }

}

void JoystickIsr(void *arg) {

   u_int s = inr(PIOA_ISR);
   if (s & _BV(21)) {
       Led1On();
   }
   if (s & _BV(22)) {
       Led2On();
   }
   if (s & _BV(23)) {
       Led3On();
   }
   if (s & _BV(24)) {
       Led4On();
   }
   if (s & _BV(25)) {
       Led1Off();
       Led2Off();
       Led3Off();
       Led4Off();
   }

}

void JoystickIsrEnable(void) {

   NutRegisterIrqHandler(&sig_PIOA, JoystickIsr, NULL);
   outr(PIOA_IER, _BV(21) | _BV(22) | _BV(23) | _BV(24) | _BV(25));
   NutIrqEnable(&sig_PIOA);

}

int main(void) {

   BlinkLed1(10);
   JoystickInit();
   JoystickPolling();
   JoystickIsrEnable();
   for (;;) {
       NutSleep(500);
   }

} </source>

See also