物联网之lora通讯一:一主多从方案

1、多个从机和1个主机组成,通讯方式为lora。

2、主芯片stm32F1,RF芯片安信可Ra-02,SPI驱动。

3、多个主机可放到一起。(调整lora的相关参数,扩频因子,带宽,编码率,使主从机在一个空中速率。具体见如下说明)。

3、主从机采用一问一答方式通讯,lora全双工,延时20s。

实际项目已经应用,唯一不足就是延时长,RF驱动分享出来,希望可以完善代码。见附件。

/*
 * THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND 
 * (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
 * CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
 * CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
 * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
 * CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
 * 
 * Copyright (C) SEMTECH S.A.
 */
/*! 
 * \file       sx1276-LoRa.h
 * \brief      SX1276 RF chip driver mode LoRa
 *
 * \version    2.0.B2 
 * \date       May 6 2013
 * \author     Gregory Cristian
 *
 * Last modified by Miguel Luis on Jun 19 2013
 */
#ifndef __SX1278_LORA_H__
#define __SX1278_LORA_H__

#include "spi.h"   

#define RF_CS_Low    GPIO_ResetBits(GPIOA, GPIO_Pin_4)//PD8 CS 
#define RF_CS_High   GPIO_SetBits(GPIOA,   GPIO_Pin_4)// 

#define RF_SDN_Low   GPIO_ResetBits(GPIOB, GPIO_Pin_0)// PD10 SDN
#define RF_SDN_High  GPIO_SetBits(GPIOB,   GPIO_Pin_0)//

//#define RF_NIRQ      GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_8)//NIRQ
#define RF_NIRQ      GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11)//NIRQ


//-----------------------------------------------------------------------------
// 子程序声明
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// define MCU GPIO
//-----------------------------------------------------------------------------

u8 SPIRead(u8 adr);

void SPIBurstRead(u8 adr, u8 *ptr, u8 length);

void RFM96_LoRaEntryRx(void);
u8 RFM96_LoRaRxPacket(u8 *buf);
u8 RFM96_LoRaEntryTx(u8 packet_length);
u8 RFM96_LoRaTxPacket(u8 *buf,u8 len);

unsigned char RFM96_Config(u8 mode);
unsigned char SX1278_Init(void);

unsigned char SX1278_TXD(u8 *buf, u8 size);

unsigned char SX1278_RXD(unsigned char *Data);
/*!
 * SX1276 Internal registers Address
 */
//RFM96 Internal registers Address
#define LR_RegFifo                                  0x0000//FIFO read/write access
// Common settings
#define LR_RegOpMode                                0x0100//Operating mode & LoRaTM / FSK selection
#define LR_RegFrMsb                                 0x0600//RF Carrier Frequency, Most Significant Bits
#define LR_RegFrMid                                 0x0700//RF Carrier Frequency, Most Significant Bits
#define LR_RegFrLsb                                 0x0800//RF Carrier Frequency, Most Significant Bits
// Tx settings
#define LR_RegPaConfig                              0x0900//PA selection and Output Power control
#define LR_RegPaRamp                                0x0A00//Control of PA ramp time, low phase noise PLL
#define LR_RegOcp                                   0x0B00//Over Current Protection control
// Rx settings
#define LR_RegLna                                   0x0C00//LNA settings
// LoRa registers
#define LR_RegFifoAddrPtr                           0x0D00//FIFO SPI pointer
#define LR_RegFifoTxBaseAddr                        0x0E00//Start Tx data
#define LR_RegFifoRxBaseAddr                        0x0F00//Start Rx data
#define LR_RegFifoRxCurrentaddr                     0x1000//Start address of last packet received 
#define LR_RegIrqFlagsMask                          0x1100//Optional IRQ flag mask
#define LR_RegIrqFlags                              0x1200//IRQ flags
#define LR_RegRxNbBytes                             0x1300//Number of received bytes
#define LR_RegRxHeaderCntValueMsb                   0x1400//Number of valid headers received
#define LR_RegRxHeaderCntValueLsb                   0x1500//
#define LR_RegRxPacketCntValueMsb                   0x1600//Number of valid packets received
#define LR_RegRxPacketCntValueLsb                   0x1700
#define LR_RegModemStat                             0x1800//Live LoRa TM  modem status
#define LR_RegPktSnrValue                           0x1900//Espimation of last packetSNR
#define LR_RegPktRssiValue                          0x1A00//RSSI of last packet
#define LR_RegRssiValue                             0x1B00//Current RSSI
#define LR_RegHopChannel                            0x1C00//FHSS start channel
#define LR_RegModemConfig1                          0x1D00//Modem PHY config 最重要的寄存器包括Signal bandwidth:Error coding rate,Explicit Header mode
#define LR_RegModemConfig2                          0x1E00//SF rate,
#define LR_RegSymbTimeoutLsb                        0x1F00//Receiver timeout value
#define LR_RegPreambleMsb                           0x2000//Size of preamble
#define LR_RegPreambleLsb                           0x2100//
#define LR_RegPayloadLength                         0x2200//LoRa TM  payload length
#define LR_RegMaxPayloadLength                      0x2300//LoRaTM maximum pay-load length
#define LR_RegHopPeriod                             0x2400//FHSS Hop period
#define LR_RegFifoRxByteAddr                        0x2500//Address of last bytewritten in FIFO
#define LR_RegModemConfig3                         0x2600//Modem PHY config 3

