智能车制作

 找回密码
 注册

扫一扫,访问微社区

查看: 4365|回复: 11
打印 上一主题 下一主题

nrf24l01不能读写寄存器。。。求大神相助

[复制链接]

2

主题

14

帖子

0

精华

高级会员

Rank: 4

积分
538
威望
249
贡献
119
兑换币
143
注册时间
2012-11-17
在线时间
85 小时
毕业学校
重庆大学
跳转到指定楼层
1#
发表于 2013-4-26 00:43:41 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
我的nrf24l01不能读写寄存器,nrf寄存器是好的,拿到别人51单片机实验过了,可以用,但是我们的xs128不行啊,一步一步检查最后发现连寄存器都不能读写,无论是模拟spi还是硬件spi,手上两块xs128都不行,下面是我现在测读写寄存器的程序,灯不灭,表示没读成功。。。。求大神帮忙,纠结好几天了#include <hidef.h>      /* common defines and macros */
#include "derivative.h"      /* derivative-specific definitions */

#define TX_ADDR_WITDH 5//发送地址宽度设置为5个字节
#define RX_ADDR_WITDH 5
#define TX_DATA_WITDH 17
#define RX_DATA_WITDH 17
/******************************************************************
// nRF24L01指令格式:
*******************************************************************/
#define R_REGISTER    0x00  // 读寄存器
#define W_REGISTER    0x20  // 写寄存器
#define R_RX_PLOAD    0x61  // 读RX FIFO有效数据,1-32字节,当读数据完成后,数据被清除,应用于接收模式
#define W_TX_PLOAD    0xA0  // 写TX FIFO有效数据,1-32字节,写操作从字节0开始,应用于发射模式
#define FLUSH_TX      0xE1  // 清除TX FIFO寄存器,应用于发射模式
#define FLUSH_RX      0xE2  // 清除RX FIFO寄存器,应用于接收模式
#define REUSE_TX_PL   0xE3  // 重新使用上一包有效数据,当CE为高过程中,数据包被不断的重新发射
#define NOP           0xFF  // 空操作,可以用来读状态寄存器
/******************************************************************
// nRF24L01寄存器地址
*******************************************************************/
#define CONFIG      0x00  // 配置寄存器
#define EN_AA       0x01  // “自动应答”功能寄存
#define EN_RX_ADDR  0x02  // 接收通道使能寄存器
#define SETUP_AW    0x03  // 地址宽度设置寄存器
#define SETUP_RETR  0x04  // 自动重发设置寄存器
#define RF_CH       0x05  // 射频通道频率设置寄存器
#define RF_SETUP    0x06  // 射频设置寄存器
#define STATUS      0x07  // 状态寄存器
#define OBSERVE_TX  0x08  // 发送检测寄存器
#define CD          0x09  // 载波检测寄存器
#define RX_ADDR_P0  0x0A  // 数据通道0接收地址寄存器
#define RX_ADDR_P1  0x0B  // 数据通道1接收地址寄存器
#define RX_ADDR_P2  0x0C  // 数据通道2接收地址寄存器
#define RX_ADDR_P3  0x0D  // 数据通道3接收地址寄存器
#define RX_ADDR_P4  0x0E  // 数据通道4接收地址寄存器
#define RX_ADDR_P5  0x0F  // 数据通道5接收地址寄存器
#define TX_ADDR     0x10  // 发送地址寄存器
#define RX_PW_P0    0x11  // 数据通道0有效数据宽度设置寄存器
#define RX_PW_P1    0x12  // 数据通道1有效数据宽度设置寄存器
#define RX_PW_P2    0x13  // 数据通道2有效数据宽度设置寄存器
#define RX_PW_P3    0x14  // 数据通道3有效数据宽度设置寄存器
#define RX_PW_P4    0x15  // 数据通道4有效数据宽度设置寄存器
#define RX_PW_P5    0x16  // 数据通道5有效数据宽度设置寄存器
#define FIFO_STATUS 0x17  // FIFO状态寄存器
#define        SlaveAddress   0x46
//*********************************************************************************
#define MISO   PORTA_PA7
#define MOSI   PORTA_PA6
#define        SCK           PORTA_PA5
#define CSN    PORTA_PA4
#define CE     PORTA_PA3
#define IRQ    PORTA_PA2
#define LED    PORTA_PA0
//---------------全局变量-----------------------
byte sta;    // 状态变量
#define RX_DR  (sta & 0x40)  // 接收成功中断标志
#define TX_DS  (sta & 0x20)  // 发射成功中断标志
#define MAX_RT (sta & 0x10)  // 重发溢出中断标志
byte const TX_Addr[TX_ADDR_WITDH]= {0x43,0x43,0x10,0x10,0x01};        //本地地址
//byte const RX_Addr[RX_ADDR_WITDH]= {0x34,0x43,0x10,0x10,0x01};        //接收地址
//byte RX_Buffer[RX_DATA_WITDH]={0};
//extern byte RX_Buffer[RX_DATA_WITDH];
byte ddd;

