试着用msp430f2012驱动了射频芯片nrf905,硬件设计失误,只能IO口模拟SPI,勉强凑合。
程序用两片430和两个905实现,一端为阅读器(读头),实时等待接受数据,并用串口显示,采用内部晶振;一端为发送器(卡片),定时发送数据,为了低功耗,采用了外部晶振。
程序如下,见附件。
从中可参考msp430串口、定时器应用及905的配置方法。
读头程序:
/*905读头,用来接收数据,物理地址08000001,频道433M*/
#include <msp430x21x2.h>
#include "api.h"
BYTE Nrf_Conf[10]={0x4c,0x0c,0x44,0x20,0x20,0x01,0x00,0x00,0x08,0x58};
//905配置字,433M频道,一般模式,无自动重发,输出功率+10db
//发送地址、接收地址都为4字节
//接收地址0x08000001
//CRC校验,8位,无外部时钟,16M外部晶振
int main( void )
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD; //关闭看门狗
Delayms();
Delayms();
Delayms();
Delayms();
init_clk(); //初始化时钟
init_io(); //初始化IO
init_RF(); //初始化射频
init_uart(); //初始化串口
_EINT();
while(1)
{
LPM1;
_NOP();
}
}
#pragma vector=PORT2_VECTOR //DR中断函数(接收到数据)
__interrupt void PORT2(void)
{
unsigned char index;
P2IFG &=0xf7; //DR中断标志位清除 /
P1OUT &=~TRX_CE; //进入停机模式
SPI_Read(READ_RX_PAYLOAD,RX_PLOAD_WIDTH); // read receive payload from RX_FIFO buffer
P1OUT |=LED; // turn on the led
for(index=0;index<32;index++)//串口显示收到数据
{
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF =rx_buf[index];
}
P1OUT &=~LED;
P1OUT |=TRX_CE; //905重新开始工作
}
#pragma vector=USCIAB0RX_VECTOR //串口中断
__interrupt void USCI0RX_ISR(void)
{
int a;
_EINT(); //开启中断嵌套
a=UCA0RXBUF;
if(a=='S') //打开设备
{
P1OUT|=PWR_UP; //上电
P1OUT&=~TX_EN; //接收模式
P1OUT|=TRX_CE; //准备接收数据,工作状态
}
else if(a=='E') //关闭设备
{
P1OUT&=~TRX_CE;//停机
P1OUT&=~PWR_UP; //掉电
}
}
void init_io(void) //GPIO初始化
{
P1DIR=0x5C; //LED,TX_EN,TRX_CE,PWR_UP为输出模式
P1OUT=0x00; //P1口输出低电平
P3SEL|=0x30; //串口与的io口启用外围模块模式
P3DIR |=0x0d; //MOSI,SCK输出模式,MISO输入模式
P3OUT=0x00; //P3口输出低电平
P2DIR &=0xE7;//AM、DR输入
P2IE |=0x08; //DR中断使能
P2IES &=0xf7; //DR中断上升沿触发
P2IFG &=0xf7; //DR中断标志位清除
P2OUT=0x00; //P2口输出低电平
}
void init_RF(void) //配置射频端,带自动应答功能
{
P1OUT &=~PWR_UP; //掉电模式
SPI_Write(WRITE_CONF, Nrf_Conf, 10); // 配置寄存器
}
void init_uart(void) //19200bps
{
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 160; // 8MHz/19200 = ~416.6
UCA0BR1 = 1; //
UCA0MCTL = UCBRS2 + UCBRS1; // Modulation UCBRSx = 5
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
P1OUT|=PWR_UP; //上电
P1OUT&=~TX_EN; //接收模式
P1OUT|=TRX_CE; //准备接收数据,工作状态
}
//////////////////////////////////////////////////////////
BYTE SPI_RW(BYTE byte) //SPI写一个字节驱动
{
uchar status=0,bit_ctr;
for(bit_ctr=0;bit_ctr<8;bit_ctr++)
{
if(byte & 0x80) //判断输出高低电平
P3OUT |=MOSI;
else P3OUT &=~MOSI;
byte = (byte << 1);
P3OUT |=SCK; //时钟高电平
if(P3IN & MISO) //读输入状态
status |=0x01;
else status &=0xFE;
P3OUT &=~SCK; //时钟低电平
}
return(status);
}
BYTE SPI_Read_One(void) //SPI读一个字节
{
uchar status=0,bit_ctr;
for(bit_ctr=0;bit_ctr<8;bit_ctr++)
{
status = ( status << 1);
P3OUT |=SCK;
if(P3IN & MISO)
status |=0x01;
else status &=0xFE;
_NOP();
_NOP();
P3OUT &=~SCK;
_NOP();
_NOP();
_NOP();
}
return(status);
}
uchar SPI_Read(BYTE reg, BYTE bytes)//读多个字节
{
uchar status,byte_ctr;
P3OUT |=CSN;
P3OUT &=~CSN; // Set CSN low, init SPI tranaction
status = SPI_RW(reg); // Select register to write to and read status byte
for(byte_ctr=0;byte_ctr<bytes;byte_ctr++)
rx_buf[byte_ctr] = SPI_Read_One(); // Perform SPI_Read_Oneto read byte from nRF24L01
P3OUT |=CSN; // Set CSN high again
return(status); // return nRF24L01 status byte
}
BYTE SPI_Write(BYTE reg, BYTE *pBuf, BYTE bytes) //SPI写多个字节寄存器
{
uchar status,byte_ctr;
P3OUT |=CSN;
P3OUT &=~CSN;
status = SPI_RW(reg);
for(byte_ctr=0; byte_ctr<bytes; byte_ctr++)
SPI_RW(*pBuf++);
P3OUT |=CSN;
return(status);
}
////////////////////////////////////////////////////////////
void Delayms(void) //延时子函数
{
uchar i;
uchar y;
for(i=0;i<150;i++)
{
for(y=0;y<15;y++);
}
}
void init_clk(void) //系统时钟初始化函数DCOCLK设置8M
{
BCSCTL1=CALBC1_8MHZ;
DCOCTL=CALDCO_8MHZ;
}