wtorek, 8 listopada 2016

[3] ATXmega - Biblioteka HID, klawiatura

Ten post chciałbym poświęcić na uruchomienie układu ATXmega, pracującego jako klawiatura.

Inicjalizacja biblioteki:


Po przygotowaniu projektu dla wybranego mikrokontrolera. Bibliotekę wgrywa się poprzez asf (atmel software framework). Po wgraniu jest ona prawie w pełni gotowa do używania. Zostało już tylko odpowiednio włączyć zegary:



Włączenie zegarów:


Następnym elementem jest włączenie zegarów dla systemu oraz dla USB. Odnośnie zegara USB wspomniałem w poprzednim poście dla rodziny tych mikrokontrolerów.

  1. void USB_WLACZ_ZEGAR()
  2. {
  3.     //Wylaczenie przerwan
  4.     cli();
  5.    
  6.     //Konfiguracja DFLL z zegarem 48MHz
  7.     OSC.DFLLCTRL = OSC_RC32MCREF_USBSOF_gc;
  8.     NVM.CMD  = NVM_CMD_READ_CALIB_ROW_gc;
  9.     DFLLRC32M.CALB = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBRCOSC));
  10.     DFLLRC32M.COMP1 = 0x1B;
  11.     DFLLRC32M.COMP2 = 0xB7;
  12.     DFLLRC32M.CTRL = DFLL_ENABLE_bm;
  13.     //Modyfikacja zegarow
  14.     CPU_CCP = CCP_IOREG_gc; //Security Signature to modify clock
  15.     //Wlaczenie zegara 32MHz oraz 2MHz
  16.     OSC.CTRL = OSC_RC32MEN_bm | OSC_RC2MEN_bm; // enable internal 32MHz oscillator
  17.     //Odczekanie na wlaczenie zegara 32MHz
  18.     while(!(OSC.STATUS & OSC_RC32MRDY_bm));
  19.    
  20.     //Ustawienie PLL'a z zegara 2MHz (2MHz * 16)
  21.     OSC.PLLCTRL = OSC_PLLSRC_RC2M_gc | 16;
  22.     //Zezwolenie na modyfikacje zegarow
  23.     CPU_CCP = CCP_IOREG_gc;
  24.     //Wlaczenie petli PLL
  25.     OSC.CTRL = OSC_RC32MEN_bm | OSC_PLLEN_bm | OSC_RC2MEN_bm;
  26.    
  27.     //Odczekanie na gotowosc
  28.     while(!(OSC.STATUS & OSC_PLLRDY_bm));
  29.    
  30.     //Wlaczenie DFLL
  31.     DFLLRC2M.CTRL = DFLL_ENABLE_bm;
  32.    
  33.     //Wlaczenie przerwan
  34.     PMIC_CTRL = PMIC_HILVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm;
  35.     //Zezwolenie na modyfikacje
  36.     CPU_CCP = CCP_IOREG_gc;
  37.     //Wybranie PLL
  38.     CLK.CTRL = CLK_SCLKSEL_PLL_gc;
  39.     //Prescaler na 0
  40.     CLK.PSCTRL = 0x00;
  41.    
  42.     //Wlaczenie watchdoga 4kCycles, 4s przy 3.3V
  43.     //Dodatkowe ustawienia nie potrzebne dla USB
  44.     ccp_write_io((uint8_t *)&WDT.CTRL, (WDT_PER_4KCLK_gc | WDT_ENABLE_bm | WDT_CEN_bm));
  45.     //Zezwolenie na mapowanie EEPROMU
  46.     NVM_CTRLB = NVM_EEMAPEN_bm;
  47.     //Ustawienie timera
  48.     TCC1.PER = 1*0xFF + 10;
  49.     TCC1.CTRLA = TC_CLKSEL_DIV64_gc;
  50.     TCD1.PER = 1*0xFF + 78;
  51.     TCD1.CTRLA = TC_CLKSEL_DIV1024_gc;
  52.    
  53.     //Wlaczenie przerwan
  54.     sei();
  55. }

Przesyłanie danych:


W celu uruchomienia transmisji po USB należy włączyć przerwania irq oraz cpu. Następnie zegar dla układ USB oraz samą bibliotekę.

Główna pętla programu w minimalnym stopniu wygląda następująco:

  1. int main(void)
  2. {
  3.     //Wlaczenie
  4.     irq_initialize_vectors();
  5.     cpu_irq_enable();
  6.     //Wlaczenie zegarow
  7.     USB_WLACZ_ZEGAR();
  8.    
  9.     //Wlaczenie biblioteki
  10.     udc_start();
  11.    
  12.     while(1)
  13.     {
  14.     }
  15. }
  16. void Send_Data_USB()
  17. {
  18.     udi_hid_kbd_down(HID_L);
  19.     udi_hid_kbd_up(HID_L);
  20.     _delay_ms(100);
  21.     udi_hid_kbd_down(HID_P);
  22.     udi_hid_kbd_up(HID_P);
  23.     _delay_ms(100);
  24.     udi_hid_kbd_down(HID_W);
  25.     udi_hid_kbd_up(HID_W);
  26.     _delay_ms(100);
  27.     udi_hid_kbd_down(HID_2);
  28.     udi_hid_kbd_up(HID_2);
  29.     _delay_ms(100);
  30. }

Klawisze należy przesyłać poprzez włączenie oraz jego wyłączenie stąd funkcje udi_hid_kbd_down() oraz udi_hid_kbd_up().

Po każdym wysłaniu przycisku należy odczekać pewien okres czasu tak aby kolejne wciśnięcie zostało przez program zapamiętane.
Następnym elementem jest przechodzenie i rozdzielanie danych w celu ich poprawnego przesłania. Jeśli będą one podawane do funkcji to muszą zostać zdefiniowane jako zmienne globalne bądź statyczne w funkcji. Przechodzenie np. po cyfrach czy liczbach w HEX-ie można wykonać poprzez instrukcje if else if czy switch.