// I/O settings
#define REG_LR_DIOMAPPING1                          0x4000
#define REG_LR_DIOMAPPING2                          0x4100
// Version
#define REG_LR_VERSION                              0x4200
// Additional settings
#define REG_LR_PLLHOP                               0x4400
#define REG_LR_TCXO                                 0x4B00//TCXO or XTAL input setting
#define REG_LR_PADAC                                0x4D00//Higher power settings of the PA
#define REG_LR_FORMERTEMP                           0x5B00//Stored temperature during the former IQ Calibration

#define REG_LR_AGCREF                               0x6100//Adjustment of the AGC thresholds
#define REG_LR_AGCTHRESH1                           0x6200
#define REG_LR_AGCTHRESH2                           0x6300
#define REG_LR_AGCTHRESH3                           0x6400

#endif //__SX1276_LORA_H__

#include "sx1278_LoRa.h"
#include "stm32f10x_spi.h"

#include <stdio.h>

#define u8  unsigned char 
#define u16 unsigned short

#define gb_SF  3
#define gb_BW  6
#define CR    0x04 
#define CRC_EN   0x00  //CRC Enable

 
 
/**********************************************************
**Parameter table define
**********************************************************/
static  const u16 RFM96FreqTbl[3] = {0x066C, 0x0780, 0x0800}; //434MHz  32M晶振0x066C, 0x0780, 0x0800 	   30M:0x0673, 0x07BB, 0x08BB   {0x85,0x89,0xd9},//26M-TCXO 434M

static  const u16 RFM96PowerTbl[4] =
{ 
  0x09FF,                   //20dbm  
  0x09FC,                   //17dbm
  0x09F9,                   //14dbm
  0x09F6,                   //11dbm 
};

 /*
 const u8 RFM96SpreadFactorTbl[7] =
{
  6,7,8,9,10,11,12
   
}; */

static const u8 RFM96SpreadFactorTbl[6] =
{
  7,8,9,10,11,12
};//由于6扩频因子档位只能是固定数据包长所以去掉6扩频因子档位

 static const u8 RFM96LoRaBwTbl[10] =
{// 0        1     2       3      4       5         6      7       8      9
//7.8KHz,10.4KHz,15.6KHz,20.8KHz,31.2KHz,41.7KHz,62.5KHz,125KHz,250KHz,500KHz
  0,1,2,3,4,5,6,7,8,9
};


extern void bsp_DelayMS(uint32_t n);
extern void bsp_DelayUS(uint32_t n);

/**********************************************************
**Name:     SPICmd8bit
**Function: SPI Write one byte
**Input:    WrPara
**Output:   none
**note:     use for burst mode
**********************************************************/
u8 SPICmd8bit(u8 WrPara)
{
   	/* Loop while DR register in not emplty */
  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

  /* Send byte through the SPI1 peripheral */
  SPI_I2S_SendData(SPI1, WrPara);

  /* Wait to receive a byte */
  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);

  /* Return the byte read from the SPI bus */
  return SPI_I2S_ReceiveData(SPI1);	
	

}

/**********************************************************
**Name:     SPIRead8bit
**Function: SPI Read one byte
**Input:    None
**Output:   result byte
**Note:     use for burst mode
**********************************************************/

//u8 SPIRead8bit(void)
//{
//   return SPICmd8bit(0XFF);
//}

/**********************************************************
**Name:     SPIRead
**Function: SPI Read CMD
**Input:    adr -> address for read
**Output:   None
**********************************************************/

