基于NRF24L01的AVR双机通信

本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.

硬件图如下:

 

 

 

硬件说明:

1.单片机ATMEGA48

2.无线模块NRF24L01

3.每个板子有2个LED,2个船形开关

 

功能:

主机(左边的)按下A KEY发送信息,从机(右边的)收到信息后返回对应信息,主机收到从机信息后处理信息

 

视频地址:http://www.tudou.com/v/8B-PSm8E_kQ

 

 

代码说明:

状态机结构

主机:

主函数:

 /*
功能:课堂系统主机主函数
作者:jdh
时间:10-8-9建
*/
#include <iom48v.h>
#include <macros.h>
#include "config.h"
#include "led_drive.h"
#include "nrf24l01.h"
#include "public_module.h"
#include "api.h"
#include "cmd.h"
#include "key.h"
#include "state.h"

//全局变量初始化
U8 read_nrf[4] = {0};

//状态机程序执行信号灯,0为未执行,1为执行
U8 flag_INIT_STATE = 0; //初始化设备状态程序执行信号灯
U8 flag_RX_STATE = 0; //接收模式状态程序执行信号灯
U8 flag_DEAL_MESSAGE = 0; //处理信息状态程序执行信号灯
U8 flag_TX_STATE = 0; //发送模式1状态程序执行信号灯

U8 sta = 0;
enum sss STATE = INIT_STATE;

//主函数
void main()
{

//INIT_STATE_FUNC();
//RX_STATE_FUNC();
//TX_STATE_FUNC();
//while (1);
//状态机
while (1)
{
switch (STATE)
{
case INIT_STATE: //初始化设备状态
{
if (!flag_INIT_STATE)
{
INIT_STATE_FUNC();
}

//检测是否有激发状态改变的事件
if (check_state_change())
{
perform_state_change();
}

break;
}
case RX_STATE: //接收模式状态
{
if (!flag_RX_STATE)
{
RX_STATE_FUNC();
}

//检测是否有激发状态改变的事件
if (check_state_change())
{
perform_state_change();
}

break;
}
case DEAL_MESSAGE_STATE: //处理信息状态
{
if (!flag_DEAL_MESSAGE)
{
DEAL_MESSAGE_FUNC();
}

//检测是否有激发状态改变的事件
if (check_state_change())
{
perform_state_change();
}

break;
}
case TX_STATE: //发送模式1状态
{
if (!flag_TX_STATE)
{
TX_STATE_FUNC();
}

//检测是否有激发状态改变的事件
if (check_state_change())
{
perform_state_change();
}

break;
}
}
}
}

//NRF中断
#pragma interrupt_handler int0_isr:iv_INT0
void int0_isr(void)
{
/*
sta = SPI_Read(STATUS); // read register STATUS's value
LED1_ON();
delay(2,2);

if(RX_DR) // if receive data ready (RX_DR) interrupt
{

SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO buffer
s5();
delay(2,2);
LED_ALL_ON();
delay(2,1);
LED_ALL_OFF();
}
if(MAX_RT)
{
SPI_RW_Reg(FLUSH_TX,0);
//LED_ALL_OFF();

}
if(TX_DS)
{
//P2=0x0f;
//LED_ALL_ON();
}

SPI_RW_Reg(WRITE_REG+STATUS,sta);// clear RX_DR or TX_DS or MAX_RT interrupt flag
*/
}

 

 

状态文件:

/*
功能:状态图文件
作者:jdh
时间:10-8-18
*/
#include "state.h"

//说明
//状态图见相关文件

//系统初始化
void INIT_SYSTEM()
{
 CLI(); //disable all interrupts
 
 //IO口初始化
 PORTB = 0x00;
  DDRB  = 0x00;
  PORTC = 0x00;
  DDRC  = 0x00;
  PORTD = 0x00;
  DDRD  = 0x00;

  MCUCR = 0x00;
  EICRA = 0x02; //extended ext ints
  EIMSK = 0x01;
 
  TIMSK0 = 0x00; //timer 0 interrupt sources
  TIMSK1 = 0x00; //timer 1 interrupt sources
  TIMSK2 = 0x00; //timer 2 interrupt sources
 
  PCMSK0 = 0x00; //pin change mask 0
  PCMSK1 = 0x00; //pin change mask 1
  PCMSK2 = 0x00; //pin change mask 2
  PCICR = 0x00; //pin change enable
  PRR = 0x00; //power controller
  SEI(); //re-enable interrupts
  //all peripherals are now initialized
 
 INIT_LED();
 init_key();
 init_nrf24l01();
 
}

//状态程序信号灯清0
void signal_led_all_off()
{
 flag_INIT_STATE = 0; //初始化设备状态程序执行信号灯
 flag_RX_STATE = 0; //接收模式状态程序执行信号灯
 flag_DEAL_MESSAGE = 0; //处理信息状态程序执行信号灯
 flag_TX_STATE = 0; //发送模式1状态程序执行信号灯
}

//检测是否有激发状态改变的事件,如有返回1
U8 check_state_change()
{
 sta = SPI_Read(STATUS);
 
 switch (STATE)
 {
 case INIT_STATE: //初始化设备状态
  {
   //按下KEY1
   if (detect_key1())
   {
    return 1;
   }
  }
 case RX_STATE: //接收模式状态
  {
   //接收完信息
   if (RX_DR)
   {
    return 1;
   }
    
   break;
  }
 case DEAL_MESSAGE_STATE: //处理信息状态
  {
   //按下KEY1
   if (detect_key1())
   {
    return 1;
   }
    
   break;
  }
 case TX_STATE: //发送模式1状态
  {
  
  //LED_ALL_OFF();
 //delay(2,2);
 //LED_ALL_ON();
 //delay(2,2);
 //LED_ALL_OFF();
 //delay(1,1);
 
   //达到重发送信息最大值或发送完信息
   if (MAX_RT || TX_DS)
   {
    return 1;
   }
    
   break;
  }
 }
 
 return 0;
}

//状态切换函数
void perform_state_change()
{
 sta = SPI_Read(STATUS);
 
 switch (STATE)
 {
 case INIT_STATE: //初始化设备状态
  {
   //按下KEY1
   if (detect_key1())
   {
    STATE = TX_STATE;
   }
   
   break;
  }
 case RX_STATE: //接收模式状态
  {
   //接收完信息
   if (RX_DR)
   {
    STATE = DEAL_MESSAGE_STATE;
   }
    
   break;
  }
 case DEAL_MESSAGE_STATE: //处理信息状态
  {
   //按下KEY1
   if (detect_key1())
   {
    STATE = TX_STATE;
   }
    
   break;
  }
 case TX_STATE: //发送模式1状态
  {
   //达到重发送信息最大值或发送完信息
   if (MAX_RT || TX_DS)
   {
    STATE = RX_STATE;
   }
    
   //清缓存
   SPI_RW_Reg(FLUSH_TX,0);
    
   break;
  }
 }
 
 //清中断标志
 SPI_RW_Reg(WRITE_REG+STATUS,sta);
}

//状态函数
//初始化设备状态函数
void INIT_STATE_FUNC()
{
 //信号灯处理
 signal_led_all_off();
 flag_INIT_STATE = 1;
 
 //初始化设备
 INIT_SYSTEM();
 
 //控制信号
 LED_ALL_OFF();
 //LED_ALL_ON();
}

//接收模式状态函数
void RX_STATE_FUNC()
{
 //信号灯处理
 signal_led_all_off();
 flag_RX_STATE = 1; 
 
 //配置成接收模式
 SPI_RW_Reg(WRITE_REG + CONFIG, 0x00);
 RX_Mode();
 
 //控制信号
 //LED_ALL_OFF();
 //LED1_ON();
}

