$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
Комментариев нет:
Отправить комментарий