在串口处已经编写了,解析串口命令的代码,直接输入相关命令可以直接操作寄存器。
在协议栈串口MT_UART.c文件中RX处代码如下:
//这里面接收串口数据读取,串口传过来数据解析成对应的处理函数!
//最终实现使用串口命令:
//1.F1获取帮助信息
//2.A1设置寄存器,读取寄存器
//3.A2发送数据 (hex 和 字符串)
//4.A3取得数据 清空数据
void serial_process( uint8 port, uint8 event )
{
(void)port;
if ((event & (HAL_UART_RX_FULL | HAL_UART_RX_ABOUT_FULL | HAL_UART_RX_TIMEOUT)))
{
if (SerialApp_TxLen < 80)
{
SerialApp_TxLen = HalUARTRead(port, Serial_Lora_Control_Buff, 80);
if (SerialApp_TxLen)
{
if(Serial_Lora_Control_Buff[0] == 0xF1)LORA_Help();
if(Serial_Lora_Control_Buff[0] == 0xA1)
{
if(SerialApp_TxLen >= 2)存在数据
{
LORA_A1(Serial_Lora_Control_Buff,SerialApp_TxLen);
}
else
{
LORA_Help_A1();
}
}
if(Serial_Lora_Control_Buff[0] == 0xA2)//A2
{
if(SerialApp_TxLen >= 2)//存在数据
{
LORA_A2(Serial_Lora_Control_Buff,SerialApp_TxLen,0);
}
else
{
LORA_Help_A2();
}
}
if (Serial_Lora_Control_Buff[0] == 65 && Serial_Lora_Control_Buff[1] == 50)//字符A2
{
if(Serial_Lora_Control_Buff[2] == '"')
{
LORA_A2(Serial_Lora_Control_Buff,SerialApp_TxLen,1);
}
else
{
LORA_Help_A2_str();
}
}
if(Serial_Lora_Control_Buff[0] == 0xA3)//A3
{
if(SerialApp_TxLen >= 2)//存在数据
{
LORA_A3(Serial_Lora_Control_Buff,SerialApp_TxLen);
}
else
{
LORA_Help_A3();
}
}
处理函数如下:
/*
配合串口命令,反馈、帮助、配置
*/
void LORA_Help(void)
{
HalUARTWrite(0, "\nSend_Hex_Format", strlen("\nSend_Hex_Format"));
HalUARTWrite(0, "\nA1-Set-Reg", strlen("\nA1-Set-Reg"));
HalUARTWrite(0, "\nA2", strlen("\nA2"));
HalUARTWrite(0, "->", strlen("->"));
HalUARTWrite(0, "\nA3", strlen("\nA3"));
HalUARTWrite(0, "<-", strlen("<-"));
}
void LORA_Help_A1(void)
{
HalUARTWrite(0, "\nSend_Hex_Format", strlen("\nSend_Hex_Format"));
HalUARTWrite(0, "\nA1空格ADR空格DATA", strlen("\nA1空格ADR空格DATA"));
HalUARTWrite(0, "\nA1空格ADR", strlen("\nA1空格ADR"));
}
void LORA_Help_A2(void)
{
HalUARTWrite(0, "\nSend_Hex_Format", strlen("\nSend_Hex_Format"));
HalUARTWrite(0, "\nA2空格DATA", strlen("\nA2空格DATA"));
HalUARTWrite(0, "\nA2“字符串”", strlen("\nA2“字符串”"));
}
void LORA_Help_A2_str(void)
{
HalUARTWrite(0, "\nSend_Char_Format", strlen("\nSend_Char_Format"));
HalUARTWrite(0, "\nA2“字符串”", strlen("\nA2“字符串”"));
}
void LORA_Help_A3(void)
{
HalUARTWrite(0, "\nSend_Hex_Format", strlen("\nSend_Hex_Format"));
HalUARTWrite(0, "\nA3空格01/00", strlen("\nA3空格空格01/00"));
}
/*
配合串口命令 A1 配置
格式:A1 adress data
*/
void LORA_A1(uint8 *lora_Order_buff,uint16 SerialApp_TxLen)
{
if(SerialApp_TxLen == 3 )
{
SX1278WriteBuffer(lora_Order_buff[1],lora_Order_buff[2]);
//SX1278ReadBuffer(lora_Order_buff[1]);
}
else
{
SX1278ReadBuffer(lora_Order_buff[1]);
}
}
/*
配合串口命令 A2 send
格式:A2"字符串" OR A2空格DATA
*/
void LORA_A2(uint8 *lora_Order_buff,uint16 SerialApp_TxLen,bool state)
{
if(state == 1)//A2"字符串"
{
if (lora_Order_buff[2] == '"' && lora_Order_buff[SerialApp_TxLen-1] == '"')
{
HalUARTWrite(0, "\nA2“字符串OK”\n", strlen("\nA2“字符串OK”\n"));
HalUARTWrite(0, ":", strlen(":"));
HalUARTWrite(0, lora_Order_buff+3, SerialApp_TxLen-4);//
FUN_RF_SENDPACKET(lora_Order_buff+2,SerialApp_TxLen-2);//2个双引号和数据留下
HalUARTWrite(0, "\nSend_Done!\n", strlen("\nSend_Done!\n"));
}
}
if(state == 0)//A2空格DATA
{
uint8 i;
HalUARTWrite(0, "\nA2“HexOK”\n", strlen("\nA2“HexOK”\n"));
for(i = 1;i<SerialApp_TxLen;i++)
{
HexToChar(lora_Order_buff[i],HEX_String_Value);//转为字符
HalUARTWrite(0, HEX_String_Value,2);
HalUARTWrite(0, " ", 1);
}
FUN_RF_SENDPACKET(lora_Order_buff+1,SerialApp_TxLen-1);//hex发送
HalUARTWrite(0, "\nSend_Done!\n", strlen("\nSend_Done!\n"));
FIFO_Flag_String = 0;
}
}
void LORA_A3(uint8 *lora_Order_buff,uint16 SerialApp_TxLen)
{
if(lora_Order_buff[1]==0x01)
{
if(DIO0 == 1 && FIFO_Flag == 0)//lora 中断触发 未读取数据
{
spi_receiver();
FIFO_Flag = 1;
}
else if(FIFO_Flag == 1 && FIFO_Flag_String == 0)//第二次读
{
HalUARTWrite(0, recv_dest_hex, RF_REC_RLEN_i*3);//-16-》字符数据地址 数据间有空格
}
else if(FIFO_Flag == 1 && FIFO_Flag_String == 1)
{
HalUARTWrite(0, recv_dest+1, RF_REC_RLEN_i-2);//--数据地址
}
}
if(lora_Order_buff[1]==0x00)
{
SX1278LoRaSetOpMode(Sleep_mode);//清空13rx获取的字节数
SX1278LoRaSetOpMode(Stdby_mode);//FIFO指向地址不变、地址内容不变、
RF_RECEIVE();
SX1278ReadBuffer(0x0E);
HalUARTWrite(0, "\nClear_FIFO_Done!\n", strlen("\nClear_FIFO_Done!\n"));
HalUARTWrite(0, "\nNothing!\n", strlen("\nNothing!\n"));
FIFO_Flag = 0;
}
}
//写入或读取寄存器时,发送信息
void SEND_UART_Information(unsigned char *dst_V,unsigned char *dst_A,u8 addr,u8 value,bool state)
{
if(state == 0)
{
HalUARTWrite(0, "\nR:", strlen("\nR:"));
HexToChar(addr,dst_A);//读取地址:dst_A 数据为:dst_V
HalUARTWrite(0, HEX_String_Addr,2);
HalUARTWrite(0, "-:", strlen("-:"));
HexToChar(value,dst_V);
HalUARTWrite(0, HEX_String_Value,2);
}
if(state == 1)
{
HalUARTWrite(0, "\n-W:", strlen("\n-W:"));
HexToChar(addr,dst_A);//写入地址:dst_A 数据为:dst_V
HalUARTWrite(0, HEX_String_Addr,2);
HalUARTWrite(0, "-:", strlen("-:"));
HexToChar(value,dst_V);
HalUARTWrite(0, HEX_String_Value,2);
}
//转为字符
static bool HexToChar(u8 temp,unsigned char *dest)
{
u8 hb,lb;
char buf[2] = {0};
hb=(temp&0xf0)>>4; //保留高位,右移去掉低位
if( hb<=9 )
hb += 0x30; //相当于+'0'转为字符了
else if( hb>=10 &&hb <=15 )
hb = hb -10 + 'A'; //转成字符A--F
else
return 0;
lb = temp&0x0f;
if( lb<=9 )
lb += 0x30;//decimal 48
else if( lb>=10 && lb<=15 )
lb = lb - 10 + 'A';
else
return 0;
buf[0] = hb;
buf[1] = lb;
memcpy(dest,buf,2);
return 1;
}
//SX1278读写
@fn SX1278写入
*/
void SX1278WriteBuffer(u8 addr,u8 buffer)
{
SPI_Write(addr | 0x80);//MSB=1 WRITE
SPI_Write(buffer);//写入数据
NSS = 1; //不使能 NSS = 1;
SEND_UART_Information(HEX_String_Value,HEX_String_Addr,addr,buffer,1);//调试用--写入-发送到串口
}
/*
@fn SX1278读取
*/
unsigned char SX1278ReadBuffer(unsigned char addr) //读取寄存器中的数据
{
unsigned char Value;
SPI_Write(addr & 0x7F);//WRITE写入一个字节数据 MSB=0-->read_data
Value = SPI_Read();
NSS = 1;
SEND_UART_Information(HEX_String_Value,HEX_String_Addr,addr,Value,0);//调试用--读取-发送到串口
return Value;
}
SPI通讯时序
具体可参考:https://blog.csdn.net/weixin_42509369/article/details/83096349
时钟极性CPOL=1则时钟初始为高电平
,0则低电平
时钟相位CPHA=1则第二个时钟沿采集数据
,0则第一个时钟沿
以上都是设置为1则
:时钟第一个沿为下降沿,第二个为上升沿,此时采集数据
SCK初始为低电平,第一个沿为上升,读取数据
若使用标准SPI驱动需要设置:CPOL=0,CPHA=0
#define NSS P0_4 //使能引脚
#define MISO P1_7 //MISO
#define SCLK P1_5 //SCLK
#define MOSI P1_6 //MOSI
#define DIO0 P1_3 //DIO0 RX接收done TX done中断标志
#include "lora.h"
/*******************************************************************************
MOSI, Master out slave in,主出从进。主控端发数据,从端接收,用于主控端写。
MISO, Master in slave out.主进从出。主控端接收数据,从端发送数据,用于主控端读。
时钟口==上升沿读取数据,下降沿写入数据
低高复位芯片
write:wnr[1] 6 5 4 3 2 1 0 自定义写数据(字节) read:wnr[0] 6 5 4 3 2 1 0 读取此地址数据(字节) MSB先传
Fsclk=MAX_10Mhz 100ns 最低允许间隔上50ns下50ns
*******************************************************************************/
/*SPI-init*/
void SPI_INIT(void)
{
P1DIR &= ~BV(7);//MISO配置为输入
P1DIR &= ~BV(3);//P1_3配置为输入,采集DIO0-LORA数据接收中断标志
P1INP &= ~BV(3);//打开P1.3上下拉模式
P2INP |= BV(6);//打开P1端口下拉
P1DIR |= BV(5);//SCLK配置为输出
P1DIR |= BV(6);//MOSI 配置为输出
P0DIR |= BV(4);//NSS配置为输出
NSS = 1;//不使能模块
SCLK = 0;
}
/********************************
从SPI器件写入一个字节数据,NSS不在此停止使能,由调用程序段停止
********************************/
void SPI_Write(unsigned char data)
{
unsigned char i;
NSS = 0;//NSS=0 使能
for(i = 0;i < 8;i++)
{
SCLK = 0;//SCLK=0
if((data & 0x80)==0x80)MOSI = 1;
else MOSI = 0;
_Delay_nus(100);
SCLK = 1 ;
data =(data<<1);
_Delay_nus(100);
}
//NSS = 1; //不使能
}
/********************************
从SPI器件读出一个字节数据,由调用程序段使能NSS,结束后本函数自动停止
********************************/
unsigned char SPI_Read(void)
{
unsigned char i,SPI_DATA;
for(i = 0; i<8 ;i++)
{
SCLK = 0;
_Delay_nus(100);
SPI_DATA = (SPI_DATA<<1);
SCLK = 1;
_Delay_nus(100);
if(MISO == 1)SPI_DATA |=0x01;
else SPI_DATA &=~0x01;
}
SCLK = 0;
NSS = 1;
return SPI_DATA;
}
/*
@fn 运行模式切换
寄存器地址0x01
*/
#define REG_LR_OPMODE 0x01
typedef enum
{
Sleep_mode = (u8)0x00,
Stdby_mode = (u8)0x01,
TX_mode = (u8)0x02,
Transmitter_mode = (u8)0x03,
RF_mode = (u8)0x04,
Receiver_mode = (u8)0x05,
receive_single = (u8)0x06,
CAD_mode = (u8)0x07,
}RFMode_SET;
void SX1278LoRaSetOpMode(RFMode_SET opMode)//运行模式选择
{
u8 opModePrev;
opModePrev = SX1278ReadBuffer(REG_LR_OPMODE);//寄存器地址0X01
opModePrev &= 0xf8;
opModePrev |= (u8) opMode;
SX1278WriteBuffer( REG_LR_OPMODE, opModePrev);
}
使2个设备初始化!
使用串口命令:
F1获取帮助信息
A1设置寄存器
A2发送数据
A3取得数据
使用串口命令:A1获取设置寄存器命令格式:
A1空格地址空格数据 –》这是设置
A1空格地址 –》这是读取
寄存器地址:
0D 读取FIFO-ptr地址
00 获取0D指向地址的数据
13 读取RX到的字节数
10 获取最后一包数据的首地址(只发了一包很长的的数据,10内数据为00首地址)
12 获取中断标志位
01 获取运行模式,其值设置为: 88为睡眠、89为待机、8D为持续接收、8B为使能发送
使用串口命令:A2 发送数据
A2空格数据 –》这是发送16进制数据
A2”字符串” –》这是发送非16进制数据
使用串口命令A3获取数据或清除数据
A3空格01 –》这是获取数据
A3空格00 –》这是清除数据
示范:设置接收端 0D 为00首地址
发送端也设置
发送端发送数据 55 55 55 三个字节的16进制数:
接收端收到数据:
获取数据包长度:
获取最后一包数据首地址:
获取数据:
这时再看下地址变化:自动增加了1,代表下次访问00内数据是访问指向01这个里面的数据
我们再次访问00获取数据:还是55这个字节
这时再看下地址变化:自动增加了1,代表下次访问00内数据是访问指向02这个里面的数据
我们可以通过命令 A1 0D 03 改变00指向的地址,从而获取指定地址数据!
也可:不修改0D,直接读取00,这时是未读数据地址(不是最新数据!)
PS此处摘取新浪文档:
原文地址
实际操作:
1、设置寄存器地址:0x01
= 0x88 睡眠
2、设置寄存器地址:0x06至0x08
设置相应频率数值 具体计算方法参考手册page:112
典型的32Mhz晶振,分辨率为61.035hz(Fstep=Focsc/2^19 ==
Fstep = 32 000 000 Hz / 524 288 = 61.035 Hz)
3、频率
是Fstep这个数x Frf(0x06至0x08设置的值,hex=6c8000十进制=7110656)即434 000 000 Hz, 即频率为434 MHz
PS此处参考其他博主文档:
原文地址
关于LORA的CAD检测参考其他博主文档:
原文地址
关于LORA的更多功能参考其他博主文档:
原文地址
END!