STC8H hardware SPI control LORA SX1268 realizes simple transceiver function

After researching for several days, I just started to treat the operation code as an address. It was so funny. I adjusted it for several days and found that it didn’t work. I found it yesterday, and then after adjusting it for a long time, it still didn’t work. Today I found something called a status code.

Then I found out from the status code that I didn’t configure interrupts and the like. Later I found out that the data was sent too fast, which made me laugh. Now I just added a 10MS delay. If you encounter problems, you can check the status first. Is there a code? Then according to the configuration in the data sheet, it is as follows

Manual configuration sequence

TX

1. Set to RC mode 0x80 0x00

2. Defined as LORA protocol 0x8A 0x01

3. Configure RF frequency 0x86 (image calibration needs to be configured before configuring frequency) 0x98

4. Power amplifier configuration 0x95

5. Output power and unknown time 0x8E

6. Configure cache base address 0x8F

7. Write data to the buffer. You should be able to write 0x1E later.

8. Air rate parameters such as spreading factor 0x8B

9. Packet parameters such as maximum packet length 0x8C

10. Configure DIO and IRQ

11. Sync Word reference 13-55 (optional)

12. Turn on the sending status. The three digits following 0x83 are the timeout time.

13. Waiting for transmission or timeout, the data packet is sent out and the chip automatically enters RC mode.

14. Clear the interrupt flag of TxDone

RX

1. Set to RC mode 0x80 0x00

2. Defined as LORA protocol 0x8A 0x01

3. Configure RF frequency 0x86 (image calibration needs to be configured before configuring frequency) 0x98

4. Configure the cache base address 0x8F

5. Air rate parameters such as spreading factor 0x8B

6. Data packet format 0x8C

7. Configure DIO and IRQ

8. Sync Word reference 13-55 (optional)

9. Turn on the receiving state. The three digits following 0x82 are the timeout time.

Project code

The following is the code I wrote while groping, so many useless modules were not deleted but commented directly. You can refer to it. If your LORA module is connected to the hardware SPI, you can use it directly.

#include "reg51.h"
#include "intrins.h"
#include <stdlib.h>

sfr P_SW1 = 0xa2;

sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xc9;
sfr P5M0 = 0xca;

sfr SPSTAT = 0xcd;
sfr SPCTL = 0xce;
sfr SPDAT = 0xcf;
#defineESPI 0x02

sbit CS = P2^6;
sbit RES = P2^1;
sbit BUSY = P2^0;


sfr S2CON = 0x9A;
sfr T2L = 0xD7;
sfr T2H = 0xD6;
sfr S2BUF = 0x9B;
sfr IE2 = 0xAF;


extern const int RX_buffer_MAX;
extern volatile unsigned int Time0_count;
volatile unsigned int rx2_count = 0;
volatile unsigned int tx2_count = 0;
volatile unsigned int t2_busy = 0;
volatile unsigned int r2_busy = 0;
volatile unsigned int RX2_Timeout = 0;
volatile unsigned char rx2_buffer[128];
volatile unsigned char rxLoraBuffer[128];

void UART2_Isr(void) interrupt 8
{
// IE2 & amp;= ~1;
if (S2CON & 0x02)
  {
    S2CON & amp;= ~0x02; //Clear the interrupt flag
    t2_busy = 0;
tx2_count + + ;
  }
  if (S2CON & 0x01)
  {
r2_busy = 0;
    S2CON & amp;= ~0x01; //Clear the interrupt flag
    if(rx2_count < RX_buffer_MAX) //Receive data when less than the maximum reception
{
rx2_buffer[rx2_count + + ] = S2BUF;
}
RX2_Timeout = Time0_count + 10; //The delay is 50MS when there is data input
if(RX2_Timeout>1000)
{
RX2_Timeout-=1000; //Afraid of the counter exceeding the range, it will become 1 every time it reaches 1000, so it must be reduced here too
}
  }
// IE2 |= 1; //Enable interrupts
}