u8 SPIRead(u8 adr)
{
  static u8 tmp; 

   

  RF_CS_Low;//NSS_Low;
  bsp_DelayUS(1);

  SPICmd8bit(adr&0x7f);                                        //Send address first
  tmp = SPICmd8bit(0XFF);  
 //  printf("读addr:%02x  val:%02x\n",adr,tmp);
	bsp_DelayUS(1);
  RF_CS_High;//NSS_High; 
  return(tmp);
}


/**********************************************************
**Name:     SPIWrite
**Function: SPI Write CMD
**Input:    WrPara -> address & data
**Output:   None
**********************************************************/

void SPIWrite(u16 WrPara)                
{                                                       
  
  
  WrPara |= 0x8000;                                        //MSB must be "1" for write 
//  printf("写addr:%02x  val:%02x\n",WrPara>>8,(u8)WrPara);
   RF_CS_Low;//NSS_Low;
 
  bsp_DelayUS(1);	
  SPICmd8bit(WrPara>>8);//	15->0
  SPICmd8bit((u8)WrPara);	
  bsp_DelayUS(1);	
  RF_CS_High;//NSS_High; 
 
}


/**********************************************************
**Name:     SPIBurstRead
**Function: SPI burst read mode
**Input:    adr-----address for read
**          ptr-----data buffer point for read
**          length--how many bytes for read
**Output:   None
**********************************************************/
void SPIBurstRead(u8 adr, u8 *ptr, u8 length)
{
  static u8 i;
  if(length<=1)                                            //length must more than one
    return;
  else
  {	 
    RF_CS_Low;
	bsp_DelayUS(1);	
    SPICmd8bit(adr&0x7f); 

    for(i=0;i<length;i++)
		{
      ptr[i] = SPICmd8bit(0xff);
			bsp_DelayUS(1);
		}
    bsp_DelayUS(1);	
    RF_CS_High;//NSS_High;
  }
}

/**********************************************************
**Name:     SPIBurstWrite
**Function: SPI burst write mode
**Input:    adr-----address for write
**          ptr-----data buffer point for write
**          length--how many bytes for write
**Output:   none
**********************************************************/
void BurstWrite(u8 adr, u8 *ptr, u8 length)
{ 
 static u8 i;
 
    RF_CS_Low;//NSS_Low; 
    bsp_DelayUS(1);	
    SPICmd8bit(adr|0x80);
    for(i=0;i<length;i++)
	   {
    	SPICmd8bit(*(ptr+i));
		//	 printf("%d",*(ptr+i));
		 }
	   bsp_DelayUS(1);
    RF_CS_High;//NSS_High;
  
}


