![](https://habrastorage.org/webt/cv/-3/nm/cv-3nmacoqaavrrkb9d9b9l3_yi.jpeg)
Здравствуйте.
Описание библиотеки для считывания, декодирования и последующей отправки инфракрасных сигналов от различных бытовых пультов, с помощью микроконтроллера 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.с. Я поленился дефайнить всё это хозяйство. При выборе другого таймера в Кубе, нужно указать только канал и внутренний источник тактирования…
![](https://habrastorage.org/webt/qu/8k/6h/qu8k6huoesrtcdie_xrng0ibjpg.jpeg)
Всё остальное программа настроит сама. Если выбрать другой номер канала, то его тоже нужно переименовать в файле 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) декодирует полученный сигнал и выводит код кнопки, тип протокола и длину пакета…
![](https://habrastorage.org/webt/_z/ge/8m/_zge8m3ea55i6vp3io4mijon4eq.png)
Других пультов у меня нет.
Для отправки раскодированного сигнала используется функция с соответствующим названием…
sendSAMSUNG(0x707048b7, 32);
my_enableIRIn();
Функция my_enableIRIn() нужна обязательно, она отключает ШИМ и переводит таймер в режим приёма. Эта же функция используется для инициализации (перед бесконечным циклом). Из-за этой функции не удастся поймать свой собственный сигнал — это можно решить, но смысла в этом не вижу.
Если не удаётся определить тип протокола…
![](https://habrastorage.org/webt/ai/1r/7v/ai1r7vxuqa_xpwya9cm8f-bksfw.png)
… то в этом нет ничего страшного, код кнопки в любом случае получен.
Если нужно не только принимать неизвестный сигнал, но и отправлять его, тогда нужно раскомментировать строчки для «вывода данных в сыром виде»…
![](https://habrastorage.org/webt/dr/0w/am/dr0wamvf3u5ydzanvpnmhlqrkv8.png)
… и отправлять прочитанные данные с помощью функции 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.с, настройка в начале.
Это всё.
Библиотека