void Uart2Init(void) //[email protected]
{
P1M0 = 0x04;
P1M1 = 0x00;
S2CON = 0x50; //8-bit data, variable baud rate
AUXR |= 0x04; //Timer clock 1T mode
T2L = 0xE0; //Set the timing initial value
T2H = 0xFE; //Set the timing initial value
AUXR |= 0x10; //Timer 2 starts timing
IE2 |= 1; //Allow interrupts
EA = 1;
}

void print(unsigned char * dat)
{
while(*dat)
{
S2BUF = *dat;
t2_busy = 1;
while(t2_busy==1);
dat + + ;
}
}

void print_char(unsigned char dat)
{
S2BUF = dat;
t2_busy=1;
while(t2_busy==1);
}

void print_int(long dat)
{
unsigned char storage[15];
int count = 0;
\t
if(dat<0)
{
print_char('-');
dat =~dat;
dat + = 1;
}
if(dat == 0)
{
print_char('0');
}
else
{
\t\t
while(dat)
{
storage[count + +] = dat % 10;
dat /= 10;
}
while(count--)
{
print_char(storage[count] + 48);
}
}
}

void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;

_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}

void Delay10us() //@11.0592MHz
{
unsigned char i, j;

i = 18;
j = 235;
do
{
while (--j);
} while (--i);
}


unsigned char Spi_WrByte(unsigned char dat)
{
SPDAT = dat; //Send test data
  while (!(SPSTAT & amp; 0x80)); //Query completion flag
  SPSTAT = 0xc0; //Clear interrupt flag
return SPDAT;
\t
}


/*
Function: Write register data
Parameters:
addres - register address
  dat - the data to write
\treturn:
SPDAT - status code received
*/
unsigned char Spi_IntWrChar(unsigned int addres,unsigned char dat)
{
int count = 0;
CS = 0;
Spi_WrByte(0x0D);
Spi_WrByte((unsigned char)(((addres & amp;0xFF00)>8)));
Spi_WrByte((unsigned char)(addres & amp;0x00FF));
Spi_WrByte(dat);
CS = 1;
return SPDAT;
}

/*
Function: Write command data
Parameters:
addres - opcode
  dat - the data to write
\treturn:
SPDAT - status code received
*/
unsigned char Spi_WrChar(unsigned char addres,unsigned char dat)
{
int count = 0;
CS = 0;
//Spi_WrByte(0x0D);
//Spi_WrByte((unsigned char)(((addres & amp;0xFF00)>8)));
Spi_WrByte(addres);
Spi_WrByte(dat);
CS = 1;
if((SPDAT & 0x0F)== 0x08)
{
print_char(0xFF);
print_char(addres);
print_char(SPDAT);
}
return SPDAT;
}


/*
Function: Write multi-bit command data
Parameters:
addres - opcode
  dat - the data to write
com_size - send length
\treturn:
SPDAT - status code received
*/
unsigned char Spi_WrData(unsigned char addres,unsigned char * dat,int com_size)
{
int count = 0;
CS = 0;
//Spi_WrByte(0x0D);
//Spi_WrByte((unsigned char)(((addres & amp;0xFF00)>8)));
Spi_WrByte(addres);
for(count=0;count<com_size;count + + )
{
Delay10us();
Spi_WrByte(dat[count]);
\t\t
\t\t
\t\t
// if((SPDAT & amp; 0x0F)== 0x08)
// {
// print_char(0xFF);
// print_char(addres);
// print_char(SPDAT);
// }
// if(addres == 0x08)
// {
// print_char(0x99);
// print_char(count);
// print_char(SPDAT);
// }
}
CS = 1;
return SPDAT;
}


/*
Function: Read lora register data
Parameters:
addresses - addresses
\treturn:
dat - the data read
*/
unsigned char Spi_IntReChar(unsigned int addres)
{
int count = 0;
unsigned char dat;
CS = 0;
Spi_WrByte(0x1D);
Spi_WrByte((unsigned char)(((addres & amp;0xFF00)>8)));
Spi_WrByte((unsigned char)(addres & amp;0xFF));
Spi_WrByte(0x00);
dat = Spi_WrByte(0xFF);
CS = 1;
return dat;
}


