пятница, 20 августа 2010 г.

Пример тестирования контроллера лотка (ATMega8)

$regfile = "m8def.dat"
$include "Shablon-m8.bas"
' Описание конфигурации
Config Com1 = 9600 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 9 , Clockpol = 0
' Описание Aliases
' Описание констант
Const cMajorVersion = &H1                                   ' Мажор и минор версии этой программы
Const cMinorVersion = &H1E                                  ' Version = "cMajorVersion.cMinorVersion"
Const cSetupTimer = 15                                      ' Сколько миллисекунд ждать, чтобы начать анализ состояния при конфигурации
Const cTimerMotor = 7                                       ' Сколько миллисекунд ждать, чтобы начать анализ состояния
' Описание процедур
Declare Sub StartMotor(ByVal MotorNum As Byte)              ' Процедура старта мотора
Declare Sub StopMotor(ByVal MotorNum As Byte)               ' Процедура стоп мотор
' Описание переменных
Dim I As Byte                                               ' Счетчик циклов
Dim AllSW As Byte                                           ' 6 ног порта B
'Dim CountRx As Byte                                         ' Счетчик приемных байтов
' Dim Lighter As Bit                                          ' Моргающий индикатор
Dim SpiralNumber As Byte                                    ' Номер спирали для прокрутки
' Признак того, что на прерывании во время ожидания подтверждения байт пришел
Dim ComandCompleted As Bit
Dim MotorCom As Byte                                        ' Байт команд моторам
Dim MotorMod As Byte                                        ' Байт моторов (1 - вращение., 0 - выкл.)
Dim MotorClick As Byte                                      ' Байт срабатывания датчиков
Dim Motor5 As Byte                                          ' Состояние 5-го сектора вращения мотора
Dim MotorSel As Byte                                        ' Байт выбора текущего мотора
Dim MotorExist As Byte                                      ' Байт наличия живых моторов (Если бит сброшен, то мотор отсутствует или поломан
Dim LighterErr As Bit                                       ' Красный индикатор ошибки, который тушится после 3-х срабатываний таймера
Dim Res As Byte                                             ' Результат извлечения
Dim TimeErr As Byte                                         ' Счетчик срабатываний таймер для засветки ошибки
Dim CountInt As Word                                        ' Счетчик срабатывания датчика
Dim lOutByte As Byte
' Инициализация переменных из EEPROM
' ReadEEProm SelfAddress , SelfAddressDefault
' ReadEEProm SpiralCount , SelfSpiralCount
' Инициализация переменных
GoSub InitEnv
' Проверяем наличие моторов
For Res = 0 To 6
   ' Включаем на 2 ms мотор
   Set MotorPort.Res : Waitms cSetupTimer
   ' Если на входе стоит логическая ебиница, то мотор существует и исправен
   MotorExist.Res = MotorSignal
   ' Останавливаем мотор
   Reset MotorPort.Res : Waitms cSetupTimer
Next
' Проверяем адрес, установленный переключателем
I = AllSW AND &B111000 : SelfAddress = SelfAddress + I
' Проверяем кол-во спиралей, установленных переключателем
I = PINB AND &B00011 : SpiralCount = SpiralCount + I
' Инициализация прерываний
On Timer0 Timer0Sub
On Timer1 Timer1Sub
On INT1 ToggleMotor
Enable INTERRUPTS
Enable Timer0
Enable Timer1
Enable INT1
' Устанавливаем режим режим мультипроцессорного обмена (РМО)
Call ReturnFromCommand
'Основной цикл
Do
  ' Если что-то есть в приемном буфере, то начинаем его чтение
  If isPortReceived = 1 Then GoSub RECEIVEMDB
  ' Прием от VMC
  If ComandCompleted = 1 Then
     If ConfirmFromVMC = 0 Then
        Select Case CommandFromVMC
           Case 0 : GoSub MDBInit
           Case 1 : GoSub MDBConfig
           Case 2 : GoSub MDBDiagnostic
           Case 3 : GoSub MDBPoll
           Case 4 : GoSub MDBEvent
           Case Else
               ' Надо вернуться в исходное состояние
               Call ReturnFromCommand
           End Select
     Else
        GoSub VMCConfirm
     End If
  End If
  ' Анализируем состояние мотора
  If MotorStatus = 0 Then
     ' Если сейчас мотор не крутится
     If MotorCom > 0 Then
        MotorSel = MotorCom - 1
        ' Обнуляем команду
        ' Print "UDR = " ; Ina ; "; MotorSel = " ; MotorSel ; "; MotorCom = " ; MotorCom ; "; PINB = " ; PINB
        ' Print "==="
        MotorCom = 0
        ' Стартуем мотор
        If MotorExist.MotorSel = 1 Then Call StartMotor(MotorSel)
     End If
  Else
     ' Если крутится, то проверяется ошибка команды
     If MotorCom > 0 Then
        MotorCom = 0                                        ' Обнуляем команду
        TimeErr = cTimeErr                                  ': Set LighterErr                 ' Включаем ошибку
     End If
     ' Собственно здесь и ловим срабатывание датчика
     ' If MotorSignal = 0 Then GoSub TOGGLEMOTOR
  End If
  ' Анализ ресета по шине длиной 480 мс при 4 MHz (Внимание! Если меняется частота, пересчитать константу cResetTimer)
  ' If RXD_MDB = 0 Then
  '  If MDBBUSResetSignal = 0 Then : Timer1 = 0 : Set MDBBUSResetSignal : End If
  '   WordTMP = TIMER1
  '   If WordTMP > cResetTimer Then Return                   ' Перезагрузка
  'Else
  '   Reset MDBBUSResetSignal
  'End If
