基于MSP430的nRF905无线模块SPI发送实验
一、实验概述与核心目标
1. 实验定位
本实验基于TI MSP430系列单片机与Nordic nRF905无线射频芯片,利用SPI接口(通常为GPIO模拟SPI,因MSP430低端机型无硬件SPI)实现无线数据的发送。实验核心是掌握nRF905的ShockBurst™突发传输模式与SPI单字节写入时序。
2. 核心功能
- IO模拟SPI:通过普通GPIO引脚翻转,模拟SPI的SCK(时钟)、MOSI(主发从收)、MISO(主收从发)时序。
- nRF905初始化:通过SPI向nRF905写入配置字(频段、地址、CRC校验等)。
- 无线数据发送:将待发送数据写入nRF905发送寄存器,拉高控制引脚,触发射频发射。
二、硬件设计方案
1. 核心硬件选型
| 模块 | 型号 | 关键参数 |
|---|---|---|
| 主控MCU | MSP430G2553 / F5529 | 低功耗16位RISC内核,支持IO模拟SPI |
| 无线模块 | nRF905 | 433/868/915MHz ISM频段,最大50kbps,支持自动CRC与地址匹配 |
| 晶振 | 16MHz无源晶振 | nRF905射频基准时钟 |
2. 引脚连接(IO模拟SPI方案)
由于MSP430G2系列等部分型号无硬件SPI,需使用4个普通GPIO模拟SPI时序。连接方式如下:
| nRF905引脚 | MSP430引脚 | 功能定义 | IO方向 |
|---|---|---|---|
| SCK | P1.5 (自行定义) | SPI时钟线 | MSP430输出 |
| MOSI | P1.7 (自行定义) | SPI主发从收(数据发送) | MSP430输出 |
| MISO | P1.6 (自行定义) | SPI主收从发(读取状态) | MSP430输入 |
| CSN | P1.4 (自行定义) | SPI片选(低电平有效) | MSP430输出 |
| TRX_CE | P2.0 (自行定义) | 发射/接收使能(高电平有效) | MSP430输出 |
| TX_EN | P2.1 (自行定义) | 发射模式使能(高电平有效) | MSP430输出 |
| PWR_UP | P2.2 (自行定义) | 模块上电控制(高电平有效) | MSP430输出 |
| DR | P2.3 (自行定义) | 数据就绪/发送完成中断引脚 | MSP430输入 |
注意:以上引脚分配为通用约定,实际可根据MSP430的Port资源灵活调整。
三、软件设计与核心代码(基于IO模拟SPI)
1. 软件执行流程
- MSP430初始化:配置GPIO的输入/输出方向,关闭看门狗。
- SPI模拟初始化:将SCK、CSN、MOSI置为高电平(SPI空闲状态)。
- nRF905配置:拉低CSN,通过SPI循环写入11字节的配置字(设定433MHz、10dBm发射功率、4字节地址宽度等)。
- 发送模式切换:拉高
TRX_CE并拉高TX_EN,使nRF905进入ShockBurst™发射模式。 - 数据打包发送:拉低CSN,发送“写发送载荷”指令,随后连续写入发送数据;写完后拉高CSN;最后拉高
TRX_CE触发发送。
2. 核心代码实现(C语言)
2.1 IO模拟SPI单字节发送函数
/*
* 函数功能:模拟SPI主机向从机发送一个字节
* 时序说明:CPOL=0, CPHA=0 (空闲时钟低电平,上升沿采样)
* 引脚假定:SCK->P1.5, MOSI->P1.7, CSN->P1.4
*/
void SPI_SendByte(unsigned char data)
{
unsigned char i;
for (i = 0; i < 8; i++) // 循环发送8位
{
if ((data & 0x80) != 0) // 判断最高位是1还是0
{
P1OUT |= BIT7; // MOSI = 1 (发送高电平)
} else {
P1OUT &= ~BIT7; // MOSI = 0 (发送低电平)
}
P1OUT |= BIT5; // SCK = 1 (制造上升沿,让从机采样接收数据)
data <<= 1; // 左移一位,准备发送下一位
P1OUT &= ~BIT5; // SCK = 0 (时钟回到低电平)
}
}
2.2 nRF905配置函数(写入11字节配置字)
/* 全局配置字数组:设定nRF905工作参数 */
unsigned char RFConf[11] = {
0x00, // 配置命令字头
0x6C, // CH_NO: 频道设置,433.2MHz
0x0E, // 输出功率10dBm,开启自动重发,正常模式
0x44, // 接收/发送地址宽度为4字节
0x10, 0x10, // 接收/发送数据宽度为16字节
0xE7, 0xE7, 0xE7, 0xE7, // 设置接收端地址 (4字节,需与发送方一致)
0xDE // CRC允许,16位CRC校验,晶振16MHz
};
/*
* 函数功能:初始化nRF905,写入配置字
*/
void Config_nRF905(void)
{
unsigned char i;
P1OUT &= ~BIT4; // CSN = 0 (拉低片选,使能SPI通信)
for (i = 0; i < 11; i++)
{
SPI_SendByte(RFConf[i]); // 逐字节写入配置字
}
P1OUT |= BIT4; // CSN = 1 (拉高片选,关闭SPI通信)
}
2.3 nRF905无线发送主逻辑
/* 宏定义与全局变量 */
#define WTP 0x20 // nRF905指令:写发送载荷 (Write TX Payload)
#define WTA 0x22 // nRF905指令:写发送地址 (Write TX Address)
#define TRX_CE_BIT BIT0 // 假定 TRX_CE 连接在 P2.0
#define TX_EN_BIT BIT1 // 假定 TX_EN 连接在 P2.1
unsigned char TxBuffer[16] = "Hello MSP430!"; // 待发送的数据包
/*
* 函数功能:将指定缓冲区数据通过nRF905发送出去
* 参数 len: 发送数据的长度(最大32字节)
*/
void nRF905_SendData(unsigned char *TxBuf, unsigned char len)
{
unsigned char i;
/* 步骤1:将nRF905设置为发射模式 */
P2OUT &= ~TRX_CE_BIT; // TRX_CE = 0
P2OUT |= TX_EN_BIT; // TX_EN = 1 (进入发射模式)
__delay_cycles(100); // 延时约几十微秒,等待模式稳定
/* 步骤2:写入发送数据 */
P1OUT &= ~BIT4; // CSN = 0
SPI_SendByte(WTP); // 发送“写发送载荷”指令
for (i = 0; i < len; i++)
{
SPI_SendByte(TxBuf[i]); // 逐个字节写入数据
}
P1OUT |= BIT4; // CSN = 1
__delay_cycles(10); // 微小延时
/* 步骤3:写入接收端地址(必须与接收方配置的地址完全一致)*/
P1OUT &= ~BIT4; // CSN = 0
SPI_SendByte(WTA); // 发送“写发送地址”指令
for (i = 0; i < 4; i++)
{
SPI_SendByte(RFConf[4+i]); // 写入前面配置好的4字节地址
}
P1OUT |= BIT4; // CSN = 1
/* 步骤4:拉高TRX_CE,触发数据发送 */
P2OUT |= TRX_CE_BIT; // TRX_CE = 1 (开始发射数据)
__delay_cycles(1000); // 等待发送完成(或使用DR引脚查询中断)
/* 步骤5:发送完毕,拉低TRX_CE,回到待机模式 */
P2OUT &= ~TRX_CE_BIT; // TRX_CE = 0
}
四、主程序调用示例
#include <msp430.h>
/* 此处需包含上述定义的宏、全局变量及函数声明 */
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // 关闭看门狗
/* 1. 初始化GPIO方向 */
P1DIR |= (BIT4 + BIT5 + BIT7); // P1.4(CSN), P1.5(SCK), P1.7(MOSI) 设为输出
P1DIR &= ~BIT6; // P1.6(MISO) 设为输入
P2DIR |= (TRX_CE_BIT + TX_EN_BIT); // P2.0/P2.1 设为输出
P2OUT &= ~(TRX_CE_BIT + TX_EN_BIT); // 默认拉低控制引脚
/* 2. 初始化SPI默认电平 */
P1OUT |= (BIT4 + BIT5); // CSN=1 (默认不选中), SCK=1 (空闲高电平视情况,这里与函数内逻辑保持一致即可)
/* 3. 上电并配置nRF905 */
P2OUT |= BIT2; // PWR_UP = 1 (给nRF905上电)
__delay_cycles(1000); // 等待模块上电稳定
Config_nRF905(); // 写入配置字
/* 4. 循环发送数据 */
while(1)
{
nRF905_SendData(TxBuffer, 16); // 发送16字节数据
__delay_cycles(1000000); // 延时约几百毫秒,避免刷屏式发送
}
}
参考代码 MSP430 无线模块nRF905 SPI接口发送实验 www.youwenfan.com/contentcnt/133664.html
五、关键注意事项
1. SPI时序与电平配合
- CPOL/CPHA匹配:MSP430模拟的SPI时序必须严格遵循nRF905的要求(一般为模式0:SCK空闲低电平,上升沿采样)。
- 建立与保持时间:在
SCK的上升沿和下降沿之间,需加入微小的空语句延时(如__delay_cycles(1)),确保数据在nRF905内部建立时间和保持时间的容限内。
2. 电源与模式切换
- 上电等待:
PWR_UP拉高后,nRF905内部的晶体振荡器起振需要一定时间(约几毫秒),务必加延时。 - 模式切换延时:当改变
TRX_CE或TX_EN的电平时,nRF905的模式切换需要约650ns~1.5us的硬件稳定时间,代码中需微量延时。
3. 地址一致性
- 收发地址必须完全相同:发送方通过
WTA指令写入的4字节地址,必须与接收方配置的接收地址(RFConf数组的第5到第8个元素)完全一致,否则接收方会自动丢弃数据包。
浙公网安备 33010602011771号