ИК-пульт на stm32



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

    Описание библиотеки для считывания, декодирования и последующей отправки инфракрасных сигналов от различных бытовых пультов, с помощью микроконтроллера 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.с, настройка в начале.

    Это всё.

    Библиотека
    • +10
    • 3,8k
    • 9
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 9

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

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

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

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

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

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

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

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое