本文共 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_INT0void int0_isr(void){ /*sta = SPI_Read(STATUS); // read register STATUS's valueLED1_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 buffers5();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_INT0void 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 buffers3();}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 bufferSPI_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模块
再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!