nrf51822之间通讯

GPIO引脚配置:

//大家51单片机用过吗?知道P0 ,P1 ,P2 ,P3这些io口吗?
//因为nrf51822是32位单片机。用下面的代码可以拆成8位单片机用。使用的效果就和51单片机一模一样
//可以P1=0x0f;这样51822的P0.8~P0.15脚就被设置了
typedef enum
{
    NRF_GPIO_PORT_SELECT_PORT0 = 0,           ///<  Port 0 (GPIO pin 0-7)
    NRF_GPIO_PORT_SELECT_PORT1,               ///<  Port 1 (GPIO pin 8-15)
    NRF_GPIO_PORT_SELECT_PORT2,               ///<  Port 2 (GPIO pin 16-23)
    NRF_GPIO_PORT_SELECT_PORT3,               ///<  Port 3 (GPIO pin 24-31)
} nrf_gpio_port_select_t;

//定义P口,用法和51单片机一样用P0,P1,P2,P3
#define P0   NRF_GPIO_PORT_SELECT_PORT0     //P0.0~P0.7(P0.0~P0.07)
#define P1   NRF_GPIO_PORT_SELECT_PORT1     //P1.0~P1.7(P0.8~P0.15)
#define P2   NRF_GPIO_PORT_SELECT_PORT2     //P2.0~P2.7(P0.16~P0.23)
#define P3   NRF_GPIO_PORT_SELECT_PORT3     //P3.0~P3.7(P0.24~P0.31)

发射程序:

//arm_startup_nrf51.s是启动文件,包含中断定义
//#include "nrf51.h"//包含51822各个寄存器结构地址。以上2文件就可以控制51822了。
//nrf51_bitfields.h包含各个寄存器设置值的作用
#include "project_nrf51822.c"//包含51822工程需要用到的头文件(晶振,延时,io脚什么的

#include <stdbool.h>//调用bool
#include "stdio.h"//标准输入输出
#include <stdint.h>//声明已知大小的整数或显示特征的整数

//packet[3]中QxC(Q开始,C结束,x是数据char)
static uint8_t packet[3]={'Q','0','C'};  //数据传输用QxC(Q代表开始,C代表结束,x代表数据)

void init(void)//51822时钟初始化
{ 
	 //判断电源时钟状态
	 if ((((*(uint32_t *)0xF0000FE0) & 0xFF) == 1) && (((*(uint32_t *)0xF0000FE4) & 0xF) == 0))
    {
        if ((((*(uint32_t *)0xF0000FE8) & 0xF0) == 0x0) && (((*(uint32_t *)0xF0000FEC) & 0xF0) == 0x0))
        {
	    //解决radio无法写入  
          *(uint32_t *)0x40000504 = 0xC007FFDF;//电源时钟设置
          *(uint32_t *)0x40006C18 = 0x00008000;//GPIOTE设置    
        }
	 else if ((((*(uint32_t *)0xF0000FE8) & 0xF0) == 0x10) && (((*(uint32_t *)0xF0000FEC) & 0xF0) == 0x0))
        {
          //解决radio无法写入  
          *(uint32_t *)0x40000504 = 0xC007FFDF;//电源时钟设置
          *(uint32_t *)0x40006C18 = 0x00008000;//GPIOTE设置  
        }
        else if ((((*(uint32_t *)0xF0000FE8) & 0xF0) == 0x30) && (((*(uint32_t *)0xF0000FEC) & 0xF0) == 0x0))
        {
          //解决radio无法写入  
          *(uint32_t *)0x40000504 = 0xC007FFDF;//电源时钟设置
          *(uint32_t *)0x40006C18 = 0x00008000;//GPIOTE设置    
        }
    }
	NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;//HFCLK晶振运行状态标志位   0关闭,1运行
  NRF_CLOCK->TASKS_HFCLKSTART = 1;//高外晶振HFCLK   0关闭,1启动
  while(!NRF_CLOCK->EVENTS_HFCLKSTARTED);//等待HFCLK晶振运行状态标志位 为1
}