//处理信息模式状态函数
void DEAL_MESSAGE_FUNC()
{
 U8 temp[4] = {1,2,3,4};
 
 //信号灯处理
 signal_led_all_off();
 flag_DEAL_MESSAGE = 1;
 
 //解码
 SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);
 cmd_decode(rx_buf,temp);
 
 //处理信息
 do
 {
  if (temp[0] == 0x00) //原型机
  {
   if (temp[1] == 0x01) //从机地址
   {
    if (temp[2] == 0x02) //回答指令
    {
     if (temp[3] == 0x00)
     {
      LED_ALL_OFF();
      LED1_ON();
     }
     
     if (temp[3] == 0x01)
     {
      LED_ALL_OFF();
      LED2_ON();
     }
     
     break;
    }
   }
  }
 }while (0);
 
 //控制信号
 //LED_ALL_OFF();
}

//发送模式状态函数
void TX_STATE_FUNC()
{
 //信号灯处理
 signal_led_all_off();
 flag_TX_STATE = 1;
 
 //配置成发送模式
 SPI_RW_Reg(WRITE_REG + CONFIG, 0x00);
 cmd_encode(tx_buf,0x00,0x00,0x01,0x00);
 TX_Mode();
 delay(0,1);
 CE_0;
 
 //控制信号
 //LED_ALL_OFF();
 //LED2_ON();
}

 

 

从机:

主函数:

/*
功能:课堂系统从机主函数
作者:jdh
时间:10-8-9建
*/
#include <iom48v.h>
#include <macros.h>
#include "config.h"
#include "led_drive.h"
#include "nrf24l01.h"
#include "public_module.h"
#include "api.h"
#include "cmd.h"
#include "key.h"

//全局变量初始化
U8 read_nrf[4] = {0};

//状态机程序执行信号灯,0为未执行,1为执行
U8 flag_RX_STATE = 0; //接收模式状态程序执行信号灯
U8 flag_DEAL_MESSAGE = 0; //处理信息状态程序执行信号灯
U8 flag_TX1_STATE = 0; //发送模式1状态程序执行信号灯
U8 flag_TX2_STATE = 0; //发送模式2状态程序执行信号灯

U8 valid_message = 0;

U8 sta = 0;
enum sss STATE = RX_STATE;
U8 flag_rx = 0;//已经接收到指令
U8 flag_mode = 0;//发送为0,接收为1

//主函数
void main()
{
//初始化系统
INIT_SYSTEM();

//状态机
while (1)
{
switch (STATE)
{
case RX_STATE: //接收模式状态
{
if (!flag_RX_STATE)
{
RX_STATE_FUNC();
}

//检测是否有激发状态改变的事件
if (check_state_change())
{
perform_state_change();
}

break;
}
case DEAL_MESSAGE_STATE: //处理信息状态
{
if (!flag_DEAL_MESSAGE)
{
DEAL_MESSAGE_FUNC();
}

//检测是否有激发状态改变的事件
if (check_state_change())
{
perform_state_change();
}

break;
}
case TX1_STATE: //发送模式1状态
{
if (!flag_TX1_STATE)
{
TX1_STATE_FUNC();
}

//检测是否有激发状态改变的事件
if (check_state_change())
{
perform_state_change();
}

break;
}
case TX2_STATE: //发送模式2状态
{
if (!flag_TX2_STATE)
{
TX2_STATE_FUNC();
}

//检测是否有激发状态改变的事件
if (check_state_change())
{
perform_state_change();
}

break;
}
}
}

/*
INIT_SYSTEM();
LED_ALL_OFF();
SPI_RW_Reg(WRITE_REG + CONFIG, 0x00);
RX_Mode();
SPI_RW_Reg(WRITE_REG + CONFIG, 0x00);
cmd_encode(tx_buf,0x00,0x00,0x01,0x00);
TX_Mode();
delay(1,100);
SPI_RW_Reg(WRITE_REG + CONFIG, 0x00);
RX_Mode();
//nRF24L01_Config();
while (1)
{
//nRF24L01_RxPacket(rx_buf);
}
*/
}

