Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Исходники » NEC протокол. Прием и передача


NEC протокол. Прием и передача

Сообщений 1 страница 5 из 5

1

1. Прием команд NEC протокола. На LCD вывод 2-х байт адреса и 2-х байт команды. Проверка целостности данных только для байт команды, тк у меня пульты выдают 16 бит адреса(основа с сайта Bascom).

Код:
$regfile = "m328pdef.dat"
$crystal = 16000000
$hwstack = 32
$swstack = 24
$framesize = 24


'-------------------------------------------------------------------------------
' Конфигурация LCD
'-------------------------------------------------------------------------------
  Config Lcdpin = Pin , Rs = Portc.0 , E = Portc.1 , Db4 = Portc.2 , Db5 = Portc.3 , Db6 = Portc.4 , Db7 = Portc.5
'-------------------------------------------------------------------------------
  Config Lcd = 16 * 2                                       ' Используемый LCD
'-------------------------------------------------------------------------------

'-------------------------------------------------------------------------------
  Initlcd                                                   ' Инициализируем LCD
  Waitms 50                                                 ' Ждем пока все запустится
  Cursor Off Noblink                                        ' Выключаем неморгающий курсор
  Cls                                                       ' Очистка экрана
'-------------------------------------------------------------------------------
'       Конфигурация портов
'-------------------------------------------------------------------------------

Led Alias Portb.5                                           ' Индикатор приема пульта
Ir_in Alias Pind.2                                          ' Вход от IR датчика

Config Ir_in = Input
Set Ir_in

Config Led = Output
Reset Led

'-------------------------------------------------------------------------------
' Конфигурация таймеров
'-------------------------------------------------------------------------------

'Config Timer0 = Timer , Prescale = 256                                         ' 16000000/256 = 62500
'Tccr0b.cs02 = 1                                                                ' Запуск таймера с Prescale = 256




'-------------------------------------------------------------------------------
' Настройка прерываний
'-------------------------------------------------------------------------------

Config Int0 = Falling                                       'Прерывание по спаду
On Timer0 Tikers                                            'работа по таймеру
On Int0 Infrared                                            'работа по прерыванию

'-------------------------------------------------------------------------------
' Запуск прерываний
'-------------------------------------------------------------------------------

Enable Timer0                                               'разрешаем работу таймера0
Enable Int0                                                 'разрешаем работу прерывания0
Enable Interrupts                                           'Разрешаем прерывания

'-------------------------------------------------------------------------------
' Опеределение переменных
'-------------------------------------------------------------------------------

Dim Tik As Word                                             'счётчик тиков таймера
Dim Byt As Byte                                             'счётчик принятых бит
Dim Repeat_flag As Bit                                      'флаг повтора
Dim Start_flag As Bit                                       'флаг стартового условия
Dim Address As Byte                                         'байт адреса
Dim Address_inv As Byte                                     'байт адреса инверт
Dim Command As Byte                                         'байт команды
Dim Command_inv As Byte                                     'байт команды инверт
Dim Address_1 As Byte                                       'прямой байт адреса
Dim Command_1 As Byte                                       'прямой байт команды
Dim Address_0 As Byte                                       'инверсный байт адреса
Dim Command_0 As Byte                                       'инверсный байт команды
Dim Checked_flag As Bit                                  'флаг успешного приема команды
Dim Summa As Word
Dim S1 As String * 10
Dim S2 As String * 10
'-------------------------------------------------------------------------------


Set Led
Waitms 2000
Reset Led

Set Checked_flag                                            ' Для первоначального вывода на LCD

Do
    If Checked_flag = 1 Then

        Locate 1 , 1
        Lcd "Add:" ; Format(s1 , "       ")
        Locate 2 , 1
        Lcd "Com:" ; Format(s2 , "       ")

        Reset Checked_flag
    End If

    If Repeat_flag = 1 Then                                 ' Индикация NEC повтора
        Locate 2 , 13
        Lcd "R"
    Else
         Locate 2 , 13
        Lcd " "
    End If

Loop
End

