发帖庆贺,ATMEGA16控制nrf905短距离无线通信基本成功(附源代码)
发送端代码点击此处下载ourdev_237989.zip(文件大小:11K)
接收端代码
点击此处下载ourdev_237990.zip(文件大小:11K)
感谢hotpower,我是参考了他的C++代码完成的。 不好意思,有点忙。电路图其实在源代码中已经有了说明
// SPI pin
#define PORT_SPI PORTB
#define DDR_SPI DDRB
#define MOSI PB5
#define MISO PB6
#define SCK PB7
#define SS PB4
// nRF905 pin
#define PORT_NRF905 PORTA
#define DDR_NRF905 DDRA
#define PIN_NRF905 PINA
#define TX_EN PA0
#define TRX_CE PA1
#define PWR_UP PA2
#define CD PA3
#define AM PA4
#define DR PA
nRF905的使用只需要使用TRX_CE TX_EN PWR_UP CD AM DR等引脚与单片机IO连接即可。其中
TX_EN 输出 设置nRF905工作于发送或接收模式 1 发送0 接收
TRX_CE输出 设置nRF905工作于工作模式或standby模式 1 工作0 standby
PWR_UP输出 设置nRF905上电 1 上电0 Power down 模式
CD 输入 nRF905检测到载波拉高该引脚
AM 输入 nRF905检测到无线数据包与本机地址匹配,拉高该引脚
DR 输入 数据准备就绪,发送或接收数据包完毕拉高该引脚 上传nRF905数据手册
点击此处打开ourdev_239078.pdf(文件大小:431K) 哈哈,谢谢共享!
COOL !
ifree64最近的精品贴子不少啊。赞一个。 过奖了,谢谢阿莫置酷。
哈哈,再接再厉 通信距离多远啊? 谢谢ifree64共享,自己的调不过,屡败屡战啊! 要试试nrf了 这东西不知道抗干扰如何?在变频器上应用不知是否可行? 在变频器上估计不行。 回楼上:我曾见过CC1100好像有类似的retry功能,可靠性要好一些。 比较感兴趣 记录! 我给同事家安了个用905做通信的遥控器,我在家测试的时候在附近10米转了几遍中间还隔2-3堵墙通信都是正常的,可装在同事家里不知道为什么距离短的很2室1厅的房子不到70平方中间隔一堵墙的时候就有很多死点,接收机是放在卧室里的,在卧室通信时还有个别死点。到客厅的沙发直线距离不到5米通信就很差了,站着的时候通信正常,坐下来就不行了根本通信不了,郁闷的很不知道是不是哪里有干扰还是小区的房子结构影响通信。最后说明下我家是在乡下不知道是不是城里无线电干扰很严重。
希望知道的大侠指点迷津 城里无线电干是一个方面,还有就是农村的房屋不是钢架结构,但是城区的是,所以有一定的屏蔽作用 即便如此也不至于这么严重吧,隔了一堵墙半径5米就有很多的死点,一定是哪里出问题了,可是我对无线电方面的知识认识不多,不知道问题在哪里? 麻烦帮我看看程序哪出问题了?是在楼主提供的程序基础上修改的。调试过程:发射端附一个确定字符串“a”,接受端用LCM1602液晶屏显示接受到的数据。可是通信一直没有实现。补充:我用的是MEGA128+PTR905.已在nRF905.h中改了端口
源程序如下:
发射端程序
#include <iom128v.h>
#include "nRF905_Config.h"
#include "nRF905.h"
#include <macros.h>
unsigned char ReceiveBuffer; // RF接收缓冲区
unsigned char SendBuffer; // RF发送缓冲区
unsigned char ReceiveCount; // RF接收缓冲区接收个数
unsigned char SendCount; // RF发送缓冲区发送个数
#define xtal 7.3728
//晶振调整 MHz
void _delay_ms(unsigned int ms) //毫秒级延时,当改晶振为几M则xtal设为几
{
unsigned int i;
while(ms--)
{
for(i=1;i<(unsigned int)(xtal*143-2);i++);
}
}
void SPI_Init(void)
{
PORT_SPI |= (1<<MOSI)|(1<<MISO)|(1<<SCK)|(1<<SS);// 设置MOSI和SCK、SS为输出,其他为输入
DDR_SPI|= (1<<MOSI)|(1<<SCK)|(1<<SS);
SPCR = (1<<SPE)|(1<<MSTR)|(0<<CPOL)|(0<<SPR0); // 主机模式,fck/16, SPI方式0
}
unsigned char SPI_ReadWrite(unsigned char cData)
{
SPDR = cData;
while(!(SPSR & (1<<SPIF) )); // 等待SPI发送完毕
return SPDR;
}
void nRF905_Init(unsigned long nRF_rxaddr)
{
unsigned char i;
DDR_NRF905 |= ((1<<TX_EN)|(1<<TRX_CE)|(1<<PWR_UP)|(0<<DR)|(0<<AM)|(0<<CD));
PORT_NRF905 |= ((0<<TX_EN)|(0<<TRX_CE)|(1<<PWR_UP)|(1<<DR)|(1<<AM)|(1<<CD));
nRF905_SetConfig(nRF_rxaddr); // 初始化nRF905,并设置接收地址
nRF905_SetReceiveMode(); // 设置为接收模式
/* 发送缓冲区清零 */
for(i = 0; i < BUF_SIZE; ++i)
{SendBuffer = 0;}
}
unsigned char nRF905_ReadStatus(void)
{
unsigned char val;
CLR_SS(); // 打开SPI
val = SPI_ReadWrite(RC); // 读状态
SET_SS(); // 关闭SPI
return val;
}
void nRF905_SetSendMode(void)
{
_delay_ms(1);
SET_TX_EN(); // 设置为发送模式
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
_delay_ms(1);
CLR_TRX_CE(); // 待机PORTD &= ~(1<<TRX_CE);
_delay_ms(1);
}
void nRF905_SetReceiveMode(void)
{
asm("nop");
asm("nop");
asm("nop");
CLR_TX_EN(); // 设置为接收模式
asm("nop");
_delay_ms(1);
SET_TRX_CE(); // 使能接收
asm("nop");
asm("nop");
asm("nop");
_delay_ms(1);
}
void nRF905_SendStart(void)
{
SET_TRX_CE(); // 开始发送
_delay_ms(10);
while(DR!=1);
CLR_TRX_CE(); // 待机模式
}
void nRF905_SetConfig(unsigned long nRFAddr) //配置nRF905
{
CLR_TRX_CE(); //设置nRF905为待机方式
asm("nop");
CLR_SS(); //打开SPI
// 配置字总共10个字节
SPI_ReadWrite(WC); // Write config command
SPI_ReadWrite(CH_NO_BYTE); // 中心频率低8位
SPI_ReadWrite(PA_PWR_10dBm | HFREQ_PLL_433MHz); // 发射+10dBm,发射频率433MHz,中心频率第9位=0
SPI_ReadWrite(TX_AFW_4BYTE | RX_AFW_4BYTE); // 接收地址宽度4字节,发送地址宽度4字节0100 0100
SPI_ReadWrite(RX_PW_32BYTE); // 接收数据宽度32字节
SPI_ReadWrite(TX_PW_32BYTE); // 发送数据宽度32字节
SPI_ReadWrite((nRFAddr >> 24)); // 接收有效地址第1字节
SPI_ReadWrite((nRFAddr >> 16) & 0xff); // 接收有效地址第2字节
SPI_ReadWrite((nRFAddr >> 8) & 0xff); // 接收有效地址第3字节
SPI_ReadWrite(nRFAddr & 0xff); // 接收有效地址第4字节
SPI_ReadWrite(CRC16_EN | XOF_16MHz); // CRC16模式使能,晶体振荡器频率16MHz
SET_SS(); // 关闭SPI
if ( PORT_NRF905 & (1 << TX_EN) ) //再回到原来的无线收发模式
{
CLR_TRX_CE(); //设置nRF905为待机方式
}
else
{
SET_TRX_CE(); //设置nRF905为工作方式
}
}
/* 参数为接收端的地址,即:发送给谁? */
void nRF905_SendPacket(unsigned long nRF_rxaddr)
{
unsigned char i;
if( (PIN_NRF905 & ((1<<CD)|(1<<AM)|(1<<DR))) == 0 ) // 周边无射频信号
{
nRF905_SetSendMode();
//LED_ON();
asm("nop");
asm("nop");
asm("nop");
_delay_ms(1);
CLR_SS();
SPI_ReadWrite(WTA); // 写发送地址
SPI_ReadWrite((nRF_rxaddr >> 24)); // 接收有效地址第1字节
SPI_ReadWrite((nRF_rxaddr >> 16) & 0xff); // 接收有效地址第2字节
SPI_ReadWrite((nRF_rxaddr >> 8) & 0xff); // 接收有效地址第3字节
SPI_ReadWrite(nRF_rxaddr & 0xff); // 接收有效地址第4字节
SET_SS();
asm("nop");
asm("nop");
asm("nop");
CLR_SS();
SPI_ReadWrite(WTP);
for( i = 0; i < 32; ++i )
{
SPI_ReadWrite(SendBuffer);
}
SET_SS();
SendCount = 32;
nRF905_SendStart(); // 开始发送
nRF905_SetReceiveMode(); // 发送完毕回到接收模式
//LED_OFF();
}
}
/* 发送端代码 */
//----------------------------------------------------------------------------------
void main()
{
char SendBuffer="a";
SPI_Init();
nRF905_Init(RX_ADDRESS);
/* ****************************
* 发送数据包格式如下
* 0xaa length B0 B1 B2 ... Bn 0x55
*******************************/
/*SendBuffer = 0xaa;
SendBuffer = 2; // 数据包大小 2
SendBuffer = 0x12;
SendBuffer = 0xab;
SendBuffer = 0x55; */
while(1)
{
//液晶显示程序
CLI();
DDRD = 0X00;
PORTD = 0XFF;
EIMSK = 0b00000001;
EIFR = 0Xff;
EICRA = 0X00;
EICRB = 0X00;
SEI();
PORTA = 0X00;
DDRA = 0X02;
DDRD |= LCD_DATA;
DDRC |= LCD_RS | LCD_EN;
LCD_EN_PORT &= ~LCD_EN; //EN=0
LCD_init();
LCD_write_char(0,0x01);//显示清屏
delay_nms(2);
LCD_write_string(1,0,"Transmitting...");
LCD_write_string(7,1,SendBuffer);
/*if( flag == 1 )
{
nRF905_SendPacket(RX_ADDRESS);
flag = 0;
}
if( PIN_NRF905 & (1<<DR) )
{
nRF905_ReceivePacket();
if( ReceiveBuffer == 0x55 )
{
flag = 1;
ReceiveBuffer = 0;
}
} */
nRF905_SendPacket(TX_ADDRESS);
_delay_ms(1000);
}
}
接受端程序如下:
#include <iom128v.h>
#include "nRF905_Config.h"
#include "nRF905.h"
#include <macros.h>
#include <math.h> //液
#include <stdio.h>//晶
#include "1602LCD.h"//屏
#include <stdlib.h> //应
#include <string.h> //用
unsigned char ReceiveBuffer; // RF接收缓冲区
unsigned char ReceiveCount; // RF接收缓冲区接收个数
unsigned char SendCount; // RF发送缓冲区发送个数
#define xtal 7.3728
//晶振调整 MHz
void _delay_ms(unsigned int ms) //毫秒级延时,当改晶振为几M则xtal设为几
{
unsigned int i;
while(ms--)
{
for(i=1;i<(unsigned int)(xtal*143-2);i++);
}
}
void SPI_Init(void)
{
PORT_SPI |= (1<<MOSI)|(1<<MISO)|(1<<SCK)|(1<<SS);// 设置MOSI和SCK、SS为输出,其他为输入
DDR_SPI|= (1<<MOSI)|(1<<SCK)|(1<<SS);
SPCR = (1<<SPE)|(1<<MSTR)|(0<<CPOL)|(0<<SPR0); // 主机模式,fck/16, SPI方式0
}
unsigned char SPI_ReadWrite(unsigned char cData)
{
SPDR = cData;
while(!(SPSR & (1<<SPIF) )) ; // 等待SPI发送完毕
return SPDR;
}
void nRF905_Init(unsigned long nRF_rxaddr)
{
unsigned char i;
DDR_NRF905 |= ((1<<TX_EN)|(1<<TRX_CE)|(1<<PWR_UP)|(0<<DR)|(0<<AM)|(0<<CD));
PORT_NRF905 |= ((0<<TX_EN)|(0<<TRX_CE)|(1<<PWR_UP)|(1<<DR)|(1<<AM)|(1<<CD));
nRF905_SetConfig(nRF_rxaddr); // 初始化nRF905,并设置接收地址
/* 接收缓冲区清零 */
for(i = 0; i < BUF_SIZE; ++i)
{
ReceiveBuffer = 0;
}
}
unsigned char nRF905_ReadStatus(void)
{
unsigned char val;
CLR_SS(); // 打开SPI
val = SPI_ReadWrite(RC); // 读状态
SET_SS(); // 关闭SPI
return val;
}
void nRF905_SetSendMode(void)
{
_delay_ms(1);
SET_TX_EN(); // 设置为发送模式
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
_delay_ms(1);
CLR_TRX_CE(); // 待机PORTD &= ~(1<<TRX_CE);
_delay_ms(1);
}
void nRF905_SetReceiveMode(void)
{ asm("nop");
asm("nop");
asm("nop");
CLR_TX_EN(); // 设置为接收模式
asm("nop");
_delay_ms(1);
SET_TRX_CE(); // 使能接收
asm("nop");
asm("nop");
asm("nop");
_delay_ms(1);
}
void nRF905_SendStart(void)
{
SET_TRX_CE(); // 开始发送
_delay_ms(10); // while(DR!=1);
CLR_TRX_CE(); // 待机模式
}
void nRF905_SetConfig(unsigned long nRFAddr) //配置nRF905
{
CLR_TRX_CE(); //设置nRF905为待机方式
asm("nop");
CLR_SS(); //打开SPI
// 配置字总共10个字节
SPI_ReadWrite(WC); // Write config command
SPI_ReadWrite(CH_NO_BYTE); // 中心频率低8位
SPI_ReadWrite(PA_PWR_10dBm | HFREQ_PLL_433MHz); // 发射+10dBm,发射频率433MHz,中心频率第9位=0
SPI_ReadWrite(TX_AFW_4BYTE | RX_AFW_4BYTE); // 接收地址宽度4字节,发送地址宽度4字节0100 0100
SPI_ReadWrite(RX_PW_32BYTE); // 接收数据宽度32字节
SPI_ReadWrite(TX_PW_32BYTE); // 发送数据宽度32字节
SPI_ReadWrite((nRFAddr >> 24)); // 接收有效地址第1字节
SPI_ReadWrite((nRFAddr >> 16) & 0xff); // 接收有效地址第2字节
SPI_ReadWrite((nRFAddr >> 8) & 0xff); // 接收有效地址第3字节
SPI_ReadWrite(nRFAddr & 0xff); // 接收有效地址第4字节
SPI_ReadWrite(CRC16_EN | XOF_16MHz); // CRC16模式使能,晶体振荡器频率16MHz
SET_SS(); // 关闭SPI
if ( PORT_NRF905 & (1 << TX_EN) ) //再回到原来的无线收发模式
{
CLR_TRX_CE(); //设置nRF905为待机方式
}
else
{
SET_TRX_CE(); //设置nRF905为工作方式
}
}
void nRF905_ReceivePacket(void)
{
unsigned char i;
nRF905_SetReceiveMode(); // 设置接收模式
// CD=1且AM=0,DR=0
if( ( PIN_NRF905 & (1<<CD) ) && ((PIND & ((1<<AM)|(1<<DR)) ) == 0) )
{
CLR_TRX_CE(); // 待机模式
asm("nop");
CLR_SS();
SPI_ReadWrite(RRP);
for(i = 0; i < 32; ++i)
{
ReceiveBuffer = SPI_ReadWrite(0xff);
}
SET_SS();
while(PIN_NRF905 & ((1<<AM)|(1<<DR)) ); // 等待
ReceiveCount = 32;
SET_TRX_CE();
// LED_ON();
}
}
/* 接收端代码 */
void main(void)
{ SPI_Init();
nRF905_Init(RX_ADDRESS);
//液晶显示程序
CLI();
DDRD = 0X00;
PORTD = 0XFF;
EIMSK = 0b00000001;
EIFR = 0Xff;
EICRA = 0X00;
EICRB = 0X00;
SEI();
PORTA = 0X00;
DDRA = 0X02;
DDRD |= LCD_DATA;
DDRC |= LCD_RS | LCD_EN;
LCD_EN_PORT &= ~LCD_EN; //EN=0
LCD_init();
LCD_write_char(0,0x01);//显示清屏
delay_nms(2);
LCD_write_string(2,0,"Receiving...");
while(1){
if( PIN_NRF905 & (1<<DR) )
{
nRF905_ReceivePacket();
LCD_write_string(6,1,"a");
}
}
} 标记. 哪出问题了? 收藏~~~~ 留个记号吧 顶上来。 http://cache.amobbs.com/bbs_upload782111/files_16/ourdev_457700.JPG
10个寄存器介绍 (原文件名:905-10个寄存器介绍.JPG)
http://cache.amobbs.com/bbs_upload782111/files_16/ourdev_457701.JPG
905-SPI读写时序 (原文件名:905-SPI读写时序.JPG)
http://cache.amobbs.com/bbs_upload782111/files_16/ourdev_457702.JPG
905-SPI读写指令 (原文件名:905-SPI读写指令.JPG)
http://cache.amobbs.com/bbs_upload782111/files_16/ourdev_457703.JPG
905-各寄存器序列 (原文件名:905-各寄存器序列.JPG)
http://cache.amobbs.com/bbs_upload782111/files_16/ourdev_457704.JPG
905频率计算介绍 (原文件名:905频率计算介绍.JPG)
http://cache.amobbs.com/bbs_upload782111/files_16/ourdev_457705.JPG
905频率计算介绍 (原文件名:905-905频率计算介绍.JPG)
http://cache.amobbs.com/bbs_upload782111/files_16/ourdev_457706.JPG
905文档精简 (原文件名:905-数据接收流程图.JPG)
NRF2401 NRF24L01 NRF905 RF903 CC1100 CC2500 CC1020等主流短距离无线技术介绍及应用指南
http://shop35079098.taobao.com/shop/xshop/wui_page-15620063.htm
NRF905基本特性:
=================================================================================
工作电压:1.9-3.6V
调制方式: GFSK
接收灵敏度:-100dBm
最大发射功率: 10mW (+10dBm)
最大传输数率:50kbps
瞬间最大工作电流: <30mA
工作频率:(422.4-473.5MHZ)
=================================================================================
接收发送功能合一,收发完成中断标志
433/868/915工作频段,433MHZ开放ISM频段可免许使用
最高发射速率50KBPS,10dbm发射功率条件下,配置外置鞭状天线有效通信距离在300米左右。
室内通信良好通信效果,4层之间可实现有效通信,抗干扰性能强,很强的扰障碍穿透性能。
单次最多可发送接收32字节,并可软件设置发送/接收缓冲区大小2/4/8/16/32字节
170个频道,可实现多点网络通讯,结合TDMA-CDMA-FDMA原理,实现无线网络通讯。
内置硬件8/16位CRC校验,数据传输可*稳定,降低系统开发难度,。
1.9-3.6V工作,低功耗,待机模式仅2.5uA.
内置SPI接口,最高SPI时钟可大10M,也可通过I/O口模拟SPI实现。
NRF905模块应用领域:
车辆监控、遥控、遥测、小型无线网络、无线抄表、门禁系统、小区传呼、工业数据采集系统、
无线标签、身份识别、非接触RF智能卡、小型无线数据终端、安全防火系统、无线遥控系统、
生物信号采集、水文气象监控、机器人控制、无线232数据通信、无线485/422数据通信等。
===================================================================================
微功率(10mW)NRF905模块开发文档:http://www.newmsg.com/products/NewMsg-RF905.pdf
中功率(100mW)NRF905模块开发文档:http://www.newmsg.com/Products/NewMsg-RFC30F.pdf
大功率(1W)NRF905模块开发文档:http://www.newmsg.com/Products/NewMsg-RFC27A.pdf mark 好東西!謝啦 mark 有兴趣谢谢分享mark 感谢分享 mark mark ding ni mark! mark手头正好有5片905的片子因为没有电路图 没有代码可以参考 自己水平又不够一直闲置着
等下载服务器维修好了之后 希望lZ把电路图也放上来 谢谢啦! 标记 好东西 let me see..参考下,谢谢! ding顶 ding mark mark! 强人,顶一下·~~ 点击此处下载 ourdev_538660.rar(文件大小:504K) (原文件名:无线数据通信汇总和选型参考(含图片).rar) 谢谢分享~~~学习下 mark 很感兴趣!!~~ 记号 mark,最近无线传输很火啊 mark 记 楼主,电路图能不能发给我啊,sunshinecyh@163.com ,谢谢 分享一下吧 好东东啊,感谢啊,在没有障碍物的情况下,最远多远啊 MARK,ATMEGA16+NRF905! mark 回复【楼主位】ifree64
-----------------------------------------------------------------------
我也求个电路图啊 刚开始学做这个 上网问了问 他们说nrf905不能直接接入开发板 是这样吗?我邮箱********@163.com 求指导!!!
站长阿莫提示:本论坛不提倡使用QQ等私下沟通技术问题,也禁止QQ群讨论。我们这里的资料,不是天上掉下来的,是大家的无私贡献才有今天的成就。 站长阿莫提示:本论坛不提倡使用QQ等私下沟通技术问题,也禁止QQ群讨论。我们这里的资料,不是天上掉下来的,是大家的无私贡献才有今天的成就。 MARK,ATMEGA16+NRF905! mark mark 而433M只是ISM的规定的第一个区域可用啊
中国是属于第三个区域,按理是不可用的!!!? mark 好东西啊 mark NRF950 M 标记 学习下 谢谢分享 MARK MARK 看贴,顶贴! MARK mark 我想问一下,mega16与905能不能直接相连?如果要加限流电阻的话要加多大的电阻? 搞了两天就是接收不到郁闷中 谢谢楼主!!有个参考,最近在做 mark,收藏了》 恩恩 很好 谢谢分享 感谢分享~~!! mark amark 非常感谢,已经成功移植使用。 谢谢分享 .............mark 楼主威武
页:
[1]