|
在PIC单片机和Arduino微控制器之间建立通信的代码 在本文中,我们使用nRF24L01库在PIC18单片机和Arduino之间通过RF发送和接收数据。我们使用Microchip代码配置器(MCC)为(PIC18F46K22)配置程序。
注意:为方便起见,我们已从Arduino移植了NRF库,您可以通过单击下面的链接来下载: Arduino库
PIC18F46K22单片机的代码 首先在代码中包含上面提到的库文件。 - #include "mcc_generated_files/mcc.h"
- #include "nrf24_lib.h"
- #include <string.h>
复制代码接下来,我们定义2个宏,用于为nRF24L01 Tx操作和Rx操作配置应用程序。对于Tx操作,我们需要将NRF24L01_TX_EX的值更改为1;对于Rx操作,我们需要将其值更改为0。 - #define NRF24L01_TX_EX 0
- #define NRF24L01_RX_EX !NRF24L01_TX_EX
复制代码接下来,我们使用Timer0定义一个回调函数,用于每1秒间隔闪烁LED。 - void blink_led() {
- LED_Toggle();
- }
复制代码
在main()函数中,我们调用SYSTEM_Initialize()函数来初始化系统外设,例如(INTERRUPT、Pin、Timer0、UART、SPI1),并启用全局和外设中断。 - void main(void)
- {
- // Initialize the device
- SYSTEM_Initialize();
- // If using interrupts in PIC18 High/Low Priority Mode you need to enable the Global High and Low Interrupts
- // If using interrupts in PIC Mid-Range Compatibility Mode you need to enable the Global and Peripheral Interrupts
- // Use the following macros to:
- // Enable the Global Interrupts
- INTERRUPT_GlobalInterruptEnable();
- // Disable the Global Interrupts
- //INTERRUPT_GlobalInterruptDisable();
- // Enable the Peripheral Interrupts
- INTERRUPT_PeripheralInterruptEnable();
- // Disable the Peripheral Interrupts
- //INTERRUPT_PeripheralInterruptDisable();
复制代码系统初始化后,我们调用TMR0_SetInterruptHandler()函数设置回调函数,然后启动Timer0。 - TMR0_SetInterruptHandler(blink_led);
- TMR0_StartTimer();
复制代码完成所有初始化后,我们可以使用nRF24L01开始该过程。首先,我们需要初始化nRF24,为此,我们调用nrf24_rf_init()函数以及nRF24L01操作模式(Tx或Rx)和RF通道频率(0-127)。成功初始化nRF24后,打印当前配置的nRF24的寄存器映射设置。 - #if NRF24L01_TX_EX
- ret = nrf24_rf_init(TX_MODE, 115); // Tx mode with 2400+115 Ghz RF frq
- #elif NRF24L01_RX_EX
- ret = nrf24_rf_init(RX_MODE, 115); // Rx mode with 2400+115 Ghz RF frq
- #endif
- if (ret == NRF24_INIT_OK) {
- printf("###############################################################\r\n");
- printf("NRF24L01 Initialize successful\r\n");
- nrf24_printf_rf_config();
- printf("###############################################################\r\n");
复制代码初始化nRF24之后,我们在while循环中执行Tx和Rx操作过程。 ● 在Tx模式下:我们创建一个带有整数变量值的缓冲区,并将该缓冲区传递给nrf24_send_rf_data()并递增整数变量值。 - #if NRF24L01_TX_EX
- static char val = 0;
- sprintf(bufferTX, "Sending: %d", val);
- nrf24_send_rf_data(bufferTX);
- val++;
- __delay_ms(100);
复制代码● 在Rx模式下:我们监视nrf24_is_rf_data_available()以获取nRF24是否接收某些数据的状态。接收到一些数据后,我们调用nrf24_read_rf_data()将接收到的数据放入缓冲区并打印缓冲区。 - #elif NRF24L01_RX_EX
- while (nrf24_is_rf_data_available()) {
- }
- nrf24_read_rf_data(bufferRX);
- printf("RX data %s\r\n", bufferRX);
- __delay_ms(10);
- #endif
复制代码
Arduino的代码 首先在代码中包含所有必需的库。该库包括用于访问nRF24L01命令的RF24、SPI库和printf库。而且,我们还包括一些将用于将模块设置为发送器和接收器。 - //Include Libraries
- #include <SPI.h>
- #include <nRF24L01.h>
- #include <RF24.h>
- #include "printf.h"
- #define NRF24L01_TX_EX 1
- #define NRF24L01_RX_EX !NRF24L01_TX_EX
复制代码接下来,我们为RF24创建一个实例,并传递CE和CSN PIN,我们还保存了要与模块进行通信的地址。 - //create an RF24 object
- RF24 radio(9, 8); // CE, CSN
- //address through which two modules communicate.
- const byte address[6] = {0xe1, 0xe1, 0xe1, 0xe1, 0xe1};
复制代码
接下来,我们定义setup函数。我们初始化了串口监视器以进行调试,并且还设置了NRF24 Radio。 - Serial.begin(115200);
- printf_begin();
- Serial.println(F("\n\rRF24/examples/scanner/"));
- // Setup and configure rf radio
- radio.begin();
- radio.setAutoAck(false);
复制代码
现在,记住我们定义的两个宏。借助这些宏,您可以非常轻松地将模块设置为发送器或接收器。 - #if NRF24L01_TX_EX
- //set the address
- radio.openWritingPipe(address);
- radio.setPALevel(RF24_PA_MIN); //set as: RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
- radio.setDataRate(RF24_2MBPS); //set as: F24_250KBPS, F24_1MBPS, F24_2MBPS ==>250KBPS = longest range
- radio.setChannel(115); //sets channel from 2.4 to 2.524 GHz in 1 MHz increments 2.483.5 GHz is normal legal limit
- radio.setCRCLength(RF24_CRC_8);
- radio.printDetails();
- //Set module as transmitter
- radio.stopListening();
- #elif NRF24L01_RX_EX
- radio.openReadingPipe(0, address);
- radio.setPALevel(RF24_PA_MIN); //set as: RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
- radio.setDataRate(RF24_2MBPS); //set as: F24_250KBPS, F24_1MBPS, F24_2MBPS ==>250KBPS = longest range
- radio.setChannel(115); //sets channel from 2.4 to 2.524 GHz in 1 MHz increments 2.483.5 GHz is normal legal limit
- radio.setCRCLength(RF24_CRC_8);
- // Get into standby mode
- radio.startListening();
- radio.stopListening();
- radio.printDetails();
- // Get into standby mode
- radio.startListening();
- #endif
复制代码
接下来,在loop()函数中,我们定义了32个数组,将消息存储到该数组中并将其发送到另一个模块。现在,借助sprint()函数,我们一次发送一个字符,并在串口监视器窗口上打印该值以进行调试。 - void loop()
- {
- #if NRF24L01_TX_EX
- //Send message to receiver
- char text[32] = {0};
- sprintf(text, "Hello PIC18 %d", val++);
- radio.write(&text, sizeof(text));
- Serial.println(text);
- #elif NRF24L01_RX_EX
- //Read the data if available in buffer
- if (radio.available())
- {
- char text[32] = {0};
- radio.read(&text, sizeof(text));
- Serial.println(text);
- }
- #endif
- delay(250);
- }’
复制代码
|