Здравствуйте.

Описание библиотеки для считывания, декодирования и последующей отправки инфракрасных сигналов от различных бытовых пультов, с помощью микроконтроллера stm32. За основу взята билиотека IRremote для ардуино, и адаптирована под stm32.

Библиотека использует один таймер, и для приёма, и для отправки сигнала. Приёмник подключается к любому пину (GPIO_Input), а передатчик к одному из каналов таймера работающего в режиме PWM Generation (ШИМ). В примере используется первый канал таймера №4 — PB6 (передатчик) и пин PB5 (приёмник).

Для приёма сигнала таймер работает в режиме прерывания — каждые 50 мкс проверяет состояние входного пина, а при передаче переключается в режим PWM Generation, посылает сигнал, и снова переходит в режим прерывания.

Настройки находятся в файле IRremote.h

extern TIM_HandleTypeDef htim4;

// настройка таймера для приема - переполнение каждые 50 мкс (в данном случае системная частота 72Мгц)
#define MYPRESCALER 71 // получаем частоту 1МГц
#define MYPERIOD 49    // 50 мкс

// настройка таймера для отправки - указать системную частоту таймера
#define MYSYSCLOCK 72000000

// настройка пина для приёма recive_IR
#define RECIV_PIN (HAL_GPIO_ReadPin(recive_IR_GPIO_Port, recive_IR_Pin))

Если будете настраивать другой таймер, то нужно указать соответствующее имя структуры — htim4, и то же самое проделать в файлах IRremote.с и irSend.с. Я поленился дефайнить всё это хозяйство. При выборе другого таймера в Кубе, нужно указать только канал и внутренний источник тактирования…



Всё остальное программа настроит сама. Если выбрать другой номер канала, то его тоже нужно переименовать в файле irSend.с.

С остальными настройками думаю всё ясно — исходя из системной частоты (в примере 72МГц) подставляются значения предделителя и переполнения для прерывания каждые 50 мкс. Далее указывается частота и чтение пина.

Ниже есть дефайны, которые определяют задействованные протоколы…

//////////////////////////////////// активированные протоколы ////////////////////////////////////////
#define DECODE_RC5           1 // чтоб отключить декодирование протокола RC5 нужно указать 0
#define SEND_RC5             1 // чтоб отключить отправку сигнала по протоколу RC5 нужно указать 0

#define DECODE_RC6           1
#define SEND_RC6             1
...

Отключение ненужных протоколов уменьшает размер программы. В принципе можно вообще выпилить функции неиспользуемых протоколов и соответствующие файлы (файлы имеют характерные имена).

Программа предельно простая, функция my_decode(&results) декодирует полученный сигнал и выводит код кнопки, тип протокола и длину пакета…



Других пультов у меня нет.

Для отправки раскодированного сигнала используется функция с соответствующим названием…

sendSAMSUNG(0x707048b7, 32); 
my_enableIRIn();

Функция my_enableIRIn() нужна обязательно, она отключает ШИМ и переводит таймер в режим приёма. Эта же функция используется для инициализации (перед бесконечным циклом). Из-за этой функции не удастся поймать свой собственный сигнал — это можно решить, но смысла в этом не вижу.

Если не удаётся определить тип протокола…


… то в этом нет ничего страшного, код кнопки в любом случае получен.

Если нужно не только принимать неизвестный сигнал, но и отправлять его, тогда нужно раскомментировать строчки для «вывода данных в сыром виде»…



… и отправлять прочитанные данные с помощью функции sendRaw()…

uint8_t khz = 38; // частоту указать экспериментальным путём, основные используемые от 36 до 40 кГц
unsigned int raw_signal[] = {1300, 400, 1300, 400, 450, 1200, 1300, 400, 1300, 400, 450, 1200, 500, 1200, 450, 1250, 450, 1200, 500, 1200, 450, 1250, 1300};

sendRaw(raw_signal, sizeof(raw_signal) / sizeof(raw_signal[0]), khz); 
my_enableIRIn(); // переинициализирование приёма (нужна обязательно)

У меня отправка в «сыром виде» работает плохо.

В библиотеке используется счётчик DWT для микросекундных задержек. На сколько я знаю он есть не у всех stm32, и возможно что не везде одинаково настраивается. Если у вашего камня нет DWT, то надо что-то придумать на замену в функции custom_delay_usec(unsigned long us) в конце файла irSend.с, настройка в начале.

Это всё.

Библиотека

Комментарии (8)


  1. Nick_Shl
    20.06.2019 21:35
    +1

    Для приёма сигнала таймер работает в режиме прерывания — каждые 50 мкс проверяет состояние входного пина
    Зачем? Настраиваем вход на Rising/Falling прерывание, а в обработчике смотрим состояние пина и берём значение из таймера сколько прошло с предыдущего прерывания, потом обнуляем таймер.


    1. devprodest
      20.06.2019 21:48
      +3

      У меня другой вопрос. Зачем статья на Хабре о том как "я портировал простую Ардуино библиотеку под стм"?


      1. Foxek
        20.06.2019 23:38

        Особенно с учётом того, что информации здесь практически нет)


        1. u_235
          21.06.2019 00:00

          С учётом дословной копипасты https://istarik.ru/blog/stm32/125.html


          1. Xalium
            21.06.2019 04:15

            а почему автор данного поста должен изменять свой собственный текст, а не просто копипастить его?


            1. u_235
              21.06.2019 06:01

              Изменять текст стоило бы для исправления ошибок и для указания, что текст был опубликован на другом ресурсе именно автором, а не кем то другим.


              1. Xalium
                22.06.2019 09:13
                -1

                1. Если бы автор исправлял ошибки, то исправлял бы в обоих местах, так что текст все равно совпадал бы
                2. Авторство и так видно, если сравнить ник автора и слово в верхнем-левом углу на сайте автора (слово «stD»)
                3. Чего-то многие пишут посты одновременно на хабр и на своем сайте и почему-то никто не возникает


  1. b_t
    24.06.2019 12:25

    Спасибо!