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

关于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日

悬赏问题

  • ¥15 smptlib使用465端口发送邮件失败
  • ¥200 总是报错,能帮助用python实现程序实现高斯正反算吗?有偿
  • ¥15 对于squad数据集的基于bert模型的微调
  • ¥15 为什么我运行这个网络会出现以下报错?CRNN神经网络
  • ¥20 steam下载游戏占用内存
  • ¥15 CST保存项目时失败
  • ¥15 树莓派5怎么用camera module 3啊
  • ¥20 java在应用程序里获取不到扬声器设备
  • ¥15 echarts动画效果的问题,请帮我添加一个动画。不要机器人回答。
  • ¥15 Attention is all you need 的代码运行