看见萌妹流鼻血 2022-09-12 21:24 采纳率: 100%
浏览 45
已结题

关于51单片机与nrf24l01的通讯问题

写了一个spi模拟通讯协议,想验证通信协议是否正确,身边就只找到了nrf24l01模块,费了九牛二虎之力撸完代码等待收获成功的喜悦,结果,status寄存器一直返回255,前面对nrf24l01一直没有研究,所以我不知道是spi时序问题还是nrf24l01的问题,下面是spi代码:

#include "SPI.h"
bit CPOL;
bit CPHA;
bit GD;

void Delay10us()        //@12MHz
{
    unsigned char i;

    _nop_();
    _nop_();
    i = 27;
    while (--i);
}

void SPI_init(unsigned char MS_1,bit MS_2){            //MS_1为模式选择(0,1,2,3),MS_2为高低位选择(0:低位在前,1:高位在前)
    switch(MS_1){
            case 0:
                CPOL = 0;
                CPHA = 0;
            break;
            case 1:
                CPOL = 0;
                CPHA = 1;
            break;
            case 2:
                CPOL = 1;
                CPHA = 0;
            break;
            case 3:
                CPOL = 1;
                CPHA = 1;
            break;
    }
    GD = MS_2;
    SCLK = CPOL;
//    CS = 1;
    MOSI = 1;
    MISO = 1;
}
unsigned char spi_RW(unsigned char spi_data){
    unsigned char tval=0x00,i;
//    CS = 0;
    for(i=0;i<8;i++)
    {
        if(CPHA)
        {
            Delay10us();
            SCLK = ~CPOL;
            if(GD)
                MOSI = 0x80&spi_data;
            else
                MOSI = 0x01&spi_data;
            Delay10us();
            Delay10us();
            SCLK = CPOL;
            if(GD)
            {
                tval <<= 1;
                if(MISO)
                    tval |= 0x01;
                spi_data <<= 1;
                
            }
            else
            {
                tval >>= 1;
                if(MISO)
                    tval |= 0x80;
                spi_data >>= 1;
                
            }
            Delay10us();
        }
        else
        {
            if(GD)
                MOSI = 0x80&spi_data;
            else
                MOSI = 0x01&spi_data;
            Delay10us();
            SCLK = ~CPOL;
            if(GD)
            {
                tval <<= 1;
                if(MISO)
                tval |= 0x01;
                spi_data <<= 1;
                
            }
            else
            {
                tval >>= 1;
                if(MISO)
                    tval |= 0x80;
                spi_data >>= 1;
                
            }
            Delay10us();
            Delay10us();
            SCLK = CPOL;
            Delay10us();
        }
    }
//  CS = 1;
    return tval;
}

上面片选信号在nrf24l01中实现,spi中未用到,下面是spi.h文件

#ifndef ___S____P___I___H__
#define ___S____P___I___H__
#include "STC.h"
#include <intrins.h>

sbit SCLK = P3^6;
sbit MOSI = P2^0;
sbit MISO = P2^2;
//sbit CS = P1^3;
void SPI_init(unsigned char MS_1,bit MS_2);           //MS_1为模式选择(0,1,2,3),MS_2为高低位选择(0:低位在前,1:高位在前)

unsigned char spi_RW(unsigned char spi_data);    //发送接收函数



#endif

nrf24l01程序有点长,