/*
Function: Collect single lora data
Parameters:
addres - opcode
\treturn:
dat - the data received
*/
unsigned char Spi_ReChar(unsigned char addres)
{
int count = 0;
unsigned char dat;
CS = 0;
Spi_WrByte(addres);
Spi_WrByte(0xFF);
dat = Spi_WrByte(0xFF);
CS = 1;
return dat;
}

/*
Function: Collect lora multi-bit data
Parameters:
addres - opcode
dat_size - collection length
\treturn:
dat - the received array
*/
unsigned char * Spi_ReData(unsigned char addres,int dat_size)
{
int count = 0;
static unsigned char dat[10];
CS = 0;
//Spi_WrByte(0x1D);
//Spi_WrByte((unsigned char)(((addres & amp;0xFF00)>8)));
Spi_WrByte(addres);
Spi_WrByte(0xFF);
for(count=0;count<dat_size;count + + )
{
dat[count] = Spi_WrByte(0xFF);
}
CS = 1;
return dat;
}

/*
Function: Configure the sending and receiving frequency of LORA device
Parameters:
RF - Decimal frequency
Return: None
*/
void SX126xSetRfFrequency(unsigned long RF) //Frequency
{
unsigned char buf[4];
unsigned long freq = 0;
unsigned long stepsInt = 0;
unsigned long SX126X_PLL_STEP_SCALED = (32000000>>(25-14));
unsigned int SX126X_PLL_STEP_SHIFT_AMOUNT = 14;
stepsInt = RF/SX126X_PLL_STEP_SCALED;
freq = RF - (stepsInt * SX126X_PLL_STEP_SCALED);
freq = ( stepsInt << SX126X_PLL_STEP_SHIFT_AMOUNT ) + // shift 14
           ( ( ( freq << SX126X_PLL_STEP_SHIFT_AMOUNT ) + ( SX126X_PLL_STEP_SCALED >> 1 ) ) /
             SX126X_PLL_STEP_SCALED );
buf[0] = (unsigned char)((freq>>24) & amp;0xff);
buf[1] = (unsigned char)((freq>>16) & amp;0xff);
buf[2] = (unsigned char)((freq>>8) & amp;0xff);
buf[3] = (unsigned char)((freq) & amp;0xff);
Spi_WrData(0x86,buf,4);
}


void SPI_Init(void)
{
P1M0 = 0x00;
P1M1 = 0x00;
P_SW1 = 0x00;
    SPCTL = 0xD0; //Enable SPI host mode
    SPSTAT = 0xc0; //Clear the interrupt flag
}

void lora_Tx_Init(void)
{
unsigned char loraData[10];
Spi_WrChar(0x80,0x00);//Configure for RC mode
Spi_WrChar(0x9D,0x01);//Configure DIO2 in TX mode
Spi_WrChar(0x96,0x01);//Configure for TX and RX mode
Spi_WrChar(0x8A,0x01);//Start lora mode
loraData[0] = 0x75;
loraData[1] = 0x81;
Spi_WrData(0x98, loraData,2); //You need to configure this before frequency configuration, I don’t know what it is //There is a problem
// print_char(0x74);
// print_char(Spi_ReChar(0xc0));
SX126xSetRfFrequency(470000000); //Configure frequency
loraData[0] = 0x04;
loraData[1] = 0x07;
loraData[2] = 0x00;
loraData[3] = 0x01;
Spi_WrData(0x95, loraData,4); //Configure duty cycle power parameters, etc. The last two digits are reserved parameters and cannot be modified. Here, the configuration is 22dBm
loraData[0] = 20;
loraData[1] = 0x02;
Spi_WrData(0x8E, loraData,2);//Configure transmit power and don’t know when
loraData[0] = 0x00;
loraData[1] = 0x00;
Spi_WrData(0x8F,loraData,2);//Configure the sending and receiving storage address
\t
//The data is sent to the temporary storage area. This should be discussed later?
loraData[0] = 0x07;
loraData[1] = 0x0A;
loraData[2] = 0x01;
loraData[3] = 0x00;
Spi_WrData(0x8B, loraData,4);//Configure the spreading factor to 7, the bandwidth to 41, the error correction code to 4/5, and turn off low-rate optimization, so the air rate is configured to 1820
loraData[0] = 0x00;
loraData[1] = 0x08; //Preamble length
loraData[2] = 0x00;//Variable data packet length
loraData[3] = 0xFF;//Maximum packet length 255
loraData[4] = 0x01;//Turn off CRC check
loraData[5] = 0x00;//Standard IQ settings
Spi_WrData(0x8C,loraData,6);//Configure the maximum packet length and other data packet parameters
loraData[0] = 0xFF;
loraData[1] = 0xFF;
loraData[2] = 0xFF;
loraData[3] = 0xFF;
loraData[4] = 0x00;
loraData[5] = 0x00;
loraData[6] = 0x00;
loraData[7] = 0x00;
Spi_WrData(0x08,loraData,8);//Configure DIO and IRQ
// print_char(0x81);
// print_char(Spi_ReChar(0xc0));
}

