大家好!这个PPM解码程序是网上下的,然后经过我的修改直接输出PWM信号驱动舵机。
但是脉宽信号总是会来回跳跃,不知道哪里错了请高手指点迷津。
代码如下:
'******************************************************
'======================================================
'System settings
'======================================================
'Definition for Mega 8
$regfile "m8def.dat"
'System frequency (8Mhz)
$crystal = 16000000
Config Lcd = 16 * 2
'Config Lcd = 20 * 4
Config Lcdpin = Pin , Db4 = Portb.0 , Db5 = Portb.1 , Db6 = Portb.2 , Db7 = Portb.3 , E = Portb.4 , Rs = Portb.5
Config Lcdmode = Port
Config Servos = 1 , Servo1 = Portc.3 , Reload = 10
'Config Timer0 = Timer , Prescale = 1
Config Portc.3 = Output
'======================================================
'Configurations
'======================================================
'I/O-Ports
'Config Portc = Output
Config Portd.2 = Input
'Size of display
'it is 4x27 really, but the compiler doesn't understand
'Interrup 0
Config Int0 = Falling 'timing of pulses on negative flank
'Configuration of timer 1 (16 bit)
Config Timer1 = Timer , Prescale = 8
'======================================================
'Declarations
'======================================================
Dim ___lcde As Byte 'for switching between upper and lower LCD half
Dim N_sync As Byte
Dim Rc_value As Word
Dim Channel(7) As Word '9 channels plus the synchonisation pulse
Dim N_ch As Word
Dim Ch_time(6) As Word
Dim Failsafe_value(6) As Word 'These will be used when no signal is available
Dim I As Integer 'Running parameter for loops
Dim Failsafemode As Bit
Dim Signal_up_flag As Bit
Dim Signal_valid_flag As Bit
Dim X As Integer , X1 As String * 3 , Xstr As String * 10
Dim A As Integer , B As Integer , Ax As Integer , Bx As Integer
Dim Ml As Integer , Mr As Integer , Mm As Integer , X2 As Integer '
'======================================================
'Initialisations
'======================================================
'Interrupt-Service-Routines
On Timer1 Signal_down 'overflow of timer occurs when the signal is down
On Int0 Read_signal 'On int0 timing of the signal pulses
'Timer-release
Enable Timer1
'Release of interrupts
Enable Int0
Enable Interrupts
'Initialise ports
'Portc = &B00000000 'Note: my hardware has non-inverted LED ports: 1 = on, 0 = off
'Initialise variables
Signal_up_flag = 1 'Signal available
Signal_valid_flag = 0 'Signal not valid
N_ch = 1
N_sync = 0 'Start at channel 1
'No sybcronisation pulse seen yet
'Failsafe settings
Failsafemode = 0 '0 for "keep old signals", 1 for the failsafe values below
Failsafe_value(1) = 1600 'Set failsafe value of channel 1 (roll)
Failsafe_value(2) = 1600 'Set failsafe value of channel 2 (pitch)
Failsafe_value(3) = 1050 'Set failsafe value of channel 3 (yaw)
Failsafe_value(4) = 1600 'Set failsafe value of channel 4 (power)
Failsafe_value(5) = 1600
Failsafe_value(6) = 1600
'Initialise timer channel values
For I = 1 To 6
Ch_time(i) = Failsafe_value(i)
Next
'Calibration of the internal oscillator.
'Write here the hex value of calibration byte 3 from the locks and fuses tab
Osccal = &HAF 'Loading the calibration byte in the OSCCAL register
'======================================================
'Writing LCD headers
'======================================================
Cls 'Clear lines
Cursor Off
'======================================================
'Main program
'======================================================
A = 2
B = -2
Ml = 60
Mr = 70
Do
X = Ch_time(1)
' X = X - 63
' X1 = X1 + X
Xstr = Str(x)
X1 = Left(xstr , 3)
' Next I
' X1 = X1 / 10
X = Val(x1)
X = X - 175
X2 = X - Mm
If X < Ml Then
Ml = X
Elseif X > Mr Then
Mr = X
End If
Mm = Ml + Mr
Mm = Mm / 2
'Calculate timing values in micro sec, only if the signal is up (simple fail safe implementation)
'Otherwise leave old values or use faisafe values
'The ch_time() array would be used for further processing
'The channel() array is only used for measurement and may contain invalid data
If Signal_valid_flag = 1 Then
For I = 1 To 6
Ch_time(i) = Channel(i)
Next
Else
If Failsafemode = 1 Then
For I = 1 To 6
Ch_time(i) = Failsafe_value(i)
Next
End If
End If
'Waitms 100
'Writing timing values to LCD display
Cls
Locate 1 , 1
Lcd X ; " c1"
Locate 1 , 9
Lcd Mm ; " mm"
Locate 2 , 1
Lcd Ml ; " ml"
Locate 2 , 9
Lcd Mr ; " mr"
If X2 > A Or X2 < B Then
Servo(1) = Mm + X2
End If
Portc.0 = Signal_valid_flag 'Showing the signal valid flag on port C0
Portc.1 = Signal_up_flag 'Showing the signal up flag on port C1
'waitstate to get readable LCD values
' For I = 1 To 10
Loop
End
'******************************************************
'Interrupt Service Routines
'******************************************************
Read_signal:
Rc_value = Timer1 'First thing: store the timer value in an intermediate variable.
Timer1 = 0 'Then reset the timer
If Rc_value > 6000 Then 'If the puls is to long it is the synchronisation pulse,
N_ch = 6 'so set channel number to number of synchonisation pulse
If N_sync < 2 Then Incr N_sync 'The sync pulse counter is increased until it is 2
If N_sync = 2 Then Signal_valid_flag = 1 'If it is the second consequitive sync puls, then the signal is declared valid
End If
Channel(n_ch) = Rc_value 'Load the measured timer value into the array of measurement data
Incr N_ch 'next channel
If N_ch = 7 Then N_ch = 1 'Limit the number of channels to 10
Signal_up_flag = 1 'set the signal up flag
Return
Signal_down: 'if no signal is detected for 65 ms
Signal_up_flag = 0 'reset signal_up_flag
Signal_valid_flag = 0 'reset signal valid flag
N_sync = 0 'reset number of syncpulses passed
Return转载
|