hyrtster 发表于 2010-2-1 12:02:30

请教我的NRF24L01怎样在中断方式下执行?

我用msp430单片机调试nrf24l01,但我找到的实例程序都是用查询方式做nrf24l01通信的,为了提高通讯的速率并减轻cpu的负担,我想改为中断方式,就是PTX的24l01每发完一个包,就申请cpu中断,进入中断服务程序。PRX的24l01每收到一个包,就申请一个中断,将数据递交cpu进行处理。
但是现在问题是我的24l01只能进入一次中断,如果我在中断服务程序中清除了中断标志位,就无法再进入中断服务程序了。
给大家看看我的代码。

//--------------------射频芯片相关定义-------------------

#define NRF24L01_TxRxBuf_Len 32
#define TXRX_ADDR_WIDTH    5   

//---------------------NRF24L01引脚定义------------------------
//                  MSP430F261x/241x
//               -----------------
//             /|\|            XIN|-
//            | |               |
//            --|RST          XOUT|-
//                |               |
//                |               |
//                |             P3.7|-> CE
//                |             P3.6|-> CSN
//                |             P3.1|-> Data Out (UCB0SIMO)
//                |               |
//                |P1.0         P3.2|<- Data In (UCB0SOMI)
//                |               |
//          IRQ ->|P1.1         P3.3|-> Serial Clock Out (UCB0CLK)
// Date:2009.12.18

#define CE_DDR_OUT()            P3DIR |= BIT7         
#define CE_ON();                    P3OUT |= BIT7
#define CE_OFF()                P3OUT &= ~BIT7
#define CSN_DDR_OUT()         P3DIR |= BIT6         
#define CSN_ON();                    P3OUT |= BIT6
#define CSN_OFF()                P3OUT &= ~BIT6

#define MOSI_DDR_OUT()          P3DIR |= BIT1         
#define MOSI_ON();                    P3OUT |= BIT1
#define MOSI_OFF()                P3OUT &= ~BIT1
#define SCK_DDR_OUT()         P3DIR |= BIT3         
#define SCK_ON();                    P3OUT |= BIT3
#define SCK_OFF()                P3OUT &= ~BIT3

#include <msp430x26x.h>
#include "nRF24L01.h"


void main(void)
{

        volatile unsigned int i;


        WDTCTL = WDTPW+WDTHOLD;                   // Stop watchdog timer
        if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)                                    
        {
                while(1);                               // If calibration constants erased
                                                    // do not load, trap CPU!!
        }   
        BCSCTL1 = CALBC1_8MHZ;                  // Set DCO
        DCOCTL = CALDCO_8MHZ;
        for(i=2100;i>0;i--);                      // Wait for DCO to stabilize.
       
        BCSCTL2 &= ~(BIT1+BIT2);
        P5DIR |= 0x70;                            // P5.6,5,4 outputs
        P5SEL |= 0x70;                            // P5.6,5,4 options
       
        SPI_Init();
        P1DIR |= BIT0;
        NRF24L01_Init();       
        NRF24L01_Write_RxADDR();
        NRF24L01_SetRxMode();
        _EINT();
       
        NRF24L01_Write_TxADDR();
        NRF24L01_TxPacket();
}
       
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
        NRF24L01_Write_TxADDR();
        NRF24L01_TxPacket();
        P1OUT &= ~BIT0;
        delay_ms(160);
        P1OUT |= BIT0;
        delay_ms(160);
        P1IFG &= ~BIT1;                                          // P1.1 IFG cleared
}

hyrtster 发表于 2010-2-1 12:04:36

然后这是我的nrf24l01.h头文件

#ifndef NRF24L01_H_
#define NRF24L01_H_

#endif /*NRF24L01_H_*/


#include "nRF24L01_def.h"

#ifndef _RX_
unsigned char NRF24L01_TxRxBuf= "NRF24L01 is working all right!!";
#endif
#ifdef _RX_
unsigned char NRF24L01_TxRxBuf= "Transmition works well !";
#endif
unsigned char NRF24L01_TxAddr= {0xcc,0xcc,0xcc,0xcc,0xcc};
unsigned char NRF24L01_RxAddr= {0xcc,0xcc,0xcc,0xcc,0xcc};
unsigned char flag = 0;

//------------------------NRF24L01寄存器配置------------------------
unsigned char NRF24L01_Config =
{
        #ifdef _RX_
        MASK_TX_DS| MASK_MAX_RT|EN_CRC|CRC16,//CONFIG
        #endif
        #ifndef _RX_
        EN_CRC|CRC16,//CONFIG
        #endif
        0,//EN_AA
        ERX_ADDR_P0,//EN_RXADDR
        AW_5,//SETUP_AW
        0x1a,//SETUP_RETR
        0,//RF_CH
        RF_DR_2Mbps|RF_PWR_0|LAN_HCURR,//RF_SETUP
};

