微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 求大神指导啊,nRF24L01通信模块,毕业设计,快一个月了还没做出来,导师说再做不出要关掉我了。。。

求大神指导啊,nRF24L01通信模块,毕业设计,快一个月了还没做出来,导师说再做不出要关掉我了。。。

时间:10-02 整理:3721RD 点击:
用的是AVR ATmega328P的单片机,现在的问题是发送端的STATUS寄存器读到的始终是0x0e,没有进行check,只是不断循环发送。
下面贴一下程序:(程序里有一些地方用到transmitByte()这个方法只是把单片机中的数据通过USART连接传到PC,与模块无关)
//nrf24l01.h 发送端和接收端相同
#ifndef _NRF24L01_H
#define _NRF24L01_H
#include <avr/io.h>
#include <avr/interrupt.h>
#define  uchar unsigned char
#define uint unsigned int
//spi symbol
#define DDR_SPI DDRB
#define DD_MOSI DDB3
#define DD_MISO DDB4
#define DD_SCK DDB5
#define DD_SS DDB2
#define CE PINB1
#define IRQ PIND2
#define MISO PINB4
#define   High_24L01_MISO    PORTB |= (1 << PINB4)
#define   Low_24L01_MISO     PORTB &= ~(1 << PINB4)
#define   Read_24L01_MISO    PINB & (1 << PINB4)
#define   High_24L01_MOSI    PORTB |= (1 << PINB3)
#define   Low_24L01_MOSI     PORTB &= ~(1 << PINB3)
#define   Read_24L01_MOSI    PINB & (1 << PINB3)
#define   High_24L01_SCK    PORTB |= (1 << PINB5)
#define   Low_24L01_SCK     PORTB &= ~(1 << PINB5)
#define   Read_24L01_SCK    PINB & (1 << PINB5)
#define   Low_24L01_CSN     PORTB &= ~(1 << PINB2)
#define   High_24L01_CSN    PORTB |= (1 << PINB2)
#define   High_24L01_CE    PORTB |= (1 << PINB1)
#define   Low_24L01_CE     PORTB &= ~(1 << PINB1)
#define   Read_24L01_CE    PINB & (1 << PINB1)
//*******************************new
#define  High_24L01_IRQ        PORTD |= (1 << PIND2)
#define  Low_24L01_IRQ        PORTD &= ~(1 << PIND2)
//*********************************************NRF24L01
#define TX_ADR_WIDTH 5
#define RX_ADR_WIDTH 5
#define TX_PLOAD_WIDTH 5
#define RX_PLOAD_WIDTH 5
//*************************************REGISTER INSTRUCTION
#define READ_REG        0x00
#define WRITE_REG       0x20
#define RD_RX_PLOAD     0x61
#define WR_TX_PLOAD     0xA0
#define FLUSH_TX        0xE1
#define FLUSH_RX        0xE2
#define REUSE_TX_PL     0xE3
#define NOP1             0xFF
//*******************************REGISTER ADDRESS
#define CONFIG          0x00
#define EN_AA           0x01
#define EN_RXADDR       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
#define RX_ADDR_P1      0x0B
#define RX_ADDR_P2      0x0C
#define RX_ADDR_P3      0x0D
#define RX_ADDR_P4      0x0E
#define RX_ADDR_P5      0x0F
#define TX_ADDR         0x10
#define RX_PW_P0        0x11
#define RX_PW_P1        0x12
#define RX_PW_P2        0x13
#define RX_PW_P3        0x14
#define RX_PW_P4        0x15
#define RX_PW_P5        0x16
#define FIFO_STATUS     0x17
//***************************************************function
void spi_init(void);
void delay_nus(uint n);
void delay_nms(uint n);
uchar SPI_RW(uchar date);
uchar SPI_Read(uchar reg);
uchar SPI_RW_Reg(uchar reg, uchar value);
uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar bites);
uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar bites);
void SetRX_Mode(void);
uchar nRF24L01_RxPacket(uchar* rx_buf);
void nRF24L01_TxPacket(uchar* tx_buf);
uchar CheckACK(void);
void init_NRF24L01(void);
//new functions to output to hyperterminal
uchar print_register_hyperterminal(uchar reg);
void print_rw_address(uchar reg);
uchar print_register_state(uchar state);
#endif
//nrf24l01.c 发送端和接收端相同
#include "nrf24l01.h"
uchar TX_ADDRESS[TX_ADR_WIDTH]={0xE7,0xE7,0xE7,0xE7,0xE7};
uchar RX_ADDRESS[RX_ADR_WIDTH]={0xE7,0xE7,0xE7,0xE7,0xE7};

void spi_init(void) {
    High_24L01_CSN;//set CSN to high(not active)
    DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_SS)|(1 << CE);//set MOSI,SCK,CSN,CE as output
    DDR_SPI &= ~(1<<DD_MISO);
    DDRD &= ~(1<<IRQ);
    SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);//enable SPI, master, fosc/16
    SPSR = 0x00;
   
    }
