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
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值