初始版本

This commit is contained in:
2026-04-23 14:02:03 +08:00
parent d68cb4273f
commit bbd563b069
121 changed files with 94711 additions and 0 deletions
+298
View File
@@ -0,0 +1,298 @@
/************************************************************************************************
* 程序版本:V3.0
* 程序日期:2022-11-3
* 程序作者:
************************************************************************************************/
#include "Imu.h"
#include "main.h"
#define Kp_New 0.9f //互补滤波当前数据的权重
#define Kp_Old 0.1f //互补滤波历史数据的权重
#define Acc_Gain 0.0001220f //加速度变成G (初始化加速度满量程-+4g LSBa = 2*4/65535.0)
#define Gyro_Gain 0.0609756f //角速度变成度 (初始化陀螺仪满量程+-2000 LSBg = 2*2000/65535.0)
#define Gyro_Gr 0.0010641f //角速度变成弧度(3.1415/180 * LSBg)
//kp=ki=0 就是完全相信陀螺仪
#define Kp 1.5f // proportional gain governs rate of convergence to accelerometer/magnetometer
//比例增益控制加速度计,磁力计的收敛速率
#define Ki 0.005f // integral gain governs rate of convergence of gyroscope biases
//积分增益控制陀螺偏差的收敛速度
#define halfT 0.005f // half the sample period 采样周期的一半
static volatile float q0 = 1, q1 = 0, q2 = 0, q3 = 0; // quaternion elements representing the estimated orientation
static volatile float exInt = 0, eyInt = 0, ezInt = 0; // scaled integral error
/*
static float MedianValue(float *value_buf, unsigned int size)
{
unsigned int i,j;
float temp;
//排序采用冒泡法
for (j=0;j<=size;j++){
for (i=0;i<=size-j;i++){
if (value_buf[i] > value_buf[i+1]){
temp = value_buf[i];
value_buf[i] = value_buf[i+1];
value_buf[i+1] = temp;
}
}
}
return value_buf[(size-1)/2];
}
*/
static float MedianValue(float *value_buf, unsigned int size)
{
unsigned int i;
float temp = 0;
for (i=0; i<size; i++)
temp += value_buf[i];
return temp/size;
}
static float Acc_Filter_X(float in_data)
{
static float value_buf[Imu_AccFilterSize] = {0};
static unsigned char cnt = 0;
value_buf[cnt] = in_data;
cnt++;
if (cnt>=Imu_AccFilterSize)cnt=0;
return MedianValue(value_buf, Imu_AccFilterSize);
}
static float Acc_Filter_Y(float in_data)
{
static float value_buf[Imu_AccFilterSize] = {0};
static unsigned char cnt = 0;
value_buf[cnt] = in_data;
cnt++;
if (cnt>=Imu_AccFilterSize)cnt=0;
return MedianValue(value_buf, Imu_AccFilterSize);
}
static float Acc_Filter_Z(float in_data)
{
static float value_buf[Imu_AccFilterSize] = {0};
static unsigned char cnt = 0;
value_buf[cnt] = in_data;
cnt++;
if (cnt>=Imu_AccFilterSize)cnt=0;
return MedianValue(value_buf, Imu_AccFilterSize);
}
static float Mag_Filter_X(float in_data)
{
static float value_buf[Imu_MagFilterSize] = {0};
static unsigned char cnt = 0;
value_buf[cnt] = in_data;
cnt++;
if (cnt>=Imu_MagFilterSize)cnt=0;
return MedianValue(value_buf, Imu_MagFilterSize);
}
static float Mag_Filter_Y(float in_data)
{
static float value_buf[Imu_MagFilterSize] = {0};
static unsigned char cnt = 0;
value_buf[cnt] = in_data;
cnt++;
if (cnt>=Imu_MagFilterSize)cnt=0;
return MedianValue(value_buf, Imu_MagFilterSize);
}
static float Mag_Filter_Z(float in_data)
{
static float value_buf[Imu_MagFilterSize] = {0};
static unsigned char cnt = 0;
value_buf[cnt] = in_data;
cnt++;
if (cnt>=Imu_MagFilterSize)cnt=0;
return MedianValue(value_buf, Imu_MagFilterSize);
}
static float Gyro_Filter_X(float in_data)
{
static float value_buf[Imu_GyroFilterSize] = {0};
static unsigned char cnt = 0;
value_buf[cnt] = in_data;
cnt++;
if (cnt>=Imu_GyroFilterSize)cnt=0;
return MedianValue(value_buf, Imu_GyroFilterSize);
}
static float Gyro_Filter_Y(float in_data)
{
static float value_buf[Imu_GyroFilterSize] = {0};
static unsigned char cnt = 0;
value_buf[cnt] = in_data;
cnt++;
if (cnt>=Imu_GyroFilterSize)cnt=0;
return MedianValue(value_buf, Imu_GyroFilterSize);
}
static float Gyro_Filter_Z(float in_data)
{
static float value_buf[Imu_GyroFilterSize] = {0};
static unsigned char cnt = 0;
value_buf[cnt] = in_data;
cnt++;
if (cnt>=Imu_GyroFilterSize)cnt=0;
return MedianValue(value_buf, Imu_GyroFilterSize);
}
static float invSqrt(float x) {
float halfx = 0.5f * x;
float y = x;
long i = *(long*)&y;
i = 0x5f3759df - (i>>1);
y = *(float*)&i;
y = y * (1.5f - (halfx * y * y));
return y;
}
static void IMUupdate(float gx, float gy, float gz, float ax, float ay, float az)
{
float vx, vy, vz;
float ex, ey, ez;
float norm;
float q0q0 = q0*q0;
float q0q1 = q0*q1;
float q0q2 = q0*q2;
float q0q3 = q0*q3;
float q1q1 = q1*q1;
float q1q2 = q1*q2;
float q1q3 = q1*q3;
float q2q2 = q2*q2;
float q2q3 = q2*q3;
float q3q3 = q3*q3;
if(ax*ay*az==0)
return;
//加速度计<测量>的重力加速度向量(机体坐标系)
norm = invSqrt(ax*ax + ay*ay + az*az);
ax = ax * norm;
ay = ay * norm;
az = az * norm;
// printf("ax=%0.2f ay=%0.2f az=%0.2f\r\n",ax,ay,az);
//陀螺仪积分<估计>重力向量(机体坐标系)
vx = 2*(q1q3 - q0q2); //矩阵(3,1)项
vy = 2*(q0q1 + q2q3); //矩阵(3,2)项
vz = q0q0 - q1q1 - q2q2 + q3q3 ; //矩阵(3,3)项
//向量叉乘所得的值
ex = (ay*vz - az*vy);
ey = (az*vx - ax*vz);
ez = (ax*vy - ay*vx);
//用上面求出误差进行积分
exInt = exInt + ex * Ki;
eyInt = eyInt + ey * Ki;
ezInt = ezInt + ez * Ki;
//将误差PI后补偿到陀螺仪
gx = gx + Kp*ex + exInt;
gy = gy + Kp*ey + eyInt;
gz = gz + Kp*ez + ezInt;//这里的gz由于没有观测者进行矫正会产生漂移,表现出来的就是积分自增或自减
//四元素的微分方程
q0 = q0 + (-q1*gx - q2*gy - q3*gz)*halfT;
q1 = q1 + (q0*gx + q2*gz - q3*gy)*halfT;
q2 = q2 + (q0*gy - q1*gz + q3*gx)*halfT;
q3 = q3 + (q0*gz + q1*gy - q2*gx)*halfT;
//单位化四元数
norm = invSqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);
q0 = q0 * norm;
q1 = q1 * norm;
q2 = q2 * norm;
q3 = q3 * norm;
// 矩阵表达式
// matrix[0] = q0q0 + q1q1 - q2q2 - q3q3; // 11
// matrix[1] = 2.f * (q1q2 + q0q3); // 12
// matrix[2] = 2.f * (q1q3 - q0q2); // 13
// matrix[3] = 2.f * (q1q2 - q0q3); // 21
// matrix[4] = q0q0 - q1q1 + q2q2 - q3q3; // 22
// matrix[5] = 2.f * (q2q3 + q0q1); // 23
// matrix[6] = 2.f * (q1q3 + q0q2); // 31
// matrix[7] = 2.f * (q2q3 - q0q1); // 32
// matrix[8] = q0q0 - q1q1 - q2q2 + q3q3; // 33
//下一步是四元数转换成欧拉角(Z->Y->X)
}
#define ALPHA 0.01
void IMU_Update(float *gy,float *acc, float *mag, RadDp Rad, DegDp Deg)
{
static volatile double Phi,Theta, Psi, Gz2, By2, Bz2, Bx3;
volatile float Gyr[XYZ], Acc[XYZ], Mag[XYZ];
Gyr[X] = gy[X];
Gyr[Y] = gy[Y];
Gyr[Z] = gy[Z];
Acc[X] = acc[X];
Acc[Y] = acc[Y];
Acc[Z] = acc[Z];
Mag[X] = -mag[X];
Mag[Y] = -mag[Y];
Mag[Z] = -mag[Z];
// IMUupdate(Gyr[X], Gyr[Y], Gyr[Z], Acc[X], Acc[Y], Acc[Z]);
// Phi = -atan2(2.f * q0*q1 + 2.f * q2*q3, 1 - 2.f * q1*q1 - 2.f * q2*q2);
// Theta = -asin(2.f * (q0*q2 - q1*q3));
// volatile float xh = Mag[0]*cos(Theta) + Mag[1]*sin(Phi)*sin(Theta) + Mag[2]*cos(Phi)*sin(Theta);
// volatile float yh = Mag[1]*cos(Phi) - Mag[2]*sin(Phi);
// Psi = atan2(yh, xh);
Phi = atan2(Acc[Y], (Acc[Z] + Acc[X] * ALPHA));
//Phi = atan2(Acc[Y], Acc[Z]);
Gz2 = Acc[Y] * sin(Phi) + Acc[Z] * cos(Phi);
Theta = atan(-Acc[X] / Gz2);
By2 = Mag[Z] * sin(Phi) - Mag[Y] * cos(Phi);
Bz2 = Mag[Y] * sin(Phi) + Mag[Z] * cos(Phi);
Bx3 = Mag[X] * cos(Theta) + Bz2 * sin(Theta);
Psi = atan2(By2, Bx3);
Rad->roll = Phi;
Rad->pitch = Theta;
Rad->yaw = Psi;
Deg->roll = Rad->roll * RAD_TO_DEG;
Deg->pitch = Rad->pitch * RAD_TO_DEG;
Deg->yaw = Rad->yaw * RAD_TO_DEG;
}
+24
View File
@@ -0,0 +1,24 @@
#ifndef _IMU_H_
#define _IMU_H_
#include <math.h>
#define PI 3.14159265358979323846f
#define RAD_TO_DEG 57.2957795 // 弧度到度的转换系数
#define DEG_TO_RAD 0.0174533 // 度到弧度的转换系数
// 定义欧拉角结构体
typedef struct {
volatile float roll, pitch, yaw;//弧度
}Rad_T, *RadDp;
typedef struct {
volatile float roll, pitch, yaw;//角度
}Deg_T, *DegDp;
#define Imu_AccFilterSize 10
#define Imu_MagFilterSize 20
#define Imu_GyroFilterSize 10
void IMU_Update(float *gy,float *acc, float *mag, RadDp Rad, DegDp Deg);
#endif
+613
View File
@@ -0,0 +1,613 @@
#include "sx127x.h"
#include "ddl.h"
#include "Debug.h"
#include "spi.h"
#include "bsp.h"
#define LORAChannel 8
#define LORARegPreamble 10
#if (LORA_MODULE == SX1278W1)
Sx1276Type_t LoRaPara = {
.ucChannel = LORAChannel, //4 or 12
.dwFreqHz = FREQ_CENT,
.ucPower = 20,
.SignalBw = SX1276_BW_250K,
.SpreadFactor = SX1276_SF_512,
.ErrorCoding = SX1276_EC_4_6,
.RegPreamble = LORARegPreamble,//10 or 16
.ucOpModePrev = RFLR_OPMODE_STANDBY,
.bAntSwPrev = RF_ANT_RECEIVER,
.RegBuff = 0,
.State = SX1276_IDLE,
.ucRxPacketSize = 0,
.ucTxPacketSize = 0,
.RxCallBack = NULL,
};
void LoraReset(void)
{
LORA_RESET_CLR();
delay_ms(1);
LORA_RESET_SET();
}
/////////////////////////////////////////////////
void SX1276SetAntSw(Sx1276AntStatus_m Status)
{
switch(Status){
case RF_ANT_TRANSMITTER:
LORA_ANTTXEN();
break;
case RF_ANT_RECEIVER:
LORA_ANTRXEN();
break;
case RF_ANT_CLOSE:
LORA_ANTCLOSE();
break;
}
}
void SX1276ReadBuffer(uint8_t ucAddr, uint8_t *pucBuff, uint8_t ucLen)
{
uint8_t ucCnt;
LORA_SPI_NSS_CLR();
LORA_SPI_READ_WRITE(ucAddr & 0x7F);
for( ucCnt = 0; ucCnt < ucLen; ucCnt++ ){
pucBuff[ucCnt] = LORA_SPI_READ_WRITE(0);
}
LORA_SPI_NSS_SET();
}
void SX1276WriteBuffer(uint8_t ucAddr, uint8_t *pucBuff, uint8_t ucLen)
{
uint8_t ucCnt;
LORA_SPI_NSS_CLR();
LORA_SPI_READ_WRITE(ucAddr | 0x80);
for( ucCnt = 0; ucCnt < ucLen; ucCnt++ ){
LORA_SPI_READ_WRITE(pucBuff[ucCnt]);
}
LORA_SPI_NSS_SET();
}
void SX1276Write(uint8_t ucAddr, uint8_t ucData)
{
SX1276WriteBuffer(ucAddr, &ucData, 1);
}
void SX1276Read(uint8_t ucAddr, uint8_t * pucData)
{
SX1276ReadBuffer(ucAddr, pucData, 1);
}
void SX1276WriteFifo(uint8_t *pucBuff, uint8_t ucLen)
{
SX1276WriteBuffer(0, pucBuff, ucLen);
}
void SX1276ReadFifo(uint8_t *pucBuff, uint8_t ucLen)
{
SX1276ReadBuffer(0, pucBuff, ucLen);
}
/////////////////////////////////////////////////
void SX1276LoRaSetNbTrigPeaks(uint8_t ucValue)
{
SX1276Read(0x31, &(LoRaPara.RegBuff.RegTestReserved31));
LoRaPara.RegBuff.RegTestReserved31 = (LoRaPara.RegBuff.RegTestReserved31 & 0xF8) | ucValue;
SX1276Write(0x31, LoRaPara.RegBuff.RegTestReserved31 );
}
void SX1276LoRaSetSignalBandwidth(Sx1276BwType Bw)
{
SX1276Read(REG_LR_MODEMCONFIG1, &(LoRaPara.RegBuff.RegModemConfig1));
LoRaPara.RegBuff.RegModemConfig1 = (LoRaPara.RegBuff.RegModemConfig1 & RFLR_MODEMCONFIG1_BW_MASK) | Bw;
SX1276Write(REG_LR_MODEMCONFIG1, LoRaPara.RegBuff.RegModemConfig1);
LoRaPara.SignalBw = Bw;
}
void SX1276LoRaSetSpreadingFactor(Sx1276SpreadFactorType Factor)
{
if (Factor > SX1276_SF_4096){
Factor = SX1276_SF_4096;
}
else if (Factor < SX1276_SF_64){
Factor = SX1276_SF_64;
}
if (Factor == SX1276_SF_64){
SX1276LoRaSetNbTrigPeaks(5);
}
else{
SX1276LoRaSetNbTrigPeaks(3);
}
SX1276Read(REG_LR_MODEMCONFIG2, &(LoRaPara.RegBuff.RegModemConfig2));
LoRaPara.RegBuff.RegModemConfig2 = (LoRaPara.RegBuff.RegModemConfig2 & RFLR_MODEMCONFIG2_SF_MASK ) | Factor;
SX1276Write(REG_LR_MODEMCONFIG2, LoRaPara.RegBuff.RegModemConfig2);
LoRaPara.SpreadFactor = Factor;
}
void SX1276LoRaSetErrorCoding(Sx1276ErrorCodingType Value){
SX1276Read(REG_LR_MODEMCONFIG1, &(LoRaPara.RegBuff.RegModemConfig1));
LoRaPara.RegBuff.RegModemConfig1 = (LoRaPara.RegBuff.RegModemConfig1 & RFLR_MODEMCONFIG1_CODINGRATE_MASK ) | Value;
SX1276Write(REG_LR_MODEMCONFIG1, LoRaPara.RegBuff.RegModemConfig1 );
LoRaPara.ErrorCoding = Value;
}
void SX1276LoRaSetFreqHz(uint32_t dwFreqHz)
{
LoRaPara.dwFreqHz = dwFreqHz;
dwFreqHz = ( uint32_t )( ( double )dwFreqHz / ( double )FREQ_STEP );
LoRaPara.RegBuff.RegFrfMsb = ( uint8_t )( ( dwFreqHz >> 16 ) & 0xFF );
LoRaPara.RegBuff.RegFrfMid = ( uint8_t )( ( dwFreqHz >> 8 ) & 0xFF );
LoRaPara.RegBuff.RegFrfLsb = ( uint8_t )( dwFreqHz & 0xFF );
SX1276WriteBuffer(REG_LR_FRFMSB, &(LoRaPara.RegBuff.RegFrfMsb), 3);
}
void SX1276LoRaSetSymbTimeout(uint16_t ucValue)
{
SX1276ReadBuffer(REG_LR_MODEMCONFIG2, &(LoRaPara.RegBuff.RegModemConfig2), 2);
LoRaPara.RegBuff.RegModemConfig2 = (LoRaPara.RegBuff.RegModemConfig2 & RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK) | (( ucValue >> 8) & ~RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK );
LoRaPara.RegBuff.RegSymbTimeoutLsb = ucValue & 0xFF;
SX1276WriteBuffer(REG_LR_MODEMCONFIG2, &(LoRaPara.RegBuff.RegModemConfig2), 2);
}
void SX1276LoRaSetLowDatarateOptimize(boolean_t bEnable)
{
SX1276Read(REG_LR_MODEMCONFIG3, &(LoRaPara.RegBuff.RegModemConfig3));
LoRaPara.RegBuff.RegModemConfig3 = (LoRaPara.RegBuff.RegModemConfig3 & RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_MASK ) | ( bEnable << 3 );
SX1276Write(REG_LR_MODEMCONFIG3, LoRaPara.RegBuff.RegModemConfig3);
}
void SX1276LoRaSetPAOutput(uint8_t ucOutputPin)
{
SX1276Read(REG_LR_PACONFIG, &(LoRaPara.RegBuff.RegPaConfig));
LoRaPara.RegBuff.RegPaConfig = (LoRaPara.RegBuff.RegPaConfig & RFLR_PACONFIG_PASELECT_MASK ) | ucOutputPin;
SX1276Write(REG_LR_PACONFIG, LoRaPara.RegBuff.RegPaConfig );
}
void SX1276LoRaSetPa20dBm(boolean_t bEnable)
{
SX1276Read(REG_LR_PADAC, &(LoRaPara.RegBuff.RegPaDac));
SX1276Read(REG_LR_PACONFIG, &(LoRaPara.RegBuff.RegPaConfig));
if ((LoRaPara.RegBuff.RegPaConfig & RFLR_PACONFIG_PASELECT_PABOOST ) == RFLR_PACONFIG_PASELECT_PABOOST ) {
if( bEnable == TRUE ){
LoRaPara.RegBuff.RegPaDac = 0x87;
}
}
else{
LoRaPara.RegBuff.RegPaDac = 0x84;
}
SX1276Write(REG_LR_PADAC, LoRaPara.RegBuff.RegPaDac );
}
void SX1276LoRaSetRfPower(int8_t sbPower)
{
SX1276Read(REG_LR_PACONFIG, &(LoRaPara.RegBuff.RegPaConfig));
SX1276Read(REG_LR_PADAC, &(LoRaPara.RegBuff.RegPaDac));
if ((LoRaPara.RegBuff.RegPaConfig & RFLR_PACONFIG_PASELECT_PABOOST ) == RFLR_PACONFIG_PASELECT_PABOOST ) {
if ((LoRaPara.RegBuff.RegPaDac & 0x87) == 0x87){
if( sbPower < 5 ){
sbPower = 5;
}
if( sbPower > 20){
sbPower = 20;
}
LoRaPara.RegBuff.RegPaConfig = (LoRaPara.RegBuff.RegPaConfig & RFLR_PACONFIG_MAX_POWER_MASK ) | 0x70;
LoRaPara.RegBuff.RegPaConfig = (LoRaPara.RegBuff.RegPaConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) |
( uint8_t )( ( uint16_t )( sbPower - 5 ) & 0x0F );
}
else{
if( sbPower < 2){
sbPower = 2;
}
if( sbPower > 17){
sbPower = 17;
}
LoRaPara.RegBuff.RegPaConfig = (LoRaPara.RegBuff.RegPaConfig & RFLR_PACONFIG_MAX_POWER_MASK ) | 0x70;
LoRaPara.RegBuff.RegPaConfig = (LoRaPara.RegBuff.RegPaConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) |
( uint8_t )( ( uint16_t )( sbPower - 2 ) & 0x0F );
}
}
else{
if( sbPower < -1){
sbPower = -1;
}
if( sbPower > 14){
sbPower = 14;
}
LoRaPara.RegBuff.RegPaConfig = (LoRaPara.RegBuff.RegPaConfig & RFLR_PACONFIG_MAX_POWER_MASK ) | 0x70;
LoRaPara.RegBuff.RegPaConfig = (LoRaPara.RegBuff.RegPaConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) |
( uint8_t )( ( uint16_t )( sbPower + 1 ) & 0x0F );
}
SX1276Write(REG_LR_PACONFIG, LoRaPara.RegBuff.RegPaConfig);
LoRaPara.ucPower = sbPower;
}
void SX1276LoRaSetOpMode(Sx1276OpModeType ucOpMode)
{
Sx1276AntStatus_m bAntSwStatus = RF_ANT_RECEIVER;
LoRaPara.ucOpModePrev = LoRaPara.RegBuff.RegOpMode & ~RFLR_OPMODE_MASK;
if( ucOpMode != LoRaPara.ucOpModePrev){
if(ucOpMode == RFLR_OPMODE_TRANSMITTER){
//CLR_LORA_RXEN();
//SET_LORA_TXEN();
bAntSwStatus = RF_ANT_TRANSMITTER;
}
else if(ucOpMode == RFLR_OPMODE_RECEIVER){
bAntSwStatus = RF_ANT_RECEIVER;
//CLR_LORA_TXEN();
//SET_LORA_RXEN();
}
else {
bAntSwStatus = RF_ANT_CLOSE;
}
if( bAntSwStatus != LoRaPara.bAntSwPrev ){
LoRaPara.bAntSwPrev = bAntSwStatus;
SX1276SetAntSw(bAntSwStatus);
}
LoRaPara.RegBuff.RegOpMode = (LoRaPara.RegBuff.RegOpMode & RFLR_OPMODE_MASK ) | ucOpMode;
SX1276Write( REG_LR_OPMODE, LoRaPara.RegBuff.RegOpMode);
}
}
////////////////////////////////////////////////////////////////
void Sx1276LoRaEnterRx(void)
{
uint8_t ucCnt;
SX1276LoRaSetOpMode(RFLR_OPMODE_STANDBY);
LoRaPara.RegBuff.RegIrqFlagsMask = RFLR_IRQFLAGS_RXTIMEOUT | RFLR_IRQFLAGS_VALIDHEADER | RFLR_IRQFLAGS_TXDONE;
SX1276Write(REG_LR_IRQFLAGSMASK, LoRaPara.RegBuff.RegIrqFlagsMask);
LoRaPara.RegBuff.RegHopPeriod = 255;
SX1276Write(REG_LR_HOPPERIOD, LoRaPara.RegBuff.RegHopPeriod );
// RxDone RxTimeout FhssChangeChannel ValidHeader
LoRaPara.RegBuff.RegDioMapping1 = RFLR_DIOMAPPING1_DIO0_00 | RFLR_DIOMAPPING1_DIO1_00 | RFLR_DIOMAPPING1_DIO2_01 | RFLR_DIOMAPPING1_DIO3_01;
// CadDetected ModeReady
LoRaPara.RegBuff.RegDioMapping2 = RFLR_DIOMAPPING2_DIO4_00 | RFLR_DIOMAPPING2_DIO5_00;
SX1276WriteBuffer(REG_LR_DIOMAPPING1, &(LoRaPara.RegBuff.RegDioMapping1), 2);
LoRaPara.RegBuff.RegFifoAddrPtr = LoRaPara.RegBuff.RegFifoRxBaseAddr;
SX1276Write(REG_LR_FIFOADDRPTR, LoRaPara.RegBuff.RegFifoAddrPtr);
SX1276LoRaSetOpMode(RFLR_OPMODE_RECEIVER);
for (ucCnt=0; ucCnt< LORA_BUFF_SIZE; ucCnt++){
LoRaPara.RxTxBuff[ucCnt] = 0;
}
LoRaPara.State = SX1276_IDLE;//COMST_RX
uint8_t temp;
SX1276Read(REG_LR_IRQFLAGS, &temp);
//设置接收模式
LORA_ANTRXEN();
}
/////////////////////////////////////////////////
void Sx1276LoRaInit(void (*RxCallBack)(uint8_t *rBuff, uint8_t rlen))
{
if(RxCallBack != NULL) {
LoRaPara.RxCallBack = RxCallBack;
}
LoraReset();
SX1276LoRaSetOpMode(RFLR_OPMODE_SLEEP);
LoRaPara.RegBuff.RegOpMode = (LoRaPara.RegBuff.RegOpMode & RFLR_OPMODE_LONGRANGEMODE_MASK ) | RFLR_OPMODE_LONGRANGEMODE_ON;
SX1276Write(REG_LR_OPMODE, LoRaPara.RegBuff.RegOpMode );
SX1276LoRaSetOpMode(RFLR_OPMODE_STANDBY);
// RxDone RxTimeout FhssChangeChannel ValidHeader
LoRaPara.RegBuff.RegDioMapping1 = RFLR_DIOMAPPING1_DIO0_00 | RFLR_DIOMAPPING1_DIO1_00 | RFLR_DIOMAPPING1_DIO2_00 | RFLR_DIOMAPPING1_DIO3_01;
// CadDetected ModeReady
LoRaPara.RegBuff.RegDioMapping2 = RFLR_DIOMAPPING2_DIO4_00 | RFLR_DIOMAPPING2_DIO5_00;
SX1276WriteBuffer(REG_LR_DIOMAPPING1, &(LoRaPara.RegBuff.RegDioMapping1), 2 );
SX1276ReadBuffer(REG_LR_OPMODE, (uint8_t*)&(LoRaPara.RegBuff) + 1, SIZE_OF_REGISTERS);
LoRaPara.State = SX1276_BUSY;
SX1276Read(REG_LR_VERSION, &(LoRaPara.RegBuff.RegVersion));
SX1276ReadBuffer(REG_LR_OPMODE, (uint8_t*)&(LoRaPara.RegBuff) + 1, SIZE_OF_REGISTERS);
LoRaPara.RegBuff.RegLna = RFLR_LNA_GAIN_G1;
SX1276WriteBuffer(REG_LR_OPMODE, (uint8_t*)&(LoRaPara.RegBuff) + 1, SIZE_OF_REGISTERS);
//set the RF settings
SX1276LoRaWriteChannel(LoRaPara.ucChannel);
//SX1276LoRaSetFreqHz(LoRaPara.dwFreqHz);
//REG_LR_MODEMCONFIG1
SX1276Read(REG_LR_MODEMCONFIG1, &(LoRaPara.RegBuff.RegModemConfig1));
//SignalBandwidth
LoRaPara.RegBuff.RegModemConfig1 = (LoRaPara.RegBuff.RegModemConfig1 & RFLR_MODEMCONFIG1_BW_MASK ) | LoRaPara.SignalBw;
//ErrorCoding
LoRaPara.RegBuff.RegModemConfig1 = (LoRaPara.RegBuff.RegModemConfig1 & RFLR_MODEMCONFIG1_CODINGRATE_MASK ) | LoRaPara.ErrorCoding;
//IMPLICITHEADER
LoRaPara.RegBuff.RegModemConfig1 = LoRaPara.RegBuff.RegModemConfig1 | RFLR_MODEMCONFIG1_IMPLICITHEADER_ON;
SX1276Write(REG_LR_MODEMCONFIG1, LoRaPara.RegBuff.RegModemConfig1);
//REG_LR_MODEMCONFIG2
SX1276Read(REG_LR_MODEMCONFIG2, &(LoRaPara.RegBuff.RegModemConfig2));
//SpreadingFactor
if( LoRaPara.SpreadFactor == SX1276_SF_64){
SX1276LoRaSetNbTrigPeaks(5);
SX1276LoRaSetLowDatarateOptimize(TRUE); //低数据速率设置
}
else{
SX1276LoRaSetNbTrigPeaks(3);
SX1276LoRaSetLowDatarateOptimize(FALSE); //低数据速率设置
}
LoRaPara.RegBuff.RegModemConfig2 = (LoRaPara.RegBuff.RegModemConfig2 & RFLR_MODEMCONFIG2_SF_MASK ) | LoRaPara.SpreadFactor;
//PacketCrcOn
LoRaPara.RegBuff.RegModemConfig2 = (LoRaPara.RegBuff.RegModemConfig2 & RFLR_MODEMCONFIG2_RXPAYLOADCRC_MASK ) | SX1276_CRC_ON; //SX1276_CRC_OFF
//验证寄存器操作是否成功
SX1276Write(REG_LR_MODEMCONFIG2, LoRaPara.RegBuff.RegModemConfig2);
LoRaPara.RegBuff.RegModemConfig2 = 0;
SX1276Read(REG_LR_MODEMCONFIG2, &(LoRaPara.RegBuff.RegModemConfig2));
SX1276LoRaSetSymbTimeout(0x3FF);
LoRaPara.RegBuff.RegPreambleMsb= (LoRaPara.RegPreamble >> 8) & 0x00ff;
LoRaPara.RegBuff.RegPreambleLsb= LoRaPara.RegPreamble & 0x00ff;
SX1276Write(REG_LR_PREAMBLEMSB, LoRaPara.RegBuff.RegPreambleMsb);
SX1276Write(REG_LR_PREAMBLELSB, LoRaPara.RegBuff.RegPreambleLsb);
SX1276Write(REG_LR_PAYLOADLENGTH, LORA_BUFF_SIZE);
SX1276Write(REG_LR_PAYLOADMAXLENGTH, LORA_BUFF_SIZE);
LoRaPara.RegBuff.RegPayloadLength = LORA_BUFF_SIZE;
#ifndef USE_LORA_860_PA
if(LoRaPara.dwFreqHz > 860000000 ){
SX1276LoRaSetPAOutput(RFLR_PACONFIG_PASELECT_RFO);
SX1276LoRaSetPa20dBm(FALSE);
LoRaPara.ucPower = 14;
}
else
#endif
{
SX1276LoRaSetPAOutput(RFLR_PACONFIG_PASELECT_PABOOST);
SX1276LoRaSetPa20dBm(TRUE);
LoRaPara.ucPower = 20;
}
SX1276LoRaSetRfPower(LoRaPara.ucPower);
SX1276LoRaSetOpMode(RFLR_OPMODE_STANDBY);
Sx1276LoRaEnterRx();
}
void IsrSx1276LoRaTxRx(void){
switch (LoRaPara.State){
case SX1276_IDLE:
case SX1276_RX:
// Clear Irq
//SET_LORA_RX_LED();
do {
SX1276Write(REG_LR_IRQFLAGS, RFLR_IRQFLAGS_RXDONE);
SX1276Read(REG_LR_IRQFLAGS, &(LoRaPara.RegBuff.RegIrqFlags));
if((LoRaPara.RegBuff.RegIrqFlags & RFLR_IRQFLAGS_RXDONE) != RFLR_IRQFLAGS_RXDONE)
break;
}while(1);
if((LoRaPara.RegBuff.RegIrqFlags & RFLR_IRQFLAGS_PAYLOADCRCERROR ) == RFLR_IRQFLAGS_PAYLOADCRCERROR) {
// Clear Irq
SX1276Write(REG_LR_IRQFLAGS, RFLR_IRQFLAGS_PAYLOADCRCERROR);
LoRaPara.State = SX1276_IDLE;
break;
}
SX1276Read(REG_LR_PKTSNRVALUE, &(LoRaPara.RegBuff.RegPktSnrValue));
SX1276Read(REG_LR_RSSIVALUE, &(LoRaPara.RegBuff.RegRssiValue));
SX1276Read(REG_LR_PKTRSSIVALUE, &(LoRaPara.RegBuff.RegPktRssiValue));
SX1276Read(REG_LR_FIFORXCURRENTADDR, &(LoRaPara.RegBuff.RegFifoRxCurrentAddr));
SX1276Read(REG_LR_NBRXBYTES, &(LoRaPara.RegBuff.RegNbRxBytes));
LoRaPara.ucRxPacketSize = LoRaPara.RegBuff.RegNbRxBytes;
LoRaPara.RegBuff.RegFifoAddrPtr = LoRaPara.RegBuff.RegFifoRxCurrentAddr;
SX1276Write(REG_LR_FIFOADDRPTR, LoRaPara.RegBuff.RegFifoAddrPtr);
SX1276ReadFifo(LoRaPara.RxTxBuff, (LoRaPara.ucRxPacketSize > LORA_BUFF_SIZE) ? LORA_BUFF_SIZE : LoRaPara.ucRxPacketSize);
uint8_t ucLen;
if(LoRaPara.ucRxPacketSize < LORA_BUFF_SIZE) {
ucLen= LoRaPara.ucRxPacketSize;
}
else {
ucLen= LORA_BUFF_SIZE;
}
LoRaPara.RxTxBuff[ucLen] = 0;
if(LoRaPara.RxCallBack != NULL)
LoRaPara.RxCallBack(LoRaPara.RxTxBuff, ucLen);
LoRaPara.ucRxPacketSize = 0;
LoRaPara.State = SX1276_IDLE;
//CLR_LORA_RX_LED();
break;
case SX1276_TX:
// Clear Irq
SX1276Write(REG_LR_IRQFLAGS, RFLR_IRQFLAGS_TXDONE);
//LORA_TXLED_OFF();
Sx1276LoRaEnterRx();
break;
default:
break;
}
}
void Sx1276LoRaLoopHandler(void)
{
if(LORA_GETDIO0() > 0){ // RxDone or TxDone
IsrSx1276LoRaTxRx();
}
}
void Sx1276LoRaSendBuffer(uint8_t* pucBuff, uint8_t ucLen)
{
//设置发送模式
LORA_ANTTXEN();
LoRaPara.State = SX1276_BUSY;
if (ucLen > LORA_BUFF_SIZE){
ucLen = LORA_BUFF_SIZE;
}
LoRaPara.ucTxPacketSize = ucLen;
while(ucLen--){
LoRaPara.RxTxBuff[ucLen] = pucBuff[ucLen];
};
SX1276LoRaSetOpMode(RFLR_OPMODE_STANDBY);
LoRaPara.RegBuff.RegIrqFlagsMask = RFLR_IRQFLAGS_RXTIMEOUT | RFLR_IRQFLAGS_RXDONE | RFLR_IRQFLAGS_PAYLOADCRCERROR | RFLR_IRQFLAGS_VALIDHEADER;
//LoRaPara.RegBuff.RegHopPeriod = 0;
//SX1276Write(REG_LR_HOPPERIOD, LoRaPara.RegBuff.RegHopPeriod);
SX1276Write(REG_LR_IRQFLAGSMASK, LoRaPara.RegBuff.RegIrqFlagsMask);
// Initializes the payload size
LoRaPara.RegBuff.RegPayloadLength = LoRaPara.ucTxPacketSize;
SX1276Write(REG_LR_PAYLOADLENGTH, LoRaPara.RegBuff.RegPayloadLength);
LoRaPara.RegBuff.RegFifoTxBaseAddr = 0x00; // Full buffer used for Tx
SX1276Write(REG_LR_FIFOTXBASEADDR, LoRaPara.RegBuff.RegFifoTxBaseAddr);
LoRaPara.RegBuff.RegFifoAddrPtr = LoRaPara.RegBuff.RegFifoTxBaseAddr;
SX1276Write(REG_LR_FIFOADDRPTR, LoRaPara.RegBuff.RegFifoAddrPtr);
// Write payload buffer to LORA modem
SX1276WriteFifo(LoRaPara.RxTxBuff, LoRaPara.RegBuff.RegPayloadLength);
// TxDone RxTimeout FhssChangeChannel ValidHeader
LoRaPara.RegBuff.RegDioMapping1 = RFLR_DIOMAPPING1_DIO0_01 | RFLR_DIOMAPPING1_DIO1_00 | RFLR_DIOMAPPING1_DIO2_00 | RFLR_DIOMAPPING1_DIO3_01;
// PllLock Mode Ready
LoRaPara.RegBuff.RegDioMapping2 = RFLR_DIOMAPPING2_DIO4_01 | RFLR_DIOMAPPING2_DIO5_00;
SX1276WriteBuffer(REG_LR_DIOMAPPING1, &(LoRaPara.RegBuff.RegDioMapping1), 2);
SX1276LoRaSetOpMode(RFLR_OPMODE_TRANSMITTER);
uint8_t temp;
SX1276Read(REG_LR_IRQFLAGS, &temp);
//LORA_TXLED_ON();
LoRaPara.State = SX1276_TX;
}
void Sx1276LoRaSleep(void)
{
SX1276LoRaSetOpMode(RFLR_OPMODE_SLEEP);//RFLR_OPMODE_STANDBY
}
void Sx1276LoRaWakeup(void)
{
Sx1276LoRaEnterRx();
}
////////////////////////////////////////
//配置本层参数的函数
//频道表
const uint32_t gdwSx1276ChannelTbl[SX1276_CHANNEL_MAX]={
FREQ_CENT-FREQ_DEV*8, FREQ_CENT-FREQ_DEV*7, FREQ_CENT-FREQ_DEV*6, FREQ_CENT-FREQ_DEV*5,
FREQ_CENT-FREQ_DEV*4, FREQ_CENT-FREQ_DEV*3, FREQ_CENT-FREQ_DEV*2, FREQ_CENT-FREQ_DEV*1,
FREQ_CENT+FREQ_DEV*0, FREQ_CENT+FREQ_DEV*1, FREQ_CENT+FREQ_DEV*2, FREQ_CENT+FREQ_DEV*3,
FREQ_CENT+FREQ_DEV*4, FREQ_CENT+FREQ_DEV*5, FREQ_CENT+FREQ_DEV*6, FREQ_CENT+FREQ_DEV*7,
FREQ_CENT+FREQ_DEV*8
};
//LORAPT_CHANNEL
uint8_t SX1276LoRaReadChannel(void)
{
return LoRaPara.ucChannel;
}
boolean_t SX1276LoRaWriteChannel(uint8_t Channel)
{
if(Channel > SX1276_CHANNEL_MAX) {
return FALSE;
}
LoRaPara.dwFreqHz = gdwSx1276ChannelTbl[Channel];
SX1276LoRaSetFreqHz(LoRaPara.dwFreqHz);
return TRUE;
}
//LORAPT_FREQ,
uint32_t SX1276LoRaReadFreq(void)
{
return LoRaPara.dwFreqHz;
}
void SX1276LoRaWriteFreq(uint32_t Freq)
{
SX1276LoRaSetFreqHz(Freq);
}
//LORAPT_BW,
uint32_t SX1276LoRaReadBw(void)
{
return LoRaPara.SignalBw;
}
void SX1276LoRaWriteBw(Sx1276BwType SignalBw)
{
LoRaPara.SignalBw = SignalBw;
SX1276LoRaSetSignalBandwidth(SignalBw);
}
//LORAPT_SF,
uint8_t SX1276LoRaReadSf(void)
{
return LoRaPara.SpreadFactor;
}
void SX1276LoRaWriteSf(Sx1276SpreadFactorType SpreadFactor)
{
LoRaPara.SpreadFactor = SpreadFactor;
SX1276LoRaSetSpreadingFactor(LoRaPara.SpreadFactor);
}
//LORAPT_EC,
uint8_t SX1276LoRaReadEc(void)
{
return LoRaPara.ErrorCoding;
}
void SX1276LoRaWriteEc(Sx1276ErrorCodingType ErrorCoding)
{
LoRaPara.ErrorCoding = ErrorCoding;
SX1276LoRaSetErrorCoding(ErrorCoding);
}
//LORAPT_RSSI,
uint32_t SX1276LoRaParaReadRssi(void)
{
uint32_t rssi;
SX1276Read(REG_LR_PKTRSSIVALUE, &(LoRaPara.RegBuff.RegPktRssiValue));
SX1276Read(REG_LR_RSSIVALUE, &(LoRaPara.RegBuff.RegRssiValue));
rssi = (uint16_t)(LoRaPara.RegBuff.RegPktSnrValue)<<16;
rssi |= (uint16_t)(LoRaPara.RegBuff.RegRssiValue)<<8;
rssi |= LoRaPara.RegBuff.RegPktRssiValue;
return rssi;
}
uint8_t SX1276LoRaReadRssiPkt(void)
{
uint8_t RssiPkt;
SX1276Read(REG_LR_PKTRSSIVALUE, &LoRaPara.RegBuff.RegPktRssiValue);
RssiPkt = LoRaPara.RegBuff.RegPktRssiValue;
return RssiPkt;
}
//LORAPT_POWER,
void SX1276LoRaWritePwr(int8_t Pwr)
{
SX1276LoRaSetRfPower(Pwr);
}
//LORAPT_SET_RX,
void SX1276LoRaWriteRx(void)
{
Sx1276LoRaEnterRx();
}
//LORAPT_SET_SLEEP,true-Sleep, false-Wakeup
void SX1276LoRaWriteSleep(boolean_t Sleep)
{
if(Sleep){
Sx1276LoRaSleep();
}
else {
Sx1276LoRaWakeup();
}
}
Sx1276StateType_t SX1276LoRaReadStatus(void)
{
return LoRaPara.State;
}
///////////////RSSI Calc///////////////
void SX1276LoCalcRssiSnr(int8_t *pswRssi, int8_t *psbSnr)
{
int8_t sbSnr= LoRaPara.RegBuff.RegPktSnrValue & 0x80 ? (-1)*((int8_t)(((~LoRaPara.RegBuff.RegPktSnrValue+ 1)& 0xFF)/4)): (~LoRaPara.RegBuff.RegPktSnrValue& 0xFF)/4;
if (sbSnr > 0) {
*pswRssi= RSSI_OFFSET_LF+ LoRaPara.RegBuff.RegPktRssiValue;
}
else {
*pswRssi= NOISE_ABSOLUTE_ZERO + 10 + SIGNAL_BW_LOG_125KHZ + NOISE_FIGURE_LF + sbSnr;
}
*psbSnr= sbSnr;
}
#endif
+826
View File
@@ -0,0 +1,826 @@
#ifndef __SX127X_H
#define __SX127X_H
#include "bsp.h"
//Constant values need to compute the RSSI value
#define RSSI_OFFSET_LF -155
#define RSSI_OFFSET_HF -150
#define NOISE_ABSOLUTE_ZERO -174
#define NOISE_FIGURE_LF 4
#define NOISE_FIGURE_HF 6
#define SIGNAL_BW_LOG_125KHZ 5
//SX1276 definitions
#define XTAL_FREQ 32000000
#define FREQ_STEP 61.03515625
//SX1276 Internal registers Address
#define REG_LR_FIFO 0x00
// Common settings
#define REG_LR_OPMODE 0x01
#define REG_LR_BANDSETTING 0x04
#define REG_LR_FRFMSB 0x06
#define REG_LR_FRFMID 0x07
#define REG_LR_FRFLSB 0x08
// Tx settings
#define REG_LR_PACONFIG 0x09
#define REG_LR_PARAMP 0x0A
#define REG_LR_OCP 0x0B
// Rx settings
#define REG_LR_LNA 0x0C
// LoRa registers
#define REG_LR_FIFOADDRPTR 0x0D
#define REG_LR_FIFOTXBASEADDR 0x0E
#define REG_LR_FIFORXBASEADDR 0x0F
#define REG_LR_FIFORXCURRENTADDR 0x10
#define REG_LR_IRQFLAGSMASK 0x11
#define REG_LR_IRQFLAGS 0x12
#define REG_LR_NBRXBYTES 0x13
#define REG_LR_RXHEADERCNTVALUEMSB 0x14
#define REG_LR_RXHEADERCNTVALUELSB 0x15
#define REG_LR_RXPACKETCNTVALUEMSB 0x16
#define REG_LR_RXPACKETCNTVALUELSB 0x17
#define REG_LR_MODEMSTAT 0x18
#define REG_LR_PKTSNRVALUE 0x19
#define REG_LR_PKTRSSIVALUE 0x1A
#define REG_LR_RSSIVALUE 0x1B
#define REG_LR_HOPCHANNEL 0x1C
#define REG_LR_MODEMCONFIG1 0x1D
#define REG_LR_MODEMCONFIG2 0x1E
#define REG_LR_SYMBTIMEOUTLSB 0x1F
#define REG_LR_PREAMBLEMSB 0x20
#define REG_LR_PREAMBLELSB 0x21
#define REG_LR_PAYLOADLENGTH 0x22
#define REG_LR_PAYLOADMAXLENGTH 0x23
#define REG_LR_HOPPERIOD 0x24
#define REG_LR_FIFORXBYTEADDR 0x25
#define REG_LR_MODEMCONFIG3 0x26
// end of documented register in datasheet
// I/O settings
#define REG_LR_DIOMAPPING1 0x40
#define REG_LR_DIOMAPPING2 0x41
// Version
#define REG_LR_VERSION 0x42
// Additional settings
#define REG_LR_PLLHOP 0x44
#define REG_LR_TCXO 0x4B
#define REG_LR_PADAC 0x4D
#define REG_LR_FORMERTEMP 0x5B
#define REG_LR_BITRATEFRAC 0x5D
#define REG_LR_AGCREF 0x61
#define REG_LR_AGCTHRESH1 0x62
#define REG_LR_AGCTHRESH2 0x63
#define REG_LR_AGCTHRESH3 0x64
//RegOpMode
typedef enum{
RFLR_OPMODE_LONGRANGEMODE_MASK =0x7F,
RFLR_OPMODE_LONGRANGEMODE_OFF =0x00, // Default
RFLR_OPMODE_LONGRANGEMODE_ON =0x80,
RFLR_OPMODE_ACCESSSHAREDREG_MASK =0xBF,
RFLR_OPMODE_ACCESSSHAREDREG_ENABLE =0x40,
RFLR_OPMODE_ACCESSSHAREDREG_DISABLE =0x00, // Default
RFLR_OPMODE_FREQMODE_ACCESS_MASK =0xF7,
RFLR_OPMODE_FREQMODE_ACCESS_LF =0x08, // Default
RFLR_OPMODE_FREQMODE_ACCESS_HF =0x00,
RFLR_OPMODE_MASK =0xF8,
RFLR_OPMODE_SLEEP =0x00,
RFLR_OPMODE_STANDBY =0x01, // Default
RFLR_OPMODE_SYNTHESIZER_TX =0x02,
RFLR_OPMODE_TRANSMITTER =0x03,
RFLR_OPMODE_SYNTHESIZER_RX =0x04,
RFLR_OPMODE_RECEIVER =0x05,
// LoRa specific modes
RFLR_OPMODE_RECEIVER_SINGLE =0x06,
RFLR_OPMODE_CAD =0x07
}Sx1276OpModeType;
//RegBandSetting
#define RFLR_BANDSETTING_MASK 0x3F
#define RFLR_BANDSETTING_AUTO 0x00 // Default
#define RFLR_BANDSETTING_DIV_BY_1 0x40
#define RFLR_BANDSETTING_DIV_BY_2 0x80
#define RFLR_BANDSETTING_DIV_BY_6 0xC0
//RegFrf (MHz)
#define RFLR_FRFMSB_434_MHZ 0x6C // Default
#define RFLR_FRFMID_434_MHZ 0x80 // Default
#define RFLR_FRFLSB_434_MHZ 0x00 // Default
#define RFLR_FRFMSB_863_MHZ 0xD7
#define RFLR_FRFMID_863_MHZ 0xC0
#define RFLR_FRFLSB_863_MHZ 0x00
#define RFLR_FRFMSB_864_MHZ 0xD8
#define RFLR_FRFMID_864_MHZ 0x00
#define RFLR_FRFLSB_864_MHZ 0x00
#define RFLR_FRFMSB_865_MHZ 0xD8
#define RFLR_FRFMID_865_MHZ 0x40
#define RFLR_FRFLSB_865_MHZ 0x00
#define RFLR_FRFMSB_866_MHZ 0xD8
#define RFLR_FRFMID_866_MHZ 0x80
#define RFLR_FRFLSB_866_MHZ 0x00
#define RFLR_FRFMSB_867_MHZ 0xD8
#define RFLR_FRFMID_867_MHZ 0xC0
#define RFLR_FRFLSB_867_MHZ 0x00
#define RFLR_FRFMSB_868_MHZ 0xD9
#define RFLR_FRFMID_868_MHZ 0x00
#define RFLR_FRFLSB_868_MHZ 0x00
#define RFLR_FRFMSB_869_MHZ 0xD9
#define RFLR_FRFMID_869_MHZ 0x40
#define RFLR_FRFLSB_869_MHZ 0x00
#define RFLR_FRFMSB_870_MHZ 0xD9
#define RFLR_FRFMID_870_MHZ 0x80
#define RFLR_FRFLSB_870_MHZ 0x00
#define RFLR_FRFMSB_902_MHZ 0xE1
#define RFLR_FRFMID_902_MHZ 0x80
#define RFLR_FRFLSB_902_MHZ 0x00
#define RFLR_FRFMSB_903_MHZ 0xE1
#define RFLR_FRFMID_903_MHZ 0xC0
#define RFLR_FRFLSB_903_MHZ 0x00
#define RFLR_FRFMSB_904_MHZ 0xE2
#define RFLR_FRFMID_904_MHZ 0x00
#define RFLR_FRFLSB_904_MHZ 0x00
#define RFLR_FRFMSB_905_MHZ 0xE2
#define RFLR_FRFMID_905_MHZ 0x40
#define RFLR_FRFLSB_905_MHZ 0x00
#define RFLR_FRFMSB_906_MHZ 0xE2
#define RFLR_FRFMID_906_MHZ 0x80
#define RFLR_FRFLSB_906_MHZ 0x00
#define RFLR_FRFMSB_907_MHZ 0xE2
#define RFLR_FRFMID_907_MHZ 0xC0
#define RFLR_FRFLSB_907_MHZ 0x00
#define RFLR_FRFMSB_908_MHZ 0xE3
#define RFLR_FRFMID_908_MHZ 0x00
#define RFLR_FRFLSB_908_MHZ 0x00
#define RFLR_FRFMSB_909_MHZ 0xE3
#define RFLR_FRFMID_909_MHZ 0x40
#define RFLR_FRFLSB_909_MHZ 0x00
#define RFLR_FRFMSB_910_MHZ 0xE3
#define RFLR_FRFMID_910_MHZ 0x80
#define RFLR_FRFLSB_910_MHZ 0x00
#define RFLR_FRFMSB_911_MHZ 0xE3
#define RFLR_FRFMID_911_MHZ 0xC0
#define RFLR_FRFLSB_911_MHZ 0x00
#define RFLR_FRFMSB_912_MHZ 0xE4
#define RFLR_FRFMID_912_MHZ 0x00
#define RFLR_FRFLSB_912_MHZ 0x00
#define RFLR_FRFMSB_913_MHZ 0xE4
#define RFLR_FRFMID_913_MHZ 0x40
#define RFLR_FRFLSB_913_MHZ 0x00
#define RFLR_FRFMSB_914_MHZ 0xE4
#define RFLR_FRFMID_914_MHZ 0x80
#define RFLR_FRFLSB_914_MHZ 0x00
#define RFLR_FRFMSB_915_MHZ 0xE4 // Default
#define RFLR_FRFMID_915_MHZ 0xC0 // Default
#define RFLR_FRFLSB_915_MHZ 0x00 // Default
#define RFLR_FRFMSB_916_MHZ 0xE5
#define RFLR_FRFMID_916_MHZ 0x00
#define RFLR_FRFLSB_916_MHZ 0x00
#define RFLR_FRFMSB_917_MHZ 0xE5
#define RFLR_FRFMID_917_MHZ 0x40
#define RFLR_FRFLSB_917_MHZ 0x00
#define RFLR_FRFMSB_918_MHZ 0xE5
#define RFLR_FRFMID_918_MHZ 0x80
#define RFLR_FRFLSB_918_MHZ 0x00
#define RFLR_FRFMSB_919_MHZ 0xE5
#define RFLR_FRFMID_919_MHZ 0xC0
#define RFLR_FRFLSB_919_MHZ 0x00
#define RFLR_FRFMSB_920_MHZ 0xE6
#define RFLR_FRFMID_920_MHZ 0x00
#define RFLR_FRFLSB_920_MHZ 0x00
#define RFLR_FRFMSB_921_MHZ 0xE6
#define RFLR_FRFMID_921_MHZ 0x40
#define RFLR_FRFLSB_921_MHZ 0x00
#define RFLR_FRFMSB_922_MHZ 0xE6
#define RFLR_FRFMID_922_MHZ 0x80
#define RFLR_FRFLSB_922_MHZ 0x00
#define RFLR_FRFMSB_923_MHZ 0xE6
#define RFLR_FRFMID_923_MHZ 0xC0
#define RFLR_FRFLSB_923_MHZ 0x00
#define RFLR_FRFMSB_924_MHZ 0xE7
#define RFLR_FRFMID_924_MHZ 0x00
#define RFLR_FRFLSB_924_MHZ 0x00
#define RFLR_FRFMSB_925_MHZ 0xE7
#define RFLR_FRFMID_925_MHZ 0x40
#define RFLR_FRFLSB_925_MHZ 0x00
#define RFLR_FRFMSB_926_MHZ 0xE7
#define RFLR_FRFMID_926_MHZ 0x80
#define RFLR_FRFLSB_926_MHZ 0x00
#define RFLR_FRFMSB_927_MHZ 0xE7
#define RFLR_FRFMID_927_MHZ 0xC0
#define RFLR_FRFLSB_927_MHZ 0x00
#define RFLR_FRFMSB_928_MHZ 0xE8
#define RFLR_FRFMID_928_MHZ 0x00
#define RFLR_FRFLSB_928_MHZ 0x00
//RegPaConfig
#define RFLR_PACONFIG_PASELECT_MASK 0x7F
#define RFLR_PACONFIG_PASELECT_PABOOST 0x80
#define RFLR_PACONFIG_PASELECT_RFO 0x00 // Default
#define RFLR_PACONFIG_MAX_POWER_MASK 0x8F
#define RFLR_PACONFIG_OUTPUTPOWER_MASK 0xF0
//RegPaRamp
#define RFLR_PARAMP_TXBANDFORCE_MASK 0xEF
#define RFLR_PARAMP_TXBANDFORCE_BAND_SEL 0x10
#define RFLR_PARAMP_TXBANDFORCE_AUTO 0x00 // Default
#define RFLR_PARAMP_MASK 0xF0
#define RFLR_PARAMP_3400_US 0x00
#define RFLR_PARAMP_2000_US 0x01
#define RFLR_PARAMP_1000_US 0x02
#define RFLR_PARAMP_0500_US 0x03
#define RFLR_PARAMP_0250_US 0x04
#define RFLR_PARAMP_0125_US 0x05
#define RFLR_PARAMP_0100_US 0x06
#define RFLR_PARAMP_0062_US 0x07
#define RFLR_PARAMP_0050_US 0x08
#define RFLR_PARAMP_0040_US 0x09 // Default
#define RFLR_PARAMP_0031_US 0x0A
#define RFLR_PARAMP_0025_US 0x0B
#define RFLR_PARAMP_0020_US 0x0C
#define RFLR_PARAMP_0015_US 0x0D
#define RFLR_PARAMP_0012_US 0x0E
#define RFLR_PARAMP_0010_US 0x0F
//RegOcp
#define RFLR_OCP_MASK 0xDF
#define RFLR_OCP_ON 0x20 // Default
#define RFLR_OCP_OFF 0x00
#define RFLR_OCP_TRIM_MASK 0xE0
#define RFLR_OCP_TRIM_045_MA 0x00
#define RFLR_OCP_TRIM_050_MA 0x01
#define RFLR_OCP_TRIM_055_MA 0x02
#define RFLR_OCP_TRIM_060_MA 0x03
#define RFLR_OCP_TRIM_065_MA 0x04
#define RFLR_OCP_TRIM_070_MA 0x05
#define RFLR_OCP_TRIM_075_MA 0x06
#define RFLR_OCP_TRIM_080_MA 0x07
#define RFLR_OCP_TRIM_085_MA 0x08
#define RFLR_OCP_TRIM_090_MA 0x09
#define RFLR_OCP_TRIM_095_MA 0x0A
#define RFLR_OCP_TRIM_100_MA 0x0B // Default
#define RFLR_OCP_TRIM_105_MA 0x0C
#define RFLR_OCP_TRIM_110_MA 0x0D
#define RFLR_OCP_TRIM_115_MA 0x0E
#define RFLR_OCP_TRIM_120_MA 0x0F
#define RFLR_OCP_TRIM_130_MA 0x10
#define RFLR_OCP_TRIM_140_MA 0x11
#define RFLR_OCP_TRIM_150_MA 0x12
#define RFLR_OCP_TRIM_160_MA 0x13
#define RFLR_OCP_TRIM_170_MA 0x14
#define RFLR_OCP_TRIM_180_MA 0x15
#define RFLR_OCP_TRIM_190_MA 0x16
#define RFLR_OCP_TRIM_200_MA 0x17
#define RFLR_OCP_TRIM_210_MA 0x18
#define RFLR_OCP_TRIM_220_MA 0x19
#define RFLR_OCP_TRIM_230_MA 0x1A
#define RFLR_OCP_TRIM_240_MA 0x1B
//RegLna
#define RFLR_LNA_GAIN_MASK 0x1F
#define RFLR_LNA_GAIN_G1 0x20 // Default
#define RFLR_LNA_GAIN_G2 0x40
#define RFLR_LNA_GAIN_G3 0x60
#define RFLR_LNA_GAIN_G4 0x80
#define RFLR_LNA_GAIN_G5 0xA0
#define RFLR_LNA_GAIN_G6 0xC0
#define RFLR_LNA_BOOST_LF_MASK 0xE7
#define RFLR_LNA_BOOST_LF_DEFAULT 0x00 // Default
#define RFLR_LNA_BOOST_LF_GAIN 0x08
#define RFLR_LNA_BOOST_LF_IP3 0x10
#define RFLR_LNA_BOOST_LF_BOOST 0x18
#define RFLR_LNA_RXBANDFORCE_MASK 0xFB
#define RFLR_LNA_RXBANDFORCE_BAND_SEL 0x04
#define RFLR_LNA_RXBANDFORCE_AUTO 0x00 // Default
#define RFLR_LNA_BOOST_HF_MASK 0xFC
#define RFLR_LNA_BOOST_HF_OFF 0x00 // Default
#define RFLR_LNA_BOOST_HF_ON 0x03
//RegFifoAddrPtr
#define RFLR_FIFOADDRPTR 0x00 // Default
//RegFifoTxBaseAddr
#define RFLR_FIFOTXBASEADDR 0x80 // Default
//RegFifoTxBaseAddr
#define RFLR_FIFORXBASEADDR 0x00 // Default
//RegFifoRxCurrentAddr (Read Only)
//RegIrqFlagsMask
#define RFLR_IRQFLAGS_RXTIMEOUT_MASK 0x80
#define RFLR_IRQFLAGS_RXDONE_MASK 0x40
#define RFLR_IRQFLAGS_PAYLOADCRCERROR_MASK 0x20
#define RFLR_IRQFLAGS_VALIDHEADER_MASK 0x10
#define RFLR_IRQFLAGS_TXDONE_MASK 0x08
#define RFLR_IRQFLAGS_CADDONE_MASK 0x04
#define RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL_MASK 0x02
#define RFLR_IRQFLAGS_CADDETECTED_MASK 0x01
//RegIrqFlags
#define RFLR_IRQFLAGS_RXTIMEOUT 0x80
#define RFLR_IRQFLAGS_RXDONE 0x40
#define RFLR_IRQFLAGS_PAYLOADCRCERROR 0x20
#define RFLR_IRQFLAGS_VALIDHEADER 0x10
#define RFLR_IRQFLAGS_TXDONE 0x08
#define RFLR_IRQFLAGS_CADDONE 0x04
#define RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL 0x02
#define RFLR_IRQFLAGS_CADDETECTED 0x01
//RegModemStat (Read Only)
#define RFLR_MODEMSTAT_RX_CR_MASK 0x1F
#define RFLR_MODEMSTAT_MODEM_STATUS_MASK 0xE0
//RegModemConfig1
#define RFLR_MODEMCONFIG1_BW_MASK 0x0F
#define RFLR_MODEMCONFIG1_BW_7_81_KHZ 0x00
#define RFLR_MODEMCONFIG1_BW_10_41_KHZ 0x10
#define RFLR_MODEMCONFIG1_BW_15_62_KHZ 0x20
#define RFLR_MODEMCONFIG1_BW_20_83_KHZ 0x30
#define RFLR_MODEMCONFIG1_BW_31_25_KHZ 0x40
#define RFLR_MODEMCONFIG1_BW_41_66_KHZ 0x50
#define RFLR_MODEMCONFIG1_BW_62_50_KHZ 0x60
#define RFLR_MODEMCONFIG1_BW_125_KHZ 0x70 // Default
#define RFLR_MODEMCONFIG1_BW_250_KHZ 0x80
#define RFLR_MODEMCONFIG1_BW_500_KHZ 0x90
#define RFLR_MODEMCONFIG1_CODINGRATE_MASK 0xF1
#define RFLR_MODEMCONFIG1_CODINGRATE_4_5 0x02
#define RFLR_MODEMCONFIG1_CODINGRATE_4_6 0x04 // Default
#define RFLR_MODEMCONFIG1_CODINGRATE_4_7 0x06
#define RFLR_MODEMCONFIG1_CODINGRATE_4_8 0x08
#define RFLR_MODEMCONFIG1_IMPLICITHEADER_MASK 0xFE
#define RFLR_MODEMCONFIG1_IMPLICITHEADER_ON 0x00
#define RFLR_MODEMCONFIG1_IMPLICITHEADER_OFF 0x01 // Default
//RegModemConfig2
#define RFLR_MODEMCONFIG2_SF_MASK 0x0F
#define RFLR_MODEMCONFIG2_SF_6 0x60
#define RFLR_MODEMCONFIG2_SF_7 0x70 // Default
#define RFLR_MODEMCONFIG2_SF_8 0x80
#define RFLR_MODEMCONFIG2_SF_9 0x90
#define RFLR_MODEMCONFIG2_SF_10 0xA0
#define RFLR_MODEMCONFIG2_SF_11 0xB0
#define RFLR_MODEMCONFIG2_SF_12 0xC0
#define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_MASK 0xF7
#define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_ON 0x08
#define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_OFF 0x00
#define RFLR_MODEMCONFIG2_RXPAYLOADCRC_MASK 0xFB
#define RFLR_MODEMCONFIG2_RXPAYLOADCRC_ON 0x04
#define RFLR_MODEMCONFIG2_RXPAYLOADCRC_OFF 0x00 // Default
#define RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK 0xFC
#define RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB 0x00 // Default
//RegHopChannel (Read Only)
#define RFLR_HOPCHANNEL_PLL_LOCK_TIMEOUT_MASK 0x7F
#define RFLR_HOPCHANNEL_PLL_LOCK_FAIL 0x80
#define RFLR_HOPCHANNEL_PLL_LOCK_SUCCEED 0x00 // Default
#define RFLR_HOPCHANNEL_PAYLOAD_CRC16_MASK 0xBF
#define RFLR_HOPCHANNEL_PAYLOAD_CRC16_ON 0x40
#define RFLR_HOPCHANNEL_PAYLOAD_CRC16_OFF 0x00 // Default
#define RFLR_HOPCHANNEL_CHANNEL_MASK 0x3F
//RegSymbTimeoutLsb
#define RFLR_SYMBTIMEOUTLSB_SYMBTIMEOUT 0x64 // Default
//RegPreambleLengthMsb
#define RFLR_PREAMBLELENGTHMSB 0x00 // Default
//RegPreambleLengthLsb
#define RFLR_PREAMBLELENGTHLSB 0x08 // Default
//RegPayloadLength
#define RFLR_PAYLOADLENGTH 0x0E // Default
//RegPayloadMaxLength
#define RFLR_PAYLOADMAXLENGTH 0xFF // Default
//RegHopPeriod
#define RFLR_HOPPERIOD_FREQFOPPINGPERIOD 0x00 // Default
//RegDioMapping1
//DIO0
#define RFLR_DIOMAPPING1_DIO0_MASK 0x3F
#define RFLR_DIOMAPPING1_DIO0_00 0x00 // Default
#define RFLR_DIOMAPPING1_DIO0_01 0x40
#define RFLR_DIOMAPPING1_DIO0_10 0x80
#define RFLR_DIOMAPPING1_DIO0_11 0xC0
//DIO1
#define RFLR_DIOMAPPING1_DIO1_MASK 0xCF
#define RFLR_DIOMAPPING1_DIO1_00 0x00 // Default
#define RFLR_DIOMAPPING1_DIO1_01 0x10
#define RFLR_DIOMAPPING1_DIO1_10 0x20
#define RFLR_DIOMAPPING1_DIO1_11 0x30
//DIO2
#define RFLR_DIOMAPPING1_DIO2_MASK 0xF3
#define RFLR_DIOMAPPING1_DIO2_00 0x00 // Default
#define RFLR_DIOMAPPING1_DIO2_01 0x04
#define RFLR_DIOMAPPING1_DIO2_10 0x08
#define RFLR_DIOMAPPING1_DIO2_11 0x0C
//DIO3
#define RFLR_DIOMAPPING1_DIO3_MASK 0xFC
#define RFLR_DIOMAPPING1_DIO3_00 0x00 // Default
#define RFLR_DIOMAPPING1_DIO3_01 0x01
#define RFLR_DIOMAPPING1_DIO3_10 0x02
#define RFLR_DIOMAPPING1_DIO3_11 0x03
//RegDioMapping2
//DIO4
#define RFLR_DIOMAPPING2_DIO4_MASK 0x3F
#define RFLR_DIOMAPPING2_DIO4_00 0x00 // Default
#define RFLR_DIOMAPPING2_DIO4_01 0x40
#define RFLR_DIOMAPPING2_DIO4_10 0x80
#define RFLR_DIOMAPPING2_DIO4_11 0xC0
//DIO5
#define RFLR_DIOMAPPING2_DIO5_MASK 0xCF
#define RFLR_DIOMAPPING2_DIO5_00 0x00 // Default
#define RFLR_DIOMAPPING2_DIO5_01 0x10
#define RFLR_DIOMAPPING2_DIO5_10 0x20
#define RFLR_DIOMAPPING2_DIO5_11 0x30
//MAP
#define RFLR_DIOMAPPING2_MAP_MASK 0xFE
#define RFLR_DIOMAPPING2_MAP_PREAMBLEDETECT 0x01
#define RFLR_DIOMAPPING2_MAP_RSSI 0x00 // Default
// RegPllHop
#define RFLR_PLLHOP_FASTHOP_MASK 0x7F
#define RFLR_PLLHOP_FASTHOP_ON 0x80
#define RFLR_PLLHOP_FASTHOP_OFF 0x00 // Default
//RegTcxo
#define RFLR_TCXO_TCXOINPUT_MASK 0xEF
#define RFLR_TCXO_TCXOINPUT_ON 0x10
#define RFLR_TCXO_TCXOINPUT_OFF 0x00 // Default
//RegPaDac
#define RFLR_PADAC_20DBM_MASK 0xF8
#define RFLR_PADAC_20DBM_ON 0x07
#define RFLR_PADAC_20DBM_OFF 0x04 // Default
//RegPll
#define RFLR_PLL_BANDWIDTH_MASK 0x3F
#define RFLR_PLL_BANDWIDTH_75 0x00
#define RFLR_PLL_BANDWIDTH_150 0x40
#define RFLR_PLL_BANDWIDTH_225 0x80
#define RFLR_PLL_BANDWIDTH_300 0xC0 // Default
//RegPllLowPn
#define RFLR_PLLLOWPN_BANDWIDTH_MASK 0x3F
#define RFLR_PLLLOWPN_BANDWIDTH_75 0x00
#define RFLR_PLLLOWPN_BANDWIDTH_150 0x40
#define RFLR_PLLLOWPN_BANDWIDTH_225 0x80
#define RFLR_PLLLOWPN_BANDWIDTH_300 0xC0 // Default
//RegModemConfig3
#define RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_MASK 0xF7
#define RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_ON 0x08
#define RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_OFF 0x00 // Default
#define RFLR_MODEMCONFIG3_AGCAUTO_MASK 0xFB
#define RFLR_MODEMCONFIG3_AGCAUTO_ON 0x04 // Default
#define RFLR_MODEMCONFIG3_AGCAUTO_OFF 0x00
//REGISTER
typedef struct _Sx1276RegType{
uint8_t RegFifo; // 0x00
// Common settings
uint8_t RegOpMode; // 0x01
uint8_t RegRes02; // 0x02
uint8_t RegRes03; // 0x03
uint8_t RegBandSetting; // 0x04
uint8_t RegRes05; // 0x05
uint8_t RegFrfMsb; // 0x06
uint8_t RegFrfMid; // 0x07
uint8_t RegFrfLsb; // 0x08
// Tx settings
uint8_t RegPaConfig; // 0x09
uint8_t RegPaRamp; // 0x0A
uint8_t RegOcp; // 0x0B
// Rx settings
uint8_t RegLna; // 0x0C
// LoRa registers
uint8_t RegFifoAddrPtr; // 0x0D
uint8_t RegFifoTxBaseAddr; // 0x0E
uint8_t RegFifoRxBaseAddr; // 0x0F
uint8_t RegFifoRxCurrentAddr; // 0x10
uint8_t RegIrqFlagsMask; // 0x11
uint8_t RegIrqFlags; // 0x12
uint8_t RegNbRxBytes; // 0x13
uint8_t RegRxHeaderCntValueMsb; // 0x14
uint8_t RegRxHeaderCntValueLsb; // 0x15
uint8_t RegRxPacketCntValueMsb; // 0x16
uint8_t RegRxPacketCntValueLsb; // 0x17
uint8_t RegModemStat; // 0x18
uint8_t RegPktSnrValue; // 0x19
uint8_t RegPktRssiValue; // 0x1A
uint8_t RegRssiValue; // 0x1B
uint8_t RegHopChannel; // 0x1C
uint8_t RegModemConfig1; // 0x1D
uint8_t RegModemConfig2; // 0x1E
uint8_t RegSymbTimeoutLsb; // 0x1F
uint8_t RegPreambleMsb; // 0x20
uint8_t RegPreambleLsb; // 0x21
uint8_t RegPayloadLength; // 0x22
uint8_t RegMaxPayloadLength; // 0x23
uint8_t RegHopPeriod; // 0x24
uint8_t RegFifoRxByteAddr; // 0x25
uint8_t RegModemConfig3; // 0x26
uint8_t RegTestReserved27[0x30 - 0x27]; // 0x27-0x30
uint8_t RegTestReserved31; // 0x31
uint8_t RegTestReserved32[0x40 - 0x32]; // 0x32-0x40
// I/O settings
uint8_t RegDioMapping1; // 0x40
uint8_t RegDioMapping2; // 0x41
// Version
uint8_t RegVersion; // 0x42
// Additional settings
uint8_t RegAgcRef; // 0x43
uint8_t RegAgcThresh1; // 0x44
uint8_t RegAgcThresh2; // 0x45
uint8_t RegAgcThresh3; // 0x46
// Test
uint8_t RegTestReserved47[0x4B - 0x47]; // 0x47-0x4A
// Additional settings
uint8_t RegPllHop; // 0x4B
uint8_t RegTestReserved4C; // 0x4C
uint8_t RegPaDac; // 0x4D
// Test
//uint8_t RegTestReserved4E[0x58-0x4E]; // 0x4E-0x57
// Additional settings
//uint8_t RegTcxo; // 0x58
// Test
//uint8_t RegTestReserved59; // 0x59
// Test
//uint8_t RegTestReserved5B; // 0x5B
// Additional settings
//uint8_t RegPll; // 0x5C
// Test
//uint8_t RegTestReserved5D; // 0x5D
// Additional settings
//uint8_t RegPllLowPn; // 0x5E
// Test
//uint8_t RegTestReserved5F[0x6C - 0x5F]; // 0x5F-0x6B
// Additional settings
//uint8_t RegFormerTemp; // 0x6C
// Test
//uint8_t RegTestReserved6D[0x71 - 0x6D]; // 0x6D-0x70
}Sx1276RegType;
#define SIZE_OF_REGISTERS (sizeof(Sx1276RegType))
//RF state machine
typedef enum{
RFLR_STATE_IDLE,
RFLR_STATE_RX_RUNNING,
RFLR_STATE_TX_RUNNING,
}LRStateType;
typedef enum{
RADIO_RESET_OFF,
RADIO_RESET_ON,
}tRadioResetState;
typedef enum{
RF_IDLE,
RF_BUSY,
RF_RX_DONE,
RF_RX_TIMEOUT,
RF_TX_DONE,
RF_TX_TIMEOUT,
RF_LEN_ERROR,
RF_CHANNEL_EMPTY,
RF_CHANNEL_ACTIVITY_DETECTED,
}Sx1276RetType;
typedef enum{
SX1276_BW_7K8= (0),
SX1276_BW_10K4= (1<<4),
SX1276_BW_15K6= (2<<4),
SX1276_BW_20K8= (3<<4),
SX1276_BW_31K2= (4<<4),
SX1276_BW_41K6= (5<<4),
SX1276_BW_62K5= (6<<4),
SX1276_BW_125K= (7<<4),
SX1276_BW_250K= (8<<4),
SX1276_BW_500K= (9<<4)
}Sx1276BwType;
typedef enum{
SX1276_SF_64= (6<<4),
SX1276_SF_128= (7<<4),
SX1276_SF_256= (8<<4),
SX1276_SF_512= (9<<4),
SX1276_SF_1024= (10<<4),
SX1276_SF_2048= (11<<4),
SX1276_SF_4096= (12<<4)
}Sx1276SpreadFactorType;
typedef enum{
SX1276_EC_4_5= (1<<1),
SX1276_EC_4_6= (2<<1),
SX1276_EC_4_7= (3<<1),
SX1276_EC_4_8= (4<<1)
}Sx1276ErrorCodingType;
typedef enum{
SX1276_CRC_OFF= (0),
SX1276_CRC_ON= (1<<2)
}Sx1276CrcOnType;
typedef enum{
SX1276_IH_OFF= (0),
SX1276_IH_ON= (1)
}Sx1276ImplicitHeaderOnType;
// ɱ
typedef struct _AutoSfType{
Sx1276SpreadFactorType Sf;
uint8_t ucRssiMin, ucRssiMax;
uint16_t wTimeout;
}AutoSfType, *PAutoSf;
//Parameter
typedef enum{
LORAPT_STATUS,
LORAPT_CHANNEL,
LORAPT_FREQ,
LORAPT_BW,
LORAPT_SF,
LORAPT_EC,
LORAPT_RSSI,
LORAPT_POWER,
LORAPT_SET_RX,
LORAPT_SET_SLEEP,
LORAPT_MAX
}Sx1276LoraParaType;
#define SX1276_CHANNEL_MAX 17
#define LORA_RESET_SET() SET_LORA_RST()
#define LORA_RESET_CLR() CLR_LORA_RST()
#define LORA_SPI_NSS_SET() Spi_SetCS(M0P_SPI0, TRUE) //取消片选
#define LORA_SPI_NSS_CLR() Spi_SetCS(M0P_SPI0, FALSE) //使能器件
#define LORA_SPI_READ_WRITE(x) Spi0SendReceive(x)
#define LORA_GETDIO0() GET_LORA_DIO0()
#define LORA_GETDIO1() GET_LORA_DIO1()
#define USE_RF_SW 0
#define USE_LORA_LED 0
#if USE_RF_SW == 1
#define LORA_ANTTXEN() { \
SET_LORA_TXEN();\
CLR_LORA_RXEN();\
}
#define LORA_ANTRXEN() { \
SET_LORA_RXEN();\
CLR_LORA_TXEN();\
}
#define LORA_ANTCLOSE() { \
CLR_LORA_RXEN();\
CLR_LORA_TXEN();\
}
#else
#define LORA_ANTTXEN()
#define LORA_ANTRXEN()
#define LORA_ANTCLOSE()
#endif
#if USE_LORA_LED == 1
#define LORA_TXLED_ON() SET_LED_PIN()
#define LORA_TXLED_OFF() CLR_LED_PIN()
#else
#define LORA_TXLED_ON() SET_LORA_TX_LED()
#define LORA_TXLED_OFF() CLR_LORA_TX_LED()
#endif
#define LORA_BUFF_SIZE 255
typedef enum {
RF_ANT_TRANSMITTER,
RF_ANT_RECEIVER,
RF_ANT_CLOSE,
}Sx1276AntStatus_m;
typedef enum {
SX1276_SLEEP,
SX1276_IDLE,
SX1276_RX,
SX1276_TX,
SX1276_BUSY,
SX1276_ERROR,
SX1276_MAX
}Sx1276StateType_t;
typedef struct {
uint8_t ucChannel;
uint32_t dwFreqHz;
int8_t ucPower;
Sx1276BwType SignalBw;
Sx1276SpreadFactorType SpreadFactor;
Sx1276ErrorCodingType ErrorCoding;
uint8_t RegPreamble;
uint8_t ucOpModePrev;
Sx1276AntStatus_m bAntSwPrev;
Sx1276RegType RegBuff;
Sx1276StateType_t State;
uint8_t ucRxPacketSize;
uint8_t ucTxPacketSize;
uint8_t RxTxBuff[LORA_BUFF_SIZE];
void (*RxCallBack)(uint8_t *rBuff, uint8_t rlen);
}Sx1276Type_t, *pSx1276Type;
//ISM Freq In China
//Up Link:
//CH0-5: 470.3-471.3MHz
//CH39-44:478.1-479.1MHz
//CH78-95:485.9-489.3MHz
//Down Link:
//CH0-47:500.3-509.7MHz
#define USE_915MHZ 0//=1ʹ 915 =0ʹ 433
#if (USE_915MHZ == 1)
// Ƶ ʣ Ĭ Ϊ449000000Hz
#define FREQ_CENT 915000000ul
//860MHz-1GHzʹ PA ţ Ĭ ϲ ʹ
//SX127x 壬HOPERFģ Ҫ
#define USE_LORA_860_PA
#endif
/*
中心频率配置:433100000ul + 200000*N
*/
#define CH0 (433100000ul + 0) //测试频率
#define CH1 (433100000ul + 200000)
#define CH2 (433100000ul + 400000)
#define CH3 (433100000ul + 600000)
#define CH4 (433100000ul + 800000)
#define CH5 (433100000ul + 1000000)
#define CH6 (433100000ul + 1200000)
#define CH7 (433100000ul + 1400000)
#define CH8 (433100000ul + 1600000)
#define CH9 (433100000ul + 1800000)
#define CH10 (433100000ul + 2000000)
#if (USE_LORA_CH == 0)
#define FREQ_CENT CH0
#elif (USE_LORA_CH == 1)
#define FREQ_CENT CH1
#elif (USE_LORA_CH == 2)
#define FREQ_CENT CH2
#elif (USE_LORA_CH == 3)
#define FREQ_CENT CH3
#elif (USE_LORA_CH == 4)
#define FREQ_CENT CH4
#elif (USE_LORA_CH == 5)
#define FREQ_CENT CH5
#elif (USE_LORA_CH == 6)
#define FREQ_CENT CH6
#elif (USE_LORA_CH == 7)
#define FREQ_CENT CH7
#elif (USE_LORA_CH == 8)
#define FREQ_CENT CH8
#elif (USE_LORA_CH == 9)
#define FREQ_CENT CH9
#elif (USE_LORA_CH == 10)
#define FREQ_CENT CH10
#endif
#if !defined FREQ_CENT
#define FREQ_CENT (433100000ul + 0)//200000
#endif
#if !defined FREQ_DEV
#define FREQ_DEV 1000000ul
#endif
//////////////////////////////////////////////////////////////////////
void Sx1276LoRaLoopHandler(void);
void Sx1276LoRaInit(void (*RxCallBack)(uint8_t *rBuff, uint8_t rlen));
void Sx1276LoRaSendBuffer(uint8_t* pucBuff, uint8_t ucLen);
uint8_t SX1276LoRaReadChannel(void);
boolean_t SX1276LoRaWriteChannel(uint8_t Channel);
uint32_t SX1276LoRaReadFreq(void);
void SX1276LoRaWriteFreq(uint32_t Freq);
void SX1276LoRaWriteBw(Sx1276BwType SignalBw);
uint32_t SX1276LoRaReadBw(void);
uint8_t SX1276LoRaReadSf(void);
void SX1276LoRaWriteSf(Sx1276SpreadFactorType SpreadFactor);
void SX1276LoRaWriteEc(Sx1276ErrorCodingType ErrorCoding);
uint8_t SX1276LoRaReadEc(void);
uint32_t SX1276LoRaParaReadRssi(void);
uint8_t SX1276LoRaReadRssiPkt(void);
void SX1276LoRaWritePwr(int8_t Pwr);
void SX1276LoRaWriteRx(void);
void SX1276LoRaWriteSleep(boolean_t Sleep);
Sx1276StateType_t SX1276LoRaReadStatus(void);
void SX1276LoCalcRssiSnr(int8_t *pswRssi, int8_t *psbSnr);
void Sx1276LoRaSleep(void);
void Sx1276LoRaWakeup(void);
#endif
+247
View File
@@ -0,0 +1,247 @@
//=====================================================================================================
// MahonyAHRS.c
//=====================================================================================================
//
// Madgwick's implementation of Mayhony's AHRS algorithm.
// See: http://www.x-io.co.uk/node/8#open_source_ahrs_and_imu_algorithms
//
// Date Author Notes
// 29/09/2011 SOH Madgwick Initial release
// 02/10/2011 SOH Madgwick Optimised for reduced CPU load
//
//=====================================================================================================
//---------------------------------------------------------------------------------------------------
// Header files
#include "MahonyAHRS.h"
#include <math.h>
//---------------------------------------------------------------------------------------------------
// Definitions
#define sampleFreq 10.0f // sample frequency in Hz
#define twoKpDef (2.0f * 1.0f) // 2 * proportional gain
#define twoKiDef (2.0f * 0.0f) // 2 * integral gain
//---------------------------------------------------------------------------------------------------
// Variable definitions
volatile float twoKp = twoKpDef; // 2 * proportional gain (Kp)
volatile float twoKi = twoKiDef; // 2 * integral gain (Ki)
volatile float q0 = 1.0f, q1 = 0.0f, q2 = 0.0f, q3 = 0.0f; // quaternion of sensor frame relative to auxiliary frame
volatile float integralFBx = 0.0f, integralFBy = 0.0f, integralFBz = 0.0f; // integral error terms scaled by Ki
//---------------------------------------------------------------------------------------------------
// Function declarations
//====================================================================================================
// Functions
//---------------------------------------------------------------------------------------------------
// AHRS algorithm update
void MahonyAHRSupdate(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz) {
float recipNorm;
float q0q0, q0q1, q0q2, q0q3, q1q1, q1q2, q1q3, q2q2, q2q3, q3q3;
float hx, hy, bx, bz;
float halfvx, halfvy, halfvz, halfwx, halfwy, halfwz;
float halfex, halfey, halfez;
float qa, qb, qc;
// Use IMU algorithm if magnetometer measurement invalid (avoids NaN in magnetometer normalisation)
// 在磁力计数据无效时使用六轴融合算法
if((mx == 0.0f) && (my == 0.0f) && (mz == 0.0f)) {
MahonyAHRSupdateIMU(gx, gy, gz, ax, ay, az);
return;
}
// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)
// 只在加速度计数据有效时才进行运算
if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {
// Normalise accelerometer measurement
// 将加速度计得到的实际重力加速度向量v单位化
recipNorm = invSqrt(ax * ax + ay * ay + az * az);
ax *= recipNorm;
ay *= recipNorm;
az *= recipNorm;
// Normalise magnetometer measurement
// 将磁力计得到的实际磁场向量m单位化
recipNorm = invSqrt(mx * mx + my * my + mz * mz);
mx *= recipNorm;
my *= recipNorm;
mz *= recipNorm;
// Auxiliary variables to avoid repeated arithmetic
// 辅助变量,以避免重复运算
q0q0 = q0 * q0;
q0q1 = q0 * q1;
q0q2 = q0 * q2;
q0q3 = q0 * q3;
q1q1 = q1 * q1;
q1q2 = q1 * q2;
q1q3 = q1 * q3;
q2q2 = q2 * q2;
q2q3 = q2 * q3;
q3q3 = q3 * q3;
// Reference direction of Earth's magnetic field
// 通过磁力计测量值与坐标转换矩阵得到大地坐标系下的理论地磁向量
hx = 2.0f * (mx * (0.5f - q2q2 - q3q3) + my * (q1q2 - q0q3) + mz * (q1q3 + q0q2));
hy = 2.0f * (mx * (q1q2 + q0q3) + my * (0.5f - q1q1 - q3q3) + mz * (q2q3 - q0q1));
bx = sqrt(hx * hx + hy * hy);
bz = 2.0f * (mx * (q1q3 - q0q2) + my * (q2q3 + q0q1) + mz * (0.5f - q1q1 - q2q2));
// Estimated direction of gravity and magnetic field
// 将理论重力加速度向量与理论地磁向量变换至机体坐标系
halfvx = q1q3 - q0q2;
halfvy = q0q1 + q2q3;
halfvz = q0q0 - 0.5f + q3q3;
halfwx = bx * (0.5f - q2q2 - q3q3) + bz * (q1q3 - q0q2);
halfwy = bx * (q1q2 - q0q3) + bz * (q0q1 + q2q3);
halfwz = bx * (q0q2 + q1q3) + bz * (0.5f - q1q1 - q2q2);
// Error is sum of cross product between estimated direction and measured direction of field vectors
// 通过向量外积得到重力加速度向量和地磁向量的实际值与测量值之间误差
halfex = (ay * halfvz - az * halfvy) + (my * halfwz - mz * halfwy);
halfey = (az * halfvx - ax * halfvz) + (mz * halfwx - mx * halfwz);
halfez = (ax * halfvy - ay * halfvx) + (mx * halfwy - my * halfwx);
// Compute and apply integral feedback if enabled
// 在PI补偿器中积分项使能情况下计算并应用积分项
if(twoKi > 0.0f) {
integralFBx += twoKi * halfex * (1.0f / sampleFreq); // integral error scaled by Ki
integralFBy += twoKi * halfey * (1.0f / sampleFreq);
integralFBz += twoKi * halfez * (1.0f / sampleFreq);
gx += integralFBx; // apply integral feedback // 应用误差补偿中的积分项
gy += integralFBy;
gz += integralFBz;
}
else {
integralFBx = 0.0f; // prevent integral windup // 避免为负值的Ki时积分异常饱和
integralFBy = 0.0f;
integralFBz = 0.0f;
}
// Apply proportional feedback
// 应用误差补偿中的比例项
gx += twoKp * halfex;
gy += twoKp * halfey;
gz += twoKp * halfez;
}
// Integrate rate of change of quaternion
// 微分方程迭代求解
gx *= (0.5f * (1.0f / sampleFreq)); // pre-multiply common factors
gy *= (0.5f * (1.0f / sampleFreq));
gz *= (0.5f * (1.0f / sampleFreq));
qa = q0;
qb = q1;
qc = q2;
q0 += (-qb * gx - qc * gy - q3 * gz);
q1 += (qa * gx + qc * gz - q3 * gy);
q2 += (qa * gy - qb * gz + q3 * gx);
q3 += (qa * gz + qb * gy - qc * gx);
// Normalise quaternion
// 单位化四元数 保证四元数在迭代过程中保持单位性质
recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
q0 *= recipNorm;
q1 *= recipNorm;
q2 *= recipNorm;
q3 *= recipNorm;
//Mahony官方程序到此结束,使用时只需在函数外进行四元数反解欧拉角即可完成全部姿态解算过程
}
//---------------------------------------------------------------------------------------------------
// IMU algorithm update
void MahonyAHRSupdateIMU(float gx, float gy, float gz, float ax, float ay, float az) {
float recipNorm;
float halfvx, halfvy, halfvz;//1/2 重力分量
float halfex, halfey, halfez;//1/2 重力误差
float qa, qb, qc;
// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)
// 在磁力计数据无效时使用六轴融合算法
if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {
// Normalise accelerometer measurement
recipNorm = invSqrt(ax * ax + ay * ay + az * az);
ax *= recipNorm;
ay *= recipNorm;
az *= recipNorm;
// Estimated direction of gravity and vector perpendicular to magnetic flux
halfvx = q1 * q3 - q0 * q2;
halfvy = q0 * q1 + q2 * q3;
halfvz = q0 * q0 - 0.5f + q3 * q3;
// Error is sum of cross product between estimated and measured direction of gravity
halfex = (ay * halfvz - az * halfvy);
halfey = (az * halfvx - ax * halfvz);
halfez = (ax * halfvy - ay * halfvx);
// Compute and apply integral feedback if enabled
if(twoKi > 0.0f) {
integralFBx += twoKi * halfex * (1.0f / sampleFreq); // integral error scaled by Ki
integralFBy += twoKi * halfey * (1.0f / sampleFreq);
integralFBz += twoKi * halfez * (1.0f / sampleFreq);
gx += integralFBx; // apply integral feedback
gy += integralFBy;
gz += integralFBz;
}
else {
integralFBx = 0.0f; // prevent integral windup
integralFBy = 0.0f;
integralFBz = 0.0f;
}
// Apply proportional feedback
gx += twoKp * halfex;
gy += twoKp * halfey;
gz += twoKp * halfez;
}
// Integrate rate of change of quaternion
gx *= (0.5f * (1.0f / sampleFreq)); // pre-multiply common factors
gy *= (0.5f * (1.0f / sampleFreq));
gz *= (0.5f * (1.0f / sampleFreq));
qa = q0;
qb = q1;
qc = q2;
q0 += (-qb * gx - qc * gy - q3 * gz);
q1 += (qa * gx + qc * gz - q3 * gy);
q2 += (qa * gy - qb * gz + q3 * gx);
q3 += (qa * gz + qb * gy - qc * gx);
// Normalise quaternion
recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
q0 *= recipNorm;
q1 *= recipNorm;
q2 *= recipNorm;
q3 *= recipNorm;
}
//---------------------------------------------------------------------------------------------------
// Fast inverse square-root
// See: http://en.wikipedia.org/wiki/Fast_inverse_square_root
float invSqrt(float x) {
float halfx = 0.5f * x;
float y = x;
long i = *(long*)&y;
i = 0x5f3759df - (i>>1);
y = *(float*)&i;
y = y * (1.5f - (halfx * y * y));
return y;
}
//====================================================================================================
// END OF CODE
//====================================================================================================
+32
View File
@@ -0,0 +1,32 @@
//=====================================================================================================
// MahonyAHRS.h
//=====================================================================================================
//
// Madgwick's implementation of Mayhony's AHRS algorithm.
// See: http://www.x-io.co.uk/node/8#open_source_ahrs_and_imu_algorithms
//
// Date Author Notes
// 29/09/2011 SOH Madgwick Initial release
// 02/10/2011 SOH Madgwick Optimised for reduced CPU load
//
//=====================================================================================================
#ifndef MahonyAHRS_h
#define MahonyAHRS_h
//----------------------------------------------------------------------------------------------------
// Variable declaration
extern volatile float twoKp; // 2 * proportional gain (Kp)
extern volatile float twoKi; // 2 * integral gain (Ki)
extern volatile float q0, q1, q2, q3; // quaternion of sensor frame relative to auxiliary frame
//---------------------------------------------------------------------------------------------------
// Function declarations
float invSqrt(float x);
void MahonyAHRSupdate(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz);
void MahonyAHRSupdateIMU(float gx, float gy, float gz, float ax, float ay, float az);
#endif
//=====================================================================================================
// End of file
//=====================================================================================================
+269
View File
@@ -0,0 +1,269 @@
/* Includes ------------------------------------------------------------------*/
#include "lsm6dsl_app.h"
#include "lsm6dsl_reg.h"
#include <string.h>
#include <stdio.h>
#include "bsp.h"
#include "UartDebug.h"
#include "main.h"
#include "i2c.h"
#include "Algorithm.h"
dev_ctx_t dev_ctx;
static bool InitFlag;
#define ACC_CVTTIME (20 * 1000)
#define ACC_COLL_CNT_MAX 6
#define ACC_FIFO_WATERMASK (ACC_COLL_CNT_MAX * 6) //采集一秒数据
#define TX_BUF_DIM 1000
#define BOOT_TIME 15 //ms
typedef enum {
Acc_Idle,
Acc_Start,
Acc_Get_Data,
Acc_Wait_GetData,
Acc_Go_Bypass,
}AccStatusType_m;
static AccStatusType_m acc_status;
static uint32_t acc_cvttime;
static bool Lsm6dslWaterMarkFullIntFlag;
static bool Lsm6dslWakeupIntFlag;
static int16_t data_raw_acceleration[3];
static int16_t data_raw_angular_rate[3];
static int16_t data_raw_temperature;
static float acceleration_mg[3][ACC_COLL_CNT_MAX];
static float angular_rate_mdps[3][ACC_COLL_CNT_MAX];
static float temperature_degC;
static uint8_t whoamI, rst;
static void platform_delay(uint32_t ms)
{
delay_ms(ms);
}
static void platform_write(uint8_t reg, uint8_t *bufp, uint32_t len)
{
uint16_t Selve_Add = LSM6DSL_I2C_ADD_L >> 1;
I2C_MasterWriteData(M0P_I2C0, Selve_Add, reg, bufp, len);
}
static void platform_read(uint8_t reg, uint8_t *bufp, uint32_t len)
{
uint16_t Selve_Add = LSM6DSL_I2C_ADD_L >> 1;
I2C_MasterReadData(M0P_I2C0, Selve_Add, reg, bufp, len);
}
static void Lsm6dsl_Init(void)
{
/* Initialize mems driver interface */
dev_ctx.write_reg = platform_write;
dev_ctx.read_reg = platform_read;
dev_ctx.mdelay = platform_delay;
/* Wait sensor boot time */
platform_delay(BOOT_TIME);
/* Check device ID */
whoamI = 0;
lsm6dsl_device_id_get(&dev_ctx, &whoamI);
acc_cvttime = 100;
while(whoamI != LSM6DSL_ID){
if(acc_cvttime <= 0){
DBG_LOG("LSM6DS INIT Err...\r\n"); /*manage here device not found */
InitFlag = false;
return;
}
}
/* Restore default configuration */
lsm6dsl_reset_set(&dev_ctx, PROPERTY_ENABLE);
do {
lsm6dsl_reset_get(&dev_ctx, &rst);
} while (rst);
lsm6dsl_xl_power_mode_set(&dev_ctx, LSM6DSL_XL_NORMAL);
/* Enable Block Data Update */
lsm6dsl_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);
/* Set Output Data Rate */
lsm6dsl_xl_data_rate_set(&dev_ctx, LSM6DSL_XL_ODR_12Hz5);
lsm6dsl_gy_data_rate_set(&dev_ctx, LSM6DSL_GY_ODR_12Hz5);
//lsm6dsl_gy_data_rate_set(&left_dev_ctx, LSM6DSL_GY_ODR_OFF); //关闭地磁
/* Set full scale */
lsm6dsl_xl_full_scale_set(&dev_ctx, LSM6DSL_2g);
lsm6dsl_gy_full_scale_set(&dev_ctx, LSM6DSL_2000dps);
/* Configure filtering chain(No aux interface) */
/* Accelerometer - analog filter */
lsm6dsl_xl_filter_analog_set(&dev_ctx, LSM6DSL_XL_ANA_BW_400Hz);
/* Accelerometer - LPF1 path ( LPF2 not used )*/
/*lsm6dsl_xl_lp1_bandwidth_set(&left_dev_ctx, LSM6DSL_XL_LP1_ODR_DIV_4);*/
/* Accelerometer - LPF1 + LPF2 path */
lsm6dsl_xl_lp2_bandwidth_set(&dev_ctx, LSM6DSL_XL_LOW_NOISE_LP_ODR_DIV_9);
/* Accelerometer - High Pass / Slope path */
/*lsm6dsl_xl_reference_mode_set(&left_dev_ctx, PROPERTY_DISABLE);*/
/*lsm6dsl_xl_hp_bandwidth_set(&left_dev_ctx, LSM6DSL_XL_HP_ODR_DIV_100);*/
/* Gyroscope - filtering chain */
lsm6dsl_gy_band_pass_set(&dev_ctx, LSM6DSL_HP_260mHz_LP1_STRONG);
//fifo模式设置
lsm6dsl_fifo_xl_batch_set(&dev_ctx, LSM6DSL_FIFO_XL_NO_DEC);//fifo加速度写入频率设置
lsm6dsl_fifo_gy_batch_set(&dev_ctx, LSM6DSL_FIFO_GY_NO_DEC);//fifo陀螺仪写入频率设置
lsm6dsl_fifo_data_rate_set(&dev_ctx, LSM6DSL_FIFO_12Hz5);//FIFO ODR选择
//中断1设置,watermark full中断
lsm6dsl_int1_route_t int1val ={0, 0, 0};
int1val.int1_full_flag = 1; //开阀值中断,fifo存储到缓存深度时触发
lsm6dsl_pin_int1_route_set(&dev_ctx, int1val);
lsm6dsl_fifo_watermark_set(&dev_ctx, ACC_FIFO_WATERMASK);//FIFO水印电平设置,阈值设置,缓存深度
lsm6dsl_fifo_stop_on_wtm_set(&dev_ctx, 1);//fifo缓存深度存满时,不再存储
//lsm6dsl_fifo_xl_gy_8bit_format_set(&left_dev_ctx, 1);//在FIFO中为XL和陀螺启用MSByte记忆,缓存宽度
lsm6dsl_block_data_update_set(&dev_ctx, 1); //fifo模式ctrl3_c bdu必须为1,直到读取MSB和LSB后才更新输出寄存器
lsm6dsl_auto_increment_set(&dev_ctx, 1); //fifo模式ctrl3_c if_inc必须为1,通过串行接口(I2C或SPI)进行多字节访问时自动增加寄存器地址。
lsm6dsl_ctrl3_c_t ctrl3_c;
platform_read(LSM6DSL_CTRL3_C, (uint8_t *)&ctrl3_c, 1);
//lsm6dsl_fifo_mode_set(&dev_ctx, LSM6DSL_FIFO_MODE);
//中断2设置,唤醒中断
// uint8_t temp = 0x90; //唤醒中断
// platform_write(LSM6DSL_TAP_CFG, &temp, 1);
// temp = 0;
// platform_write(LSM6DSL_WAKE_UP_DUR, &temp, 1);
// lsm6dsl_wkup_threshold_set(&left_dev_ctx, 0x20);
// lsm6dsl_int2_route_t int2val ={0, 0, 0};
// int2val.int2_wu = 1;
// lsm6dsl_pin_int2_route_set(&left_dev_ctx, int2val);
if(InitFlag == false){
DBG_LOG("LSM6DS INIT OK...\r\n");
InitFlag = true;
}
}
extern void Lsm6dDataProcessCallBack(float *Acc, float *Gy);
static void Acc_IntHandler(void)
{
uint16_t DiffFifo;
AccGyData_t AccGy;
AccData_t Acc;
float VectorG;
float AverageAcc[XYZ], AverageGy[XYZ];
lsm6dsl_fifo_data_level_get(&dev_ctx, &DiffFifo);
if(DiffFifo == 0) {
return;
}
if(DiffFifo > ACC_FIFO_WATERMASK)
DiffFifo = ACC_FIFO_WATERMASK;
for(int i = 0; i < DiffFifo / 6; i++) {
lsm6dsl_fifo_raw_data_get(&dev_ctx, (uint8_t *)&AccGy, sizeof(AccGy));
angular_rate_mdps[X][i] = lsm6dsl_from_fs2000dps_to_mdps(AccGy.GyX);
angular_rate_mdps[Y][i] = lsm6dsl_from_fs2000dps_to_mdps(AccGy.GyY);
angular_rate_mdps[Z][i] = lsm6dsl_from_fs2000dps_to_mdps(AccGy.GyZ);
acceleration_mg[X][i] = lsm6dsl_from_fs2g_to_mg(AccGy.AccX);
acceleration_mg[Y][i] = lsm6dsl_from_fs2g_to_mg(AccGy.AccY);
acceleration_mg[Z][i] = lsm6dsl_from_fs2g_to_mg(AccGy.AccZ);
}
AverageGy[X] = IntFilter_Float(angular_rate_mdps[0], DiffFifo / 6, 2);
AverageGy[Y] = IntFilter_Float(angular_rate_mdps[1], DiffFifo / 6, 2);
AverageGy[Z] = IntFilter_Float(angular_rate_mdps[2], DiffFifo / 6, 2);
AverageAcc[X] = IntFilter_Float(acceleration_mg[0], DiffFifo / 6, 2);
AverageAcc[Y] = IntFilter_Float(acceleration_mg[1], DiffFifo / 6, 2);
AverageAcc[Z] = IntFilter_Float(acceleration_mg[2], DiffFifo / 6, 2);
Lsm6dDataProcessCallBack(AverageAcc, AverageGy);
acc_status = Acc_Go_Bypass;
}
static void ReadWakeUpIntStatus(void)
{
lsm6dsl_wake_up_src_t wake_up_src;
if(Lsm6dslWakeupIntFlag) {
Lsm6dslWakeupIntFlag = false;
platform_read(LSM6DSL_WAKE_UP_SRC, (uint8_t *)&wake_up_src, sizeof(lsm6dsl_wake_up_src_t));
}
}
void Lsm6dslLoopHandler(void)
{
ReadWakeUpIntStatus();
switch(acc_status)
{
case Acc_Idle:
break;
case Acc_Start:
if(acc_cvttime > 0)
break;
lsm6dsl_fifo_mode_set(&dev_ctx, LSM6DSL_FIFO_MODE);
acc_status = Acc_Get_Data;
acc_cvttime = ACC_CVTTIME;
break;
case Acc_Get_Data:
acc_cvttime = 1000;
acc_status = Acc_Wait_GetData;
break;
case Acc_Wait_GetData:
if(acc_cvttime <= 0){
acc_status = Acc_Go_Bypass;
}
else if(Lsm6dslWaterMarkFullIntFlag) {
Lsm6dslWaterMarkFullIntFlag = false;
uint8_t wtm_flag;
lsm6dsl_fifo_wtm_flag_get(&dev_ctx, &wtm_flag);
Acc_IntHandler();
acc_status = Acc_Go_Bypass;
}
break;
case Acc_Go_Bypass:
lsm6dsl_fifo_mode_set(&dev_ctx, LSM6DSL_BYPASS_MODE);
Lsm6dsStop();
acc_status = Acc_Idle;
acc_cvttime = 1;
break;
}
}
void Lsm6dsl1mSRoutine(void)
{
if(acc_cvttime > 0)
acc_cvttime--;
}
void Lsm6dslInit(void)
{
Lsm6dsl_Init();
}
void Lsm6dsStart(void)
{
Lsm6dsl_Init();
acc_status = Acc_Start;
}
void Lsm6dsStop(void)
{
lsm6dsl_xl_data_rate_set(&dev_ctx, LSM6DSL_XL_ODR_OFF);
lsm6dsl_gy_data_rate_set(&dev_ctx, LSM6DSL_GY_ODR_OFF);
lsm6dsl_fifo_data_rate_set(&dev_ctx, LSM6DSL_FIFO_DISABLE);
acc_status = Acc_Idle;
}
void Lsm6dsInt1CallBack(void)
{
Lsm6dslWaterMarkFullIntFlag = true;
}
void Lsm6dsInt2CallBack(void)
{
Lsm6dslWakeupIntFlag = true;
//Tilt.Acc_IRQ_Status = true;
}
+36
View File
@@ -0,0 +1,36 @@
#ifndef __LSM6DSL_APP_H__
#define __LSM6DSL_APP_H__
#include "bsp.h"
#define X 0
#define Y 1
#define Z 2
#define XYZ 3
typedef struct {
uint16_t GyX;
uint16_t GyY;
uint16_t GyZ;
uint16_t AccX;
uint16_t AccY;
uint16_t AccZ;
}AccGyData_t;
typedef struct {
uint16_t AccX;
uint16_t AccY;
uint16_t AccZ;
}AccData_t;
void Lsm6dslInit(void);
void Lsm6dslLoopHandler(void);
void Lsm6dsl1mSRoutine(void);
void Lsm6dsStart(void);
void Lsm6dsStop(void);
void Lsm6dsInt1CallBack(void);
void Lsm6dsInt2CallBack(void);
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+343
View File
@@ -0,0 +1,343 @@
#include "main.h"
#include "mmc5983.h"
#include "UartDebug.h"
#include "i2c.h"
#include "Algorithm.h"
static int32_t max_in[XYZ];
static int32_t min_in[XYZ];
static bool InitFlag;
static bool MMC5983IntFlag;
static MMC5983Var_t MMC5983Var;
/*****************************************************************************************
* 函数名称: MMC5983_Write_Reg
* 功能描述: MMC5983写寄存器
* 参 数: reg 寄存器地址
val 寄存器数据
* 返 回 值: 成功返回true,失败返回false
*****************************************************************************************/
static bool MMC5983_Write_Reg(uint8_t reg, uint8_t val)
{
return I2C_MasterWriteData(M0P_I2C0, MMC5983_ADDRESS, reg, &val, 1);
}
/*****************************************************************************************
* 函数名称: MMC5983_Read_Reg
* 功能描述: MMC5983读寄存器
* 参 数: reg 寄存器地址
* 返 回 值: 返回寄存器值
*****************************************************************************************/
static uint8_t MMC5983_Read_Reg(uint8_t reg)
{
uint8_t res;
if(I2C_MasterReadData(M0P_I2C0, MMC5983_ADDRESS, reg, &res, 1) == false)
res = 0;
return res;
}
/*****************************************************************************************
* 函数名称: MMC5983_Read_Buffer
* 功能描述: MMC5983读数据
* 参 数: reg 寄存器地址
buffer 读取数据输出缓存入口
len 读取长度
* 返 回 值: 成功返回true,失败返回false
*****************************************************************************************/
static bool MMC5983_Read_Buffer(uint8_t reg, void *buffer, uint8_t len)
{
return I2C_MasterReadData(M0P_I2C0, MMC5983_ADDRESS, reg, buffer, len);
}
/*****************************************************************************************
* 函数名称: MMC5983StartCov
* 功能描述: MMC5983开启连续转换
* 参 数: 无
* 返 回 值: 无
*****************************************************************************************/
static void MMC5983StartCov(void)
{
MMC5983RegCtrl2 Ctrl2Reg; //开启/关闭连续转换
Ctrl2Reg.Byte = 0x00;
Ctrl2Reg.Bit.Cm_freq = 0x04;
Ctrl2Reg.Bit.Cmm_en = 1; //连续设1,单次设0
Ctrl2Reg.Bit.Prd_set = 3;
Ctrl2Reg.Bit.En_prd_set = 1; //连续设1,单次设0
MMC5983_Write_Reg(MMC5983_CTRL_2, Ctrl2Reg.Byte);
}
/*****************************************************************************************
* 函数名称: MMC5983_Init
* 功能描述: MMC5983初始化
* 参 数: 无
* 返 回 值: 无
*****************************************************************************************/
static void MMC5983_Init(void)
{
uint8_t id;
id = MMC5983_Read_Reg(MMC5983_ID);
//DBG_LOG("MMC5983 id=0x%x\r\n",id);
MMC5983Var.MMC5983Delay1mSCnt = 100;
while(id != 0x30){
if(MMC5983Var.MMC5983Delay1mSCnt <= 0) {
DBG_LOG("LEFT MMC5983 INIT Err...\r\n");
InitFlag = false;
return;
}
}
MMC5983RegCtrl1 Ctrl1Reg;
Ctrl1Reg.Byte = 0x00;
Ctrl1Reg.Bit.SW_RST = 1;
MMC5983_Write_Reg(MMC5983_CTRL_1, Ctrl1Reg.Byte);
MMC5983Delay(15);
MMC5983RegCtrl2 Ctrl2Reg; //开启/关闭连续转换
Ctrl2Reg.Byte = 0x00;
Ctrl2Reg.Bit.Cm_freq = 0x04;
Ctrl2Reg.Bit.Cmm_en = 0; //连续设1,单次设0
Ctrl2Reg.Bit.Prd_set = 3;
Ctrl2Reg.Bit.En_prd_set = 0; //连续设1,单次设0
MMC5983_Write_Reg(MMC5983_CTRL_2, Ctrl2Reg.Byte);
MMC5983RegCtrl3 Ctrl3Reg;
Ctrl3Reg.Byte = 0x00;
Ctrl3Reg.Bit.St_enm = 1;
Ctrl3Reg.Bit.St_enp = 1;
MMC5983_Write_Reg(MMC5983_CTRL_3, Ctrl3Reg.Byte);
MMC5983RegCtrl0 Ctrl0Reg;
Ctrl0Reg.Byte = 0x00;
Ctrl0Reg.Bit.TM_M = 1;
Ctrl0Reg.Bit.Auto_SR_en = 1;
Ctrl0Reg.Bit.NT_meas_done_en = 1;
MMC5983_Write_Reg(MMC5983_CTRL_0, Ctrl0Reg.Byte);
if(InitFlag == false){
DBG_LOG("MMC5983 INIT OK...\r\n");
InitFlag = true;
}
}
/*****************************************************************************************
* 函数名称: MMC5983_Read
* 功能描述: MMC5983读取原始数据
* 参 数: MagAdcX X轴数据
MagAdcY Y轴数据
MagAdcZ Z轴数据
* 返 回 值: 成功返回true,失败返回false
*****************************************************************************************/
static bool MMC5983_Read(int32_t *MagAdcX, int32_t *MagAdcY, int32_t *MagAdcZ)
{
static uint8_t buff[7];
if (MMC5983_Read_Buffer(MMC5983_X_OUT_H, buff, 7) == false)
return false;
*MagAdcX = (buff[0] << 10) | (buff[1] << 2) | ((buff[6] & 0xC0) >> 6);
*MagAdcY = (buff[2] << 10) | (buff[3] << 2) | ((buff[6] & 0x30) >> 4);
*MagAdcZ = (buff[4] << 10) | (buff[5] << 2) | ((buff[6] & 0x0C) >> 2);// Turn the 18 bits into unsigned 32-bit value
return true;
}
/*****************************************************************************************
* 函数名称: MMC5983_Get_Mag
* 功能描述: 外部获取MMC5983磁场强度数据
* 参 数: mag 读取数据输出缓存入口
* 返 回 值: 无
*****************************************************************************************/
void MMC5983_Get_Mag(float *mag)
{
if(mag == NULL)
return;
float ADVal[XYZ];
ADVal[X] = MMC5983Var.Mag_Original[X] - 131072.0f;
ADVal[Y] = MMC5983Var.Mag_Original[Y] - 131072.0f;
ADVal[Z] = MMC5983Var.Mag_Original[Z] - 131072.0f;
mag[0] = (float) (ADVal[X] * MMC5983_MAG_SCALE_18BIT);
mag[1] = (float) (ADVal[Y] * MMC5983_MAG_SCALE_18BIT);
mag[2] = (float) (ADVal[Z] * MMC5983_MAG_SCALE_18BIT);
}
/*****************************************************************************************
* 函数名称: MMC5983LoopHandler
* 功能描述: MMC5983循环处理函数
* 参 数: 无
* 返 回 值: 无
*****************************************************************************************/
extern void MmcDataProcessCallBack(float *Mag);
void MMC5983LoopHandler(void)
{
static int32_t mag_array[XYZ][10];
static uint8_t magcnt;
static uint8_t TimeOutMagcnt;
switch(MMC5983Var.Status) {
case MMC5983_STATUS_IDLE:{
break;}
case MMC5983_STATUS_START:{
for(int i = 0; i < 10; i++) {
mag_array[X][i] = 0;
mag_array[Y][i] = 0;
mag_array[Z][i] = 0;
}
magcnt = 0;
TimeOutMagcnt = 0;
memset(&MMC5983Var, NULL, sizeof(MMC5983Var));
MMC5983Var.Status = MMC5983_STATUS_DELAY;
break;}
case MMC5983_STATUS_DELAY:{
MMC5983StartRead();
MMC5983Var.MMC5983Delay1mSCnt = 50;
MMC5983Var.Status = MMC5983_STATUS_WAIT_DELAY;
break;}
case MMC5983_STATUS_WAIT_DELAY:{
if(MMC5983Var.MMC5983Delay1mSCnt <= 0){
MMC5983Var.Status = MMC5983_STATUS_READ;
}
break;}
case MMC5983_STATUS_READ:{
MMC5983Var.MMC5983Delay1mSCnt = 50;
MMC5983Var.Status = MMC5983_STATUS_WAIT_READ;
break;}
case MMC5983_STATUS_WAIT_READ:{
if(MMC5983Var.MMC5983Delay1mSCnt <= 0){
MMC5983Var.Status = MMC5983_STATUS_DELAY;
TimeOutMagcnt++;
}
if(MMC5983IntFlag == true){
MMC5983IntFlag = false;
MMC5983_Read(&mag_array[X][magcnt], &mag_array[Y][magcnt], &mag_array[Z][magcnt]);
magcnt++;
MMC5983Var.Status = MMC5983_STATUS_DELAY;
}
if(TimeOutMagcnt >= 10){
TimeOutMagcnt = 0;
if(magcnt > 0){
MMC5983Var.Mag_Original[X] = AverageFilter_32t(mag_array[X], magcnt);
MMC5983Var.Mag_Original[Y] = AverageFilter_32t(mag_array[Y], magcnt);
MMC5983Var.Mag_Original[Z] = AverageFilter_32t(mag_array[Z], magcnt);
magcnt = 0;
MMC5983_Get_Mag(MMC5983Var.Mag);
MmcDataProcessCallBack(MMC5983Var.Mag);
MMC5983Var.Status = MMC5983_STATUS_STOP;
}
else{
MMC5983Var.Status = MMC5983_STATUS_STOP;
// DBG_LOG("LEFT MMC5983 TimeOut...\r\n");
}
}
if(magcnt >= 10){
MMC5983Var.Mag_Original[X] = AverageFilter_32t(mag_array[X], magcnt);
MMC5983Var.Mag_Original[Y] = AverageFilter_32t(mag_array[Y], magcnt);
MMC5983Var.Mag_Original[Z] = AverageFilter_32t(mag_array[Z], magcnt);
magcnt = 0;
MMC5983_Get_Mag(MMC5983Var.Mag);
MmcDataProcessCallBack(MMC5983Var.Mag);
MMC5983Var.Status = MMC5983_STATUS_STOP;
}
break;}
case MMC5983_STATUS_STOP:{
MMC5983Stop();
MMC5983Var.Status = MMC5983_STATUS_IDLE;
//MMC5983Var.Status = MMC5983_STATUS_START;//持续工作
break;}
}
}
/*****************************************************************************************
* 函数名称: LeftMMC59831mSRoutine
* 功能描述: MMC59831ms时基循环处理函数
* 参 数: 无
* 返 回 值: 无
*****************************************************************************************/
void MMC59831mSRoutine(void)
{
if(MMC5983Var.MMC5983Delay1mSCnt > 0)
MMC5983Var.MMC5983Delay1mSCnt--;
}
/*****************************************************************************************
* 函数名称: LeftMMC5983Init
* 功能描述: MMC5983初始化
* 参 数: 无
* 返 回 值: 无
*****************************************************************************************/
void MMC5983Init(void)
{
if(!InitFlag){
MMC5983_Init();
return;
}
MMC5983Var.Status = MMC5983_STATUS_START;
}
/*****************************************************************************************
* 函数名称: LeftMMC5983Start
* 功能描述: MMC5983启动
* 参 数: 无
* 返 回 值: 无
*****************************************************************************************/
void MMC5983Start(void)
{
if(!InitFlag){
MMC5983_Init();
return;
}
MMC5983Var.Status = MMC5983_STATUS_START;
}
/*****************************************************************************************
* 函数名称: LeftMMC5983StartRead
* 功能描述: MMC5983启动读取
* 参 数: 无
* 返 回 值: 无
*****************************************************************************************/
void MMC5983StartRead(void)
{
MMC5983_Init();//读取时重新初始化
}
/*****************************************************************************************
* 函数名称: MMC5983Stop
* 功能描述: MMC5983停止
* 参 数: 无
* 返 回 值: 无
*****************************************************************************************/
void MMC5983Stop(void)
{
MMC5983RegCtrl0 Ctrl0Reg;
Ctrl0Reg.Byte = 0x00;
MMC5983_Write_Reg(MMC5983_CTRL_0, Ctrl0Reg.Byte);
MMC5983RegStatus StatusReg;
StatusReg.Byte = MMC5983_Read_Reg(MMC5983_STATUS);
if(StatusReg.Bit.Meas_M_Done == 1){
MMC5983_Write_Reg(MMC5983_STATUS, StatusReg.Byte);
}
}
/*****************************************************************************************
* 函数名称: LeftMMC5983IntCallBack
* 功能描述: MMC5983中断回调
* 参 数: 无
* 返 回 值: 无
*****************************************************************************************/
void MMC5983IntCallBack(void)
{
MMC5983IntFlag = true;
}
+140
View File
@@ -0,0 +1,140 @@
/**
*****************************************************************************
* @file ak8975.h
* @author WWJ
* @version v1.0
* @date 2019/04/09
* @environment stm32f407
* @brief
*****************************************************************************
**/
#ifndef _MMC5983_H
#define _MMC5983_H
#include "bsp.h"
#define X 0
#define Y 1
#define Z 2
#define XYZ 3
#define MAX(A, B) (A > B) ? A : B;
#define MIN(A, B) (A < B) ? A : B;
#define MMC5983_X_OUT_H 0X00 //Device ID = 0x48
#define MMC5983_X_OUT_L 0X01
#define MMC5983_Y_OUT_H 0X02
#define MMC5983_Y_OUT_L 0X03
#define MMC5983_Z_OUT_H 0X04
#define MMC5983_Z_OUT_L 0X05
#define MMC5983_XYZ_OUT 0X06
#define MMC5983_TMP_OUT 0X07
#define MMC5983_STATUS 0X08
#define MMC5983_CTRL_0 0X09
#define MMC5983_CTRL_1 0X0A
#define MMC5983_CTRL_2 0X0B
#define MMC5983_CTRL_3 0X0C
#define MMC5983_ID 0X2F
#define MMC5983_ADDRESS 0x30
#define MMC5983_MAG_SCALE_16BIT 0.24414f
#define MMC5983_MAG_SCALE_18BIT 0.061035f
#define MMC5983Delay(x) delay_ms(x)
typedef union {
struct {
uint8_t Meas_M_Done: 1;
uint8_t Meas_T_Done: 1;
uint8_t Res0: 2;
uint8_t OTP_Read_Done: 1;
uint8_t Res1: 3;
}Bit;
uint8_t Byte;
}MMC5983RegStatus;
typedef union {
struct {
uint8_t TM_M: 1;
uint8_t TM_T: 1;
uint8_t NT_meas_done_en: 1;
uint8_t Set: 1;
uint8_t Reset: 1;
uint8_t Auto_SR_en: 1;
uint8_t OTP_Read: 1;
uint8_t Res0: 1;
}Bit;
uint8_t Byte;
}MMC5983RegCtrl0;
typedef union {
struct {
uint8_t BW: 2;
uint8_t X_Inhibit: 1;
uint8_t YZ_Inhibit: 2;
uint8_t Res0: 2;
uint8_t SW_RST: 1;
}Bit;
uint8_t Byte;
}MMC5983RegCtrl1;
typedef union {
struct {
uint8_t Cm_freq: 3;
uint8_t Cmm_en: 1;
uint8_t Prd_set: 3;
uint8_t En_prd_set: 1;
}Bit;
uint8_t Byte;
}MMC5983RegCtrl2;
typedef union {
struct {
uint8_t Res0: 1;
uint8_t St_enp: 1;
uint8_t St_enm: 1;
uint8_t Res1: 3;
uint8_t Spi_3w: 1;
uint8_t Res2: 1;
}Bit;
uint8_t Byte;
}MMC5983RegCtrl3;
typedef enum{
MMC5983_STATUS_IDLE,
MMC5983_STATUS_START,
MMC5983_STATUS_DELAY,
MMC5983_STATUS_WAIT_DELAY,
MMC5983_STATUS_READ,
MMC5983_STATUS_WAIT_READ,
MMC5983_STATUS_STOP,
}MMC5983Status_m;
typedef struct {
MMC5983Status_m Status;
uint16_t MMC5983Delay1mSCnt;
float Mag[3];
int32_t Mag_Original[XYZ];
}MMC5983Var_t;
void MMC5983LoopHandler(void);
void MMC59831mSRoutine(void);
void MMC5983Init(void);
void MMC5983Start(void);
void MMC5983Stop(void);
void MMC5983IntCallBack(void);
void MMC5983Calib(void);
void MMC5983GetADValue(int32_t *Mag);
void MMC5983_Get_Mag(float *mag);
MMC5983Status_m GetMMC5983Status(void);
void MMC5983StartRead(void);
bool GetMMC5983CalibStatus(void);
#endif
/* end of ak8975.h */