基于si4432和sx1212间无线通信的实现
来源:原创 作者: 发布时间: 2015-7-27 点击数: 66
一、引言
在为客户提供和rf定制的过程中,我们发现由于功能要求升级和产品更新换代等原因,经常会遇到需要内嵌不同无线芯片的模块能相互通信的问题,但芯片间的规格、参数、数据格式的各种区别让人不知从何着手。
本次测试选用的是深圳市思为无线科技有限公司自主研发的rf模块rf4432pro(内嵌si4432芯片)和rf4463pro(内嵌si4463芯片),并描述了详细实验过程、硬件接口和相关示例程序,希望为解决不同无线芯片间的通信问题提供一个参考的方法。
深圳市思为无线科技有限公司是一家专注于rf及传感器类模块应用开发的技术、服务及销售型公司。其针对不同的射频芯片开发了多种应用模块和方案。目前产品覆盖有20mw、100mw、500mw、1w、2w、3w、5w 等不同功率等级;spi、uart(含ttl/rs232/rs485及usb)等多种通讯接口; 315/ 433/470/868/915 mhz及2.4 ghz等不同工作频率,总共上百种模块。多年的沉淀和积累使得深圳市思为无线科技有限公司在射频应用的软硬件方面都有着强劲的研发实力和丰富的应用经验。
二、实验系统硬件设计
1. 芯片性能和特点
2.系统硬件设计
实验系统硬件使用了无线模块rf4432pro和rf4463pro及其相应的demo演示板。rf4432pro和rf4463pro模块内含了经严格测试通过的工业级高性能的芯片应用电路。将各模块通过插针连接在一起,便完成了硬件平台的搭建。通过demo演示板中单片机的spi口控制,两个无线收发模块之间相互通信,从而实现数据的无线传输。
无线模块demo演示板(如下图2)是配合无线前端收发模块,为方便客户调试程序、测试距离而研发的开发板。该demo演示板外置无线模块引脚,设置参数可掉电保存。用户可通过按键设置修改模块的工作频率、发射功率以及通讯速率等相关参数。demo演示板共有5种工作模式,如表2。
表3和表4分别是rf4463pro模块和rf4432pro模块的脚位定义,具体可见深圳市思为无线科技有限公司中的rf4432pro规格书和rf4463pro规格书。
三、无线模块工作原理
无线信号的发射和接收是将信号调制和解调的过程。无论是相同还是不同的无线模块通信,发射和接收两部分调制格式、调制速率和频率、频偏和接收带宽等调制参数的差别都会导致模块之间无法通信的情况。
3.1 spi总线控制时序
rf4432pro和rf4463pro模块与单片机的通信是rf模块根据单片机通过spi总线写入的控制命令和数据将无线信号发射出去,并将接收到的数据和自身的相关信息通过spi总线传送给单片机。si4432与si4463的spi时序稍有区别。
3.2 测试模式
rf4432pro和rf4463pro模块的demo演示板都有常发和常收两种测试模式,便于调试程序。rf4432pro和rf1212模块在demo演示板测试模式下共同点是不停地传送“101010......”,并可在相应引脚看到接收的实时波形。
3.3 正常模式
rf4432pro和rf4463pro模块的demo演示板的正常收发模式运行在si4432和si4463的ph+fifo模式。
si4432与si4463都配置了64字节的fifo及相应的数据包处理功能。该模式下,芯片自动添加和侦测前导码、同步字、校验等,并通过中断表示通信状态,大大方便了通信过程。在正常模式下通信,必须保证通信的两个模块的数据包格式设置*一致,否则芯片将无法产生中断。
3.4 总结
对比si4432和si4463芯片的数据包格式如表5。可以发现除了si4463的数据包中可分为多个部分并各自设crc校验外,其余部分基本一致。为保证两个芯片可以通信,将测试数据包格式设置如表6。
si4432
si4463
前导码preamble
1~8 bytes
1~8 bytes
同步字sync word
1~4 bytes
1~4 bytes
字头tx header
√
√
数据长度packet length
√
√
数据data
0~64 bytes
0~64 bytes
crc
0~2 bytes
0,2,4 bytes
表5: si4432与si4463数据包格式对比
前导码
同步字
字头
数据
长度
si4432
8 bytes
2 bytes
4 bytes
10 bytes
si4463
8 bytes
2 bytes
4 bytes
10 bytes
内容
si4432
“010101...”
0xb42b
“sw”
“abcdefghim”
si4463
“010101...”
0xb42b
“sw”
“abcdefghim”
表6:测试数据包格式
四、具体调试过程
系统通信采用的射频参数设置为:收发频率433.0 mhz、频偏20 khz、rf速率:1.2 kbps。发送的数据格式如表6所示。
为确保rf4432pro和rf4463pro模块都能正常工作和提供参考波形,首先分别使相同模块能在该设置下使用demo演示板的正常模式通信。
4.1 对比接收与发射波形
数据包模式由于芯片自动处理数据,只显示结果,不利于程序的调试。因此我们使用demo演示板测试模式和外置引脚,通过同步观察发送和接收波形这种zui直观的方式,来判断通信质量的好坏。
将rf4432pro和rf4463pro的gpio2和gpio1设置为rx data output功能输出,使接收的数据可以分别从gpio2和gpio1脚上实时输出。使用逻辑分析仪来同步观察rf4463pro和rf4432pro模块发射、接收的波形并做相应的对比。如图10,可发现rf4432pro和rf4463pro能正确接收对方的发射信号。
4.2 数据包模式接收
rf4432pro模块和rf4463pro模块互相接收波形正确,因此保留射频参数,将demo演示板的工作模式设为正常模式,看能否让芯片产生中断。发现没有rf4432pro模块和rf4463pro模块都没有产生接收中断。
分别将demo演示板设置成rf4432pro正常发射、rf4463pro测试接收,rf4463pro正常发射、rf4432pro测试接收,对比rf4432pro和rf4463pro发射的数据包波形,发现两模块的数据包格式设置不一致。
5.2 软件结果
图19中4432irq为rf4432pro中断引脚,4463irq为rf4463pro的中断引脚。可见每个发送中断都有相应的接收中断。
六、示例程序
实验的关键在于rf4432pro和rf4463pro模块的初始化设置部分,其余与相同模块间的通信程序一致。将以下测试可行的rf4432pro和rf4463pro模块初始化代码直接代入通信程序,即可实现rf4432pro和rf4463pro模块间的通信。本实验使用的完整测试程序可见深圳市思为无线科技有限公司的rf4432 demo code和rf4463 demo code。
6.1 rf4432pro初始化示例
void si4432_init(void)
{
itstatus1 = spi_rw(0x03,0x00); // clr rf interrupt factor
itstatus2 = spi_rw(0x04,0x00);
spiwritecfg(0x06|0x80, 0x00); // set rf interrupt
spiwritecfg(0x07|0x80, si4432_pwrstate_ready); // enter ready mode
spiwritecfg(0x09|0x80, 0x7f); // load cap = 12p
spiwritecfg(0x0a|0x80, 0x05); // output clk set
spiwritecfg(0x0b|0x80,0xea); // gpio0 for digital output
spiwritecfg(0x0c|0x80,0xea); // gpio0 for digital output
spiwritecfg(0x0d|0x80, 0xf4); // gpio 2 = rx data
spiwritecfg(0x70|0x80, 0x2c);
spiwritecfg(0x1d|0x80, 0x40); // enable afc
// 1.2k bps setting
spiwritecfg(0x1c, 0x16); // according to silabs's excel
spiwritecfg(0x20, 0x83);
spiwritecfg(0x21, 0xc0);
spiwritecfg(0x22, 0x13);
spiwritecfg(0x23, 0xa9);
spiwritecfg(0x24, 0x00);
spiwritecfg(0x25, 0x04);
spiwritecfg(0x2a, 0x14);
spiwritecfg(0x72, 0x20);
spiwritecfg(0x6e, 0x09);
spiwritecfg(0x6f, 0xd5);
spiwritecfg(0x70, 0x2c);
// 1.2k bps setting end
spiwritecfg(0x30|0x80, 0x88); // enable packet handler, msb first, enable crc,
spiwritecfg(0x32|0x80, 0xff); // 0x32address enable for headere byte 0, 1,2,3, receive header check for byte 0, 1,2,3
spiwritecfg(0x33|0x80, 0x4a); // header 3, 2, 1,0 used for head length, fixed packet length,
spiwritecfg(0x34|0x80, 64); // preamble = 64 nibbles
spiwritecfg(0x35|0x80, 0x20); // preamble detection = 20 bit
spiwritecfg(0x36|0x80,b4); // sync word = 0xb42b
spiwritecfg(0x37|0x80,2b);
spiwritecfg(0x38|0x80, 0x00);
spiwritecfg(0x39|0x80, 0x00);
spiwritecfg(0x3a|0x80, 's'); // tx header
spiwritecfg(0x3b|0x80, 'w');
spiwritecfg(0x3c|0x80, 'w');
spiwritecfg(0x3d|0x80, 'x');
spiwritecfg(0x3e|0x80, 10); // total tx 10 byte
spiwritecfg(0x3f|0x80, 's'); // check hearder
spiwritecfg(0x40|0x80, 'w');
spiwritecfg(0x41|0x80, 'w');
spiwritecfg(0x42|0x80, 'x');
spiwritecfg(0x43|0x80, 0xff); // all the bit to be checked
spiwritecfg(0x44|0x80, 0xff); // all the bit to be checked
spiwritecfg(0x45|0x80, 0xff); // all the bit to be checked
spiwritecfg(0x46|0x80, 0xff); // all the bit to be checked
spiwritecfg(0x6d|0x80, 0x07); // maximum ouput power
spiwritecfg(0x79|0x80, 0x0); // non hop
spiwritecfg(0x7a|0x80, 0x0); // non hop
spiwritecfg(0x71|0x80, 0x22); // fifo, fsk , not need clk
spiwritecfg(0x72|0x80, 0x50); // deviation: 50khz
spiwritecfg(0x73|0x80, 0x0); // no frequency offset
spiwritecfg(0x74|0x80, 0x0); // no frequency offset
spiwritecfg(0x75|0x80,0x53);
spiwritecfg(0x76|0x80,0x57);
spiwritecfg(0x77|0x80,0x80); // frequency:433.5 mhz
}
6.2 rf4463初始化示例
const unsigned char rf_modem_clkgen_band_1_data[] = {rf_modem_clkgen_band_1};
//according to silabs's wireless development suite
const unsigned char rf_freq_control_inte_8_data[] = {rf_freq_control_inte_8};
const unsigned char rf_power_up_data[] = { rf_power_up};
const unsigned char rf_gpio_pin_cfg_data[] = { rf_gpio_pin_cfg};
const unsigned char rf_global_xo_tune_1_data[] = { rf_global_xo_tune_1};
const unsigned char rf_global_config_1_data[] = { rf_global_config_1};
const unsigned char rf_frr_ctl_a_mode_4_data[] = { rf_frr_ctl_a_mode_4};
const unsigned char rf_preamble_tx_length_9_data[] = { rf_preamble_tx_length_9};
const unsigned char rf_sync_config_5_data[] = { rf_sync_config_5};
const unsigned char rf_pkt_crc_config_1_data[] = { rf_pkt_crc_config_1};
const unsigned char rf_pkt_config1_1_data[] = { rf_pkt_config1_1};
const unsigned char rf_pkt_len_3_data[] = { rf_pkt_len_3};
const unsigned char rf_pkt_field_1_length_12_8_12_data[]={ rf_pkt_field_1_length_12_8_12};
const unsigned char rf_pkt_field_4_length_12_8_8_data[] = { rf_pkt_field_4_length_12_8_8};
const unsigned char rf_modem_freq_dev_0_1_data[] = { rf_modem_freq_dev_0_1};
const unsigned char rf_modem_agc_control_1_data[] ={ rf_modem_agc_control_1};
const unsigned char rf_match_value_1_12_data[] ={ rf_match_value_1_12};
const unsigned char rf_modem_rssi_comp_1_data[] = { rf_modem_rssi_comp_1};
const unsigned char rf_modem_mod_type_12_data[]= {rf_modem_mod_type_12};
const unsigned char rf_modem_tx_ramp_delay_8_data[]= {rf_modem_tx_ramp_delay_8};
const unsigned char rf_modem_bcr_osr_1_9_data[]={rf_modem_bcr_osr_1_9};
const unsigned char rf_modem_afc_gear_7_data[]={rf_modem_afc_gear_7};
const unsigned charrf_modem_agc_window_size_9_data[]={rf_modem_agc_window_size_9};
const unsigned char rf_modem_ook_cnt1_11_data[]={rf_modem_ook_cnt1_11};
const unsigned char rf_modem_chflt_rx1_chflt_coe13_7_0_12_data[]=
{rf_modem_chflt_rx1_chflt_coe13_7_0_12};
const unsigned char rf_modem_chflt_rx1_chflt_coe1_7_0_12_data[]
={rf_modem_chflt_rx1_chflt_coe1_7_0_12};
const unsigned char rf_modem_chflt_rx2_chflt_coe7_7_0_12_data[]=
{rf_modem_chflt_rx2_chflt_coe7_7_0_12};
const unsigned char rf_synth_pfdcp_cpff_7_data[]={rf_synth_pfdcp_cpff_7};
void si4463_init(void)
{
u8 app_command_buf[20],i;
//spi_write(0x07, rf_gpio_pin_cfg_data);
app_command_buf[0] = 0x13; // set gpio port
app_command_buf[1] = 0x14; // gpio 0 ,rx data
app_command_buf[2] = 0x02; // gpio1, output 0
app_command_buf[3] = 0x21; // gpio2, hign while in receive mode
app_command_buf[4] = 0x20; // gpio3, hign while in transmit mode
app_command_buf[5] = 0x27; // nirq
app_command_buf[6] = 0x0b; // sdo
spi_write(7, app_command_buf);
// spi_write(0x05, rf_global_xo_tune_1_data);
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x00;
app_command_buf[2] = 0x01;
app_command_buf[3] = 0x00;
app_command_buf[4] = 98; // freq adjustment
spi_write(5, app_command_buf);
// spi_write(0x05, rf_global_config_1_data);
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x00;
app_command_buf[2] = 0x01;
app_command_buf[3] = 0x03;
app_command_buf[4] = 0x40; // tx = rx = 64 byte,ph,high performance mode
spi_write(5, app_command_buf);
spi_write(0x08, rf_frr_ctl_a_mode_4_data); // disable all fast response register
// spi_write(0x0d, rf_preamble_tx_length_9_data); // set preamble
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x10;
app_command_buf[2] = 0x09;
app_command_buf[3] = 0x00;
app_command_buf[4] = 0x08; // 8 bytes preamble
app_command_buf[5] = 0x14; // detect 20 bits
app_command_buf[6] = 0x00;
app_command_buf[7] = 0x0f;
app_command_buf[8] = 0x32; // no manchest.1010...
app_command_buf[9] = 0x00;
app_command_buf[10] = 0x00;
app_command_buf[11] = 0x00;
app_command_buf[12] = 0x00;
spi_write(13, app_command_buf); //
// rf_sync_config_5_data, // set sync
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x11;
app_command_buf[2] = 0x05;
app_command_buf[3] = 0x00;
app_command_buf[4] = 0x01; // no manchest , 2 bytes
app_command_buf[5] = 0x2d; // sync byte3
app_command_buf[6] = 0xd4; // sync byte2
app_command_buf[7] = 0x00; // sync byte1
app_command_buf[8] = 0x00; // sync byte0
spi_write(9, app_command_buf);
// packet crc
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x12;
app_command_buf[2] = 0x01;
app_command_buf[3] = 0x00;
app_command_buf[4] = 0x80; // no crc
spi_write(5, app_command_buf);
// packet gernale configuration
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x12;
app_command_buf[2] = 0x01;
app_command_buf[3] = 0x06;
app_command_buf[4] = 0x02; // crc msb, data msb
spi_write(5, app_command_buf);
// spi_write(0x07, rf_pkt_len_3_data);
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x12;
app_command_buf[2] = 0x03;
app_command_buf[3] = 0x08;
app_command_buf[4] = 0x00;
app_command_buf[5] = 0x00;
app_command_buf[6] = 0x00;
spi_write(7, app_command_buf);
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x12;
app_command_buf[2] = 0x0c;
app_command_buf[3] = 0x0d;
app_command_buf[4] = 0x00;
app_command_buf[5] = 14; //header(4)+10 bytes
app_command_buf[6] = 0x04;
app_command_buf[7] = 0xaa;
app_command_buf[8] = 0x00;
app_command_buf[9] = 0x00;
app_command_buf[10] = 0x00;
app_command_buf[11] = 0x00;
app_command_buf[12] = 0x00;
app_command_buf[13] = 0x00;
app_command_buf[14] = 0x00;
app_command_buf[15] = 0x00;
spi_write(16, app_command_buf); // set length of field 1 -- 4
// spi_write(0x0c, rf_pkt_field_4_length_12_8_8_data);
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x12;
app_command_buf[2] = 0x08;
app_command_buf[3] = 0x19;
app_command_buf[4] = 0x00;
app_command_buf[5] = 0x00;
app_command_buf[6] = 0x00;
app_command_buf[7] = 0x00;
app_command_buf[8] = 0x00;
app_command_buf[9] = 0x00;
app_command_buf[10] = 0x00;
app_command_buf[11] = 0x00;
spi_write(12, app_command_buf);
spi_write(0x10, rf_modem_mod_type_12_data);
spi_write(0x05, rf_modem_freq_dev_0_1_data);
spi_write(0x0c, rf_modem_tx_ramp_delay_8_data);
spi_write(0x0d, rf_modem_bcr_osr_1_9_data);
spi_write(0x0b, rf_modem_afc_gear_7_data);
spi_write(0x05, rf_modem_agc_control_1_data);
spi_write(0x0d, rf_modem_agc_window_size_9_data);
spi_write(0x0f, rf_modem_ook_cnt1_11_data);
// spi_write(0x05, rf_modem_rssi_comp_1_data);
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x20;
app_command_buf[2] = 0x01;
app_command_buf[3] = 0x4e;
app_command_buf[4] = 0x40;
spi_write(5, app_command_buf);
spi_write(0x10, rf_modem_chflt_rx1_chflt_coe13_7_0_12_data);
spi_write(0x10, rf_modem_chflt_rx1_chflt_coe1_7_0_12_data);
spi_write(0x10, rf_modem_chflt_rx2_chflt_coe7_7_0_12_data);
// rf_pa
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x22;
app_command_buf[2] = 0x04;
app_command_buf[3] = 0x00;
app_command_buf[4] = 0x08;
app_command_buf[5] = 127; // set max power
app_command_buf[6] =0x00;
app_command_buf[7] = 0x3d;
spi_write(8, app_command_buf);
spi_write(0x0b, rf_synth_pfdcp_cpff_7_data);
// header match
app_command_buf[0] = 0x11;
app_command_buf[1] = 0x30;
app_command_buf[2] = 0x0c;
app_command_buf[3] = 0x00;
app_command_buf[4] = 's';
app_command_buf[5] = 0xff;
app_command_buf[6] = 0x40;
app_command_buf[7] = 'w';
app_command_buf[8] = 0xff;
app_command_buf[9] = 0x01;
app_command_buf[10] = 'w';
app_command_buf[11] =0xff;
app_command_buf[12] =0x02;
app_command_buf[13] = 'x';
app_command_buf[14] = 0xff;
app_command_buf[15] = 0x03;
spi_write(16, app_command_buf);
spi_write(5, rf_modem_clkgen_band_1_data);
spi_write(12, rf_freq_control_inte_8_data); // set frequency =433.5
7 总结
本文描述了深圳市思为无线科技有限公司的无线收发模块通信rf4432pro和rf4463pro间的详细实现过程、硬件接口和示例程序,经实验验证可行。实现通信的基本方法是将rf4432pro和rf4463pro设置相同射频参数及数据格式。这个方法也可以引申至其他不同无线模块和无线芯片的通信。如遇到与文中不同的实验现象,对实验过程有疑问或其他想法欢迎与我们进行技术交流。