//---------------------------NRF24L01射频芯片初始化函数--------------------------------------
void NRF24L01_Init(void)
{
        unsigned int i;
//        unsigned char j;
      //掉电模式
        CE_OFF();
        NRF24L01_WriteReg(CONFIG,~PWR_UP);
//         delay_ms(1);
        for(i=2100;i>0;i--);
//        for(l=255;l>0;l--);

       //默认配置
    NRF24L01_WriteReg(EN_AA, NRF24L01_Config);      
        NRF24L01_WriteReg(EN_RXADDR, NRF24L01_Config);
        NRF24L01_WriteReg(SETUP_AW, NRF24L01_Config);
        NRF24L01_WriteReg(SETUP_RETR, NRF24L01_Config);
        NRF24L01_WriteReg(RF_CH, NRF24L01_Config);      
        NRF24L01_WriteReg(RF_SETUP, NRF24L01_Config);   
        NRF24L01_WriteReg(CONFIG,NRF24L01_Config);
        NRF24L01_WriteReg(RX_PW_P0, NRF24L01_TxRxBuf_Len);
       
        NRF24L01_Write_RxADDR();
        NRF24L01_Write_TxADDR();

}



//---------------------------NRF24L01设置接收模式函数--------------------------------------
void NRF24L01_SetRxMode(void)
{
//        unsigned char j;
        CE_OFF();
        NRF24L01_WriteReg(CONFIG, ((NRF24L01_ReadReg(CONFIG))&0xfc)|PWR_UP|PRIM_RX);   
        CE_ON();
        delay_10us(13);
//        for(j=135;j>0;j--);
}

//---------------------------NRF24L01数据包接收函数--------------------------------------
unsigned char NRF24L01_RxPacket(void)
{
        unsigned char i,cur_status,rev;
//        unsigned char status = 0;

//        _DINT();
       cur_status = NRF24L01_ReadReg(STATUS);
        if(RX_DR&cur_status)                               
        {
                CSN_OFF();                                 
//                SPI_Write(RRP);
                SPI_RW(RRP);
                for(i=0; i<NRF24L01_TxRxBuf_Len; i++)
                {
//                        NRF24L01_TxRxBuf = SPI_Read();
                        NRF24L01_TxRxBuf = SPI_RW(RR);
                }
                CSN_ON();      
               
                CSN_OFF();                                 
//                SPI_Write(FRX);
                SPI_RW(FRX);
                CSN_ON();   
               
                CE_OFF();
                rev =TRUE;
        }
        else
        {
                rev =FALSE;
        }
//        status = NRF24L01_ReadReg(STATUS);
        NRF24L01_WriteReg(STATUS,cur_status);
//        _EINT();
        return rev;       

}

//---------------------------NRF24L01数据包发送函数--------------------------------------
void NRF24L01_TxPacket(void)
{
        unsigned char i;

//        _DINT();       
        CE_OFF();

        CSN_OFF();   
        SPI_RW(FTX)                              
//        SPI_Write(FTX);
        CSN_ON();   

        CSN_OFF();                  
//        SPI_Write(WRP);
        SPI_RW(WRP);
        for(i=0; i<NRF24L01_TxRxBuf_Len; i++)
        {
//                SPI_Write( NRF24L01_TxRxBuf);
                SPI_RW( NRF24L01_TxRxBuf);
        }
        CSN_ON();      

        NRF24L01_WriteReg(CONFIG, ((NRF24L01_ReadReg(CONFIG))&0xfc)|PWR_UP);   
        CE_ON();
//        _EINT();
       
}
//---------------------------NRF24L01寄存器写入函数--------------------------------------
voidNRF24L01_WriteReg(unsigned charaddr, unsigned char value)
{
        CSN_OFF();                  
//        SPI_Write(addr|WR);      
//        SPI_Write(value);   
        SPI_RW(addr|WR);
        SPI_RW(value);      
        CSN_ON();               
}
//---------------------------NRF24L01寄存器读取函数--------------------------------------
unsigned charNRF24L01_ReadReg(unsigned charaddr)
{
        unsigned char value;
        CSN_OFF();                  
//        SPI_Write(addr|RR);      
//        value = SPI_Read();
        value = SPI_RW(addr|RR);         
        CSN_ON();         
        return value;
}
//---------------------------NRF24L01接收地址设置函数--------------------------------------
void NRF24L01_Write_RxADDR(void)
{
        unsigned char i;
        CSN_OFF();                  
//        SPI_Write(RX_ADDR_P0|WR);
        SPI_RW(RX_ADDR_P0|WR);
        for(i=0; i<TXRX_ADDR_WIDTH; i++)
        {
//                SPI_Write(NRF24L01_RxAddr);
                SPI_RW(NRF24L01_RxAddr);
        }
        CSN_ON();      
}
//---------------------------NRF24L01发送地址设置函数--------------------------------------
void NRF24L01_Write_TxADDR(void)
{
        unsigned char i;
    CSN_OFF();                  
//        SPI_Write(TX_ADDR|WR);
        SPI_RW(TX_ADDR|WR);
        for(i=0; i<TXRX_ADDR_WIDTH; i++)
        {
//                SPI_Write(NRF24L01_TxAddr);
                SPI_RW(NRF24L01_TxAddr);
        }
        CSN_ON();      
}
// *
// *
void SPI_Init(void)
{
        CE_DDR_OUT();            
        CSN_DDR_OUT();
//        P3DIR |= (BIT1+BIT3);
        P3SEL |= 0x0E;                            // P3.3,2,1 option select
        UCB0CTL0 |= UCMST+UCSYNC+UCCKPH+UCMSB;    // 3-pin, 8-bit sync SPI master
//        UCB0CTL0 |= UCMST+UCSYNC+UCMSB;                      // 3-pin, 8-bit sync SPI master
        UCB0CTL1 |= UCSSEL_2;                     // SMCLK
        UCB0BR0 = 0;                                     // SMCLK
        UCB0BR1 = 0;
        UCB0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
       
        P1IE |= 0x02;                           // P1.1 interrupt enabled
        P1IES |= 0x02;                            // P1.1 Hi/Lo edge
        P1IFG &= ~0x02;                           // P1.1 IFG cleared
       
        CSN_ON();   
//        SCK_OFF();
}