/*************函数声明*****************/
void nRF24L01_Init(void);
byte SPI_RW(byte byte);
byte SPI_W_Reg(byte reg,byte value);
byte SPI_R_byte(byte reg);
//byte SPI_R_DBuffer(byte reg,byte *Dat_Buffer,byte Dlen);
byte SPI_W_DBuffer(byte reg,byte *TX_Dat_Buffer,byte Dlen);
void nRF24L01_Set_TX_Mode(byte *TX_Data);
//void nRF24L01_Set_RX_Mode(void);
byte Check_Ack(void);
//byte nRF24L01_RX_Data(void);
//void nrf_send_com(byte *TX_Data);

void S12_init()
        {
           CLKSEL&=0x7f;         //选定外部时钟           
           PLLCTL&=0xbc;         //禁止锁相环                    
           SYNR=0x02;     //PLL增频因子
           REFDV=0x01;     //PLL分频因子,最终得到24M总线频率
           PLLCTL|=0x40;         //锁相环电路使能
           _asm(nop);                  
    _asm(nop);
     CLKSEL|=0x80;    //选定锁相环时钟为系统时钟
           IRQCR&=0xbf;    //禁止触发外部中断
           COPCTL=0X00;    //看门狗无效
        }
/*软件延时,24M总线频率时延时时间约为delaytime 1us*/
void _delay_us(int delaytime)
        {
     int i;byte j;
     for (i=0;i<delaytime;i++)
      for (j=0;j<8;j++);        
        }

/*软件延时,24M总线频率时延时时间约为delaytime 1ms*/       
void delay(int delaytime)
        {
         int i;
     for (i=0;i<delaytime;i++)
     _delay_us(1000);
        }
       
/*nRF24L01初始化*/
void nRF24L01_Init(void)
{
        _delay_us(2000);
        CE=0;//待机模式
        CSN=1;
        SCK=0;
        IRQ=1;
}

/*SPI时序函数*/
byte SPI_RW(byte data)
{
        byte i;
        for(i=0;i<8;i++)//一字节8位循环8次写入
        {
          MOSI = (data & 0x80);   // byte最高位输出到MOSI
                data<<=1;//低一位移到最高位
                SCK=1;//SCK拉高,写入一位数据,同时读取一位数据
                if(MISO)
                data|=0x01;
                SCK=0;//SCK拉低
        }
        return data;//返回读取一字节
}

/*SPI写寄存器一字节函数*/
/*reg:寄存器地址*/
/*value:一字节(值)*/
byte SPI_W_Reg(byte reg,byte value)
{
        byte status;//返回状态
        CSN=0;//SPI片选
        status=SPI_RW(reg);//写入寄存器地址,同时读取状态
        SPI_RW(value);//写入一字节
        CSN=1;//
        return status;//返回状态
}

/*SPI*/
byte SPI_R_byte(byte reg)
{
        byte reg_value;
        CSN=0;//SPI片选
        SPI_RW(reg);//写入地址
        reg_value=SPI_RW(0);//读取寄存器的值
        CSN=1;
        return reg_value;//返回读取的值
}