#include "nrf24l01.h"
unsigned char TX_addr1[]={0xc3,0xe4,0x6a,0xde,0xc6};
void NRF_init(){    //初始化工作
    SPI_init(0,1);  //SPI工作方式0,高位在前
    nrf_cs = 1;
    nrf_ce = 0;
}
unsigned char nrf_w_byte(unsigned char commd,unsigned char dat){ //写一个字节,带格式化地址
    unsigned char val1;
    commd &= 0x1f;
    commd |= 0x20;
    nrf_cs = 0;
    val1 = spi_RW(commd);
    spi_RW(dat);
    nrf_cs = 1;
    return val1;
}
unsigned char nrf_r_byte(unsigned char commd,unsigned char dat){ //读取一个字节  参数为地址,数据(一般是0xff)带地址格式化
    unsigned char val1;
    commd &= 0x1f;
    nrf_cs = 0;
    spi_RW(commd);
    val1 = spi_RW(dat);
    nrf_cs = 1;
    return val1;
}
unsigned char nrf_w_str(unsigned char commd,unsigned char *ndat,unsigned char nnum){//写入数组   参数为地址命令,数据数组,数据字节
    unsigned char i,val;
    nrf_cs = 0;
    val = spi_RW(commd); 
    for(i=0;i<nnum;i++){
        spi_RW(ndat[i]);
    }
    nrf_cs = 1;
    return val;
}
unsigned char nrf_r_str(unsigned char commd,unsigned char *ndat,unsigned char nnum){//读取数组,参数同上
    unsigned char i,val;
    nrf_cs = 0;
    val = spi_RW(commd); 
    for(i=0;i<nnum;i++){
        ndat[i] = spi_RW(0xff);
    }
    nrf_cs = 1;
    return val;
}
void NRF_send(unsigned char *dat,unsigned char snum){//准备作为写FIFO函数
    nrf_w_str(0xa0,dat,snum);
}
void NRF_accept(unsigned char *dat,unsigned char snum){//准备作为读FIFO函数
    nrf_w_str(0x61,dat,snum);
}
void NRF_clear(unsigned char mod_reg){ //FIFO寄存器清除操作参数mod_regT表示发送寄存器清0,R为接收寄存器清0
    switch(mod_reg){
        case 0:
            nrf_cs = 0;
            spi_RW(0xe1);
            spi_RW(0xff);
            nrf_cs = 1;
            break;
        case 1:
            nrf_cs = 0;
            spi_RW(0xe2);
            spi_RW(0xff);
            nrf_cs = 1;
            break;
    }
}
unsigned char NRF_status(){//读取状态寄存器
  return nrf_r_byte(0x07,0xff);//status
}
void NRF_TX_MODE(){//发送端设置,注释为对应寄存器名称
    nrf_w_byte(0x00,0x0a);//config
    nrf_w_byte(0x01,0x3f);//en_aa
    nrf_w_byte(0x02,0x01);//en_rx_addr
    nrf_w_byte(0x03,0x03);//setup_aw
    nrf_w_byte(0x04,0x0a);//setup_retr
    nrf_w_byte(0x05,0x3a);//rf_ch
    nrf_w_byte(0x06,0x0f);//config
    nrf_w_byte(0x07,0x0e);//status
    
    nrf_w_str(0x0a+0x20,TX_addr1,5);//rx_addr_p0
    nrf_w_str(0x10+0x20,TX_addr1,5);//tx_addr
    NRF_clear(0);
}


如上为所有代码,main函数只做了初始化并一直读取status寄存器数据,但是读取数据一直为0xff,为此我斥巨资35购入一台逻辑分析仪来观测数据时序,结果如图

img

img

img

观测到的mosi波形应该是正确的,但是nrf24l01一直返回0xff就让我非常迷茫

希望大家能指出是什么问题,怎么能正确收到status寄存器值

  • 写回答

3条回答 默认 最新

  • 小谦· 2022-09-13 08:53
    关注

    时钟线和片选线挂哪了???
    C51的P0端口要外接上拉电阻,否则无法输出高电平,也就是说你的片选和时钟一直是低电平,芯片是无法正常通讯的,

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 9月25日
  • 已采纳回答 9月17日
  • 创建了问题 9月12日

悬赏问题

  • ¥500 求华为P30PRO手机硬盘数据恢复
  • ¥15 关于#vscode#的问题:ESP32开发板对接MQTT实现小灯泡的开关
  • ¥15 TMC2209串口模式下读取不到寄存器的值串口助手蓝色字体是发过去的消息,绿色字体是收到的消息,第二行发送读取寄存器的指令但是没有读取到寄存器的值串口助手如下图:接线如下图,如何解决?
  • ¥15 高通安卓11提取完整线刷包软件,或者优博讯dt50顺丰刷机包
  • ¥20 C,有个译码器,换了信道就跑不出原来数据
  • ¥15 MIMIC数据库安装问题
  • ¥60 基于JTag协议开发Fpga下载器上位机,哪位大🐂有偿指导?
  • ¥20 全书网Java爬取数据
  • ¥15 怎么获取红包封面的原始链接,并且获取红包封面序列号
  • ¥100 微信小程序跑脚本授权的问题