void lora_Rx_Init(void)
{
unsigned char loraData[10];
Spi_WrChar(0x80,0x00);//Configure for RC mode
Spi_WrChar(0x9D,0x00);//Configure DIO2 in RX mode
Spi_WrChar(0x96,0x01);//Configure for TX and RX mode
Spi_WrChar(0x8A,0x01);//Start lora mode
loraData[0] = 0x75;
loraData[1] = 0x81;
Spi_WrData(0x98,loraData,2); //You need to configure this before frequency configuration. I don’t know what it is.
SX126xSetRfFrequency(470000000); //Configure frequency
loraData[0] = 0x00;
loraData[1] = 0x00;
Spi_WrData(0x8F,loraData,2);//Configure the sending and receiving storage address
loraData[0] = 0x07;
loraData[1] = 0x0A;
loraData[2] = 0x01;
loraData[3] = 0x00;
Spi_WrData(0x8B, loraData,4);//Configure the spreading factor to 7, the bandwidth to 41, the error correction code to 4/5, and turn off low-rate optimization, so the air rate is configured to 1820
loraData[0] = 0x00;
loraData[1] = 0x08; //Preamble length
loraData[2] = 0x00;//Variable data packet length
loraData[3] = 0xFF; //Maximum packet length 255
loraData[4] = 0x01;//Turn off CRC check
loraData[5] = 0x00;//Standard IQ settings
Spi_WrData(0x8C,loraData,6);//Configure the maximum packet length and other data packet parameters
loraData[0] = 0xFF;
loraData[1] = 0xFF;
loraData[2] = 0xFF;
loraData[3] = 0xFF;
loraData[4] = 0x00;
loraData[5] = 0x00;
loraData[6] = 0x00;
loraData[7] = 0x00;
Spi_WrData(0x08,loraData,8);//Configure DIO and IRQ
Spi_IntWrChar(0x08D8,Spi_IntReChar(0x08D8)|0x1E);//When the chip is initialized, the first to fourth bits of 0x08D8 need to be configured as 1
Spi_IntWrChar(0x0736,Spi_IntReChar(0x0736)|0x02);//When the chip is initialized, the first to fourth bits of 0x08D8 need to be configured as 1
}
\t
void lora_Init(void)
{
//unsigned char calFreq[10];
//unsigned char loraData[10];
\t
\t
\t
\t
\t
// loraData[0] = 0x00;
// loraData[1] = 0x00;
// Spi_WrChar(0x0080,0x00); //Configured in XOSC mode, but the case is not in this mode and needs to be modified.
// Spi_WrData(0x008F, loraData,2); //Configure sending and receiving addresses
// Spi_WrChar(0x0096,0x01);
// Spi_WrChar(0x0008,0x00);//Mask interrupt
// Spi_WrChar(0x8A,0x01);//Start lora mode
// loraData[0] = 0x34;
// loraData[1] = 0x44;
// Spi_WrData(0x0740, loraData,2); //Configure as public address
//
// loraData[0] = 0x07;
// loraData[1] = 0x0A;
// loraData[2] = 0x01;
// loraData[3] = 0x00;
// Spi_WrData(0x008B, loraData, 4); //Configure the spreading factor to 7, the bandwidth to 41, the error correction code to 4/5, and turn off low-rate optimization, so the air rate is configured to 1820
// loraData[0] = 0x00;
// loraData[1] = 0x01; //Preamble length
// loraData[2] = 0x00; //Variable data packet length
// loraData[3] = 0xFF; //Maximum packet length 255
// loraData[4] = 0x01; //Turn off CRC check
// loraData[5] = 0x00; //Standard IQ settings
// Spi_WrData(0x008C, loraData,6); //Configure the basic parameters of the data packet
// Spi_WrChar(0x08D8,Spi_ReChar(0x08D8)|0x1E);//When the chip is initialized, the first to fourth bits of 0x08D8 need to be configured as 1
// loraData[0] = 0x04;
// loraData[1] = 0x07;
// loraData[2] = 0x00;
// loraData[3] = 0x01;
// Spi_WrData(0x0095, loraData, 4); //Configure duty cycle power parameters, etc. The last two digits are reserved parameters and cannot be modified. Here, the configuration is 22dBm
// loraData[0] = 0x00;
// loraData[1] = 0x04;
// Spi_WrData(0x008E, loraData,2); //Configure transmit power and don’t know when
// calFreq[0] = 0x75;
// calFreq[1] = 0x81;
// Spi_WrData(0x0098,calFreq,2); //You need to configure this before frequency configuration. I don’t know what it is.
// SX126xSetRfFrequency(475200000); //Configure frequency
// Spi_WrChar(0x009F,0x00); //Close the receive timeout when the preamble is received
// Spi_WrChar(0x08E7,0x38); //Circuit protection level is set to 140ma, the lowest is 0x18 60ma
\t
\t
// CS = 0;
// calFreq[0] = 0x75;
// calFreq[1] = 0x81;
// Spi_WrData(0x0098,calFreq,2); //You need to configure this before frequency configuration. I don’t know what it is.
// CS = 1;
// SX126xSetRfFrequency(475200000); //Configure frequency
// loraData[0] = 0x00;
// loraData[0] = 0x00;
// Spi_WrChar(0x08D8, Spi_ReChar( 0x08D8 ) | 0x1E ); // During initialization, it is necessary to give it or add 1E. I don’t know why. It is said in Section 15 of the data manual.
// Spi_WrData(0x008F, loraData,2); //The address bit of RXTX
// SX126xSetPaConfig(0x04, 0x07, 0x00, 0x01);
// Spi_WrChar(0x08E7,0x38); //Circuit protection level is set to 140ma, the lowest is 0x18 60ma
// loraData[0] = 22;
// loraData[1] = 0x00;
// Spi_WrData(0x008E, loraData, 2); //Configure power and don’t know when
}


