05:44


Копироание статей сайта без уведомления администрации сайта ЗАПРЕЩЕНО!!!
Манчестер кодирование - Форум
Приветствую Вас, Гость · RSS 19.03.2024, 05:44

[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Форум » Программирование - Bascom AVR » Исходники » Манчестер кодирование
Манчестер кодирование
YuriyДата: Вторник, 24.01.2017, 19:43 | Сообщение # 1
Master
Группа: Администраторы
Сообщений: 54
Награды: 2
Репутация: 101
Статус: Offline
Код
'###############################################################################
'
'
'        Библиотека обработки приема данных с кодированием Manchester
'
'        В библиотеке задействованы ресурсы MK:
'        * Таймер T0 (для подсчета длительности импульсов мanchester сигнала)
'        * Линия внешнего прерывания Int0 (вход сигнала)
'
'        Ресурсы контроля и управления:
'        * Transmit - бит флаг активности режима передачи пакета (1=идет передача)
'        * Man_in_line - порт приема должен быть порт INT0 (Man_in_line Alias Pin_x.x)
'        * Man_out_line - порт отправки (Man_out_line Alias Port_х.х)
'        * Rcvdata_check (возвращает количество принятых байт) - функция проверки наличии данных
'        * Transmit_start (количество отправляемых байт) - программа отправки данных из буффера Manbuffer ()
'        * Receive_start - программа инициализации и старта приема данных, по приему пакета останавливается.
'
'
'                          Programmed By Yuriy.pv
'                          
'
'###############################################################################

'Const $crystal = 8000000                    'Частота МК
Const Man_speed = 1000                    '800-4000 бит\сек - частота Manchester cигнала
Const Man_period_len = 125                    '$crystal / 64 / MAN_SPEED - длит периода MANCHESTER сигнала (в тиках таймера)
Const Period_1_2 = 194                    'Period 1/2 = 256-(Man_period_len/2)
Const Period_2_3 = 83                    'Period 2/3 = Man_period_len*2/3
Const Period_3_4 = 163                    'Period 3/4 = 256-(Man_period_len*3/4)

Const Man_pilot_len = 1                    '1-16 бит. Длина пилотного сигнала
Const Man_buf_length = 2                    '1-255 байта, размер буфера данных
Const Man_identifier_length = 2                             '1-16 байта, размер идентификатора пакета
Dim Man_identifier As String * Man_identifier_length
Dim Manidentifier(man_identifier_length) As Byte At Man_identifier Overlay       'идентификационный заголовок сообщения

    Man_identifier = "sh"                    '1-16 латинских символов должно = Man_identifier_length. строковый - идентификатор пакета

Dim Manbuffer(man_buf_length) As Byte                       'буфер для накопления принимаемых Manchester данных
Dim Checksumm_byte As Byte                    'байт подсчета CRC
Dim Bit_counter As Byte                    'счетчик количества принятых бит
Dim Byte_counter As Byte                    'счетчик принимаемых байтов
Dim Byte_in_out As Byte                    'накопитель принимаемого \ контейнер передаваемого - байта
Dim Data_length As Byte                    'длина блока данных в принимаемой\передаваемой серии (может быть <= MAN_BUF_LENGTH)

Dim Manflags_temp As Byte
Dim Manflags As Byte                    'байт флагов
    Data_enbl Alias Manflags.0                    'флаг наличия в буфере принятых данных
    Tim0_ovf Alias Manflags.1                    'флаг наличия переполнения Т0
    Flag_pilot Alias Manflags.2                             'флаг окончания пилотного сигнала
    Header_rcv Alias Manflags.3                             'флаг приема заголовка
    Line_inv Alias Manflags.4                    'флаг необходимости инверсии сигнала в линии
    Transmit_stop Alias Manflags.5                          'флаг завершения передачи
    Bit_part_num Alias Manflags.6                           'флаг младшей\старшей половины бита при передаче
    Transmit Alias Manflags.7                    'флаг активности режима передачи пакета

Dim Timer_val As Byte                    'значение таймера
Dim Temp_lib As Byte
'Dim Byte_ As Byte

'######################### Функции и подпрограммы ##############################
Declare Sub Init_
Declare Sub Receive_start
Declare Sub Receive_stop
Declare Sub Checksumm(byval Data_ As Byte)
Declare Sub Transmit_start(byval Count As Byte)
Declare Function Rcvdata_check As Byte

Config Pind.2 = Input : Man_in_line Alias Pind.2            'порт приема (должен быть порт INT0)
Config Portd.3 = Output : Man_out_line Alias Portd.3

'###########################  Главный цикл  ####################################
Dim Temp As Byte
Dim Tempw As Word

Print "Test Manchester"
Call Init_
Call Receive_start
Do
   Tempw = Rcvdata_check()
   If Tempw > 0 Then
     ' Set Led
      For Temp = 1 To Tempw
        Print "Rcvdata_check() = 1    data out=" ; Manbuffer(temp)
      Next
     ' Reset Led
      Call Receive_start
   End If

Loop

'###############################################################################

Sub Init_                    'Инициализация
   Disable Interrupts
   Config Timer0 = Timer , Prescale = 64                    'предделитель на 64 (частота счета 8000000 / 64 = 125000 Hz)
   On Timer0 Timer_ovf_vector:                    'вектор прерывания при переполнении
   Enable Timer0
   Config Int0 = Change                    'прерывание по любому изменению уровня INT0
   On Int0 Int0_vector:                    'вектор прерывания INT0
   Enable Interrupts
End Sub

Sub Receive_start                    'Инициализация и старт приема данных
   Transmit = 0
   Data_enbl = 0                    'очистить флаг наличия данных
   Tim0_ovf = 0                    'и флаг переполнения
   Header_rcv = 1                    'включить режим приема заголовка
   Byte_counter = 0                    'начать прием с начала
   Byte_in_out = 0                    'очистить байт приемник
   Start Timer0
   Enable Timer0
   Gifr.6 = 1                    'сбросить возможно проскочившее прерывание
   Enable Int0
End Sub

Sub Receive_stop                    'Останов приема данных
   Stop Timer0                    'выключить прерывание при переполнении Т0
   Disable Int0                    'выключить внешнее прерывание от INT0
End Sub

Function Rcvdata_check                    'Проверка наличия Manchester данных в буфере
   If Data_enbl = 1 Then                    'проверка наличия принятых данных если есть,
      Data_enbl = 0                    'очистить флаг наличия данных
      Rcvdata_check = Data_length                           'при наличии данных - возвращаем количество принятых байт
   Else
      Rcvdata_check = 0
   End If
End Function

Sub Transmit_start(byval Count As Byte)
    Call Receive_stop()
    Checksumm_byte = 0
    Call Checksumm(count)                    'подсчет контрольной суммы пакета для передачи
    For Temp_lib = 1 To Count
       Call Checksumm(manbuffer(temp_lib))                  'подсчет контрольки пакета
    Next
    Byte_in_out = 128                    'для передачи пилот сигнала
    Byte_counter = 0                    'до 0 - передача пилота, а от 0 до sizeof(MAN_IDENTIFIER)  - передача идентификатора
    Data_length = Count                    'передать столько байт из буфера
    Flag_pilot = 0
    Bit_part_num = 0 : Transmit_stop = 0                    'сбросить флаги
    Transmit = 1 : Header_rcv = 1                           'включить режим передачи заголовка
    Start Timer0                    'включить "прерывание при переполнении Т0"
End Sub

  Sub Checksumm(byval Data_ As Byte)
'CheckSummByte - глобальная переменная контрольной суммы
'в начале обмена необходимо обнулить CheckSummByte
   Local Temp As Byte
   Local I As Byte

   For I = 1 To 7

     Temp = Data_
     Temp = Temp Xor Checksumm_byte

     If Temp.0 = 1 Then
       Checksumm_byte = Checksumm_byte Xor 24
       Temp = 128
     Else
       Temp = 0
     End If

     Shift Checksumm_byte , Right
     Checksumm_byte = Checksumm_byte Or Temp
     Shift Data_ , Right

   Next

End Sub

Timer_ovf_vector:                    'Обработка прерывания при переполнении TIMER0
   'Byte_ = Byte_in_out

  'Если включена передача
   If Transmit = 1 Then

      Timer0 = Period_1_2

     'начало передачи первой чсти бита
      If Bit_part_num = 0 Then
         If Byte_in_out.7 = 1 Then
            Man_out_line = 0
         Else
            Man_out_line = 1
         End If

         If Transmit_stop = 1 Then
            Stop Timer0
            Transmit = 0
         End If
      Else
        'Начало передачи второй части бита
         If Byte_in_out.7 = 1 Then
            Man_out_line = 1
         Else
            Man_out_line = 0
         End If
         Shift Byte_in_out , Left                           'сдвигаем биты в передаваемом байте
         Incr Bit_counter

        'Если это пилот или заголовок
         If Header_rcv = 1 Then
           'Если это пилот
            If Byte_counter < Man_pilot_len And Flag_pilot = 0 Then
               Byte_in_out = 128                            'для передачи бита 1
               Incr Byte_counter
               If Byte_counter = Man_pilot_len Then
                  Byte_in_out = Manidentifier(1)
                  Bit_counter = 0                           'счетчик переданных бит
                  Flag_pilot = 1
                  Byte_counter = 1
               End If
           'Если это заголовок
            Elseif Bit_counter = 8 Then                     'если переданы все биты байта

               Bit_counter = 0

               If Byte_counter = Man_identifier_length Then 'если ноль - значит конец строки идентификатора
                  Header_rcv = 0
                  Byte_counter = 0
                  Byte_in_out = Data_length
               Else
                  Incr Byte_counter
                  Byte_in_out = Manidentifier(byte_counter)
               End If

            End If

        'Если это передача блока данных
         Elseif Bit_counter = 8 Then                        'если переданы все биты байта
            Bit_counter = 0
            If Byte_counter < Data_length Then              'передаем основной блок данных
               Incr Byte_counter
               Byte_in_out = Manbuffer(byte_counter)
            Elseif Byte_counter = Data_length Then          'передаем контрольную сумму
               Byte_in_out = Checksumm_byte
               Incr Byte_counter
            Else                    'завершение передачи
               Transmit_stop = 1                            'установить флаг завершения передачи
               Byte_in_out = 128                            '128                    'для сброса линии в 0
            End If
         End If
      End If

      Toggle Bit_part_num                    'меняем состояние флага младшей\старшей половины бита

   Else

     'Если включен прием
      If Gicr.6 = 1 Then                    'если ожидали внеш прерывания INT0 то
         Tim0_ovf = 1                    'отметить переполнение
      Else                    'если внеш прерывания INT0 были выключены то
         Gifr.6 = 1                    'сбросить возможно проскочившее прерывание
         Enable Int0
      End If
   End If

   'Byte_in_out = Byte_
Return

Int0_vector:                    'Обработка внешнего прерывания INT0
   Byte_in_out = Byte_in_out

   Timer_val = Timer0
   Timer0 = Period_3_4                    'счетчик таймера настроить на 3/4 длины периода MANCHESTER бита данных
   Disable Int0
   Gifr.6 = 1                    'сбросить возможно проскочившее прерывание

  'задвигаем принятый бит
   Shift Byte_in_out , Left                    'сдвигаем байт перед записью бита
   If Man_in_line <> 0 Then Byte_in_out.0 = 1

  'проверка на корректность длительности замера (измеряли начиная с 1/4 бита до середина бита (момент перепада)
   If Timer_val > Period_2_3 Or Tim0_ovf = 1 Then
Init:
      Tim0_ovf = 0                    'сбросить флаг переполнения
      Header_rcv = 1                    'ожидать прием заголовка
      Byte_counter = 0                    'начать прием с начала
      Byte_in_out = 0                    'очистить байт приемник
   End If

  'крутимся тут до окончания приема хедера
   If Header_rcv = 1 Then

     If Byte_counter = 0 Then                    'крутимся тут пока не совпадет первый байт хедера

       If Byte_in_out = Manidentifier(1) Then
          Line_inv = 0                    'сбросить флаг инверсии
          Bit_counter = 0                    'готовимся к приему следующих байтов хедера
          Incr Byte_counter
          Incr Byte_counter
       End If

       Toggle Byte_in_out
       If Byte_in_out = Manidentifier(1) Then
          Line_inv = 1                    'инверсное совпадение
          Bit_counter = 0                    'готовимся к приему следующих байтов хедера
          Incr Byte_counter
          Incr Byte_counter
       End If
       Toggle Byte_in_out

       Goto Return_
     End If

    'принимаем остальные байты хедера и байт длины пакета
     Incr Bit_counter
     If Bit_counter < 8 Then Goto Return_                   'ждем заполнения байта
     If Line_inv = 1 Then Toggle Byte_in_out                'если сигнал инверсный

     If Byte_counter <= Man_identifier_length Then          'если хедер еще не закончен
       If Byte_in_out <> Manidentifier(byte_counter) Then Goto Init       'проверяем идентичность хедера
       Bit_counter = 0                    '
       Incr Byte_counter                    'ожидаем следующий байт хедера
       Goto Return_
     End If

    'хедер закончился, значит принят байт длины блока данных
     If Byte_in_out > Man_buf_length Then Goto Init         'размер блока данных превышает допустимый - рестарт
     Data_length = Byte_in_out                    'запомним длину пакета

     Header_rcv = 0                    'заголовок принят переходим к приему основного файла
     Bit_counter = 0
     Byte_counter = 0
     Goto Return_

   End If

  'принимаем основной блок данных
   Incr Bit_counter
   If Bit_counter < 8 Then Goto Return_                     'ждем накопления байта
   Bit_counter = 0

   If Line_inv = 1 Then Toggle Byte_in_out                  'необходима ли инверсия

   If Byte_counter < Data_length Then                       'если это еще байты пакета
     Incr Byte_counter
     Manbuffer(byte_counter) = Byte_in_out                  'сохраняем принятый байт
   Else                    'если пакет закончен
     Checksumm_byte = 0                    'очистить байт контрольной суммы
     Call Checksumm(data_length)                            'подсчет контрольки длинны пакета
     For Temp_lib = 1 To Data_length
        Call Checksumm(manbuffer(temp_lib))                 'подсчет контрольки пакета
     Next
     If Checksumm_byte <> Byte_in_out Then Goto Init        'если контролька не верна (не 0) - рестарт                    'Контролька правильная
     Data_enbl = 1                    'установить флаг наличия данных
     Call Receive_stop()                    'тормозим дальнейший прием
   End If

   Return_:
  ' Byte_in_out = Byte_
Return
 
Форум » Программирование - Bascom AVR » Исходники » Манчестер кодирование
  • Страница 1 из 1
  • 1
Поиск:

Copyright Elektron © 2024

Яндекс цитирования Проверка PR и ТИЦ