/*SPI读取RXFIFO寄存器数据*/
/*reg:寄存器地址*/
/**Dat_Buffer:用来存读取的数据*/
/*DLen:数据长度*/
//byte SPI_R_DBuffer(byte reg,byte *Dat_Buffer,byte Dlen)
//{
//        byte reg_value,i;
//        CSN=0;
//        reg_value=SPI_RW(reg);
//        for(i=0;i<Dlen;i++)
//        {
//        Dat_Buffer[i]=SPI_RW(0);
//        }
//        CSN=1;
//        return reg_value;
//}

/*SPI向TXFIFO寄存器写入数据*/
/*reg:写入寄存器地址*/
/*TX_Dat_Buffer:存放需要发送的数据*/
/*Dlen:数据长度*/
byte SPI_W_DBuffer(byte reg,byte *TX_Dat_Buffer,byte Dlen)
{
        byte status,i;
        CSN=0;//SPI片选,启动时序
        status=SPI_RW(reg);
        for(i=0;i<Dlen;i++)
        {
        SPI_RW(TX_Dat_Buffer[i]);//发送数据
        }
        CSN=1;
        return status;
}
/*设置发送模式*/
void nRF24L01_Set_TX_Mode(byte *TX_Data)
{
        CE=0;//待机(写寄存器之前一定要进入待机模式或掉电模式)
        SPI_W_DBuffer(W_REGISTER+TX_ADDR,TX_Addr,TX_ADDR_WITDH);/*写寄存器指令+接收节点地址+地址宽度*/
        SPI_W_DBuffer(W_REGISTER+RX_ADDR_P0,TX_Addr,TX_ADDR_WITDH);/*为了接收设备应答信号,接收通道0地址与发送地址相同*/
        SPI_W_DBuffer(W_TX_PLOAD,TX_Data,TX_DATA_WITDH);/*写有效数据地址+有效数据+有效数据宽度*/
        SPI_W_Reg(W_REGISTER+EN_AA,0x01);/*接收通道0自动应答*/
        SPI_W_Reg(W_REGISTER+EN_RX_ADDR,0x01);/*使能接收通道0*/
        SPI_W_Reg(W_REGISTER+SETUP_RETR,0x0a);/*自动重发延时250US+86US,重发10次*/
        //SPI_W_Reg(W_REGISTER+RX_PW_P0,RX_DATA_WITDH);
        SPI_W_Reg(W_REGISTER+RF_CH,0x40);/*(2400+40)MHZ选择射频通道0X40*/
        SPI_W_Reg(W_REGISTER+RF_SETUP,0x07);/*1Mbps速率,发射功率:0DBM,低噪声放大器增益*/
        SPI_W_Reg(W_REGISTER+CONFIG,0x0e);/*发送模式,上电,16位CRC校验,CRC使能*/
        CE=1;//启动发射
        delay(5);/*CE高电平持续时间最少10US以上*/
}

/*设置接收模式*/
//void nRF24L01_Set_RX_Mode(void)
//{
//        CE=0;//待机
//        //SPI_W_DBuffer(W_REGISTER+TX_ADDR,TX_Addr,TX_ADDR_WITDH);
//        SPI_W_DBuffer(W_REGISTER+RX_ADDR_P0,RX_Addr,TX_ADDR_WITDH);
//        SPI_W_Reg(W_REGISTER+EN_AA,0x01);
//        SPI_W_Reg(W_REGISTER+EN_RX_ADDR,0x01);
//        //SPI_W_Reg(W_REGISTER+SETUP_RETR,0x0a);
//        SPI_W_Reg(W_REGISTER+RX_PW_P0,RX_DATA_WITDH);
//        SPI_W_Reg(W_REGISTER+RF_CH,0x40);
//        SPI_W_Reg(W_REGISTER+RF_SETUP,0x07);
//        SPI_W_Reg(W_REGISTER+CONFIG,0x0f);
//        CE=1;
//        delay(5);
//}

