查看: 891|回复: 0
打印 上一主题 下一主题

bascom ATMEGA8 PPM解码后舵机总是微弱抖动

[复制链接]
跳转到指定楼层
沙发
发表于 2015-10-29 08:49:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

大家好!这个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转载

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入因仑

本版积分规则

快速回复 返回顶部 返回列表