//NRF中断
#pragma interrupt_handler int0_isr:iv_INT0
void int0_isr(void)
{
/*
LED_ALL_OFF();
delay(2,2);
LED_ALL_ON();
delay(2,2);
LED_ALL_ON();
*/
/*
LED_ALL_OFF();
delay(2,1);
LED_ALL_ON();
delay(2,1);
LED_ALL_OFF();
delay(2,1);
*/

//sta = SPI_Read(STATUS);
/*
U8 i = 0;
U8 temp[4] = {0};

sta=SPI_Read(STATUS); // read register STATUS's value
//P2=0x03;

if(RX_DR) // if receive data ready (RX_DR) interrupt
{
SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO buffer
s3();
}
if(MAX_RT)
{
SPI_RW_Reg(FLUSH_TX,0);
//P2=0xaa;
//LED2_ON();
LED_ALL_ON();
delay(2,2);
LED_ALL_OFF();
delay(2,2);
LED_ALL_ON();
delay(2,2);
LED_ALL_OFF();

}
if(TX_DS)
{
//P2=0x0f;
LED_ALL_ON();
delay(2,2);
LED_ALL_OFF();
delay(2,2);
}
//SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO buffer
SPI_RW_Reg(WRITE_REG+STATUS,sta);// clear RX_DR or TX_DS or MAX_RT interrupt flag
*/
/*
if (rx_buf[1] == 0x11)
{
LED_ALL_ON();
}
*/
//SPI_RW_Reg(WRITE_REG+STATUS,sta);
//SPI_RW_Reg(FLUSH_TX,0);
}

 

 

状态文件:

/*
功能:状态图文件
作者:jdh
时间:10-8-18
*/
#include "state.h"

//说明
//状态图见相关文件

//系统初始化
void INIT_SYSTEM()
{
 CLI(); //disable all interrupts
 
 //IO口初始化
 PORTB = 0x00;
  DDRB  = 0x00;
  PORTC = 0x00;
  DDRC  = 0x00;
  PORTD = 0x00;
  DDRD  = 0x00;

  MCUCR = 0x00;
  EICRA = 0x02; //extended ext ints
  EIMSK = 0x01;
 
  TIMSK0 = 0x00; //timer 0 interrupt sources
  TIMSK1 = 0x00; //timer 1 interrupt sources
  TIMSK2 = 0x00; //timer 2 interrupt sources
 
  PCMSK0 = 0x00; //pin change mask 0
  PCMSK1 = 0x00; //pin change mask 1
  PCMSK2 = 0x00; //pin change mask 2
  PCICR = 0x00; //pin change enable
  PRR = 0x00; //power controller
  SEI(); //re-enable interrupts
  //all peripherals are now initialized
 
 INIT_LED();
 init_key();
 init_nrf24l01();
 
}

//状态程序信号灯清0
void signal_led_all_off()
{
 flag_RX_STATE = 0; //接收模式状态程序执行信号灯
 flag_DEAL_MESSAGE = 0; //处理信息状态程序执行信号灯
 flag_TX1_STATE = 0; //发送模式1状态程序执行信号灯
 flag_TX2_STATE = 0; //发送模式2状态程序执行信号灯
}

//检测是否有激发状态改变的事件,如有返回1
U8 check_state_change()
{
 sta = SPI_Read(STATUS);
 
 switch (STATE)
 {
 case RX_STATE: //接收模式状态
  {
   //接收完信息
   if (RX_DR)
   {
    return 1;
   }
    
   break;
  }
 case DEAL_MESSAGE_STATE: //处理信息状态
  {
   //信息无效或信号有效且按下KEY1或信号有效且按下KEY2
   if ((!valid_message) || (valid_message && detect_key1()) || (valid_message && detect_key2()))
   {
    return 1;
   }
    
   break;
  }
 case TX1_STATE: //发送模式1状态
  {
   //达到重发送信息最大值或发送完信息
   if (MAX_RT || TX_DS)
   {
    return 1;
   }
    
   break;
  }
 case TX2_STATE: //发送模式2状态
  {
   //达到重发送信息最大值或发送完信息
   if (MAX_RT || TX_DS)
   {
    return 1;
   }
    
   break;
  }
 }
 
 return 0;
}

