SAM D10 Xplained Mini - 02 LED Rider

Zápisník experimentátora

Hierarchy: SAM D10 Xplained Mini

V tomto článku sa zameriame na vytvorenie animácie postupujúcich LED. Použijeme 8 LED diód a naučíme sa používať funkciu delay na pozastavenie činnosti programu na definovaný čas. Na animovanie diód použijeme digitálne piny v ľavej dolnej polovici obrázku, kde máme k dispozícii piny PA11 - PA31.

Delay

Túto funkciu poznáme z Arduina ako funkciu, ktorá zastaví beh programu na určitý počet milisekúnd. V IDE Atmel Studio sa nachádza podobná funkcia delay_ms. Aby sme ju ale mohli použiť, musíme ju do projektu dostať. Na to slúži ASF Wizard.

Po jeho zobrazení sa dá v zozname modulov nájsť modul Delay routines. Ten je treba nastaviť v projekte. Modul má dve možnosti nastavenia. Systick alebo cycle. Obe budú fungovať, líšia sa od seba iba internou implementáciou. Jedna používa meranie času podľa systémového timera a druhá ráta počet cyklov podľa známej hodnoty frekvencie hodín. Druhý spôsob vám môže byť povedomý, pretože takto sa ráta aj v klasickom Arduine.

Aby to ale fungovalo, je potrebné vo funkcii main zavolať funkciu delay_init(). Takto ale môžeme stále použiť iba funkciu delay_ms. Do dokonalosti to môžeme doviesť napríklad definíciou makra #define delay delay_ms, ktoré nám umožní použiť funkciu aj pod názvom delay.

Pretože túto dosku možno debuggovať, využite to a sledujte, čo sa bude diať vo vnútri funkcií delay_init() a delay() v prípade nastavenia systick alebo cycle.

Súbory

Podobne ako v predchádzajúcom projekte budú použité nasledovné súbory:

  • main.c - Hlavný program.
  • arduino.h - Deklarácie funkcií.
  • arduino.c - Telá funkcií.

main.c

Tu sa zmenila iba drobnosť. Pribudlo volanie funkcie delay_init(), ktoré inicializuje používanie funkcie delay().

#include <asf.h>
#include "arduino.h"

int main (void)
{
system_init();
delay_init();
rurInit();
while(1)
  rurLoop();
}

arduino.h

Tu pribudla funkcia digitalWrite, ktorá je obdobou tej z Arduina a makro delay.

#ifndef ARDUINO_H_
#define ARDUINO_H_

void rurInit(void);
void rurLoop(void);
bool isOnboardButton(void);
void digitalWriteOnboardLed(bool value);
void digitalWrite(int pin, bool value);
#define delay delay_ms

#endif /* ARDUINO_H_ */

arduino.c

Tu máme hlavný program. V poli led sú čísla pinov, ktoré budeme používať. Zaujímavý je pin PIN_PA27, ktorý chýba v hlavičkových súboroch. Ale rýchlym náhľadom do definícii pinov v súbore samd10d14am.h sa dalo uhádnuť, akú konštantu namiesto neho použiť. Je to zjavná chyba IDE 7.0.594 a v novších IDE bude pravdepodobne opravená.

Teraz už potrebujeme nastaviť všetky tieto piny ako výstupné a spôsob nastavenia je vidno vo funkcii rurInit(). Zo vzorového kódu možno pochopiť, ako sa konkrétny pin nastavuje ako výstupný.

Vo funkcii rurLoop() sa nastavuje výsledná animácia. Svieti jediná LED, ktorá sa pohybuje od jedného okraja k druhému,

#include <asf.h>
#include "arduino.h"

const int led[]={PIN_PA11,PIN_PA10,PIN_PA16,PIN_PA17,27/*PIN_PA27*/,PIN_PA25,PIN_PA30,PIN_PA31};
const int ledsize=sizeof(led)/sizeof(int);
int pos=0;
int dir=1;
#define spd 100

///
/// Local setup
///
void rurInit(void)
{
struct port_config pin_conf;
port_get_config_defaults(&pin_conf);
pin_conf.direction = PORT_PIN_DIR_OUTPUT;
for(int i=0;i<ledsize;i++)
  port_pin_set_config(led[i], &pin_conf);
}

///
/// Main loop
///
void rurLoop(void)
{
for(int i=0;i<ledsize;i++)
  {
  // simple moving LED
  digitalWrite(led[i], i==pos ? HIGH : LOW);
  }

pos+=dir;
if(pos==0)
  dir=1; // move to the right
if(pos==ledsize-1)
  dir=-1; // move to the left
delay(spd);
}

///
/// Onboard button
///
bool isOnboardButton(void)
{
return port_pin_get_input_level(BUTTON_0_PIN) == BUTTON_0_ACTIVE;
}

///
/// Onboard LED on/off
///
void digitalWriteOnboardLed(bool value)
{
port_pin_set_output_level(LED_0_PIN, value ? (LED_0_ACTIVE) : (!LED_0_ACTIVE));
}

///
/// Logical true/false on a pin
///
void digitalWrite(int pin, bool value)
{
port_pin_set_output_level(pin, value);
}

Video

Ukážku animácie LED si môžete pozrieť v sprievodnom videu.



Download

03.02.2016


Menu