void ioinit()//51822引脚初始化
{
    //接收用usb-jtag的nrf51822
//	  gpio_init_in(9,9,3);//p0.09输入
//	  gpio_init_in(11,11,3);//p0.11输入
//    gpio_init_out(21,23);//led:red,green,blue
	
    	gpio_init_out(0,15);//设置0~15脚配置为输出
  	  gpio_init_in(16,17,3);//设置16~17脚配置为输入3代表上拉电阻(开发板为按钮key0,key1)
    	gpio_init_out(18,25);//设置18~25脚配置为输出/那个26~27接的是低速晶振
      gpio_init_out(28,31);//设置28~31脚配置为输出
}

	int main(void)//main主程序开始
{
    init();//时钟初始化
    ioinit();//引脚初始化
	  radio_configure();//无线电配置(也可用于和nrf2401通讯)
  // 设置有效载荷指针
    NRF_RADIO->PACKETPTR = (uint32_t)packet;//指针指向数据缓冲packet  
	
	//检查io脚是否正常
    NRF_GPIO->OUTSET=(1<<22);//led4亮,表示51822已经工作中
    
	while(1)
  {
    packet[1]= (NRF_GPIO->IN>>16)&3; //读到的key0,key1数据给发射缓冲
		nrf_gpio_pin_clear(18);//led0灭,表示数据还没发出
		//数据准备发送
		NRF_RADIO->EVENTS_READY = 0U;//收发模式转换完成标志位。复位
    NRF_RADIO->TASKS_TXEN = 1U;//启动无线电为发射模式
        while (NRF_RADIO->EVENTS_READY == 0U);//等待收发模式转换完成

        // Start transmission.
    NRF_RADIO->EVENTS_END  = 0U;//传输完成标志位,复位     
		NRF_RADIO->TASKS_START = 1U;//开始传输
        while(NRF_RADIO->EVENTS_END == 0U) //等待传输完成
        {
					  nrf_gpio_pin_clear(18);//传输失败led0灭
            // Do nothing.
        }

        // 组1引脚(8~15)
        nrf_gpio_port_write(P1, packet[1]);//数值显示在单片机P1口上
        nrf_gpio_pin_set(18);//传输成功led0亮,越暗说明有干扰,需要改频率
				
        NRF_RADIO->EVENTS_DISABLED = 0U;//无线关闭标志位  复位
        NRF_RADIO->TASKS_DISABLE   = 1U; // 关闭无线
        while(NRF_RADIO->EVENTS_DISABLED == 0U)//等待无线关闭
        {
            // Do nothing.
        }
    }
}


接收程序:

//arm_startup_nrf51.s是启动文件,包含中断定义
//#include "nrf51.h"//包含51822各个寄存器结构地址。以上2文件就可以控制51822了。
//nrf51_bitfields.h包含各个寄存器设置值的作用
#include "project_nrf51822.c"//包含51822工程需要用到的头文件(晶振,延时,io脚什么的

#include <stdbool.h>//调用bool
#include "stdio.h"//标准输入输出
#include <stdint.h>//声明已知大小的整数或显示特征的整数


void init(void)//51822时钟初始化
{ 
	 //判断电源时钟状态
	 if ((((*(uint32_t *)0xF0000FE0) & 0xFF) == 1) && (((*(uint32_t *)0xF0000FE4) & 0xF) == 0))
    {
        if ((((*(uint32_t *)0xF0000FE8) & 0xF0) == 0x0) && (((*(uint32_t *)0xF0000FEC) & 0xF0) == 0x0))
        {
					//解决radio无法写入  
          *(uint32_t *)0x40000504 = 0xC007FFDF;//电源时钟设置
          *(uint32_t *)0x40006C18 = 0x00008000;//GPIOTE设置    
        }
				else if ((((*(uint32_t *)0xF0000FE8) & 0xF0) == 0x10) && (((*(uint32_t *)0xF0000FEC) & 0xF0) == 0x0))
        {
          //解决radio无法写入  
          *(uint32_t *)0x40000504 = 0xC007FFDF;//电源时钟设置
          *(uint32_t *)0x40006C18 = 0x00008000;//GPIOTE设置  
        }
        else if ((((*(uint32_t *)0xF0000FE8) & 0xF0) == 0x30) && (((*(uint32_t *)0xF0000FEC) & 0xF0) == 0x0))
        {
          //解决radio无法写入  
          *(uint32_t *)0x40000504 = 0xC007FFDF;//电源时钟设置
          *(uint32_t *)0x40006C18 = 0x00008000;//GPIOTE设置    
        }
    }
	NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;//HFCLK晶振运行状态0关闭,1运行
  NRF_CLOCK->TASKS_HFCLKSTART = 1;//高外晶振HFCLK 0关闭,1启动
  while(!NRF_CLOCK->EVENTS_HFCLKSTARTED);//等待HFCLK晶振运行状态为1
}

void ioinit()//51822引脚初始化
{
    //接收用usb-jtag的nrf51822
	  gpio_init_in(9,9,3);//p0.09输入
	  gpio_init_in(11,11,3);//p0.11输入
    gpio_init_out(21,23);//led:red,green,blue
	
//  	gpio_init_out(0,15);//设置0~15脚配置为输出
//	  gpio_init_in(16,17,3);//设置16~17脚配置为输入(开发板为按钮key0,key1)
//  	gpio_init_out(18,25);//设置18~25脚配置为输出/那个26~27接的是低速晶振
//    gpio_init_out(28,31);//设置28~31脚配置为输出
}