//状态切换函数
void perform_state_change()
{
 sta = SPI_Read(STATUS);
 
 switch (STATE)
 {
 case RX_STATE: //接收模式状态
  {
   //接收完信息
   if (RX_DR)
   {
    STATE = DEAL_MESSAGE_STATE;
   }
    
   break;
  }
 case DEAL_MESSAGE_STATE: //处理信息状态
  {
   //信号无效
   if (!valid_message)
   {
    STATE = RX_STATE;
   }
   
   //信号有效且按下KEY1
   if (valid_message && detect_key1())
   {
    STATE = TX1_STATE;
   }
   
   //信号有效且按下KEY2
   if (valid_message && detect_key2())
   {
    STATE = TX2_STATE;
   }
   
   break;
  }
 case TX1_STATE: //发送模式1状态
  {
   //达到重发送信息最大值或发送完信息
   if (MAX_RT || TX_DS)
   {
    STATE = RX_STATE;
    
    //清缓存
    SPI_RW_Reg(FLUSH_TX,0);
   }
   
   break;
  }
 case TX2_STATE: //发送模式2状态
  {
   //达到重发送信息最大值或发送完信息
   if (MAX_RT || TX_DS)
   {
    STATE = RX_STATE;
    
    //清缓存
    SPI_RW_Reg(FLUSH_TX,0);
   }
    
   break;
  }
 }
}

//状态函数
//接收模式状态函数
void RX_STATE_FUNC()
{
 //信号灯处理
 signal_led_all_off();
 flag_RX_STATE = 1; 
 
 //配置成接收模式
 SPI_RW_Reg(WRITE_REG + CONFIG, 0x00);
 RX_Mode();
 
 //控制信号
 LED_ALL_OFF();
 LED_ALL_ON();
}

//处理信息模式状态函数
void DEAL_MESSAGE_FUNC()
{
 U8 temp[4] = {1,2,3,4};
 
 //信号灯处理
 signal_led_all_off();
 flag_DEAL_MESSAGE = 1;
 
 //解码
 SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);
 cmd_decode(rx_buf,temp);
 
 //处理信息
 do
 {
  if (temp[0] == 0x00) //原型机
  {
   if (temp[1] == 0x00) //广播地址
   {
    if (temp[2] == 0x01) //询问指令
    {
     valid_message = 1; //条件都满足,信息有效
     break;
    }
   }
  }
  valid_message = 0; //条件不满足,信息无效
 }while (0);
 
 //清中断标志
 SPI_RW_Reg(WRITE_REG+STATUS,sta);
 
 //控制信号
 LED_ALL_OFF();
}

//发送模式1状态函数
void TX1_STATE_FUNC()
{
 //信号灯处理
 signal_led_all_off();
 flag_TX1_STATE = 1;
 
 //配置成发送模式1
 SPI_RW_Reg(WRITE_REG + CONFIG, 0x00);
 cmd_encode(tx_buf,0x00,0x01,0x02,0x00);
 TX_Mode();
 delay(0,1);
 CE_0;
 
 //控制信号
 LED_ALL_OFF();
 LED1_ON();
}

//发送模式2状态函数
void TX2_STATE_FUNC()
{
 //信号灯处理
 signal_led_all_off();
 flag_TX2_STATE = 1;
 
 //配置成发送模式2
 SPI_RW_Reg(WRITE_REG + CONFIG, 0x00);
 cmd_encode(tx_buf,0x00,0x01,0x02,0x01);
 TX_Mode();
 delay(0,1);
 CE_0;
 
 //控制信号
 LED_ALL_OFF();
 LED2_ON();
}

 

 

后记:

NRF24L01是半双工通信,如果要双工通信,可以考虑每个板子用2个NRF模块

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值