unsigned char SPI_RW(unsigned char txdata)
{
//        unsigned char rec;
        while (!(IFG2 & UCB0TXIFG));            // USCI_B0 TX buffer ready?
        UCB0TXBUF = txdata;
//        rec = UCB0RXBUF;
        while (!(IFG2 & UCB0RXIFG));            // USCI_B0 RX buffer ready?
        return (UCB0RXBUF);
}

hyrtster 发表于 2010-2-1 12:08:02

程序写的很杂,都不太好意思贴出来,贴出来的的主程序是PTX,就是发送端的程序,还望大家不吝赐教

happlylife 发表于 2010-2-3 16:21:57

你进中断了后需要判断是何种原因引起的中断,也有可能是发送达到最大次数引起的中断,你要对这些情况都做处理才可以,你需要一点点地跟踪程序.尤其是中断服务函数里的执行情况,从而找出原因.

hyrtster 发表于 2010-2-6 21:19:47

我现在在单独调试RX_DR的中断,但是现在又遇到了另一个问题,每次我用JTAG进入调试时,中断信号就不能正常产生了,必须要把nrf24l01和单片机断电,再上电,才能正常产生中断信号。我想可能是nrf24l01初始化的问题,因为程序初始化2401时是先进入掉电模式,但是进入掉电模式后,数据还在寄存器里面,当程序执行到2401上电时,就产生了一个中断信号,然后再无论如何设置2401都没有中断了。

smile.dan 发表于 2010-2-6 21:52:55

好像没看到你设置 P1.1中断啊

P1IES_bit.P1IES_1 = 1;//下降沿
P1IFG_bit.P1IFG_1 = 0;
P1IE_bit.P1IE_1   = 1;

还有你代码貌似没进低功耗模式,跑飞了吧

NJ8888 发表于 2010-2-6 22:10:29

我碰到的问题很奇怪:自动应答发送时,如果得不到响应,再不会来IRQ低电平,即使对状态REG写0X71,重初始化,都不行,断电后才恢复,不知道原因

hyrtster 发表于 2010-2-7 22:01:58

我设置了中断方式,下降沿触发的。
奋斗了几个晚上,终于把PRX端搞通了,每次中断信号发送出来后,都必须写入STATUS寄存器对应的中断位“1”来清中断,比如我的PRX设备就要在进入中断后NRF24L01_WriteReg(STATUS,RX_DR);
回复【6楼】888888888888
我昨天也遇到了,后来发现就是用上述的方法可以解决这个问题。

现在是我的PTX端了,最新的情况是我的TX_DS中断正常工作,而且可以正常发送数据,但是,当我把PRX端设备断电,还是能够正常进入中断,读STATUS寄存器的值是0x2E也就是说依然是TX_DS中断,拿不到MAX_RT中断让我很迷茫。

还有一个问题就是我平均下来每秒钟只能收发1.4k个包,拿每个包32字节算也不到40kb/s。这个速度太慢了,视频很难加载上来啊。请教怎样才能更快呢,nrf24L01可是号称2M速率啊

surf98 发表于 2010-12-8 09:03:55

楼主很幸运了,我倒现在用F2616的USCI都没调通发送。看来得下功夫拿示波器量了。

煮酒fu 发表于 2014-7-11 10:46:28

hyrtster 发表于 2010-2-7 22:01
我设置了中断方式,下降沿触发的。
奋斗了几个晚上,终于把PRX端搞通了,每次中断信号发送出来后,都必须写 ...

是2Mbps。。。。。。不是2M。

jackieha 发表于 2014-7-26 00:01:33

楼主,关于数据传输速率,我的个人理解是:2Mbps 是指的数据在空中的传输速率,真正限制你数据传输速率的是将数据送入nrf24L01发送端的那些程序段,每发送一个包都要延时等等,所以,不可能达到真正2Mbps的 。
页: [1]
查看完整版本: 请教我的NRF24L01怎样在中断方式下执行?