//packet[3]中QxC(Q开始,C结束,x是数据char)
static uint8_t volatile packet[3];  //< 数据传输的缓冲包packet[1]是数据

	int main(void)//main主程序开始
{
    init();//时钟初始化
    ioinit();//引脚初始化
	  radio_configure();//无线电配置(也可用于和nrf2401通讯)
    //检查io脚是否正常
	  nrf_gpio_pin_set(21);//  red灭p0.21
	  nrf_gpio_pin_set(22);//green灭p0.22
          nrf_gpio_pin_set(23);// blue灭p0.23

	// 设置有效载荷指针
        NRF_RADIO->PACKETPTR    = (uint32_t)packet;//指针指向数据缓冲packet
        
    while(1)
    {
			  NRF_RADIO->EVENTS_READY = 0U; //收发模式转换完成  标志位       
        NRF_RADIO->TASKS_RXEN   = 1U; //接收模式
        while(NRF_RADIO->EVENTS_READY == 0U) //等待收发模式转换完成(接收模式)标志位
          {
            // Do nothing.等待
          }
        NRF_RADIO->EVENTS_END  = 0U;//传输完成  标志位     
        NRF_RADIO->TASKS_START = 1U; // 开始传输

        while(NRF_RADIO->EVENTS_END == 0U)//等待传输完成  标志位
           {
             nrf_gpio_pin_set(23);// blue灭  //传输不成功
						 // Do nothing.等待
           }
        if (NRF_RADIO->CRCSTATUS == 1U)//如果CRC校验正确
        {
            //nrf_gpio_port_write(NRF_GPIO_PORT_SELECT_PORT1, packet[0]);
	         if(packet[0]==('Q'))//确定开始
	       {
                    if(packet[2]==('C'))//结束正确
                   {  
		     NRF_GPIO->OUT=(packet[1]<<21);//数据给io脚
		     nrf_gpio_pin_clear(23);// blue亮,数据成功了,灯越暗说明数据传输越快。
				                     //不亮说明,数据传输失败。
                   }
               }
        }

        NRF_RADIO->EVENTS_DISABLED = 0U;//无线关闭   标志位
        NRF_RADIO->TASKS_DISABLE   = 1U;// 关闭无线设备

        while(NRF_RADIO->EVENTS_DISABLED == 0U)//等待设备关闭
        {
            // Do nothing.
        }
    }   
}

无线电配置:

//无线功率4分贝,2440MHz,通道0地址0x99999999C0,通道1~7地址0x66666666XX
//速率2MHz,数据字节3字节QxC(Q开始,C结束,x是数据char)
void radio_configure()//无线配置,准备和nrf24L01通讯
{
  //无线功率04:+4分贝,0:0分贝,FC:-4分贝,F8:-8分贝
	//    F4:-12分贝,F0:-16分贝,EC:-20分贝,D8:-30分贝
	NRF_RADIO->TXPOWER = (0x04<<0);//无线功率4分贝
  
	NRF_RADIO->FREQUENCY = 40UL;//无线频率40MHz+2400MHz=2440MHz

	//无线速率:00:1Mbit,01:2Mbit,02:250Kbit,03:1Mbit(蓝牙)
	NRF_RADIO->MODE = (01<<0);//速率2MHz

	// 无线地址设置
  NRF_RADIO->PREFIX0 = 0xC3C2C1C0UL;  // 通道3 到 0 的低1字节
  NRF_RADIO->PREFIX1 = 0xC7C6C5C4UL;  // 通道7 到 4 的低1字节
  NRF_RADIO->BASE0   = 0x99999999UL;  // 通道0的高字节
  NRF_RADIO->BASE1   = 0x66666666UL;  // 通道1-7的高字节
  NRF_RADIO->TXADDRESS = 0x00UL;      // 发射使用的通道号:0通道
  NRF_RADIO->RXADDRESSES = 0x01UL;    // 接收的通道号:1通道

  // 配置包0的设置
  NRF_RADIO->PCNF0 = (0<<16)| //S1领域的长度
                                   (0<<8) | //S0场的长度
                                   (0<<0);  //长度字段中的比特数

  // 配置包1的设置
   NRF_RADIO->PCNF1 = (0<<25)| //效验位(0关,1开)
                                   (1<<24)| //数据大小端(高低字节哪个先发 0低字节,1高字节)
                                   (4<<16)| //通道1~7高字节长度( nrf24高低字节5字节:4个高+1个低)
                                    (3<<8) | //数据字节长度(255~1)3字节QxC
                                    (3<<0);  //硬件传输字节长度(255~1)3字节QxC

  // CRC 校验长度配置
  NRF_RADIO->CRCCNF = 2; // 校验长度 2个char
  if ((NRF_RADIO->CRCCNF & 0x03)== 2 )
  {
    NRF_RADIO->CRCINIT = 0xFFFFUL;      // 校验初始值
    NRF_RADIO->CRCPOLY = 0x11021UL;     // CRC poly: x^16+x^12^x^5+1
  }
  else if ((NRF_RADIO->CRCCNF & 0x03) == 1 )
  {
    NRF_RADIO->CRCINIT = 0xFFUL;        // 校验初始值
    NRF_RADIO->CRCPOLY = 0x107UL;       // CRC poly: x^8+x^2^x^1+1
  }
	
//接收寄存器是  NRF_RADIO->PACKETPTR	
}


