|
折腾好几个星期啦,今天终于调试通过,甲乙单片机双向通信。3.3v给模块供电,电源输入和输出加10uf电容,模块vcc和gnd加104瓷片。模块的引脚和单片机的引脚直接相连,不用担心不会烧坏模块。我当时看到网上说要加限流电阻或模块和单片机连接的引脚要下拉,结果很多网上的程序都调不通,去掉限流电阻一切正常。希望能帮到像我一样的菜菜鸟!!!!!!1- /************************************************
- 功能 :双单片机通过NRF24L01进行无线通信
- 甲单片机按下按键控制乙单片机的数码管显示
- 乙单片机按下按键控制甲单片机的LED显示
- 调试通过。
- 甲单片机:STC12C5608AD
- 乙单片机:STC12C5A60S2
- 晶 振:11.0592M
- 作 者:苏义江改编自网络
- 时 间:2016.4.30
- 注 释 :甲单片机发个乙单片机,乙单片机接收到数据
- 再发给甲单片机。同理乙发给甲单片机数据,
- 甲单片机接收到数据再发给乙单片机。
- 双方相互通信
- ***********************************************/
- #include <reg52.h>
- #include <intrins.h>
- typedef unsigned char uchar;
- typedef unsigned char uint;
- #define uz unsigned uint
- //甲单片机STC12C5608AD端口定义
- /*sbit MISO =P1^7; //数字输出(从 SPI 数据输出脚)
- sbit MOSI =P1^4; //数字输入(从 SPI 数据输入脚)
- sbit SCK =P1^5; //数字输入(SPI 时钟)
- sbit CE =P1^3; //数字输入(RX 或 TX 模式选择)
- sbit CSN =P1^2; //数字输入(SPI片选信号)
- sbit IRQ =P1^6; //数字输入(可屏蔽中断)
- sbit KEY1 =P2^4;//按键S1
- sbit KEY2 =P2^5;//按键S2
- sbit led1 =P2^0; //LED0
- sbit led2 =P2^1; //LED1
- sbit led3 =P2^2; //LED2
- sbit led4 =P2^3; //LED3 */
-
- //乙单片机STC12C5A60S2端口定义
- sbit MISO =P2^1; //数字输出(从 SPI 数据输出脚)
- sbit MOSI =P2^2; //数字输入(从 SPI 数据输入脚)
- sbit SCK =P2^3; //数字输入(SPI 时钟)
- sbit CE =P1^6; //数字输入(RX 或 TX 模式选择)
- sbit CSN =P2^4; //数字输入(SPI片选信号)
- sbit IRQ =P2^0; //数字输入(可屏蔽中断)
- sbit KEY1 =P3^7;//按键S1
- sbit KEY2 =P3^6;//按键S2
- sbit led1 =P0^0; //LED0
- sbit led2 =P0^1; //LED1
- sbit led3 =P0^2; //LED2
- sbit led4 =P0^3; //LED3
- sbit fmq =P1^7;
- sbit wei=P2^7;
- sbit duan=P2^6;
- uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,
- 0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,
- 0xa1,0x86,0x8e,0x89};
- uchar code tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
- uchar code tab1[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
- #define TX_ADR_WIDTH 5 // 5 uints TX address width
- #define RX_ADR_WIDTH 5 // 5 uints RX address width
- #define TX_PLOAD_WIDTH 20 // 20 uints TX payload
- #define RX_PLOAD_WIDTH 20 // 20 uints TX payload
- uint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址
- uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址
- #define READ_REG 0x00 // 读寄存器指令
- #define WRITE_REG 0x20 // 写寄存器指令
- #define RD_RX_PLOAD 0x61 // 读取接收数据指令
- #define WR_TX_PLOAD 0xA0 // 写待发数据指令
- #define FLUSH_TX 0xE1 // 冲洗发送 FIFO指令
- #define FLUSH_RX 0xE2 // 冲洗接收 FIFO指令
- #define REUSE_TX_PL 0xE3 // 定义重复装载数据指令
- #define NOP 0xFF // 保留
- #define CONFIG 0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式
- #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 // 频道0接收数据地址
- #define RX_ADDR_P1 0x0B // 频道1接收数据地址
- #define RX_ADDR_P2 0x0C // 频道2接收数据地址
- #define RX_ADDR_P3 0x0D // 频道3接收数据地址
- #define RX_ADDR_P4 0x0E // 频道4接收数据地址
- #define RX_ADDR_P5 0x0F // 频道5接收数据地址
- #define TX_ADDR 0x10 // 发送地址寄存器
- #define RX_PW_P0 0x11 // 接收频道0接收数据长度
- #define RX_PW_P1 0x12 // 接收频道0接收数据长度
- #define RX_PW_P2 0x13 // 接收频道0接收数据长度
- #define RX_PW_P3 0x14 // 接收频道0接收数据长度
- #define RX_PW_P4 0x15 // 接收频道0接收数据长度
- #define RX_PW_P5 0x16 // 接收频道0接收数据长度
- #define FIFO_STATUS 0x17 // FIFO栈入栈出状态寄存器设置
- void Delay(unsigned int s); //大延时
- void inerDelay_us(unsigned char n); //小延时
- void init_NRF24L01(void); //NRF24L01 初始化
- uint SPI_RW(uint dat); //根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01读出一字节
- uchar SPI_Read(uchar reg); //从reg寄存器读一字节
- void SetRX_Mode(void);
- //数据接收配置
- uint SPI_RW_Reg(uchar reg, uchar value);
- //写数据value到reg寄存器
- uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars);
- //从reg寄存器读出bytes个字节,通常用来
- uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars);
- //把pBuf缓存中的数据写入到nRF24L01,通常用来写入发
- //射通道数据或接收/发送地址
- unsigned char nRF24L01_RxPacket(unsigned char* rx_buf);
- //数据读取后放入rx_buf接收缓冲区中
- void nRF24L01_TxPacket(unsigned char * tx_buf);
- //发送 tx_buf中数据
- void Delay(unsigned int s)
- {
- unsigned int i;
- for(i=0; i<s; i++);
- for(i=0; i<s; i++);
- }
- uint bdata sta; //状态标志
- sbit RX_DR =sta^6; //RX_DR 为 sta 的第六位
- sbit TX_DS =sta^5; //TX_DS 为 sta 的第五位
- sbit MAX_RT =sta^4; //MAX_RT 为 sta 的第四位
- void inerDelay_us(unsigned char n) //延时,us 级
- {
- for(;n>0;n--)
- _nop_();
- }
- void init_NRF24L01(void)
- {
- inerDelay_us(100);
- CE=0; // 芯片使能
- CSN=1; // 禁止 SPI
- SCK=0; // SPI时钟置低
- SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);
- // 写本地地址
- SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH);
- // 写接收端地址
- SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);
- // 频道0自动 ACK应答允许
- SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);
- // 允许接收地址只有频道0,如果需要多频道可以参考Page21
- SPI_RW_Reg(WRITE_REG + RF_CH, 0);
- // 设置信道工作为2.4GHZ,收发必须一致
- SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH);
- //设置接收数据长度,本次设置为32字节
- SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);
- //设置发射速率为1MHZ,发射功率为最大值0dB
- }
- uint SPI_RW(uint dat)
- {
- uint i;
- for(i=0;i<8;i++) // 循环8次
- {
- MOSI = (dat & 0x80);
- // dat的最高位输出到MOSI
- dat = (dat << 1);
- // 从右向左进一位
- SCK = 1;
- // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据 Set SCK high..
- dat |= MISO; //读MISO到 dat 最低位
- SCK = 0; // SCK置低
- }
- return(dat);
- //返回读出的一字节
- }
- uchar SPI_Read(uchar reg)
- {
- uchar reg_val;
- CSN = 0;
- //CSN置低,开始传输数据
- SPI_RW(reg); //选择寄存器
- reg_val = SPI_RW(0); //然后从该寄存器读数据
- CSN = 1; //CSN拉高,结束数据传输
- return(reg_val); //返回寄存器数据
- }
- uint SPI_RW_Reg(uchar reg, uchar value)
- {
- uchar status;
- CSN = 0;
- // CSN置低,开始传输数据
- status = SPI_RW(reg);
- // 选择寄存器,同时返回状态字
- SPI_RW(value);
- // 然后写数据到该寄存器
- CSN = 1;
- // CSN拉高,结束数据传输
- return(status); // 返回状态寄存器
- }
- uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)
- {
- uint status,i;
- CSN = 0;
- //CSN置低,开始传输数据
- status = SPI_RW(reg);
- //选择寄存器,同时返回状态字
- for(i=0;i<uchars;i++)
- pBuf[i] = SPI_RW(0);
- //逐个字节从nRF24L01读出
- CSN = 1; //CSN拉高,结束数据传输
- return(status);
- //返回状态寄存器return nRF24L01 status uchar
- }
- uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)
- {
- uint status,i;
- CSN = 0;
- //CSN置低,开始传输数据
- status = SPI_RW(reg);
- //选择寄存器,同时返回状态字
- inerDelay_us(10);
- for(i=0; i<uchars; i++)
- SPI_RW(*pBuf++); //逐个字节写入nRF24L01
- CSN = 1;
- //CSN拉高,结束数据传输
- return(status); //返回状态寄存器
- }
- void SetRX_Mode(void)
- {
- CE=0;
- SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);
- //CRC使能,16位CRC校验,上电,接收模式
- CE = 1;
- // 拉高CE启动接收设备
- inerDelay_us(130);
- }
- unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)
- {
- unsigned char revale=0;
- sta=SPI_Read(STATUS);
- // 读取状态寄存其来判断数据接收状况
- if(RX_DR) // 判断是否接收到数据
- {
- CE = 0; //SPI使能
- SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);
- revale =1; //读取数据完成标志
- }
- SPI_RW_Reg(WRITE_REG+STATUS,sta);
- //接收到数据后 RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志
- return revale;
- }
- void nRF24L01_TxPacket(unsigned char * tx_buf)
- {
- CE=0; //StandBy I模式
- SPI_Write_Buf(WRITE_REG+RX_ADDR_P0,TX_ADDRESS,TX_ADR_WIDTH);
- // 装载接收端地址
- SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH);
- // 装载数据
- SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);
- // IRQ收发完成中断响应,16位CRC,主发送
- CE=1; //置高CE,激发数据发送
- inerDelay_us(10);
- }
- void delay1(uint z)
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=650;y>0;y--);
- }
- void main(void)
- {
- unsigned char tf =0;
- uint i ;
- unsigned char TxBuf[20]={0};
- // 要发送的数组
- unsigned char RxBuf[20]={0};
- // 接收的数据 数组
- init_NRF24L01(); //模块初始化
- led1=1;led2=1;led3 =1;led4 =1; //led 灯关闭
- Delay(1000);
- while(1)
- {
- if(KEY1 ==0 ) //按键 1 按下
- {
-
- TxBuf[1] = 1; //赋值
- tf = 1;
- led1=0; //本地led 灯闪烁
- Delay(200);
- led1=1;
- Delay(200);
- }
- if(KEY2 ==0 ) //按键 2 按下
- {
-
- TxBuf[2] =1; //赋值
- tf = 1 ;
- led2=0; //本地led 灯闪烁
- Delay(200);
- led2=1;
- Delay(200);
- }
- if (tf==1) //有键按下
- {
- nRF24L01_TxPacket(TxBuf);
- //发送数据Transmit Tx buffer data
-
- TxBuf[1] = 0x00;
- //清零
- TxBuf[2] = 0x00;
- tf=0;
- Delay(1000);
- }
-
- SetRX_Mode(); //设置成接受模式
- RxBuf[1] = 0x00;
- //接收的数组相应位清零
- RxBuf[2] = 0x00;
- Delay(1000);
- nRF24L01_RxPacket(RxBuf); //接收数据
- if(RxBuf[1]|RxBuf[2])
- {//如果有一组为高就执行下面语句
- if( RxBuf[1]==1)
- {
- wei=1;//乙单片机接收的数据
- P0=0xef;
- wei=0;
- duan=1;
- P0= table[2] ;
- duan=0;
- Delay(30);
- for(i=0;i<8;i++)
- {
- P0=tab[i];
- Delay(20000);
- }
- for(i=0;i<8;i++)
- {
- P0=0XAA;
- Delay(30000);
- P0=0XFF;
- Delay(30000);
- }
- for(i=300;i>0;i--)
- {
- fmq=0;
- delay1(60000);delay1(60000);
- // fmq=1;
- delay1(60000);delay1(60000);
- }
- /* led3=RxBuf[0];//甲单片机接收的数据 */
- }
-
- if( RxBuf[2]==1)
- {
- wei=1;//乙单片机接收的数据
- P0=0x00;
- wei=0;
- for(i=0;i<17;i++)
- {
- duan=1;
- P0= table[i] ;
- duan=0;
- Delay(60000); Delay(60000);
- }
- for(i=0;i<8;i++)
- {
- P0=tab1[i];
- Delay(20000);
- }
- for(i=0;i<8;i++)
- {
- P0=0X55;
- Delay(30000);
- P0=0XFF;
- Delay(30000);
- }
- /* led4=RxBuf[4];//甲单片机接收的数据 */
- }
-
- Delay(3000); //old is '1000'
- }
- RxBuf[1] = 0x00;
- //清零
- RxBuf[2] = 0x00; //清零
- fmq=1;
- led3=1; //关灯
- led4=1; //关灯
- duan=1;
- P0=0xff;//关数码管
- duan=0;
- }
- }
复制代码
|
评分
-
查看全部评分
|