Hallo Bascom-Fans,
Mit den im Dezember 2009 erschienenen Bascom-Versionen (aktuell 1.11.9. hat Mark Alberts deutliche Fortschritte bei der Unterstützung der Xmegas erzielt. Leider fehlt für die Modellbau/Robotik/UAV-Szene noch etwas Elementares - nämlich der Bascom-support von PWM und Servos. Das kann man aber selbst mit kleinen Veränderungen an der XM128def.dat hinbekommen. Wie, ist in nachstehendem Source snippet erläutert.
Wünsche noch einen guten Rutsch,
Natalius
Code:
'----------------------------------------------------------------
' (C) MCS 2009 & N.Kiedro
' Xmega2Servo.bas
' This snippet demonstrates PWM on the Xmega128A1
' Platform: Xmega A1 USB module from http://shop.avr-praxis.de
'
' USE port D to create six RC servo signals in 4000 steps/ms
' resolution via interrupt-free single slope PWM.
' Servo signals are pulses between 1 and 2 ms,
' corresponding to 4000 to 8000 here - center at 6000.
' In my own kixm128a1def.dat file I have done these extensions for
' all Timer/Counters which allows to control 20 Servos (=24-4 because
' of USART F0 in use) via the Xmega-A1-USB module. Of course, jitter-free
' and with best achievable resolution @ 32 MHz.
'-----------------------------------------------------------------
$regfile = "kixm128a1def.dat"
'For Bascom 1.11.9.8: This snippet needs an extended definition dat with the following
'changes:
''(1) Load xm128def.dat into the editor and save it under a different name, e.g. kixm128a1def.dat
''(2) Find the following definitions for TCD0, TCD1
'' _CNT
'' _PER
'' _CCA
'' _CCB
'' _CCC
'' _CCD
'' _PERBUF
'' _CCABUF
'' _CCBBUF
''
''(3) Replace the corresponding sections as follows:
'' TCD0_CNTL = 2336 ; Count
'' TCD0_CNTH = 2337 ; Count
'' TCD0_PERL = 2342 ; Period
'' TCD0_PERH = 2343 ; Period
'' TCD0_CCAL = 2344 ; Compare or Capture A
'' TCD0_CCAH = 2345 ; Compare or Capture A
'' TCD0_CCBL = 2346 ; Compare or Capture B
'' TCD0_CCBH = 2347 ; Compare or Capture B
'' TCD0_CCCL = 2348 ; Compare or Capture C
'' TCD0_CCCH = 2349 ; Compare or Capture C
'' TCD0_CCDL = 2350 ; Compare or Capture D
'' TCD0_CCDH = 2351 ; Compare or Capture D
'' TCD0_PERBUFL = 2358 ; Period Buffer
'' TCD0_PERBUFH = 2359 ; Period Buffer
'' TCD0_CCABUFL = 2360 ; Compare Or Capture A Buffer
'' TCD0_CCABUFH = 2361 ; Compare Or Capture A Buffer
'' TCD0_CCBBUFL = 2362 ; Compare Or Capture B Buffer
'' TCD0_CCBBUFH = 2363 ; Compare Or Capture B Buffer
'' TCD0_CCCBUFL = 2364 ; Compare Or Capture C Buffer
'' TCD0_CCCBUFH = 2365 ; Compare Or Capture C Buffer
'' TCD0_CCDBUFL = 2366 ; Compare Or Capture D Buffer
'' TCD0_CCDBUFH = 2367 ; Compare Or Capture D Buffer
''
'' TCD1_CNTL = 2400 ; Count
'' TCD1_CNTH = 2401 ; Count
'' TCD1_PERL = 2406 ; Period
'' TCD1_PERH = 2407 ; Period
'' TCD1_CCAL = 2408 ; Compare or Capture A
'' TCD1_CCAH = 2409 ; Compare or Capture A
'' TCD1_CCBL = 2410 ; Compare or Capture B
'' TCD1_CCBH = 2411 ; Compare or Capture B
'' TCD1_PERBUFL = 2422 ; Period Buffer
'' TCD1_PERBUFH = 2423 ; Period Buffer
'' TCD1_CCABUFL = 2424 ; Compare Or Capture A Buffer
'' TCD1_CCABUFH = 2425 ; Compare Or Capture A Buffer
'' TCD1_CCBBUFL = 2426 ; Compare Or Capture B Buffer
'' TCD1_CCBBUFH = 2427 ; Compare Or Capture B Buffer
''(4) Dont forget to save the changes
$crystal = 32000000
$hwstack = 512
$swstack = 256
$framesize = 256
'include the following lib and code, the routines will be replaced since they are a workaround
$lib "xmega.lib"
$external _xmegafix_clear
$external _xmegafix_rol_r1014
'$timeout = 8000000 TIMEOUT WILL WORK FOR ALL UARTS
'first enable the osc of your choice
Config Osc = Enabled , 32mhzosc = Enabled 'remarkably accurate given the fact that no xtal is employed
'Config Osc = Enabled , Extosc = Enabled , Range = 12mhz_16mhz , Startup = Xtal_16kclk (so far doesn't work)
'configure the systemclock
Config Sysclock = 32mhz , Prescalea = 1 , Prescalebc = 1_1
Dim N As String * 16 , B As Byte
Dim Tel As Byte , Channum As Byte , Jst As String * 1 , Chanval As Word , Chanpwm(6) As Word , Iby As Byte
Config Com7 = 38400 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8
Config Input7 = Cr , Echo = Crlf ' CR is used for input, we echo back CR and LF
Open "COM7:" For Binary As #7
' ^^^^ change from COM1-COM8
Config Portf = Output
Config Portf.3 = Output ' TX pin must be output
Config Portf.2 = Input
Config Portq = Output
'Waitms 500
Print #7 , "Press <CR> to start";
'pwm initialisation here
'RC cycle period should be ideally at 20ms, viz. 50 Hz.
'With fpwm = fosc/per/clkdiv = 32MHz/(2^16)/8 = 1MHz/2^14 = 61.0352 Hz we have a
'cycle period of 16.384 ms most Servos should be able to live with.
' From the Xmega 128A1 manual:
' 6.4 Using a Timer/Counter for PWM Generation
' Task: Configure TCC0 for pulse width modulation output with varying duty cycle on channel A.
' 1. Configure PC0 for output by setting bit 0 in PORTC.DIR.
' 2. Select the timer period by setting the PER[H:L] register.
' 3. Select a waveform generation mode by setting the WGMODE[2:0] bits in CTRLB
' 4. Enable Compare Channel A by setting the CCAEN bit in CTRLB.
' 5. Start the TC by selecting a clock source (CLKSEL[3:0] in CTRLA).
' 6. Calculate the desired compare value.
' 7. Write the new compare value to CCA[H:L].
' 8. Wait for the TC Overflow Flag to be set. (OVFIF in INTFLAGS).
' 9. Clear the TC Overflow flag.
' 10. Go to step 6.
'Using this sequence, the compare value will be updated once every PWM period.
'Modification: free running pwm - no interrupt, but ASAP update instead:
' 1. Configure PD0 and PD1 for output --> PORTD.DIR.
' 2. Select the timer period by setting the PER[H:L] register.
' 3. Select a waveform generation mode by setting the WGMODE[2:0] bits in CTRLB
' 4. Enable Compare Channel A-D by setting the CCAEN bits in CTRLB.
' 5. Start the TC by selecting a clock source (CLKSEL[3:0] in CTRLA).
' 6. Calculate the desired compare value.
' 7. Write the new compare value to CCxBUF[H:L].
' 8. Go to step 6
'ad 1.
Portd_dir = &HFF
'ad2.
Tcd0_perl = &HFF
Tcd0_perh = &HFF
Tcd1_perl = &HFF
Tcd1_perh = &HFF
'ad 3 & 4
Tcd0_ctrlb = &HF3 'define WGMODE 011 = single slope and set OCA-D active
Tcd1_ctrlb = &HC3
'ad 5
Tcd0_ctrla = &H04 'Divide Clock By 8 , Enable Timers (Bits 3..0 define clckdiv)
Tcd1_ctrla = &H04
'ad 6
For Iby = 1 To 6
Chanpwm(iby) = 6000
Next Iby
'ad 7
Gosub Update
'configure the priority
'config priority=static|roundrobin,vector=application|boot,HI=enabled|disabled, LO=enabled|disabled,ME=enabled|disabled
Config Priority = Static , Vector = Application , Lo = Enabled
'test an interrupts
On Usartf0_rxc Rxc_isr
Enable Usartf0_rxc , Lo
Enable Interrupts
Tel = 65
Do
Print #7 , "Channel(1-6)?";
Tel = Waitkey(#7)
Jst = Chr(tel)
Channum = Val(jst)
Print #7 , Channum
Input #7 , "value?" , N 'enter values between 4000 (1ms) and 8000 (2ms)
Chanval = Val(n)
Print #7 , N
Chanpwm(channum) = Chanval
'ad 7
Gosub Update
Loop
Rxc_isr:
Toggle Portq.3
'Incr Teller
Return
Update:
Tcd0_ccabufL = Low(chanpwm(1))
Tcd0_ccabufH = High(chanpwm(1))
Tcd0_ccbbufL = Low(chanpwm(2))
Tcd0_ccbbufH = High(chanpwm(2))
Tcd0_cccbufL = Low(chanpwm(3))
Tcd0_cccbufH = High(chanpwm(3))
Tcd0_ccdbufL = Low(chanpwm(4))
Tcd0_ccdbufH = High(chanpwm(4))
Tcd1_ccabufL = Low(chanpwm(5))
Tcd1_ccabufH = High(chanpwm(5))
Tcd1_ccbbufL = Low(chanpwm(6))
Tcd1_ccbbufH = High(chanpwm(6))
Return
Lesezeichen