/**********************************************************
**Name:     RFM96_Config
**Function: RFM96 base config
**Input:    mode
**Output:   None
**********************************************************/
unsigned char RFM96_Config(u8 mode)
{
unsigned char i,tmp=0,Sx1276VerNO=0; 
   //必须进入休眠状态 
   SPIWrite(LR_RegOpMode+0x08);                                          //Change modem mode Must in Sleep mode 
		bsp_DelayUS(20);
   SPIWrite(LR_RegOpMode+0x88);
   // SPIWrite(0x5904);   //?? Change digital regulator form 1.6V to 1.47V: see errata note
	 Sx1276VerNO=SPIRead((u8)(REG_LR_VERSION>>8)); //获取SX1276 版本号 是0X11(V1A版本 工程版) 或者是 0X12(V1B 正式版)
	 //printf("\r\nsx1278(V12) v:%02X\r\n",Sx1276VerNO);
	if(Sx1276VerNO!=0xff||Sx1276VerNO!=0)
	{
		 GPIO_ResetBits(GPIOA,  GPIO_Pin_5);	
				bsp_DelayUS(1000);
		 GPIO_SetBits(GPIOA,  GPIO_Pin_5);	
	}
	
	//	 SPIWrite(RFM96FreqTbl[0]); 
	//	 Sx1276VerNO=SPIRead((u8)(RFM96FreqTbl[0]>>8));
	//   printf("RFM96FreqTbl[0](0X06_6C) R:0x%02X",Sx1276VerNO);

    for(i=0;i<3;i++)                                       //setting frequency parameter
    {
      SPIWrite(RFM96FreqTbl[i]);  
    }
    //setting base parameter 
    SPIWrite(RFM96PowerTbl[0]);             //Setting output power parameter      
    SPIWrite(LR_RegOcp+0x0B);                              //RegOcp,Close Ocp
    SPIWrite(LR_RegLna+0x23);                              //RegLNA,High & LNA Enable
    
    if(RFM96SpreadFactorTbl[gb_SF]==6)           //SFactor=6
    {									
      SPIWrite(LR_RegModemConfig1+(RFM96LoRaBwTbl[gb_BW]<<4)+(CR<<1)+0x01);//带宽设置,包结构,Implicit Enable CRC Enable(0x02) & Error Coding rate 4/5(0x01), 4/6(0x02), 4/7(0x03), 4/8(0x04)
      SPIWrite(LR_RegModemConfig2+(RFM96SpreadFactorTbl[gb_SF]<<4)+(CRC_EN<<2)+0x03);      
      tmp = SPIRead(0x31);
      tmp &= 0xF8;
      tmp |= 0x05;
      SPIWrite(0x3100+tmp);
      SPIWrite(0x3700+0x0C);
    } 
    else
    {
      SPIWrite(LR_RegModemConfig1+(RFM96LoRaBwTbl[gb_BW]<<4)+(CR<<1)+0x00);//Explicit Enable CRC Enable(0x02) & Error Coding rate 4/5(0x01), 4/6(0x02), 4/7(0x03), 4/8(0x04)
      SPIWrite(LR_RegModemConfig2+(RFM96SpreadFactorTbl[gb_SF]<<4)+(CRC_EN<<2)+0x03);  //SFactor &  LNA gain set by the internal AGC loop 
    }


//	SPIWrite(LR_RegModemConfig1+0x36); //BW=3 20.8KHz , CR=3 4/7, explit
//	SPIWrite(LR_RegModemConfig2+0x77); //SF=6, CRC on


    SPIWrite(LR_RegSymbTimeoutLsb+0xFF);                   //RegSymbTimeoutLsb Timeout = 0x3FF(Max) 
    
    SPIWrite(LR_RegPreambleMsb + 0);                       //RegPreambleMsb 
    SPIWrite(LR_RegPreambleLsb + 12);                      //RegPreambleLsb 8+4=12byte Preamble
    
    SPIWrite(REG_LR_DIOMAPPING2+0x01);                     //RegDioMapping2 DIO5=00, DIO4=01
    SPIWrite(LR_RegOpMode+0x09);  												//Entry standby mode
		
		return Sx1276VerNO;		
}


/**********************************************************
**Name:     RFM96_LoRaEntryRx
**Function: Entry Rx mode
**Input:    None
**Output:   None
**********************************************************/
void RFM96_LoRaEntryRx(void)
{
	unsigned char addr; 
        
  RFM96_Config(0);                                         //setting base parameter
  
  SPIWrite(0x4D00+0x84);                                   //Normal and Rx
  SPIWrite(LR_RegHopPeriod+0xFF);                          //RegHopPeriod NO FHSS
  SPIWrite(REG_LR_DIOMAPPING1+0x01);                       //DIO0=00, DIO1=00, DIO2=00, DIO3=01  DIO0=00--RXDONE
      
  SPIWrite(LR_RegIrqFlagsMask+0x3F);                       //Open RxDone interrupt & Timeout
 // RFM96_LoRaClearIrq(); 换成 SPIWrite(LR_RegIrqFlags+0xFF);	
  SPIWrite(LR_RegIrqFlags+0xFF);	
  
  //TODO
  SPIWrite(LR_RegPayloadLength+21);                       //RegPayloadLength  21byte(this register must difine when the data long of one byte in SF is 6)
    
  addr = SPIRead((u8)(LR_RegFifoRxBaseAddr>>8));           //Read RxBaseAddr
  SPIWrite(LR_RegFifoAddrPtr+addr);                        //RxBaseAddr -> FiFoAddrPtr  
  SPIWrite(LR_RegOpMode+0x0D);                        //Continuous Rx Mode
  
}