'*******************************************************************************

 Tikers:                                                    'работа по таймеру

 Timer0 = 250                                               '62500/(256-250)=10416,66 Hz (96 мкс)
                                                             '252 - TV SAMSUNG, 250 - DVD SAMSUNG и другие NEC
 Incr Tik
 If Tik >= 1200 Then                                        'если время паузы (без сигнала) больше 110 мс, то прекращаем прием данных
 Tik = 0
 Repeat_flag = 0
 Start_flag = 0
 Address_1 = 0
 Command_1 = 0
 Address_0 = 0
 Command_0 = 0
 Reset Led
 Stop Timer0                                                'останавливаем таймер
 End If

  Return
'*******************************************************************************

 Infrared:                                                  'работа по прерыванию

  Tccr0b.cs02 = 1                                           'Start Timer0  'запускаем таймер
  Set Led
  If Tik >= 139 And Tik < 150 Then                          'если случилось от 139 до 150 тиков - "СТАРТ"
      Address = 1
      Repeat_flag = 0
      Start_flag = 1
      Address_1 = 0
      Command_1 = 0
      Address_0 = 0
      Command_0 = 0
  End If

  If Tik >= 116 And Tik < 139 Then                          'если случилось от 116 до 138 тиков - "ПОВТОР"
      Repeat_flag = 1
      Start_flag = 0
  End If

  If Tik >= 22 And Tik < 116 And Start_flag = 1 Then        'если случилось от 22 до 115 тиков - приняли "1"
   Incr Byt

    If Byt < 9 Then
     Shift Address_0 , Right
     Address_0.7 = 1
    End If

    If Byt >= 9 And Byt < 17 Then
     Shift Address_1 , Right
     Address_1.7 = 1
    End If

    If Byt >= 17 And Byt < 25 Then
     Shift Command_0 , Right
     Command_0.7 = 1
    End If

    If Byt >= 25 Then
     Shift Command_1 , Right
     Command_1.7 = 1
    End If
  End If

  If Tik >= 10 And Tik < 22 And Start_flag = 1 Then         'если случилось от 10 до 21 тика - приняли "0"
   Incr Byt

    If Byt < 9 Then
     Shift Address_0 , Right
    End If

    If Byt >= 9 And Byt < 17 Then
     Shift Address_1 , Right
    End If

    If Byt >= 17 And Byt < 25 Then
     Shift Command_0 , Right
    End If

    If Byt >= 25 Then
     Shift Command_1 , Right
    End If
  End If

 Tik = 0

  If Byt = 32 Then                                          'если приняли 4 байта, проверяем правильность приёма команды
                                                             'если адрес 16-ричный, проверка не проходит
    Address = Address_0
    Address_inv = Address_1
    S1 = Str(address)
    S1 = S1 + " "
    S1 = S1 + Str(address_inv)

    Summa = Command_0 + Command_1
        If Summa = 255 Then                                 ' Если сумма байт команды дает 255, значит данные приняты корректно
            Command = Command_0
            Command_inv = Command_1
            S2 = Str(command)
            S2 = S2 + " "
            S2 = S2 + Str(command_inv)
            Set Checked_flag
        Else
            Command = 0
            Command_inv = 0
            S2 = "err"
        End If

  Byt = 0
  Repeat_flag = 0
  Start_flag = 0
  Stop Timer0                                               'останавливаем таймер
  End If
 Return

0

2

2. Передача NEC команд (эмуляция пульта). ИК диод на ноге PORTD.6 напрямую (без ключа). Кнопка на PIND.0 на массу - собственно эмуляция пульта. Байты адреса и команды заданы переменными стационарно.

Код:
$regfile = "m328pdef.dat"                                   '
$crystal = 16000000                                         '
$hwstack = 32
$swstack = 24
$framesize = 24

'-------------------------------------------------------------------------------
'       Конфигурация портов
'-------------------------------------------------------------------------------                                                 '
Set Ddrd.6                                                  ' Настройка пина PORTD.6 на выход
Set Ddrb.5                                                  ' Настройка пина PORTB.5 на выход
Reset Ddrd.0                                                ' Настройка пина PORTD.0 на вход
Portd.0 = 1

Led Alias Portb.5                                           ' Светодиод индикации
Button Alias Pind.0                                         ' Кнопка - режим передачи данных NEC

'-------------------------------------------------------------------------------

