Przez długi okres czasu trzymałem się od nich z daleka. Częściowo ze strachu przed nowym oraz chronicznym brakiem czasu.
Aż do momentu gdy Bartek namówił mnie na zakup płytki testowej z LEON INSTRUMENTS z Xmega128A3U na pokładzie.
http://www.leon-instruments.pl/
Oczywiście układ musiał nabrać mocy prawnej przeleżał na półce prawie rok aż w końcu nadszedł czas na testy.
Pierwszym pozytywnym zaskoczeniem było programowanie przy pomocy FLIP-a wpinamy USB naciskamy dwa przyciski zwalniamy najpierw RESET potem FLIP i gotowe. Teraz wystarczy kliknąć OK i nasz układ jest już zaprogramowany.
Pierwsze kroki i zdecydowany plus.
Kolejnym zdecydowanym plusem (w moim prywatnym odczuciu) było zasilanie układu z 3.3V gdy zaistniała potrzeba podłączenia się do jednego z modułów WIFI.
W miarę "dotykania" nowa Xmega zaskakiwała mnie coraz bardziej niekończącą się listą usprawnień i udogodnień w stosunku do swoich poprzedników.
Nie ma sensu w tym momencie wymieniać wszystkich.
Dlatego wymienię tylko trzy:
Taktowanie 32Mhz
Duża ilość uartów (Xmega 128A3U ma ich aż 8)
Oraz wbudowana sprzętowa obsługa enkoderów inkrementalnych.
Chcąc koniecznie zrozumieć działanie systemu zdarzeń oraz w końcu skorzystać z wbudowanej obsługi enkodera.
Natrafiłem na przykład napisany przez jednego z bascomowych wyjadaczy użytkownika MAK3 z forum bascomforum.de
https://www.mcselec.com/index.php?optio ... &Itemid=57
Było tam kilka operacji na rejestrach ponieważ Mark Alberts jeszcze nie skończył pisać bibliotek do Bascoma.
Wspomagając się notą aplikacyjną dla Xmega_Au postanowiłem uruchomić sprzętową obsługę enkodera co okazało się wręcz banalne.
Poniżej przedstawiam dwa działające przykłady obsługi enkodera inkrementalnego.
Przykład pierwszy jest wycinkiem kodu kolegi MAK3 z wykorzystaniem rejestrów.
Code: [Zaznacz cały] [Rozwiń/Zwiń]
- '***********************************************************************
- 'Xmega quadrature encoder test base on MAK3 exaple
- ' Przykład 1
- '$sim
- $regfile = "xm128a3udef.dat"
- $crystal = 32000000
- $hwstack = 64
- $swstack = 64
- $framesize = 64
- 'Enable The Osc
- Config Osc = Enabled , 32mhzosc = Enabled
- ' ***************** SYSTEM CLOCK CONFIG ********************************
- ' INTERNAL 32MHz NO PRESCALE
- '
- Config Osc = Disabled , 32mhzosc = Enabled , 32khzosc = Enabled
- Config Sysclock = 32mhz , Prescalea = 1 , Prescalebc = 1_1
- '
- 'ENABLING AUTOMATIC OSCILLATOR CALIBRATION
- Osc_dfllctrl.0 = 1
- Dfllrc32m_ctrl.0 = 1
- '
- '***********************************************************************
- Config Priority = Static , Vector = Application , Lo = Enabled 'Enable Lo Level Interrupts
- '***********************************************************************
- '*******************Xmega 128A3U***********************
- '* UART *********** TX pin * RX pin *
- '* ****************************************************
- '* COM1 - UART_C0 * PORTC.3 * PORTC.2 *
- '******************************************************
- '* COM2 - UART_C1 * PORTC.7 * PORTC.6 *
- '******************************************************
- '* COM3 - UART_D0 * PORTD.3 * PORTD.2 *
- '******************************************************
- '* COM4 - UART_D1 * PORTD.7 * PORTD.6 *
- '******************************************************
- '* COM5 - UART_E0 * PORTE.3 * PORTE.2 *
- '******************************************************
- '* COM6 - UART_E1 * PORTE.7 * PORTE.6 *
- '******************************************************
- '* COM7 - UART_F0 * PORTF.3 * PORTF.2 *
- '******************************************************
- '* COM8 - UART_F1 * PORTF.7 * PORTF.6 *
- '******************************************************
- '***********************************************************************
- Dim Buart_channel As Byte '0 = COM1 ...... 7 = COM8
- Config Com3 = 115200 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8 'COM3 - UART_D0 PORTD.3 PORTD.2
- Config Com1 = 115200 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8 'COM1 - UART_C0 PORTC.3 PORTC.2
- Buart_channel = 2
- Print #buart_channel , "This use COM3" 'print current Uart
- Print #buart_channel , "MCU Rev. = " ; Mcu_revid 'version of the MCU
- '***********************************************************************
- DIm enkoder_tmp as dword 'zmienna dla enkodera '
- Enable Interrupts 'włacz przerwania globalne
- '--------------------------MAK3 example---------------------------------
- Config PortA.0 = Input 'PinA.0 = A
- PortA_pin0ctrl = &B00_000_011 'Totempole/low level
- '^ ^
- '^ low level
- '^
- 'No Pull configuration
- Config PortA.1 = Input 'PinA.1 = B
- PortA_pin1ctrl = &B00_000_011 'Totempole/low level
- '***********************************************************************
- Evsys_ch0mux = &B0101_0_000 'PortA Pin 0 i automatycznie pin 1
- '^ ^ 'manual xmega_Au page 78
- '^ ^
- '^ ^Pin0
- 'portA
- reset Evsys_ch0ctrl.2 : Set Evsys_ch0ctrl.1 : Set Evsys_ch0ctrl.0 '011- Digital Filter dla 4 probki
- Set Evsys_ch0ctrl.3 'właczenie enkodera strona 78 xmega_Au manual
- '***********************************************************************
- 'ustawiamy Timer/Counter D0 aby zliczał impusly ekondera z systemu zdażen
- TcD0_ctrld = &B011_0_1000 'Event Action = Quadratur Encoding, nasłuchuj na kanale 0
- '^ '^ '^
- '^ '^ 'EVSEL[3:0]
- '^
- 'Evact[7:5] manual xmega_Au strona 175
- '000 OFF None
- '001 CAPT Input capture
- '010 UPDOWN Externally controlled up/ down count
- '011 QDEC Quadrature decode
- '100 RESTART Restart waveform period
- '101 FRQ Frequency capture
- '110 PW Pulse width capture
- '111 Reserved
- 'EVDLY
- 'EVSEL[3:0]
- '1nnn CHn Event channel n, n={0,...,7}
- '**********************************************************************
- Tcd0_ctrla = &B0000_1000 'Start Timer event chanel 0 xmega manual_Au strona 175
- '**********************************************************************
- enkoder_tmp = 0
- Do
- if TCD0_cnt <> enkoder_tmp then 'jesli zawartosc timera TCD0 jest różna od naszej zmiennej to
- enkoder_tmp = TCD0_cnt 'przepisz nową wartość z timera TCD0 do zmiennej enkoder_tmp
- Print #buart_channel , enkoder_tmp 'wyśli przez port szeregowy 2 zmienna buart=2
- end if
- Loop
- end 'end program
Wystarcz tylko sześć linii kodu aby uruchomić obsługę enkodera.
Przechwytywanie zdarzeń wykonywane jest automatycznie w tle bez potrzeby dodatkowego kodu.
config pinA.1 = input
config PinA.0 = input
Config Xpin = PortA.1 , Outpull = pullup , Sense = low_level
Config Xpin = PortA.0 , Outpull = pullup , Sense = low_level
config Event_system = Dummy , Mux0 = portA.0 , QD0 = enabled , Digflt0 = 8
Config Tcd0 = Normal , Prescale = e0 , Event_source = E0 , Event_action = QDEC
Code: [Zaznacz cały] [Rozwiń/Zwiń]
- '***********************************************************************
- 'Xmega quadrature encoder test base on MAK3 exaple
- 'Przyklad 2
- '$sim
- $regfile = "xm128a3udef.dat"
- $crystal = 32000000
- $hwstack = 64
- $swstack = 64
- $framesize = 64
- 'Enable The Osc
- Config Osc = Enabled , 32mhzosc = Enabled
- ' ***************** SYSTEM CLOCK CONFIG ********************************
- ' INTERNAL 32MHz NO PRESCALE
- '
- Config Osc = Disabled , 32mhzosc = Enabled , 32khzosc = Enabled
- Config Sysclock = 32mhz , Prescalea = 1 , Prescalebc = 1_1
- '
- 'ENABLING AUTOMATIC OSCILLATOR CALIBRATION
- Osc_dfllctrl.0 = 1
- Dfllrc32m_ctrl.0 = 1
- '
- '***********************************************************************
- Config Priority = Static , Vector = Application , Lo = Enabled 'Enable Lo Level Interrupts
- '***********************************************************************
- '*******************Xmega 128A3U***********************
- '* UART *********** TX pin * RX pin *
- '* ****************************************************
- '* COM1 - UART_C0 * PORTC.3 * PORTC.2 *
- '******************************************************
- '* COM2 - UART_C1 * PORTC.7 * PORTC.6 *
- '******************************************************
- '* COM3 - UART_D0 * PORTD.3 * PORTD.2 *
- '******************************************************
- '* COM4 - UART_D1 * PORTD.7 * PORTD.6 *
- '******************************************************
- '* COM5 - UART_E0 * PORTE.3 * PORTE.2 *
- '******************************************************
- '* COM6 - UART_E1 * PORTE.7 * PORTE.6 *
- '******************************************************
- '* COM7 - UART_F0 * PORTF.3 * PORTF.2 *
- '******************************************************
- '* COM8 - UART_F1 * PORTF.7 * PORTF.6 *
- '******************************************************
- '***********************************************************************
- Dim Buart_channel As Byte '0 = COM1 ...... 7 = COM8
- Config Com3 = 115200 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8 'COM3 - UART_D0 PORTD.3 PORTD.2
- Config Com1 = 115200 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8 'COM1 - UART_C0 PORTC.3 PORTC.2
- Buart_channel = 2
- Print #buart_channel , "This use COM3" 'print current Uart
- Print #buart_channel , "MCU Rev. = " ; Mcu_revid 'version of the MCU
- '***********************************************************************
- DIm enkoder_tmp as dword 'zmienna dla enkodera
- Enable Interrupts 'włacz przerwania globalne
- '***********************************************************************
- 'config pinA.2 = input 'index pin of the encoder
- config pinA.1 = input 'enkoder B
- config PinA.0 = input 'enkoder A
- 'Config Xpin = PinA.2 , Outpull = pullup , Sense = low_level
- Config Xpin = PortA.1 , Outpull = pullup , Sense = low_level 'enable Pull up and reaction on low level
- Config Xpin = PortA.0 , Outpull = pullup , Sense = low_level
- 'konfigurujemy system zdarzeń
- config Event_system = Dummy , Mux0 = portA.0 , QD0 = enabled , Digflt0 = 8
- 'konfiguracja systemu zdarzeń multiplexer kanał 0 , portA.0, obsługa enkodera QDO właczona, filtr cyfrowy 8
- 'gdy używamy idndexu musimy dodać QDIO=enabled
- 'config Event_system = Dummy , Mux0 = portA.0 , QD0 = enabled , QDI0 = enabled , Digflt0 = 8
- '***********************************************************************
- Config Tcd0 = Normal , Prescale = e0 , Event_source = E0 , Event_action = QDEC
- 'konfiguracja timera TCD0 normal= bez generowania sygnałów, preskaler =e0, zródło zdarzenia=podajemy zródło czyli event system
- 'kanał 0 , event action =czyli reakcja na zdarzenie QDEC właczenie obsługi enkodera
- '***********************************************************************
- enkoder_tmp = 0
- Do
- if TCD0_cnt <> enkoder_tmp then 'jesli zawartosc timera TCD0 jest różna od naszej zmiennej to
- enkoder_tmp = TCD0_cnt 'przepisz nową wartość z timera TCD0 do zmiennej enkoder_tmp
- Print #buart_channel , enkoder_tmp 'wyśli przez port szeregowy 2 (zmienna buart=2)
- end if
- 'na ekranie termianla zobaczymy liczbe impulsów policzonych przez nasz timer.
- 'na jeden przeskok enkodera przypadaja 4 impulsy
- Loop
- end 'end program
Którą można pobrać z mojego droboxa.
https://www.dropbox.com/sh/ot7nltgx0kjc ... Heqta?dl=0
Co tak naprawdę jest wymagane do uruchomienia naszego enkodera dokładnie widać w przykładzie pierwszym.
Koniecznie musimy wybrać piny ale muszą to być dwa (lub trzy jeśli używamy Indexu) w kolejności.
Code: [Zaznacz cały] [Rozwiń/Zwiń]
- config pinA.1 = input 'encoder B
- config PinA.0 = input 'enkoder A
- Config Xpin = PortA.1 , Outpull = pullup , Sense = low_level 'enable Pull up and reaction on low level
- Config Xpin = PortA.0 , Outpull = pullup , Sense = low_level
- 'konfigurujemy system zdarzeń
Ustawiamy bity według tabeli dla portu A będzie to:
Evsys_ch0mux = &B0101_0_000 'PortA Pin 0 i automatycznie pin 1
Kolejny krok to ustawienie odpowiednich bitów w rejestrze CHnCTRL- Event Channel n Control register
Code: [Zaznacz cały] [Rozwiń/Zwiń]
- reset Evsys_ch0ctrl.2 : Set Evsys_ch0ctrl.1 : Set Evsys_ch0ctrl.0 '011- Digital Filter dla 4 probki
- Set Evsys_ch0ctrl.3 'właczenie enkodera strona 78 xmega_Au manual
Wybieramy 4 próbki bity 2 do 0 oraz włączamy obsługę naszego enkodera bit 3.
Jeśli nie używamy indexu pomijamy bit 4.
Teraz wystarczy włączyć nasz Timer TCD0 aby zliczał impulsy:
W rejestrze CTRLA dla timera TCD0 wybierając odpowiedni kanał zdarzeń w tym przypadku 0
Code: [Zaznacz cały] [Rozwiń/Zwiń]
- Tcd0_ctrla = &B0000_1000 'Start Timer event chanel 0 xmega manual_Au strona 175
I możemy cieszyć się sprzętową obsługą enkodera.
Prawda jakie to proste