博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于NRF24L01的AVR双机通信
阅读量:3948 次
发布时间:2019-05-24

本文共 10814 字,大约阅读时间需要 36 分钟。

               

本文博客链接:,作者:jdh,转载请注明.

硬件图如下:

 

 

 

硬件说明:

1.单片机ATMEGA48

2.无线模块NRF24L01

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

 

功能:

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

 

视频地址:

 

 

代码说明:

状态机结构

主机:

主函数:

 /*

功能:课堂系统主机主函数
作者: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模块

           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!

你可能感兴趣的文章
让创意瞄准市场
查看>>
高效经理人应具有的八个重要习惯
查看>>
优秀的领导者能读懂人才
查看>>
大智若愚也是领导力
查看>>
android如何编译MTK的模拟器
查看>>
android如何添加AP中要使用的第三方JAR文件
查看>>
利用sudo命令为Ubuntu分配管理权限
查看>>
Ubuntu下几个重要apt-get命令用法与加速UBUNTU
查看>>
Ubuntu中网页各种插件安装命令
查看>>
使用tar命令备份Ubuntu系统
查看>>
ubuntu flash 文字乱码解决方案
查看>>
在ubuntu中运行exe文件
查看>>
ubuntu安装命令
查看>>
Android学习笔记(四十):Preference的使用
查看>>
Android学习笔记(四二):SQLite、ListView、ContextMenu
查看>>
Android学习笔记(四三):文件访问
查看>>
Android学习笔记(四六):互联网通信-文件下载
查看>>
Android学习笔记(五一):服务Service(上)- IntentService
查看>>
在职找工作的宜与忌
查看>>
低迷时,谁在坚持CSR
查看>>