LORA芯片的SX1278的SPI接口中CPOL=0和CPHA=0相对应的同步全双工协议从SPI接
口访问配置寄存器。仅在从机(slave)进行
有三种访问寄存器的方式:
单访问:写访问时发送地址字节之后紧跟数据字节,读访问时地址字节之后紧跟读取字
节。NSS引脚在帧的起点拉低,并只在最后一个数据字节后才拉高。
突发访问:地址字节之后跟有多个数据字节。该地址在各数据字节间自动内部递增。这
一模式在进行读访问和写访问时都是可用的。NSS引脚在帧的起点拉低并在各字节间
一直保持低位,仅在最后一个字节传输完后才拉高。
FIFO访问:如果地址字节与FIFO的地址一致,随后的数据字节将寻址FIFO。这一地址
不会自动递增,但会被记住,同时也不需要在各数据字节之间进行发送。NSS引脚在
帧的起点拉低并在各字节间一直保持低位,仅在最后一个字节传输完后才拉高
下图显示了对寄存器的典型SPI单次访问。
SPI时序图
MOSI在SCK下降沿由主机生成,并由SCK上升沿的从机(即SPI接口)进行抽样。MISO在
SCK下降沿由从机生成。
传输始终由变低的NSS引脚启动。当NSS较高时,MISO处在高阻抗状态。
第一个字节为地址字节,包括:
一个wnr位,写访问时为1,读访问时为0;
地址的7个位,首先为最高有效位。
无论是写访问中MOSI 主机发送的第二个字节还是读访问中MISO 主机接收的第二个字节
都是数据字节。该数据字节首先发送的是最高有效位。
进程中的字节可能通过MOSI(写访问)发送或MISO(读访问)接收,无需NSS 上升沿,
也无需重新发送地址。在FIFO 模式下,如果地址为FIFO 地址,这些字节将在FIFO 地址
中进行写/读。在突发模式下,如果地址不是FIFO 地址,该地址将在每收到一个新字节时
自动递增。
当NSS 变高时,帧结束。下一帧必须以一个地址字节开始。因此,单次访问模式是FIFO/
突发模式只有一个数据字节转移的一种特殊情况。
在写访问中,MISO 线路中由从机传输到主机的字节为写操作前被写入寄存器的值。
#include
#include #include "stm32f10x.h"
#include "sx1276-Hal.h"void SpiInit( void );
uint8_t SpiInOut( uint8_t outData );void SX1276InitIo( void )
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_AFIO, ENABLE );GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;// Configure NSS as outputGPIO_WriteBit( NSS_IOPORT, NSS_PIN, Bit_SET );GPIO_InitStructure.GPIO_Pin = NSS_PIN;GPIO_Init( NSS_IOPORT, &GPIO_InitStructure );// Configure radio DIO as inputsGPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;// Configure DIO0GPIO_InitStructure.GPIO_Pin = DIO0_PIN;GPIO_Init( DIO0_IOPORT, &GPIO_InitStructure );// Configure DIO1GPIO_InitStructure.GPIO_Pin = DIO1_PIN;GPIO_Init( DIO1_IOPORT, &GPIO_InitStructure );// Configure DIO2GPIO_InitStructure.GPIO_Pin = DIO2_PIN;GPIO_Init( DIO2_IOPORT, &GPIO_InitStructure );// Configure DIO3GPIO_InitStructure.GPIO_Pin = DIO3_PIN;GPIO_Init( DIO3_IOPORT, &GPIO_InitStructure );// Configure DIO4GPIO_InitStructure.GPIO_Pin = DIO4_PIN;GPIO_Init( DIO4_IOPORT, &GPIO_InitStructure );// Configure DIO5GPIO_InitStructure.GPIO_Pin = DIO5_PIN;GPIO_Init( DIO5_IOPORT, &GPIO_InitStructure );GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin = RESET_PIN;GPIO_Init( RESET_IOPORT, &GPIO_InitStructure );//SX1278 PA CONTROLGPIO_InitStructure.GPIO_Pin = TR_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(TR_IOPORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = PAEN_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(PAEN_IOPORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = PABYP_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(PABYP_IOPORT, &GPIO_InitStructure);GPIO_WriteBit( RESET_IOPORT, RESET_PIN, Bit_RESET );
}void SX1276Write(uint8_t addr, uint8_t data )
{//NSS = 0;NSS_IOPORT->BRR = NSS_PIN;SpiInOut( addr | 0x80 );SpiInOut( data);//NSS = 1;NSS_IOPORT->BSRR = NSS_PIN;
}void SX1276Read(uint8_t addr, uint8_t *data )
{//NSS = 0;NSS_IOPORT->BRR = NSS_PIN;SpiInOut( addr & 0x7F );*data = SpiInOut( 0 );//NSS = 1;NSS_IOPORT->BSRR = NSS_PIN;}void SX1276WriteBuffer( uint8_t addr, uint8_t *buffer, uint8_t size )
{uint8_t i;//NSS = 0;NSS_IOPORT->BRR = NSS_PIN;SpiInOut( addr | 0x80 );for( i = 0; i < size; i++ ){SpiInOut( buffer[i] );}//NSS = 1;NSS_IOPORT->BSRR = NSS_PIN;
}void SX1276ReadBuffer( uint8_t addr, uint8_t *buffer, uint8_t size )
{uint8_t i;//NSS = 0;NSS_IOPORT->BRR = NSS_PIN;SpiInOut( addr & 0x7F );for( i = 0; i < size; i++ ){buffer[i] = SpiInOut( 0 );}//NSS = 1;NSS_IOPORT->BSRR = NSS_PIN;
}void SX1276WriteRxTx( uint8_t txEnable )
{if( txEnable != 0 ){PAEN_IOPORT->BSRR = PAEN_PIN;PABYP_IOPORT->BRR = PABYP_PIN; // PABYP_IOPORT->BSRR = PABYP_PIN; TR_IOPORT->BSRR = TR_PIN;}else{//set RX modePAEN_IOPORT->BSRR = PAEN_PIN;PABYP_IOPORT->BRR = PABYP_PIN; // PABYP_IOPORT->BSRR = PABYP_PIN; TR_IOPORT->BRR = TR_PIN;}
}//#define SPI_SIMULATION#define SPI_INTERFACE SPI2
#define SPI_CLK RCC_APB1Periph_SPI2#define SPI_PIN_SCK_PORT GPIOB
#define SPI_PIN_SCK_PORT_CLK RCC_APB2Periph_GPIOB
#define SPI_PIN_SCK GPIO_Pin_13#define SPI_PIN_MISO_PORT GPIOB
#define SPI_PIN_MISO_PORT_CLK RCC_APB2Periph_GPIOB
#define SPI_PIN_MISO GPIO_Pin_14#define SPI_PIN_MOSI_PORT GPIOB
#define SPI_PIN_MOSI_PORT_CLK RCC_APB2Periph_GPIOB
#define SPI_PIN_MOSI GPIO_Pin_15void SpiInit( void )
{SPI_InitTypeDef SPI_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;/* Enable peripheral clocks --------------------------------------------------*//* Enable SPIy clock and GPIO clock for SPIy */RCC_APB2PeriphClockCmd( SPI_PIN_MISO_PORT_CLK | SPI_PIN_MOSI_PORT_CLK |SPI_PIN_SCK_PORT_CLK, ENABLE );RCC_APB1PeriphClockCmd( SPI_CLK, ENABLE );#ifdef SPI_SIMULATION//tian change/* GPIO configuration ------------------------------------------------------*/GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin = SPI_PIN_SCK;GPIO_Init( SPI_PIN_SCK_PORT, &GPIO_InitStructure );GPIO_InitStructure.GPIO_Pin = SPI_PIN_MOSI;GPIO_Init( SPI_PIN_MOSI_PORT, &GPIO_InitStructure );GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = SPI_PIN_MISO;GPIO_Init( SPI_PIN_MISO_PORT, &GPIO_InitStructure );//end
#else/* GPIO configuration ------------------------------------------------------*/GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = SPI_PIN_SCK;GPIO_Init( SPI_PIN_SCK_PORT, &GPIO_InitStructure );GPIO_InitStructure.GPIO_Pin = SPI_PIN_MOSI;GPIO_Init( SPI_PIN_MOSI_PORT, &GPIO_InitStructure );GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = SPI_PIN_MISO;GPIO_Init( SPI_PIN_MISO_PORT, &GPIO_InitStructure );// RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO, ENABLE );/* SPI_INTERFACE Config -------------------------------------------------------------*/SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;SPI_InitStructure.SPI_Mode = SPI_Mode_Master;SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;// SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; // 5 MHzSPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; // 2.25 MHzSPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;SPI_InitStructure.SPI_CRCPolynomial = 7;SPI_Init( SPI_INTERFACE, &SPI_InitStructure );SPI_Cmd( SPI_INTERFACE, ENABLE );#endif}
#define SPI_DELAY(x) delay(100*x)
#define NOP(x) delay(2)
void delay(unsigned short t)
{while(t--);
}uint8_t SpiInOut( uint8_t outData )
{/* Send SPIy data */
#ifdef SPI_SIMULATIONuint8_t i,SdoData=0x00;for(i = 0; i < 8; i++){SPI_DELAY(20);GPIO_WriteBit(SPI_PIN_SCK_PORT,SPI_PIN_SCK,Bit_RESET);if(outData & 0x80)GPIO_WriteBit(SPI_PIN_MOSI_PORT,SPI_PIN_MOSI,Bit_SET);elseGPIO_WriteBit(SPI_PIN_MOSI_PORT,SPI_PIN_MOSI,Bit_RESET);SPI_DELAY(20);outData <<= 1;SdoData<<=1;//SPI_CLK = LOW;if(GPIO_ReadInputDataBit(SPI_PIN_MISO_PORT,SPI_PIN_MISO) == Bit_SET){SdoData |= 0x01;}else{SdoData &= 0xfe;}SPI_DELAY(20); GPIO_WriteBit(SPI_PIN_SCK_PORT,SPI_PIN_SCK,Bit_SET);}SPI_DELAY(20); GPIO_WriteBit(SPI_PIN_SCK_PORT,SPI_PIN_SCK,Bit_RESET);return SdoData;
#elseSPI_I2S_SendData( SPI_INTERFACE, outData );
//DBUG("%02x\r\n",outData);while( SPI_I2S_GetFlagStatus( SPI_INTERFACE, SPI_I2S_FLAG_RXNE ) == RESET );return SPI_I2S_ReceiveData( SPI_INTERFACE );
#endif
}
上一篇:推荐算法 - 汇总