转载自:http://www.openedv.com/posts/list/0/25014.htm?privmsg=1,在此感谢!

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 如果您想使用两个nrf24l01进行通信,每个nrf24l01都需要连接到一个独立的STM32微控制器。这样可以实现双向通信,每个STM32都可以发送和接收数据。 在两个STM32之间建立通信连接时,需要确保它们使用相同的通信协议和通信频率。您可以使用SPI接口将nrf24l01与STM32连接,并使用nRF24L01库或自己编写的通信协议进行通信。 需要注意的是,每个nrf24l01都需要设置唯一的地址,以确保它们之间的通信不会与其他nrf24l01设备冲突。在设置地址时,您可以使用硬件地址或动态地址。如果您使用硬件地址,则需要确保每个nrf24l01具有唯一的地址。如果您使用动态地址,则需要确保每个设备已配置为使用相同的地址。 因此,您需要编写适当的代码来初始化nrf24l01和STM32,并确保它们正确地连接和通信。 ### 回答2: 如果要实现两个nRF24L01之间的通信,可以使用两个STM32微控制器来实现。首先,确保每个STM32上都有一个nRF24L01模块,并且每个模块都有独立的电源供应。 接下来,需要根据nRF24L01模块的规格进行引脚连接。通常,模块上的VCC引脚连接到STM32的5V电源引脚,GND引脚连接到STM32的地引脚。将模块的CE(片选使能)引脚和CSN(SPI片选)引脚连接到STM32的GPIO引脚,同时连接SPI总线的SCK、MISO、MOSI引脚到STM32的相应GPIO引脚。此外,在两个板子之间,还需要将nRF24L01模块的IRQ引脚连接到STM32的GPIO引脚,以便实现中断功能。 一旦硬件连接完成,需要在两个STM32的代码中配置nRF24L01模块。可以使用nRF24L01库函数来简化配置和通信过程。首先,在发送STM32上,将模块配置为TX(发送器)模式,设置通信通道、发射功率和数据速率等参数。然后,将要发送的数据写入发送缓冲区,并为要接收数据的STM32的接收缓冲区设置地址。 在接收STM32上,将模块配置为RX(接收器)模式,并设置与发送STM32相同的通信通道、发射功率和数据速率等参数。启用接收中断,并设置接收缓冲区地址。一旦接收到数据,可以在中断服务函数中读取数据。 最后,使用SPI总线进行通信。在发送STM32上,通过SPI发送命令和数据到接收STM32上的nRF24L01模块。在接收STM32上,通过SPI接收命令和数据,并根据需要执行相应的操作。 综上所述,通过两个STM32微控制器和两个nRF24L01模块的配置和通信过程,可以实现两个设备之间的无线通信。其中一个STM32充当发送器,另一个STM32充当接收器,通过nRF24L01模块和SPI总线进行数据的发送和接收。 ### 回答3: 两个 nrf24l01 通讯的系统包含两个 stm32 微控制器。每个 stm32 微控制器都连接一个 nrf24l01 无线收发模块以实现通讯。以下是该系统的基本工作原理。 首先,每个 stm32 需要设置与之连接的 nrf24l01 模块的参数,如通道选择、数据速率和地址等。两个 nrf24l01 模块需要使用相同的通道和地址设置,以确保它们可以彼此通信。 然后,当一个 stm32 微控制器想要向另一个 stm32 发送数据时,它将将数据写入 nrf24l01 模块的发送缓冲区。发送缓冲区是用来临时存储要发送的数据。 接着,发送端的 nrf24l01 模块会自动将数据经过无线信道发送给接收端的 nrf24l01 模块。无线信道可以通过配置的通道来传输数据。 接收端的 nrf24l01 模块接收到数据后,将其存储在接收缓冲区中。接收缓冲区是用来临时存储从无线信道接收到的数据。 最后,接收端的 stm32 微控制器可以读取接收缓冲区中的数据,并进行进一步的处理或回复等操作。这样,两个 stm32 微控制器之间通讯就完成了。 需要注意的是,两个 nrf24l01 通讯使用的是无线信道,因此在使用之前需要确保在通讯距离范围内只有这两个设备使用相同的通道,以避免干扰或冲突。此外,还需要注意设置合适的数据速率和地址等参数,以保证通讯的稳定性和可靠性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值