void delay_nus(uint n) {
    while(n--)
    ;
}
void delay_nms(uint n) {
    uint j;
    while(n--)
    for(j=0;j<1140;j++);
}
//***************************************SPI read and write
uchar SPI_RW(uchar date) {
    SPDR=date;
    while(!(SPSR&(1<<SPIF)));
    return SPDR;
    }
   
//*********************************** read nRF24L01 register
uchar SPI_Read(uchar reg) {
    uchar reg_val;
    Low_24L01_CSN;
    SPI_RW(reg);
    reg_val = SPI_RW(0xff);
    High_24L01_CSN;
    return(reg_val);
}
//************************************** write nRF24L01 register
uchar SPI_RW_Reg(uchar reg, uchar value) {
    uchar status;
    Low_24L01_CSN;
    status = SPI_RW(reg);
    SPI_RW(value);
    High_24L01_CSN;
    return(status);
}
//******************************************read RX-fifo buffer or register with 5 bytes
uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar bites) {
    uint status1,uchar_ctr;
    Low_24L01_CSN;
    status1 = SPI_RW(reg);
    for(uchar_ctr=0;uchar_ctr<bites;uchar_ctr++)
    pBuf[uchar_ctr] = SPI_RW(0xff);
    High_24L01_CSN;
    return(status1);
}
//**************************************write TX-FIFO buffer
uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar bites) {
    uchar status1,uchar_ctr;
    Low_24L01_CSN;                //SPI enable
    status1 = SPI_RW(reg);
    for(uchar_ctr=0; uchar_ctr<bites; uchar_ctr++) //
    SPI_RW(*pBuf++);
    High_24L01_CSN;            //SPI disable
    return(status1);            //
}
//****************************** set to RX mode
void SetRX_Mode(void) {
    Low_24L01_CE;
    SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH);    //set rx address
    SPI_RW_Reg(WRITE_REG + EN_AA, 0x00);        //pipe0 automatical acknowledge
    SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);        //enable pipe 0
    //SPI_RW_Reg(WRITE_REG + SETUP_AW, 0x02);
    SPI_RW_Reg(WRITE_REG + RF_CH, 0x70);                //set channel
    SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH);        //set payload width of the rx pipe0  
    SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x01);            //-18dBm 1M
    SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);            //set to rx mode
    High_24L01_CE;                                //start monitor
    delay_nus(200);                            //delay
    }
//********************************** receive packet
uchar nRF24L01_RxPacket(uchar* rx_buf)
{
    uchar sta,flag=0;
    sta=SPI_Read(STATUS);            //read STATUS register
    if(sta&0x40)                    //judge RX_DR==1?
    {
        Low_24L01_CE;                //start to monitor
        SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);        //read data from RX_FIFO buffer
        flag = 1;                    //end flag of receving data
        }
        SPI_RW_Reg(WRITE_REG+STATUS,sta);            //set RX_DR,TX_DS,MAX_PT to 1,to erase interruption flag
        //SPI_RW_Reg(WRITE_REG+STATUS,0xFF);
        return (flag);
}
//********************************* send packets
void nRF24L01_TxPacket(uchar* tx_buf) {
    uchar sta=0;
    uchar flag=0;
    Low_24L01_CE;        //start to write register
    SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);
    SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);        //set rx address for pipe0 for receiving acknowledge
    SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH);        //tx_payload operation to send data
   
    SPI_RW_Reg(WRITE_REG + EN_AA, 0x00);                //
    SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);            //
                                                        //SPI_RW_Reg(WRITE_REG + SETUP_AW, 0x02);
    SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x03);                //500+86us
    SPI_RW_Reg(WRITE_REG + RF_CH, 0x70);                        //
    SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x01);                    //-18dBm, 1Mbps
    SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);                    //set to transmitter
    delay_nms(2);
    High_24L01_CE;                                        //start to send
    delay_nus(15);
    //delay_nus(10);
    Low_24L01_CE;
}
uchar CheckACK(void) {
    uchar sta1;
    sta1=SPI_Read(STATUS);            //return STATUS register
    delay_nms(500);
    if((sta1&0x20)||(sta1&0x10))        //if tx_ds or max_rt set
    {
    //Low_24L01_CSN;
    SPI_RW_Reg((READ_REG+STATUS),0xff);        //flush TX_DS and MAX_RT
    Low_24L01_CSN;
    SPI_RW(FLUSH_TX);   //flush TX-FIFO
    High_24L01_CSN;
    return(0);
    }
    else
    return(1);
}
void init_NRF24L01(void) {
    uart0_init();
    spi_init();
   
    Low_24L01_CE;            //standby mode
   
    Low_24L01_CSN;
    SPI_RW(FLUSH_TX);
    SPI_RW(FLUSH_RX);
   
    High_24L01_CSN;        //disable SPI
    Low_24L01_SCK;        //disable clock
    High_24L01_IRQ;
   
}
//下面的3个方法是自己写的,目的是把从寄存器里读出来的状态字可以通过usart通信在终端程序上面显示出来,与主题关联不大!
//*******************************add a new function to output the state of a register on the hyperterminal
uchar print_register_state(uchar state){
   
if(state&0x01){
    transmitByte('0');
    delay_nms(100);
}
else{
    transmitByte('N');
    delay_nms(100);
}
if(state&0x02){
    transmitByte('1');
    delay_nms(100);
}
else{
    transmitByte('N');
    delay_nms(100);
}
if(state&0x04){
    transmitByte('2');
    delay_nms(100);
}
else{
    transmitByte('N');
    delay_nms(100);
}
if(state&0x08){
    transmitByte('3');
    delay_nms(100);
}
else{
    transmitByte('N');
    delay_nms(100);
}
if(state&0x10){
    transmitByte('4');
    delay_nms(100);
}
else{
    transmitByte('N');
    delay_nms(100);
}
if(state&0x20){
    transmitByte('5');
    delay_nms(100);
}
else{
    transmitByte('N');
    delay_nms(100);
}
if(state&0x40){
    transmitByte('6');
    delay_nms(100);
}
else{
    transmitByte('N');
    delay_nms(100);
}
if(state&0x80){
    transmitByte('7');
    delay_nms(100);
}
else{
    transmitByte('N');
    delay_nms(100);
}
transmitByte(0x0d);
delay_nms(100);
transmitByte(0x0a);
delay_nms(100);
//return reg_content;
}
//**********************get the state of rx_addr or tx_addr register (5 bytes)
void print_rw_address(uchar reg){
    uchar rw_address[TX_PLOAD_WIDTH];
    SPI_Read_Buf(reg, rw_address, TX_PLOAD_WIDTH);
    for(int i=0; i<TX_PLOAD_WIDTH; i++){
        print_register_state(rw_address[i]);
    }
   
   
}
//*****************************get the state of registers (1 byte)
uchar print_register_hyperterminal(uchar reg){
    uchar reg_content=SPI_Read(reg);
    print_register_state(reg_content);
    return reg_content;
   
}
//接收端的主程序
#define F_CPU 3686400UL      //To make the delay function work correctly
//#define F_CPU 8000000UL
#include <util/delay.h>
#include "nrf24l01.h"

