欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
15單片機進行通過NRF24L01的雙向通信有問題
[打印本頁]
作者:
十點差三分
時間:
2021-10-23 15:30
標題:
15單片機進行通過NRF24L01的雙向通信有問題
這個是我寫的程序,大部分是網上找的程序,用的是15單片機,然后兩個MCU通過NRF24L01通信,但不知道為什么就是通信不了,就接收不到數據。有沒有大佬找找我的問題。
單片機源程序如下:
#include <reg51.h>
#include <intrins.h>
#define TX_ADR_WIDTH 5 //5字節寬度的發送/接收地址
#define TX_PLOAD_WIDTH 4//數據通道有效數據寬度
#define uchar unsigned char
#define uint unsigned int
#define out P0
uchar code lcd1602[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
uchar code TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01}; // 定義一個靜態發送地址
uchar RX_BUF[TX_PLOAD_WIDTH];
uchar TX_BUF[TX_PLOAD_WIDTH];
uchar flag;
uchar bdata sta;
sbit RX_DR =sta^6;
sbit TX_DS =sta^5;
sbit MAX_RT=sta^4;
/*sbit CE = P1^5;
sbit CSN = P1^4;
sbit SCK = P1^2;
sbit MOSI = P1^1;
sbit MISO = P1^3;
sbit IRQ = P1^0;*/
sbit CE = P2^4;
sbit CSN = P2^0;
sbit SCK = P2^3;
sbit MOSI = P2^1;
sbit MISO = P3^3;
sbit IRQ = P2^2;
//SPI要使用的IO
sbit MOSIO=P3^4;
sbit R_CLK=P3^5;
sbit S_CLK=P3^6;
//SPI(NFR24L01)命令
#define RFAD_REG 0x00 //定義讀命令以注冊
#define WRITE_REG 0x20 //定義要寫的命令
#define RD_RX_PLOAD 0x61 //定義RX有效負載寄存器地址
#define WR_TX_PLOAD 0xA0 //定義TX有效負載寄存器地址
#define FLUSH_TX 0xE1 //定義刷新 Tx寄存器命令
#define FLUSH_RX 0xE2 //定義刷新 Rx寄存器命令
#define REUSE_TX_PL 0xE3 //定義重復TX負載寄存器命令
#define NOP 0xFF //定義無操作
//SPI(NRF24L01)寄存器
#define CONFIG 0x00 //配置寄存器地址
#define EN_AA 0x01 //“啟用自動確認”的注冊地址
#define EN_RXADDR 0x02 //'Enabled RX addresses'寄存器地址
#define SETUP_AW 0x03 //“設置地址寬度”寄存器地址
#define SETUP_RETR 0x04 //“自動設置。Retrans的寄存器地址
#define RF_CH 0x05 // '射頻信道'寄存器地址
#define RF_SETUP 0x06 //射頻設置寄存器地址
#define STATUS 0x07 // 狀態寄存器地址
#define OBSERVE_TX 0x08 //“收到Tx”寄存器地址
#define CD 0x09 //"載波檢測'寄存器地址
#define RX_ADDR_P0 0x0A //RX地址0管道的寄存器地址
#define RX_ADDR_P1 0x0B //RX地址1管道的寄存器地址
#define RX_ADDR_P2 0x0C //RX地址2管道的寄存器地址
#define RX_ADDR_P3 0x0D //RX地址3管道的寄存器地址
#define RX_ADDR_P4 0x0E //RX地址4管道的寄存器地址
#define RX_ADDR_P5 0x0F //RX地址5管道的寄存器地址
#define TX_ADDR 0x10 //“Tx address”的寄存器地址
#define RX_PW_P0 0x11 //"RX有效載荷寬度,0管'寄存器地址
#define RX_PE_P1 0x12 //"RX有效載荷寬度,1管'寄存器地址
#define RX_PE_P2 0x13 //"RX有效載荷寬度,2管'寄存器地址
#define RX_PE_P3 0x14 //"RX有效載荷寬度,3管'寄存器地址
#define RX_PE_P4 0x15 //"RX有效載荷寬度,4管'寄存器地址
#define RX_PE_P5 0x16 //"RX有效載荷寬度,5管'寄存器地址
#define FIFO_STATUS 0x17 //“FIFO狀態寄存器”的寄存器地址
void delay500ms(void);
void lcd_initial (void); //LCD1602初始化
void write_data(uchar dat); //寫數據函數
void check_busy (void); //忙檢測
void write_command (uchar com); //寫命令函數
void string (uchar ad,uchar *s);//字符寫入,(字符開始地址,字符)
void delay100ms(void); //延時100MS
void delay10ms(void); //延時10MS
void delay1ms(void); //延時1ms
uchar ajlb(uchar x); //按鍵濾波
uchar JCAJ(void); //檢測按鍵按下
uchar HC08JS = 0;
bit flag1 = 0;
sbit E=P2^5;
sbit RW=P2^6;
sbit RS=P2^7;
sbit FMQ=P1^2;
sbit BG=P2^4;
sbit DQ=P1^0;
sbit K1=P1^3;
sbit K2=P1^4;
sbit K3=P1^5;
sbit K4=P1^6;
sfr AUXR = 0x8E;
sfr T2H = 0xd6;
sfr T2L = 0xd7;
void lcd_initial (void) //LCD1602初始化
{
write_command(0x38);//寫入0x38(命令6):兩行顯示,5X7點陣,8位數據接口
_nop_(); //空操作
write_command(0x0C);//寫入0x38(命令4):開整體顯示,光標關,無閃爍
_nop_(); //空操作
write_command(0x04);//寫入0x38(命令3):
_nop_(); //空操作
write_command(0x01);//寫入0x38(命令1):清屏
delay1ms();
}
void check_busy (void)//忙檢測
{
uchar dt;
do
{
dt=0xff; //dt為變量單元,初值為0xff
E=0;
RS=0;
RW=1;
E=1;
dt=out; //out為LCD數據口,將out的狀態送入dt
}
while(dt&0x80); //如果忙標志位BF=1,繼續循環檢測,等待BF=0
E=0; //BF=0,LCD不忙,結束檢測
}
void write_command (uchar com)//寫命令函數
{
check_busy();
E=0;
RS=0; //RS與E同時為零時。才可以寫入命令
RW=0;
out=com; //將命令com寫入數據口
E=1; //寫入命令時,E為上升沿,所以E開始為0
_nop_();
E=0; //E由高變低,LCD開始執行命令
delay1ms();
}
void write_data(uchar dat) //寫數據函數
{
check_busy();
E=0;
RS=1;
RW=0;
out=dat;
E=1;
_nop_();
E=0;
delay1ms();
}
void string (uchar ad,uchar *s)
{
write_command(ad);
while(*s>0)
{
write_data(*s++); //輸出字符串,且指針加一
delay1ms();
}
}
void string1(uchar ad,uchar a)
{uchar b=0,c=0;
write_command(ad);
ad=ad+0x01;
b=a/10;
b=lcd1602[b];
write_data(b);
c=a%10;
c=lcd1602[c];
write_data(c);
}
void lcd_xs(uchar a)
{
if(a==0)
{string(0x83,"->NRF24L01");
string(0xC5,"HC-08");
}
else if(a==1)
{string(0x83,"->HC-08");
string(0xC5,"EV1527");
}
else if(a==2)
{string(0x83,"->EV1527");
string(0xC5,"NRF24L01");
}
}
void delay5us(void) //誤差 0us
{
unsigned char a;
for(a=12;a>0;a--);
}
void delay5(uchar n) //延時5us程序
{
do
{
delay5us();
n--;
}
while(n);
}
void delay1ms(void) //誤差 0us
{
unsigned char a,b;
for(b=222;b>0;b--)
for(a=12;a>0;a--);
}
void delay10ms(void) //誤差 -0.000000000001us
{
unsigned char a,b;
for(b=202;b>0;b--)
for(a=147;a>0;a--);
}
void delay50ms(void) //誤差 -0.000000000003us
{
unsigned char a,b,c;
for(c=6;c>0;c--)
for(b=116;b>0;b--)
for(a=214;a>0;a--);
}
void delay100ms(void) //誤差 -0.000000000006us
{
unsigned char a,b,c;
for(c=246;c>0;c--)
for(b=116;b>0;b--)
for(a=9;a>0;a--);
}
//////////////////////////////////////////////////////DS18B20程序開頭
void init_ds18b20(void) //18B20初始化
{
uchar x=0;
DQ=0;
delay5(120);
DQ=1;
delay5(16);
delay5(80);
}
uchar readbyte(void) //讀取1字節數據
{
uchar i=0;
uchar date=0;
for(i=8;i>0;i--)
{
DQ=0;
delay5(1);
DQ=1;
date>>=1;
if(DQ)
date|=0x80;
delay5(11);
}
return(date);
}
void writebyte(uchar dat) //寫1B函數
{
uchar i=0;
for(i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
delay5(12);
DQ=1;
dat>>=1;
delay5(5);
}
}
uchar retemp(void) //讀取溫度
{
uchar a,b,tt;
uint t;
init_ds18b20();
writebyte(0xcc);
writebyte(0x44);
init_ds18b20();
writebyte(0xcc);
writebyte(0xBE);
a=readbyte();
b=readbyte();
t=b;
t<<=8;
t=t|a;
tt=t*0.0625;
return(tt);
}
////////////////////////////////////////////DS18B20程序結尾
//NFR24L01發送
void init_io (void) //2401初始化
{
CE =0; //待機
CSN=1; //SPI禁止
SCK=0; //SPI時鐘置低
IRQ=1; //中斷復位
}
uchar SPI_RW(uchar byte) //根據spi協議,寫一節數據到2401,同時讀出一節數據
{
uchar i;
for(i=0;i<8;i++) //循環8次
{
MOSI=(byte&0x80); //byte最高位輸出到MOSI
byte<<=1; //低一位移到最高位
SCK=1;
byte |=MISO; //讀MSIO到byte最低位
SCK=0;
}
return(byte); //發回讀出的一字節
}
uchar SPI_RW_Reg(uchar reg, uchar value) //寫數據value到reg寄存器
{
uchar status;
CSN = 0; // CSN置低,開始傳輸數據
status = SPI_RW(reg); // 選擇寄存器,同時返回狀態字
SPI_RW(value); // 然后寫數據到該寄存器
CSN = 1; // CSN拉高,結束數據傳輸
return(status); // 返回狀態寄存器
}
uchar SPI_Read(uchar reg) //從reg寄存器讀一字節
{
uchar reg_val;
CSN=0; //CSN置低,開始傳輸數據
SPI_RW(reg);
reg_val=SPI_RW(0);
CSN=1;
return(reg_val);
}
uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar bytes) //從reg寄存器讀出bytes個字節,通常用來讀取接收通道數據或接收/發送地址
{
uchar status,i;
CSN=0;
status=SPI_RW(reg);
for(i=0;i<bytes;i++)
pBuf[i]=SPI_RW(0);
CSN=1;
return(status);
}
uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar bytes) //把pBuf緩存中的數據寫入到nRF24L01,通常用來寫入發射通道數據或接收/發送地址
{
uchar status, i;
CSN = 0; // CSN置低,開始傳輸數據
status = SPI_RW(reg); // 選擇寄存器,同時返回狀態字
for(i=0; i<bytes; i++)
SPI_RW(pBuf[i]); // 逐個字節寫入nRF24L01
CSN = 1; // CSN拉高,結束數據傳輸
return(status); // 返回狀態寄存器
}
void RX_Mode(void) //這個函數設置nRF24L01為接收模式,等待接收發送設備的數據包
{
CE = 0;
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 接收設備接收通道0使用和發送設備相同的發送地址
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 使能接收通道0自動應答
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0
SPI_RW_Reg(WRITE_REG + RF_CH, 40); // 選擇射頻通道0x40
SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // 接收通道0選擇和發送通道相同有效數據寬度
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // 數據傳輸率1Mbps,發射功率0dBm,低噪聲放大器增益
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // CRC使能,16位CRC校驗,上電,接收模式
CE = 1; // 拉高CE啟動接收設備
}
void TX_Mode(uchar * BUF)
{
CE = 0;
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); // 為了應答接收設備,接收通道0地址和發送地址相同
SPI_Write_Buf(WR_TX_PLOAD, BUF, TX_PLOAD_WIDTH); // 寫數據包到TX FIFO
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 使能接收通道0自動應答
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0
SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x0a); // 自動重發延時等待250us+86us,自動重發10次
SPI_RW_Reg(WRITE_REG + RF_CH, 40); // 選擇射頻通道0x40
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // 數據傳輸率1Mbps,發射功率0dBm,低噪聲放大器增益
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // CRC使能,16位CRC校驗,上電
CE = 1;
}
uchar Check_ACK(bit clear) //檢查接收設備有無接收到數據包,設定沒有收到應答信號是否重發
{
while(IRQ);
sta = SPI_RW(NOP); // 返回狀態寄存器
if(MAX_RT)
if(clear) // 是否清除TX FIFO,沒有清除在復位MAX_RT中斷標志后重發
SPI_RW(FLUSH_TX);
SPI_RW_Reg(WRITE_REG + STATUS, sta); // 清除TX_DS或MAX_RT中斷標志
IRQ = 1;
if(TX_DS)
return(0x00);
else
return(0xff);
}
void NRF24L01_CX(void) //NRF24L01程序執行
{uchar b=1,temp,a=0,temp1=0x00;
FMQ=1;
lcd_initial(); //調用lcd初始化
string(0x80,"24L01TXD:");
string(0xc0,"RXD:");
init_io();
while(b)
{
temp=retemp();
string1(0x8A,temp);
TX_BUF[0] = ~temp; // 數據送到緩存
TX_Mode(TX_BUF); // 把nRF24L01設置為發送模式并發送數據
//IRQ=0;
a=JCAJ();
if(a==4)
b=0;
Check_ACK(1); // 等待發送完畢,清除TX FIFO
RX_Mode(); // 設置為接收模式
sta = SPI_Read(STATUS); // 讀狀態寄存器
if(RX_DR) // 判斷是否接受到數據
{
SPI_Read_Buf(RD_RX_PLOAD, RX_BUF, TX_PLOAD_WIDTH); // 從RX FIFO讀出數據
flag = 1;
}
SPI_RW_Reg(WRITE_REG + STATUS, sta); // 清除RX_DS中斷標志
if(flag) // 接受完成
{
flag = 0; // 清標志
temp1 = RX_BUF[0]; // 數據送到temp1
}
string1(0xCA,temp1);
delay50ms();
a=JCAJ();
if(a==4)
b=0;
}
}uchar JCAJ(void) //檢測按鍵按下
{
uchar x=0,y=0;
if(K1==0)
{y=1;
x=ajlb(y);
return x;
}
else if(K2==0)
{y=2;
x=ajlb(y);
return x;
}
else if(K3==0)
{y=3;
x=ajlb(y);
return x;
}
else if(K4==0)
{y=4;
x=ajlb(y);
return x;
}
return x;
}
uchar ajlb(uchar x) //按鍵濾波
{
delay10ms();
if(x==1)
{
if(K1==0)
{return x;}
else
{x=0;
return x;}
}
else if(x==2)
{
if(K2==0)
{return x;}
else
{x=0;
return x;}
}
else if(x==3)
{
if(K3==0)
{return x;}
else
{x=0;
return x;}
}
else if(x==4)
{
if(K4==0)
{return x;}
else
{x=0;
return x;}
}
return x;
}
void main ()
{
NRF24L01_CX();
}
復制代碼
作者:
stycx
時間:
2021-10-24 22:21
粗略看了一下,程序有幾個問題:1、兩個單片機的程序收發地址應該設置不同;2、工作時得有握手協議來協調收發狀態的切換。
建議你先單獨寫收、發兩個程序,調試通過了再合并一起。
歡迎光臨 (http://m.raoushi.com/bbs/)
Powered by Discuz! X3.1