'-------------------------------------------------------------------------------
' Конфигурация таймеров
'-------------------------------------------------------------------------------
Tccr0a.wgm01 = 1                                            ' Задаем режим ШИМ  CTC на TIMER0
'Tccr0a.com0a0 = 1                                           ' Подключение выхода ШИМ на PORTD.6
Tccr0b.cs00 = 1                                             ' Запуск таймера с   Prescale = 1

Ocr0a = 209                                                 ' Настройка частоты ШИМ F = 160000/2*Prescale*(1+Ocr0a)  = 38095 Гц


Tccr2a.wgm21 = 1                                            ' Задаем режим ШИМ  CTC на TIMER2
Tccr2b.cs21 = 1                                             ' Запуск таймера с   Prescale = 8

Ocr2a = 225                                                 ' Настройка частоты прерываний от TIMER2 F=16000000/Prescale*Ocr2a = 8888,88 Гц  = 112,5 мкс

Config Timer1 = Timer , Prescale = 64                       ' Настройка таймера1 на переполнение каждые Т= Prescale * 65536/F = 64*65536/16000000= 0.262144 сек
'-------------------------------------------------------------------------------

'-------------------------------------------------------------------------------
' Настройка прерываний
'-------------------------------------------------------------------------------
Timsk2.ocie2a = 1                                           ' Разрешаем прерывание по совпадению Compare Match A для TIMER2

Enable Timer1                                               ' Разрешаем прерывание по переполнению TIMER1
Start Timer1                                                ' Запуск TIMER1
Enable Interrupts                                           ' Разрешаем прерывания
On Compare2a Time_counter_nec                               ' Прерывания по совпадению для TIMER2. Для отсчета временных интервалов NEC протокола
On Timer1 Timer1_int                                        ' ПП обработки прерываний от TIMER1
'-------------------------------------------------------------------------------

'-------------------------------------------------------------------------------
' Опеределение переменных
'-------------------------------------------------------------------------------
Const Preset_110ms = 977                                    ' Предустановка счетчика на 110 мс
Const Preset_40ms = 360                                     ' Предустановка счетчика на 40 мс    для повтора
Const Preset_9ms = 80                                       ' Предустановка счетчика на 9 мс
Const Preset_4_5ms = 40                                     ' Предустановка счетчика на 4,5 мс
Const Preset_2_25ms = 20                                    ' Предустановка счетчика на 2,25 мс
Const Preset_1_6875ms = 15                                  ' Предустановка счетчика на 1,6875 мс
Const Preset_562_5us = 5                                    ' Предустановка счетчика на 562,5 мкс

Dim Count_110ms As Word                                     ' Cчетчик на 110 мс
Dim Count_40ms As Word                                      ' Cчетчик на 40 мс
Dim Count_9ms As Byte                                       ' Cчетчик на 9 мс
Dim Count_4_5ms As Byte                                     ' Cчетчик на 4,5 мс
Dim Count_2_25ms As Byte                                    ' Cчетчик на 2,25 мс
Dim Count_1_6875ms As Byte                                  ' Cчетчик на 1,6875 мс
Dim Count_562_5us As Byte                                   ' Cчетчик на 562,5 мкс

Dim Flag_110ms As Bit                                       ' Флаг запуска отрезка времени 110 мс
Dim Flag_40ms As Bit                                        ' Флаг запуска отрезка времени 40 мс
Dim Flag_9ms As Bit                                         ' Флаг запуска отрезка времени 9 мс
Dim Flag_4_5ms As Bit                                       ' Флаг запуска отрезка времени 4,5 мс
Dim Flag_2_25ms As Bit                                      ' Флаг запуска отрезка времени 2,25 мс
Dim Flag_1_6875ms As Bit                                    ' Флаг запуска отрезка времени 1,6875 мс
Dim Flag_562_5us As Bit                                     ' Флаг запуска отрезка времени 562,5 мкс

Dim Nec_bit_send As Byte                                    ' Кол-во отправленных бит
Dim Send_byte As Byte                                       ' Отправляемый байт
Dim Start_send_flag As Bit                                  ' Команда на отправку данных NEC
Dim Nec_repeat_flag As Bit                                  ' Флаг повтора передачи данных