int main(void){
   
    uchar sta1,sta2;
    uchar RX_BUF[5];
    uchar flag=0;
  
  
        while(!flag){
            
        init_NRF24L01();
        SetRX_Mode();
        delay_nms(500);
        print_register_hyperterminal(CD);
     
        //*******************************
        High_24L01_CE;                                //start monitor
        delay_nus(200);                            //delay
        //*********************************
        sta1=print_register_hyperterminal(STATUS);
        TX_NEWLINE;
        if(sta1&0x40)                    //judge RX_DR==1?
        {
            Low_24L01_CE;                //start to transmit
            SPI_Read_Buf(RD_RX_PLOAD,RX_BUF,TX_PLOAD_WIDTH);        //read data from RX_FIFO buffer
            flag = 1;                    //end flag of receving data
        }
        else{
            flag=0;
        }
        SPI_RW_Reg(WRITE_REG+STATUS,sta1);            //set RX_DR,TX_DS,MAX_PT to 1,to erase interruption flag
  
        }
   
        for(int i=0;i<5;i++){
            transmitByte(RX_BUF[i]);
              }
            
    return 0;
}
//发送端的主程序
#define F_CPU 3686400UL      //To make the delay function work correctly
#include <util/delay.h>
#include "nrf24l01.h"
#include "usart_routines.h"

int main(void){
    uchar TX_BUF[5]={'A','B','C','D','E'};
    uchar sta1;
            
        while(1){
            init_NRF24L01();
               
            nRF24L01_TxPacket(TX_BUF);
            
            delay_nms(500);
            sta1=print_register_hyperterminal(STATUS);//print STATUS
            
            if((sta1&0x20)||(sta1&0x10))        //if tx_ds or max_rt set
            {
               
               
                SPI_RW_Reg((READ_REG+STATUS),0xff);        //flush TX_DS and MAX_RT
                Low_24L01_CSN;
                SPI_RW(FLUSH_TX);   //flush TX-FIFO
                High_24L01_CSN;
               
            }
         
            transmitByte(0x0d);
            delay_nms(100);
            transmitByte(0x0a);
            delay_nms(100);
           
        }
    return 0;
}







nRF2401很简单的啊?~
什么问题?~

数据发送以后,发送端的STATUS寄存器始终是0x0e的状态,tx_ds和max_rt都没有置位,接收端收不到数据,CD寄存器也没有载波信号

还有,忘说了,读写寄存器都是OK的,说明SPI应该没什么问题

你用软件SPI吧!

所以是因为硬件不稳定或是连接问题才会做不出来的吗?

NRF2401感觉对电源的要求很高,如果电源影响过大数据传输会非常不稳定...
我去年搞毕业设计时就碰到过这类问题,我那有电机,在MCU电源两端加上几个电容数据就稳定了...

我是AVR和PC连接的,用的是mysmartUSB MK2这块板,USB转换的串口,电源的话也是直接用USB供电的,这样的话要怎么加电容啊?

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top