/*检测应答信号*/
byte Check_Ack(void)
{
        sta=SPI_R_byte(R_REGISTER+STATUS);/*读取寄存状态*/
        if(TX_DS||MAX_RT)/*如果TX_DS或MAX_RT为1,则清除中断和清除TX_FIFO寄存器的值*/
        {
                SPI_W_Reg(W_REGISTER+STATUS,0xff);
                CSN=0;
                SPI_RW(FLUSH_TX);
                CSN=1;
                return 0;
        }
        else
        return 1;
}

/*检测接收是否成功*/
//byte nRF24L01_RX_Data(void)
//{
//        //byte i,status;
//        sta=SPI_R_byte(R_REGISTER+STATUS);
//        if(RX_DR)
//        {
//                CE=0;
//                SPI_R_DBuffer(R_RX_PLOAD,RX_Buffer,RX_DATA_WITDH);
//                //P3=RX_Buffer[0];
//                SPI_W_Reg(W_REGISTER+STATUS,0xff);
//                CSN=0;
//                SPI_RW(FLUSH_RX);
//                CSN=1;
//                return 1;
//        }
//        else
//        return 0;
//}

//void nrf_send_com(byte *TX_Data)
//{
//         nRF24L01_Set_TX_Mode(TX_Data);
//        delay(100);
//        while(Check_Ack());       
//}





void main(void) {
  /* put your own code here */


    DDRA=0XFF;
    nRF24L01_Init();
    LED=1;
    while(1)
    {
       /* CE=0;
        SPI_W_Reg(W_REGISTER+EN_RX_ADDR,0x03);
        CE=1;
        delay(20); */
        ddd=SPI_R_byte(R_REGISTER+EN_RX_ADDR);
        if(ddd==0x03)
        {
            LED=0;
        }
        else  
        {
            LED=1;
        }
        delay(500);
    }
        EnableInterrupts;


  for(;;) {
   /* feeds the dog */
  } /* loop forever */
  /* please make sure that you never leave main */
}


注:EN_RX_ADDR默认值是0x03.灯不灭。。。


4

主题

203

帖子

0

精华

常驻嘉宾

我也有头衔

Rank: 8Rank: 8

积分
3354
威望
1835
贡献
891
兑换币
713
注册时间
2013-9-10
在线时间
314 小时
毕业学校
浙江大学
12#
发表于 2013-9-23 08:52:09 | 只看该作者
/*SPI*/
byte SPI_R_byte(byte reg)
{
        byte reg_value;
        CSN=0;//SPI片选
        SPI_RW(reg);//写入地址
        reg_value=SPI_RW(0);//读取寄存器的值
        CSN=1;
        return reg_value;//返回读取的值
}
别的不说 这一段有问题
读取寄存器应该写0xFF :
reg_value=SPI_RW(0xFF); //你回去改一下吧
然后 送你一段检测24L01的函数:
u8 NRF24L01_Check(void)
{
        u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
        u8 i;
        SPIx_SetSpeed(SPI_SPEED_8); //spi速度为9Mhz(24L01的最大SPI时钟为10Mhz)
        NRF24L01_Write_Buf(WRITE_REG+TX_ADDR,buf,5);//写入5个字节的地址.
        NRF24L01_Read_Buf(TX_ADDR,buf,5); //读出写入的地址
        for(i=0;i<5;i++)if(buf[i]!=0XA5)break;
        if(i!=5)return 1;//检测24L01错误
        return 0;                 //检测到24L01
}
自己改下函数名吧 相信你没问题
回复 支持 反对

使用道具 举报

29

主题

598

帖子

0

精华

常驻嘉宾

Rank: 8Rank: 8

积分
3536

优秀会员奖章活跃会员奖章论坛元老奖章在线王奖章

威望
1932
贡献
834
兑换币
199
注册时间
2012-2-5
在线时间
385 小时
毕业学校
保密
11#
发表于 2013-4-26 21:48:36 | 只看该作者
好的
回复 支持 反对

使用道具 举报

2

主题

14

帖子

0

精华

高级会员

Rank: 4

积分
538
威望
249
贡献
119
兑换币
143
注册时间
2012-11-17
在线时间
85 小时
毕业学校
重庆大学
10#
 楼主| 发表于 2013-4-26 18:57:41 | 只看该作者