Loop
'Подпрограммы обработки команд
' (c)
MDBInit:
   If ControlSumError = 0 Then Call SendMDB(cACK , 1) Else Call SendMDB(cNAK , 1)
   ' Ищем и читаем ID термометра
   RegNumber(1) = 1wsearchfirst()
   Call ReturnFromCommand
Return
' (c)
MDBConfig:
   ' Сначала посылаем мажор и минор версии этой программы (2 байта)
   Call Byte2MDB(cMajorVersion) : Call Byte2MDB(cMinorVersion)
   ' Посылаем кол-во спиралей прошитых и обнаруженных
   Call Byte2MDB(SpiralCount) : Call Byte2MDB(MotorExist)
   ' Отсылаем ID термометра VMC
   GoSub SendRegNumber
   ' Отсылаем контрольную сумму
   Call CRC2MDB
   ' Включаем ожидание от VMC
   Set ConfirmFromVMC
Return
' (c)
MDBDiagnostic:
   If ControlSumError = 0 Then Call SendMDB(cACK , 1) Else Call SendMDB(cNAK , 1)
   Call ReturnFromCommand
   ' Даем команду на измерение температуры (convert)
   GoSub Reset1Wire
   1wwrite &H44
   Wait 1
   GoSub Reset1Wire
   1wwrite &HBE
   ' Читаем ее и заполняем массив, который отправится при следующем EVENT
   RegAnswer(1) = 1wread(9)
   1wreset
Return
' (c)
MDBPoll:
   If ControlSumError = 0 Then Call SendMDB(cACK , 1) Else Call SendMDB(cNAK , 1)
   Call ReturnFromCommand
Return
' (c)
MDBEvent:
   ' Анализируем событие во втором байте. Если событие в диапазоне &H11..&H17, значит крутим спираль
   InA = FromVMC(2) AND &H30
   ' Если спираль сейчас крутится, то игнорируем команду
   If MotorStatus <> 0 Then Ina = &HF0
   Select Case InA
      Case &H10
         ' Выделяем адрес спирали. Если спираль указана правильно, то уменьшаем ее номер, так как ноги считаются от 0
         SpiralNumber = FromVMC(2) AND &B111                ' : If SpiralNumber > 0 Then Decr SpiralNumber
         ' Запускаем на обработку команды
         MotorCom = SpiralNumber
         Call Byte2MDB(MotorCom)
      Case &H20
         ' Отсылаем заранее подготовленный массив RegNumber
         GoSub SendRegAnswer
      Case Else
         Call Byte2MDB(0)
   End Select
   Call Byte2MDB(SelfAddress)
   Call CRC2MDB()
   Set ConfirmFromVMC
Return
' Процедура отсылки RegNumber(8) VMC
SendRegNumber:
   For I = 1 to 8 : Call Byte2MDB(RegNumber(I)) : Next