Dim Address(2) As Byte                                      ' Адресс NEC устройства
Dim Command(2) As Byte                                      ' Команда NEC устройства

'-------------------------------------------------------------------------------

'-------------------------------------------------------------------------------
' Опеределение подпрограмм
'-------------------------------------------------------------------------------
Declare Sub Nec_send_command(nec_add0 As Byte , Nec_add1 As Byte , Nec_cmd0 As Byte , Nec_cmd1 As Byte)
Declare Sub Nec_send_repeat()
'-------------------------------------------------------------------------------


Address(1) = 97
Address(2) = 214
Command(1) = 9
Command(2) = 246

Do

    If Start_send_flag = 1 Then
        If Nec_repeat_flag = 0 Then Call Nec_send_command(address(1) , Address(2) , Command(1) , Command(2))       ' Вызов ПП отправки NEC данных
        If Nec_repeat_flag = 1 Then Call Nec_send_repeat()  ' Вызов ПП повторной отправки NEC данных
    End If
Loop

End

'-------------------------------------------------------------------------------
' Прерывание от TIMER2 каждые 112,5 мкс
'-------------------------------------------------------------------------------
Time_counter_nec:

    If Flag_9ms = 1 Then                                    ' 9мс для начала пакета. Модуляция
        Incr Count_9ms
        If Count_9ms = Preset_9ms Then
            Count_9ms = 0
            Reset Flag_9ms
            Tccr0a.com0a0 = 0                               ' Выключение модуляции
        End If
    End If

    If Flag_4_5ms = 1 Then                                  ' Пауза 4,5 мс в начале пакета
        Incr Count_4_5ms
        If Count_4_5ms = Preset_4_5ms Then
            Count_4_5ms = 0
            Reset Flag_4_5ms
        End If
    End If

    If Flag_1_6875ms = 1 Then                               ' Пауза. лог. 1 = 2,25 мс = 562,5 мкс + 1,6875 мс
        Incr Count_1_6875ms
        If Count_1_6875ms = Preset_1_6875ms Then
            Count_1_6875ms = 0
            Reset Flag_1_6875ms
        End If
    End If

    If Flag_562_5us = 1 Then                                ' начало бита даннных и оно же равно паузе в лог. 0
        Incr Count_562_5us
        If Count_562_5us = Preset_562_5us Then
            Count_562_5us = 0
            Reset Flag_562_5us
            Tccr0a.com0a0 = 0                               ' Выключение модуляции
        End If
    End If

    If Flag_40ms = 1 Then                                   ' Пауза. 40мс для окончания пакета
        Incr Count_40ms
        If Count_40ms = Preset_40ms Then
            Count_40ms = 0
            Reset Flag_40ms
        End If
    End If

    If Flag_2_25ms = 1 Then                                 ' 2,25мс пауза
        Incr Count_2_25ms
        If Count_2_25ms = Preset_2_25ms Then
            Count_2_25ms = 0
            Reset Flag_2_25ms
        End If
    End If

    If Flag_110ms = 1 Then                                  ' Длина пакета на повторе
        Incr Count_110ms
        If Count_110ms = Preset_110ms Then
            Count_110ms = 0
            Reset Flag_110ms
        End If
    End If


Return