verm 发表于 2013-4-26 12:35
调试时限制调试发射 查看寄存器STATUS和FIFO_STATUS状态 读写时序 你随便找个历程看一看就行 感觉没有错

找到问题了,程序还是有错,miso要设为输入口,网上好多例子都没有设,真不知道是怎么工作了,不过还是谢谢了
回复 支持 反对

使用道具 举报

29

主题

598

帖子

0

精华

常驻嘉宾

Rank: 8Rank: 8

积分
3536

优秀会员奖章活跃会员奖章论坛元老奖章在线王奖章

威望
1932
贡献
834
兑换币
199
注册时间
2012-2-5
在线时间
385 小时
毕业学校
保密
9#
发表于 2013-4-26 12:36:30 | 只看该作者
'限制'“先只”
回复 支持 反对

使用道具 举报

29

主题

598

帖子

0

精华

常驻嘉宾

Rank: 8Rank: 8

积分
3536

优秀会员奖章活跃会员奖章论坛元老奖章在线王奖章

威望
1932
贡献
834
兑换币
199
注册时间
2012-2-5
在线时间
385 小时
毕业学校
保密
8#
发表于 2013-4-26 12:35:39 | 只看该作者
调试时限制调试发射 查看寄存器STATUS和FIFO_STATUS状态 读写时序 你随便找个历程看一看就行 感觉没有错
回复 支持 反对

使用道具 举报

2

主题

14

帖子

0

精华

高级会员

Rank: 4

积分
538
威望
249
贡献
119
兑换币
143
注册时间
2012-11-17
在线时间
85 小时
毕业学校
重庆大学
7#
 楼主| 发表于 2013-4-26 11:11:35 | 只看该作者
1508323954 发表于 2013-4-26 10:35
同意上楼

谢谢你的答复,不过你再看看我主函数,我没调用那些,你说的那些我也试过,不行,现在主函数检测的是能不能读写寄存器,而不是发送,现在我都检测到spi时序了,感觉是发出指令了,但还是不能读写,就是不知道nrf24l01有没有接收到指令,下午准备用示波器测一下看情况了。
回复 支持 反对

使用道具 举报

2

主题

14

帖子

0

精华

高级会员

Rank: 4

积分
538
威望
249
贡献
119
兑换币
143
注册时间
2012-11-17
在线时间
85 小时
毕业学校
重庆大学
6#
 楼主| 发表于 2013-4-26 11:08:07 | 只看该作者
verm 发表于 2013-4-26 10:06
单独发送应该将自动重发 关掉

谢谢你的答复,不过你再看看我主函数,我没调用那些,你说的那些我也试过,不行,现在主函数检测的是能不能读写寄存器,而不是发送,现在我都检测到spi时序了,感觉是发出指令了,但还是不能读写,就是不知道nrf24l01有没有接收到指令,下午准备用示波器测一下看情况了。
回复 支持 反对

使用道具 举报

2

主题

14

帖子

0

精华

高级会员

Rank: 4

积分
538
威望
249
贡献
119
兑换币
143
注册时间
2012-11-17
在线时间
85 小时
毕业学校
重庆大学
5#
 楼主| 发表于 2013-4-26 10:59:57 | 只看该作者
verm 发表于 2013-4-26 10:04
你的发送成功不??

就是没有发送成功啊,现在一步一步检查,发现不能读寄存器,,,
回复 支持 反对

使用道具 举报

27

主题

798

帖子

0

精华

跨届大侠

Rank: 10Rank: 10Rank: 10

积分
6257

优秀会员奖章活跃会员奖章在线王奖章论坛元老奖章

威望
2948
贡献
1741
兑换币
1138
注册时间
2012-2-20
在线时间
784 小时
4#
发表于 2013-4-26 10:35:41 | 只看该作者
同意上楼
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

关于我们|联系我们|小黑屋|智能车制作 ( 黑ICP备2022002344号

GMT+8, 2024-10-2 14:21 , Processed in 0.117748 second(s), 32 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表