Return
' Процедура отсылки RegAnswer(9) VMC. После отсылки очищаем массив
SendRegAnswer:
   For I = 1 to 9
       Call Byte2MDB(RegAnswer(I)) : RegAnswer(I) = &HFF
   Next
Return
' Процедура ожидания подтверждения от VMC
' (c) В С++ эта процедура реализована как confirm_vmc
VMCConfirm:
   Reset ComandCompleted
   Select Case FromVMC(nFromVMC)
      Case cACK
         Call ReturnFromCommand : Reset ConfirmFromVMC
      Case cNAK
         Call ReturnFromCommand : Reset ConfirmFromVMC
      Case cRET
         Set ConfirmFromVMC
   End Select
Return
'Подпрограмма обработки Timer0 (c)
Timer0Sub:
   If Timer0Counter <> 0 Then                               ' Ждем, пока Timer0Counter станет равным нулю
      Decr Timer0Counter
   Else
      If BlinkLamp <> 0 Then Reset BlinkLamp
   End If
Return
'Подпрограмма обработки Timer1 (c)
Timer1Sub:
   ' Toggle Lighter                                           ' Print "Timer1: " ;
   ' Проверяем, крутиться ли мотор
   If MotorStatus <> 0 Then Incr Motor5                     ' Еслит крутиться, то прибавляем счетчик сработанного таймера
   ' Если сейчас светик ошибки не светится, то выходим из прерывания
   If LighterErr <> 0 Then
       ' Ждем, пока TimeErr станет равным нулю
       If TimeErr = 0 Then Reset LighterErr Else Decr TimeErr
   End If
   ' Читаем значение ADC
   'Print "ch0 = " ; Getadc(0) ; "; ch1 = " ; Getadc(1)
Return
'Подпрограмма ресета и поиска устройста 1wire
Reset1Wire:
   1wreset : 1wwrite &H55 : 1wwrite RegNumber(1) , 8
Return
'Подпрограмма инициализации переменных
' (c)
InitEnv:
    GoSUB Blinking
    SelfAddress = cSelfAddress : SpiralCount = cSpiralCount
    RcvControlSum = 0 : SndControlSum = 0
    ReSet ControlSumError : ReSet ComandCompleted
    ConfirmFromVMC = 0 : SpiralNumber = &HFF : nFromVMC = 1
    'CountRx = 0
    ' Set Lighter
    ' Чтение переключателей
    AllSW = NOT PIND : Shift AllSW , Right , 2
    For I = 1 To 9 : RegAnswer(I) = &HFF : Next
    MotorMod = 0 : MotorCom = 0 : TimeErr = 0 : CountInt = 0 : Ina = 0 : MotorSel = &HFF
    Reset LighterErr                                        ' : Reset Lighter
    GoSUB Blinking
Return
'Подпрограмма обработки срабатывания концевого датчика (c)
ToggleMotor:
   Incr CountInt
   'Print "INT1= " ; CountInt ; "; Mode = " ; Bin(PINB) ; "; Motor5 = " ; Motor5 ; "; Timer = " ; Timer1 ; "; UDR = " ; Ina
   If MotorClick.MotorSel = 1 Then
       Call StopMotor(MotorSel)
   Else
       Set MotorClick.MotorSel
       ' Если таймер еще не сработал, а уже пришло прерывание, то тормозим сразу
       If Motor5 < 1 Then Call StopMotor(MotorSel)
   End If
Return
$include ".\..\TPALibs.bas"
' Старт Мотора (c)
Sub StartMotor(ByVal MotorNum As Byte)                      ' Процедура старта мотора
   Set MotorPort.MotorNum                                   ' Включаем мотор
   TIMER1 = 0 : Set GIFR.7                                  ' Обнуляем таймер
   Waitms cTimerMotor
   Enable INT1                                              ' Разрешаем прерывания
End Sub
' Стоп Мотор (c)
Sub StopMotor(ByVal MotorNum As Byte)                       ' Процедура стоп мотор
   Disable INT1 : Set GIFR.7                                ' Устраняем дребезг прерывания
   MotorClick = 0 : Motor5 = 0 : MotorSel = &HFF
   Reset MotorPort.MotorNum
End Sub
End
$eepromhex
' EEPROM
$eeprom
SelfAddressDefault:
Data &HA0                                                   ' Собственный адрес по умолчанию
SelfSpiralCount:
Data 4
$data

Комментариев нет:

Отправить комментарий