В данной статье мы рассмотрим подключение к микроконтроллерам PIC радиочастотных модулей и осуществим передачу данных между ними используя радиосвязь.
В данном проекте мы будем осуществлять следующие основные операции:
- Мы будем подключать к микроконтроллеру PIC16F877A модуль передатчика, а к микроконтроллеру PIC18F4520 – модуль приемника.
- Мы будем подключать к микроконтроллеру PIC ЖК дисплей и клавиатуру 4х4.
- На передающей стороне мы будем передавать по радиоканалу данные, водимые на клавиатуре, а на приемной стороне мы будем принимать их и отображать на экране ЖК дисплея.
- Мы будем использовать микросхемы кодера и декодера для передачи 4 битных данных.
- Радиосвязь будет осуществляться на частоте 433 МГц с помощью дешевых радиочастотных модулей.
Для лучшего понимания материала данной статьи рекомендуем ознакомиться с проектами подключения к микроконтроллеру PIC ЖК дисплея и матричной клавиатуры 4×4.
Также на нашем сайте мы рассматривали использование радиочастотных модулей в следующих проектах:
Необходимые компоненты
- Микроконтроллер PIC16F877A (купить на AliExpress).
- Микроконтроллер PIC18F4520.
- Программатор PICkit 3 (купить на AliExpress).
- ЖК дисплей 16х2 (купить на AliExpress).
- Матричная клавиатура 4х4 (купить на AliExpress).
- Радиочастотный модуль (передающая и приемная часть) (купить на AliExpress).
- Микросхемы HT12D и HT12E (купить на AliExpress).
- Кварцевый генератор 20 МГц (купить на AliExpress).
- Конденсаторы 33 пФ (2 шт.) (купить на AliExpress).
- Резисторы 4,7 кОм, 33 кОм, 1 МОм (купить на AliExpress).
- Потенциометр 10 кОм (купить на AliExpress).
- Макетная плата (2 шт.) и соединительные провода.
Реклама: ООО «АЛИБАБА.КОМ (РУ)» ИНН: 7703380158
Передающий и приемный радиочастотный модули 433 МГц
Это одни из самых дешевых радиомодулей, работающих на частоте 433 МГц. Они позволяют осуществлять передачу последовательных данных по одному каналу, используя амплитудную модуляцию. Данные передаются со скоростью 4 кбит/с.
В спецификациях на данные модули указано, что модуль передатчика может запитываться от напряжения 3.5-12V и может осуществлять передачу данных на расстояния 20-200 метров. Излучаемая в эфир мощность сигнала составляет 10 мВт.
Распиновка модуля передатчика 433 МГц приведена на следующем рисунке.
Как мы видим, у модуля всего три контакта – VCC, DATA и GND. Также к модулю можно самостоятельно припаять антенну в специально отведенном для этого месте.
Приемный модуль работает от напряжения 5V dc и осуществляет прием сигнала на частоте 433,92 МГц. Его чувствительность составляет -105 дБ.
Распиновка приемного модуля приведена на следующем рисунке.
Как мы видим, он имеет 4 контакта – VCC, DATA, DATA и GND. Средние 2 контакта соединены вместе внутри модуля. Можно использовать или один контакт данных, или два, но лучше использовать два для лучшей борьбы с помехами.
Потенциометр в центре приемного модуля используется для калибровки частоты. Если связи нет, то одной из причин этого может быть несовпадение частот передающего и приемного модуля, помочь с решением этой проблемы как раз может регулировка частоты настройки приемного модуля. На приемном модуле также имеет специальное место куда можно припаять антенну.
Дальность связи зависит от величины питающего напряжения, подаваемого на передающий модуль, и от характеристик антенн обоих модулей. Для нашего проекта мы не использовали внешних антенн и запитывали передающий модуль от напряжения 5V. На дистанции 5 метров радиосвязь в нашем проекте работала отлично.
Необходимость использования кодера и декодера
Используемые нами радиочастотные модули имеют следующие недостатки:
- Один способ связи.
- Только один канал.
- Сильная подверженность помехам.
В связи с этими недостатками вместе с радиочастотными модулями целесообразно использование микросхем кодера и декодера, HT12D и HT12E. Буква D обозначает декодер, который будет использоваться на приемной стороне, а буква E – кодер, который будет использоваться на передающей стороне. Эти микросхемы кодера и декодера обеспечивают 4 канала для связи. Также связи с кодированием и декодированием информации уменьшается уровень шумов (помех).
Внешний вид и распиновка микросхем HT12D и HT12E приведена на следующем рисунке.
Обе микросхемы идентичны. Их контакты с A0 по A7 используются для кодирования информации. Мы можем использовать микроконтроллер для управления этими контактами и установки конфигурации микросхемы. Такая же самая конфигурация должна быть установлена и на другой стороне.
Эти 8 контактов можно подключить к Gnd или VCC или оставить не подключенными. Какую бы конфигурацию вы не выбрали в кодере, точно такую же конфигурацию необходимо использовать и в декодере. В нашем проекте мы эти 8 контактов оставили не подключенными.
Важной частью микросхем кодера и декодера являются контакты OSC, к которым подключаются резисторы для обеспечения их колебаний. Обычно для микросхемы кодера требуется резистор большего номинала (в нашем случае 1 МОм) чем для микросхемы декодера (в нашем случае 33 кОм).
Контактом данных в модуле, подключаемом к передатчику, является контакт DOUT, а подключаемым к модулю приемника – DIN.
В микросхеме HT12E контакты с AD8 по AD11 являются 4-мя входными каналами, которые после преобразования последовательно передаются с помощью радиочастотного модуля. В микросхеме декодера происходят обратные процессы – последовательные данные принимаются и декодируются и на его выходе мы получаем 4 параллельных выходных канала на контактах с D8 по D11.
Схема проекта
Схема передающей части проекта представлена на следующем рисунке.
Внешний вид собранной конструкции передающей части проекта показан на следующем рисунке.
Схема приемной части проекта представлена на следующем рисунке.
Внешний вид собранной конструкции приемной части проекта показан на следующем рисунке.
Объяснение программы для микроконтроллеров PIC
Полный код программ передающей и приемной частей проекта приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.
Код для передающей части
Первым делом в программе мы должны установить биты конфигурации микроконтроллера, определить ряд макросов, подключить необходимые библиотеки и задать тактовую частоту работы микроконтроллера. Контакты AD8-AD11 микросхемы кодера будут у нас обозначены как RF_TX на PORTD.
Мы будем использовать две функции, void system_init(void) и void encode_rf_sender (char data). Функция system_init используется для инициализации контактов микроконтроллера и инициализации клавиатуры, которая осуществляется из библиотеки для работы с клавиатурой (keypad library).
Порт, к которому подключена клавиатура, также настраивается в keypad.h. Мы задали режим работы его контактов на вывод данных с помощью команды TRISD = 0x00 и установили RF_TX в 0x00 по умолчанию.
1 2 3 4 5 |
void system_init(void){ TRISD = 0x00; RF_TX = 0x00; keyboard_initialization(); } |
В функции encode_rf_sender мы будем изменять состояние 4-х контактов микросхемы кодера в зависимости от нажатой клавиши на клавиатуре. Всего у нас будет 16 различных шестнадцатеричных значений, соответствующих 16 кнопкам клавиатуры.
1 2 3 4 5 6 7 8 |
void encode_rf_sender (char data){ if(data=='1') RF_TX=0x10; if(data=='2') RF_TX=0x20; if(data=='3') ……… …. .. …. …. |
В функции main мы сначала будем определять нажатую на клавиатуре клавишу с помощью switch_press_scan() и сохранять ее в соответствующей переменной. После этого мы будем кодировать данные с помощью функции encode_rf_sender() и изменять состояние контактов PORTD.
Код для приемной части
Первым делом мы установим биты конфигурации в микроконтроллере PIC18f4520, их установка будет немного отличаться от установки битов конфигурации для микроконтроллера PIC16F877A.
Также мы подключим заголовочный файл библиотеки для работы с ЖК дисплеем. Настроим соединение с D8-D11 микросхемы декодера через PORTD с помощью команды #define RF_RX PORTD. Настройка работы порта, к которому подключен ЖК дисплей, осуществляется в файле lcd.c.
1 2 3 |
#include <xc.h> #include "supporing_cfile\lcd.h" #define RF_RX PORTD |
Поскольку мы будем использовать внутренний генератор микроконтроллера PIC18f4520, то мы запрограммируем функцию system_init, в которой мы сконфигурируем регистр OSCON микроконтроллера чтобы настроить его внутренний генератор на частоту 8 MHz. Также мы настроим биты TRIS для контактов, к которым подключен ЖК дисплей, и микросхема декодера. Поскольку выходные контакты D8-D11 микросхемы декодера HT-12D подключены к PORTD микроконтроллера, то мы должны настроить его контакты в режим работы на ввод данных.
1 2 3 4 5 6 |
void system_init (void){ OSCCON = 0b01111110; // 8Mhz, , intosc //OSCTUNE = 0b01001111; // PLL enable, Max prescaler 8x4 = 32Mhz TRISB = 0x00; TRISD = 0xFF; // Last 4 bit as input bit. } |
Итого, мы настроим регистр OSCON на частоту 8 MHz, port B сконфигурируем для работы на вывод данных, а port D – на ввод данных.
Далее в функции void rf_analysis мы будем декодировать принятое шестнадцатеричное значение, определять по нему нажатую на передающей части клавишу и отображать ее на ЖК дисплее.
1 2 3 4 5 6 7 8 |
void rf_analysis (unsigned char recived_byte){ if(recived_byte==0x10) lcd_data('1'); if(recived_byte==0x20) lcd_data('2'); if(recived_byte==0x30) ……. ….. … … ……….. |
Функция lcd_data вызывается из файла.
В функции main мы сначала будем инициализировать систему и ЖК дисплей. Затем мы будем принимать байт, переданный по радиоканалу с передающей части, определять по нему нажатую клавишу и выводить ее на экран ЖК дисплея.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
void main(void) { unsigned char byte = 0; system_init(); lcd_init(); while(1){ lcd_com(0x80); lcd_puts("CircuitDigest"); lcd_com (0xC0); byte = RF_RX; rf_analysis(byte); lcd_com (0xC0); } return; } |
Перед тестированием работы проекта необходимо настроить схему. Первым делом нам необходимо нажать клавишу ‘D’ на клавиатуре. Через радиоканал при этом должно передаться значение 0xF0, на ЖК дисплее должен отобразиться символ ‘D’. Иногда модули правильно настроены уже на заводе-изготовителе, но это не всегда так. Если при нажатии клавиши в нашем проекте ничего не происходит это может свидетельствовать о том, что не настроен модуль приемника. В этом случае с помощью соответствующего регулятора на модуле приемника необходимо настроить частоту его работы. После этого схема должна начать работать должным образом.
Более подробно работу проекта вы можете посмотреть на видео, приведенном в конце статьи.
Исходный код программы
Код для передающей части
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
/* * File: main.c * Author: Sourav Gupta * By:- circuitdigest.com * Created on April 13, 2018, 2:26 PM */ // PIC16F877A Configuration Bit Settings // 'C' source line config statements // CONFIG #pragma config FOSC = HS // Oscillator Selection bits (HS oscillator) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled) #pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3/PGM pin has PGM function; low-voltage programming enabled) #pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off) #pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control) #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off) #include <xc.h> #include <stdio.h> #include <string.h> #include "supporing_cfile/Keypad.h" #define RF_TX PORTD /* Hardware related definition */ #define _XTAL_FREQ 200000000 //Crystal Frequency, used in delay /* Other Specific definition */ void system_init(void); void encode_rf_sender (char data); void main(void){ system_init(); char Key = 'n'; while(1){ Key = switch_press_scan(); encode_rf_sender(Key); } } /* * System Init */ void system_init(void){ TRISD = 0x00; RF_TX = 0x00; keyboard_initialization(); } void encode_rf_sender (char data){ if(data=='1') RF_TX=0x10; if(data=='2') RF_TX=0x20; if(data=='3') RF_TX=0x30; if(data=='4') RF_TX=0x40; if(data=='5') RF_TX=0x50; if(data=='6') RF_TX=0x60; if(data=='7') RF_TX=0x70; if(data=='8') RF_TX=0x80; if(data=='9') RF_TX=0x90; if(data=='0') RF_TX=0x00; if(data=='*') RF_TX=0xa0; if(data=='#') RF_TX=0xb0; if(data=='A') RF_TX=0xc0; if(data=='B') RF_TX=0xd0; if(data=='C') RF_TX=0xe0; if(data=='D') RF_TX=0xf0; } |
Код для приемной части
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
/* * File: main.c * Author: Sourav Gupta *CircuitDigest.com * Created on 17 May 2018, 12:18 */ // PIC18F4520 Configuration Bit Settings // 'C' source line config statements // CONFIG1H #pragma config OSC = INTIO7 // Oscillator Selection bits (Internal oscillator block, CLKO function on RA6, port function on RA7) #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled) #pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled) // CONFIG2L #pragma config PWRT = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config BOREN = SBORDIS // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled)) #pragma config BORV = 3 // Brown Out Reset Voltage bits (Minimum setting) // CONFIG2H #pragma config WDT = ON // Watchdog Timer Enable bit (WDT enabled) #pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768) // CONFIG3H #pragma config CCP2MX = PORTC // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1) #pragma config PBADEN = OFF // PORTB A/D Enable bit (PORTB<4:0> pins are configured as analog input channels on Reset) #pragma config LPT1OSC = OFF // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation) #pragma config MCLRE = ON // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled) // CONFIG4L #pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset) #pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled) #pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode)) // CONFIG5L #pragma config CP0 = OFF // Code Protection bit (Block 0 (000800-001FFFh) not code-protected) #pragma config CP1 = OFF // Code Protection bit (Block 1 (002000-003FFFh) not code-protected) #pragma config CP2 = OFF // Code Protection bit (Block 2 (004000-005FFFh) not code-protected) #pragma config CP3 = OFF // Code Protection bit (Block 3 (006000-007FFFh) not code-protected) // CONFIG5H #pragma config CPB = OFF // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected) #pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected) // CONFIG6L #pragma config WRT0 = OFF // Write Protection bit (Block 0 (000800-001FFFh) not write-protected) #pragma config WRT1 = OFF // Write Protection bit (Block 1 (002000-003FFFh) not write-protected) #pragma config WRT2 = OFF // Write Protection bit (Block 2 (004000-005FFFh) not write-protected) #pragma config WRT3 = OFF // Write Protection bit (Block 3 (006000-007FFFh) not write-protected) // CONFIG6H #pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected) #pragma config WRTB = OFF // Boot Block Write Protection bit (Boot block (000000-0007FFh) not write-protected) #pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected) // CONFIG7L #pragma config EBTR0 = OFF // Table Read Protection bit (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks) #pragma config EBTR1 = OFF // Table Read Protection bit (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks) #pragma config EBTR2 = OFF // Table Read Protection bit (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks) #pragma config EBTR3 = OFF // Table Read Protection bit (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks) // CONFIG7H #pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot block (000000-0007FFh) not protected from table reads executed in other blocks) // #pragma config statements should precede project file includes. // Use project enums instead of #define for ON and OFF. #include <xc.h> #include "supporing_cfile\lcd.h" #define RF_RX PORTD void system_init (void); void rf_analysis (unsigned char recived_byte); void main(void) { unsigned char byte = 0; system_init(); lcd_init(); while(1){ lcd_com(0x80); lcd_puts("CircuitDigest"); lcd_com (0xC0); byte = RF_RX; rf_analysis(byte); lcd_com (0xC0); } return; } void system_init (void){ OSCCON = 0b01111110; // 8Mhz, , intosc //OSCTUNE = 0b01001111; // PLL enable, Max prescaler 8x4 = 32Mhz TRISB = 0x00; TRISD = 0xFF; // Last 4 bit as input bit. } void rf_analysis (unsigned char recived_byte){ if(recived_byte==0x10) lcd_data('1'); if(recived_byte==0x20) lcd_data('2'); if(recived_byte==0x30) lcd_data('3'); if(recived_byte==0x40) lcd_data('4'); if(recived_byte==0x50) lcd_data('5'); if(recived_byte==0x60) lcd_data('6'); if(recived_byte==0x70) lcd_data('7'); if(recived_byte==0x80) lcd_data('8'); if(recived_byte==0x90) lcd_data('9'); if(recived_byte==0x00) lcd_data('0'); if(recived_byte==0xa0) lcd_data('*'); if(recived_byte==0xb0) lcd_data('#'); if(recived_byte==0xc0) lcd_data('A'); if(recived_byte==0xd0) lcd_data('B'); if(recived_byte==0xe0) lcd_data('C'); if(recived_byte==0xf0) lcd_data('D'); } |
Все необходимые файлы для этого проекта вы можете скачать по этой ссылке.