本文博客链接: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模块