用的是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 INSTRUC
tiON
#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;
}
数据发送以后,发送端的STATUS寄存器始终是0x0e的状态,tx_ds和max_rt都没有置位,接收端收不到数据,CD寄存器也没有载波信号
还有,忘说了,读写寄存器都是OK的,说明SPI应该没什么问题
所以是因为硬件不稳定或是连接问题才会做不出来的吗?
我去年搞毕业设计时就碰到过这类问题,我那有电机,在MCU电源两端加上几个电容数据就稳定了...
一周热门 更多>