/*
Function: Write data to FIFO space
Parameters:
dat - array to write to
dataSize - data length
Return: None
*/
void FIFO_Wr(unsigned char * dat,unsigned int dataSize)
{
int count=0;
CS = 0;
Spi_WrByte(0x0E);
Spi_WrByte(0x00);
for(count = 0; count < dataSize; count ++ )
{
Spi_WrByte(dat[count]);
}
CS = 1;
}

/*
Function: Read data into FIFO space
Parameters:
dat - array to store readings
dataSize - data length
Return: None
*/
void FIFO_Re(unsigned char * dat,unsigned int dataSize)
{
int count=0;
CS = 0;
Spi_WrByte(0x1E);
Spi_WrByte(0x00);
Spi_WrByte(0x00);
for(count = 0; count < dataSize; count ++ )
{
dat[count] = Spi_WrByte(0xFF);
}
CS = 1;
}

void main()
{
int a = 0,b = 0,count=0,mode = 0;//mode 0 send 1 receive
unsigned char * dat = NULL;
unsigned long RF_data = 0;
unsigned char loraData[10];
unsigned char RxBuffer[10];
\t
P2M0 = 0x00;
    P2M1 = 0x00;
CS = 1;
    SPI_Init();
// RES = 0;
// Delay1000ms();
// RES = 1;
// Delay1000ms();
Uart2Init();
//lora_Init();
if(mode == 0)
{
lora_Tx_Init();
Spi_IntWrChar(0x0889,Spi_IntReChar(0x0889)|0x02);//Requires configuration before sending
// loraData[0] = 0xff;
// loraData[1] = 0xff;
// loraData[2] = 0xff;
// Spi_WrData(0x0083, loraData,3);
}
else
{
lora_Rx_Init();
// print_char(0x71);
// print_char(Spi_ReChar(0xc0));
loraData[0] = 0xff;
loraData[1] = 0xff;
loraData[2] = 0xff;
Spi_WrData(0x82,loraData,3);//Configure for RX mode
// print_char(0x72);
// print_char(Spi_ReChar(0xc0));
}
    while (1)
{
a + + ;
// print_char(a%2);
// Delay1000ms();
// if(a%2==0)
// {
//
// }
// if(a%2==1)
// {
// CS = 0;
// calFreq[0] = 0x6B;
// calFreq[1] = 0x6F;
// Spi_WrData(0x0098,calFreq,2);
// CS = 1;
// SX126xSetRfFrequency(433000000);
// }
\t\t\t
//Read and write test
// loraData[0] = a%5;
// loraData[1] = a%5 + 5;
// Spi_WrData(0x95,loraData,2);
// dat = Spi_ReData(0x95,2);
// print_char(dat[0]);
// print_char(dat[1]);

dat= Spi_ReData(0x12,2);//Reading interruption situation
\t\t\t
if((dat[1] & 0x01) == 0x01)
{
// print_char(0x66);
// print_char(dat[0]);
// print_char(dat[1]);
Spi_WrData(0x02,dat,3);//Clear interrupt
}
else
{
//print_char(dat[0]);
//print_char(dat[1]);
Spi_WrData(0x02,dat,3);//Clear interrupt
//print_char('\\
');
}
if(mode == 0)
{
loraData[0] = 0x02;//Sending timeout
loraData[1] = 0x01; //Sending completed
loraData[2] = 0x02;
loraData[3] = 0x01;
loraData[4] = 0x00;
loraData[5] = 0x00;
loraData[6] = 0x00;
loraData[7] = 0x00;
Spi_WrData(0x08,loraData,8);//Configure DIO and IRQ
//
// print_char(0x70);
// print_char(Spi_ReChar(0xc0));
\t\t\t\t
loraData[0] = 0x00;
loraData[1] = 0x08; //Preamble length
loraData[2] = 0x00;//Variable data packet length
loraData[3] = 0x03; //The maximum packet length is 255 //Depending on the packet you send, you can send one every 64 bytes
loraData[4] = 0x01;//Turn off CRC check
loraData[5] = 0x00;//Standard IQ settings
Spi_WrData(0x8C,loraData,6);//Configure the maximum packet length and other data packet parameters
\t\t\t\t
loraData[0] = a%2;
loraData[1] = a%3;
loraData[2] = a%4;
FIFO_Wr(loraData,3); //Send data
\t\t\t\t
// print_char(0x71);
// print_char(Spi_ReChar(0xc0));
\t\t\t\t
loraData[0] = 0x00;
loraData[1] = 0x00;
loraData[2] = 0x00;
Spi_WrData(0x83,loraData,3);//Configure for TX mode

\t\t\t\t
\t\t\t\t
Delay1000ms();
Delay1000ms();
Delay1000ms();
Delay1000ms();
Delay1000ms();
FIFO_Re(loraData,3);
print_char(loraData[0]);
print_char(loraData[1]);
print_char(loraData[2]);
Delay1000ms();
Delay1000ms();
Delay1000ms();
Delay1000ms();
Delay1000ms();
}
else
{
if((dat[1] & amp; 0x02) == 0x02)
{
Spi_IntWrChar(0x0902,0x00);
Spi_IntWrChar(0x0944,Spi_IntReChar(0x0944)|0x02);
dat = Spi_ReData(0x13,2);//Read the received packet length and first address
print_char(dat[0]);
print_char(dat[1]);
FIFO_Re(RxBuffer,dat[0]);
for(count=0; count<dat[0]; count + + )
{
print_char(RxBuffer[count]);
}
loraData[0] = 0x00;
loraData[1] = 0x00;
Spi_WrData(0x8F,loraData,2);//Configure the sending and receiving storage address
Delay1000ms();
Delay1000ms();
}
}
Delay1000ms();
\t\t\t
}
}