/**********************************************************
**Name:     RFM96_LoRaRxPacket
**Function: Receive data in LoRa mode
**Input:    None
**Output:   1- Success
            0- Fail
**********************************************************/
u8 RFM96_LoRaRxPacket(u8 *buf)
{
unsigned char packet_size,addr;

	for(addr=0;addr<32;addr++) //清Buffer
		buf[addr] = 0x00;

	addr = SPIRead((u8)(LR_RegFifoRxCurrentaddr>>8));      //last packet addr 数据包的最后地址(数据的尾地址)
	SPIWrite(LR_RegFifoAddrPtr+addr);                      //RxBaseAddr -> FiFoAddrPtr   
	bsp_DelayMS(1);

	if(RFM96SpreadFactorTbl[gb_SF]==6)           //When SpreadFactor is six,will used Implicit Header mode(Excluding internal packet length)
		packet_size=21;
	else
		packet_size = SPIRead((u8)(LR_RegRxNbBytes>>8));     //Number for received bytes    

	SPIBurstRead(0x00, buf, packet_size);

	SPIWrite(LR_RegIrqFlags+0xFF);	
	bsp_DelayUS(1);
	 return packet_size;
}


/**********************************************************
**Name:     RFM96_LoRaEntryTx
**Function: Entry Tx mode
**Input:    None
**Output:   None
**********************************************************/
u8 RFM96_LoRaEntryTx(u8 packet_length)
{
unsigned char addr;
unsigned char SysTime = 0;
unsigned char temp;

		RFM96_Config(0);                                         //模块发射参数设置
		bsp_DelayUS(10);
		SPIWrite(0x4D00+0x87);                                   //发射功率 for 20dBm
		SPIWrite(LR_RegHopPeriod);                               //RegHopPeriod NO FHSS
		SPIWrite(REG_LR_DIOMAPPING1+0x41);                       //DIO0=01, DIO1=00, DIO2=00, DIO3=01

		SPIWrite(LR_RegIrqFlags+0xFF);	
		SPIWrite(LR_RegIrqFlagsMask+0xF7);                       //Open TxDone interrupt
		SPIWrite(LR_RegPayloadLength+packet_length);                       //RegPayloadLength  21byte负载和fifo的字节数的关系是什么??

		addr = SPIRead((u8)(LR_RegFifoTxBaseAddr>>8));           //RegFiFoTxBaseAddr
		SPIWrite(LR_RegFifoAddrPtr+addr);                        //RegFifoAddrPtr
		
	for(SysTime=0;SysTime<3;SysTime++)
	{
		temp=SPIRead((u8)(LR_RegPayloadLength>>8) );
		if(temp==packet_length)
		{
			return 	packet_length;
		}
			bsp_DelayUS(100);	
	}
	return 	0;	
}

/**********************************************************
**Name:     RFM96_LoRaTxPacket
**Function: Send data in LoRa mode
**Input:    None
**Output:   1- Send over
**********************************************************/
u8 RFM96_LoRaTxPacket(u8 *buf,u8 len)
{ 
		u8 i=0;
		BurstWrite(0x00, (u8 *)buf, len); 

	  for(i=0;i<len;i++)	bsp_DelayMS(30);
		SPIWrite(LR_RegOpMode+0x8b);                    //Tx Mode       
		//Packet send over 发送完成了IRQ 变为H,平时L
		for(i=0;i<100;i++)
		{
			if(RF_NIRQ)                      //Packet send over
			 {      
				SPIRead((u8)(LR_RegIrqFlags>>8));
				SPIWrite(LR_RegIrqFlags+0xFF);                               //Clear irq
				SPIWrite(LR_RegOpMode+0x09);                            //Entry Standby mode     			
				return 1;
			 }
			 bsp_DelayMS(30);
		}
		// printf("\r\n RF发送失败.\r\n");
		return 0;
}


unsigned char SX1278_Init(void)
{
	 unsigned char flag;
	
	 RF_SDN_Low; 
	 bsp_DelayUS(600);
   RF_SDN_High; 
	 bsp_DelayUS(600);
	
	flag = RFM96_Config(0);     //初始化模块
	RFM96_LoRaEntryRx(); //设置接收模式
	
	return flag;
}

unsigned char SX1278_TXD(u8 *buf, u8 size)
{
	unsigned char flag;
	
	RFM96_LoRaEntryTx(size);  //进入网络模式
	flag = RFM96_LoRaTxPacket(buf,size);	 //在LoRa模式下发送
	bsp_DelayUS(20);
	RFM96_LoRaEntryRx();   //接收模式
	
	return flag;
}

unsigned char SX1278_RXD(unsigned char *Data)
{
unsigned char length = 0;
	if ( RF_NIRQ==1) //收到数据高电平中断

	{
 	 	length=RFM96_LoRaRxPacket(Data);  //在LoRa模式下接收数据
		RFM96_LoRaEntryRx();       //接收模式
   return(length);
	}
	return  0;
}

 

  • 8
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值