'-------------------------------------------------------------------------------
' Обработка подпрограммы
'-------------------------------------------------------------------------------
Sub Nec_send_command(nec_add0 As Byte , Nec_add1 As Byte , Nec_cmd0 As Byte , Nec_cmd1 As Byte)       ' Отрпавка кода NEC

    Set Nec_repeat_flag                                     ' Сразу разрешаем повтор отправки NEC данных, пока нажата кнопка

    Set Flag_9ms                                            ' Начало отсчета 9 мс
    Tccr0a.com0a0 = 1                                       ' Включение модуляции
    Do                                                      ' Ждем окончания отрезка времени
    Loop Until Flag_9ms = 0

    Set Flag_4_5ms                                          ' Начало отсчета 4,5 мс
    Do                                                      ' Ждем окончания отрезка времени
    Loop Until Flag_4_5ms = 0

    Nec_bit_send = 0                                        ' Обнуляем кол-во отправленных бит
    Do                                                      ' Отправка бит данных
        Incr Nec_bit_send                                   ' Считаем количество бит отправленных данных
        Select Case Nec_bit_send                            ' Определение отправляемого байта
            Case 1
                Send_byte = Nec_add0
            Case 9
                Send_byte = Nec_add1
            Case 17
                Send_byte = Nec_cmd0
            Case 25
                Send_byte = Nec_cmd1
        End Select

        Set Flag_562_5us                                    ' Начало отсчета 562,5 мкс. Передача данных
        Tccr0a.com0a0 = 1                                   ' Включение модуляции
        Do
        Loop Until Flag_562_5us = 0

        If Send_byte.0 = 1 Then Set Flag_1_6875ms Else Set Flag_562_5us       ' В зависимости от значения передаваемого бита устанавливается длина паузы
        Shift Send_byte , Right                             ' Сдвиг битов вправо
        Do
        Loop Until Flag_562_5us = 0 And Flag_1_6875ms = 0   ' Ждем окончания отрезка времени
    Loop Until Nec_bit_send = 32

    Set Flag_562_5us                                        ' Начало отсчета 562,5 мкс. Обозначим окончание передачи последнего бита данных
    Tccr0a.com0a0 = 1                                       ' Включение модуляции
    Do
    Loop Until Flag_562_5us = 0

    Set Flag_40ms                                           ' Начало отсчета 40 мс   - окончание посылки для повтора
    Do                                                      ' Ждем окончания отрезка времени
    Loop Until Flag_40ms = 0
End Sub

'-------------------------------------------------------------------------------
' Обработка подпрограммы
'-------------------------------------------------------------------------------
Sub Nec_send_repeat()                                       ' Повтор отправки NEC
    Set Flag_110ms                                          ' Начало отсчета 110 мс
    Set Flag_9ms                                            ' Начало отсчета 9 мс
    Tccr0a.com0a0 = 1                                       ' Включение модуляции
    Do                                                      ' Ждем окончания отрезка времени
    Loop Until Flag_9ms = 0
    Set Flag_2_25ms                                         ' Начало отсчета 2,25 мс
    Do                                                      ' Ждем окончания отрезка времени
    Loop Until Flag_2_25ms = 0
    Set Flag_562_5us                                        ' Начало отсчета 562,5 мкс. Модуляция
    Tccr0a.com0a0 = 1                                       ' Включение модуляции
    Do
    Loop Until Flag_562_5us = 0
    Do
    Loop Until Flag_110ms = 0
End Sub


'-------------------------------------------------------------------------------
' Прерывание от TIMER1 каждые 0.262144 сек
'-------------------------------------------------------------------------------
Timer1_int:
    If Button = 0 Then
        Set Start_send_flag                                 ' Разрешаем отправки NEC данных
        Set Led                                             ' Индикация
    Else
        Reset Start_send_flag                               ' Останавливаем отправку NEC данных
        Reset Nec_repeat_flag                               ' Сбрасываем флаг повтора
        Reset Led                                           ' Индикация
    End If

Return

Настройка таймеров напрямую регистрами.
http://s3.uploads.ru/t/m5BKY.jpg
http://sd.uploads.ru/t/mMvdt.jpg
http://sf.uploads.ru/t/LAD6K.jpg
http://s1.uploads.ru/t/6yvLR.jpg
http://s6.uploads.ru/t/EOkqN.jpg

Управление таймером2 аналогичное.

Отредактировано MACTEPok (2016-05-13 15:44:14)

0

3

Mrshilov, спасибо. А есть такое же для передачи?

0

4

задача в лучших традициях извращенства. Устройство должно запомнить команды от нескольких пультов. Затем на это устройство через ардуиновский шилд Ehternet  будут приходить задания воспроизводить NEC команды.
Начальник хочет управлять TV приставкой и сопутствующими приблудами. Приставка одна, теликов 2. Задача переключать каналы на приставке, находясь у телика (телик №2 находится в другом помещении и этаже)

Отредактировано MACTEPok (2016-05-13 20:41:38)

0

5

Классный подход, мне понравился. На асме перепишу для себя, штоб побыстрее работало.

0


Вы здесь » Программирование ATMEL в BASCOM. » Исходники » NEC протокол. Прием и передача