打印
[其他]

基于MindSDK实现水深度数据采集

[复制链接]
527|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
一. 开发环境搭建
开发环境搭建及固件下载参考“【MM32F5270开发板试用】+ 开发环境的搭建并测试GPIO例程”
MindSDK体验测试参考“【MM32F5270开发板试用】 MindSDK使用测评”
二、关于深度传感器
MS5837-30BA水深压力传感器模块包括一个高线性压力芯片和一个低功耗24位ADC,内部校准系数。提供精确的数字24位压力和温度值以及不同的操作模式,允许优化转换速度和电流消耗。高分辨率的温度输出允许在没有任何附加传感器的情况下实现高度计和温度计功能。MS5837-30BA可以通过IC总线接口连接到任何微控制器。通信协议简单,无需对设备内部寄存器进行编程。

1. MS5837-30BA水深传感器解读
1.简介:四轴飞行器实现定高飞行要依靠高度数据,那么水下航行器想要实现定深航行同样需要垂直方向的位置数据,也就是深度,我们使用MS5837-30BA这款压力传感器来测量水深。关于MS5837的使用网上有很多教程,其实都不用看,看数据手册就行了,写得非常非常全面。什么?看不懂英文?好的我已经把它翻译了一遍,可以说是非常非常详细了,相信我,看了数据手册,就会写驱动程序了。

2. 性能参数
MS5837-30BA可以配置成不同的ADC转换精度,用OSR表示,精度越高转换越慢,下表显示了不同精度对应的转换时间。每次读ADC转换数据前要先发送转换命令,必须要按照最大的转换时间去写一个延时,延时时间够了才能继续发送读转换完成的数据,不然数据是错的。比如OSR=4096时转换时间是7.40-9.04,那么延时时间可以设置成10ms.



电气特性,性能特征等请看手册,我们只关注算法。

MS5837-30BA可以配置成不同的ADC转换精度,用OSR表示,精度越高转换越慢,下表显示了不同精度对应的转换时间。每次读ADC转换数据前要先发送转换命令,必须要按照最大的转换时间去写一个延时,延时时间够了才能继续发送读转换完成的数据,不然数据是错的。比如OSR=4096时转换时间是7.40-9.04,那么延时时间可以设置成10ms.
MS5837使用IIC通讯,典型应用电路如下图。经典的IIC通讯电路。



模块硬件连接电路





如上图将MS5837接到开发板GPIO的I2C1的C6、C7上,基于driver_examples\i2c\i2c_master_detect程序检测传感器是否存在,串口输出如下(红框即为传感器地址):



三、功能源码实现
1、时钟滴答及延时实现:

static uint64_t SysRunTimeMs = 0;
static uint8_t fac_us = 0;
static uint32_t fac_ms = 0;

void SysTick_Init(void)
{
        uint32_t reload = 0;

        SysTick->CTRL &= (uint32_t)0xFFFFFFFB;
        fac_us = CLOCK_SYS_FREQ / 8000000U;
        fac_ms = CLOCK_SYS_FREQ / 8000U;

        reload = CLOCK_SYSTICK_FREQ/1000;
        reload--;

        SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
        SysTick->LOAD = reload;
        SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
}
/**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
void SysTick_Handler(void)
{
  SysRunTimeMs++;
}

uint32_t GetSysRunTimeMs(void)
{
    return SysRunTimeMs;
}

void delay_us(uint16_t nus)
{
    uint32_t ticks = 0;
    uint32_t told = 0;
    uint32_t tnow = 0;
    uint32_t tcnt = 0;
    uint32_t reload = 0;
    reload = SysTick->LOAD;
    ticks = nus * fac_us;
    told = SysTick->VAL;
    while (1)
    {
        tnow = SysTick->VAL;
        if (tnow != told)
        {
            if (tnow < told)
            {
                tcnt += told - tnow;
            }
            else
            {
                tcnt += reload - tnow + told;
            }
            told = tnow;
            if (tcnt >= ticks)
            {
                break;
            }
        }
    }
}

void delay_ms(uint16_t nms)
{
    uint32_t ticks = 0;
    uint32_t told = 0;
    uint32_t tnow = 0;
    uint32_t tcnt = 0;
    uint32_t reload = 0;
    reload = SysTick->LOAD;
    ticks = nms * fac_ms;
    told = SysTick->VAL;
    while (1)
    {
        tnow = SysTick->VAL;
        if (tnow != told)
        {
            if (tnow < told)
            {
                tcnt += told - tnow;
            }
            else
            {
                tcnt += reload - tnow + told;
            }
            told = tnow;
            if (tcnt >= ticks)
            {
                break;
            }
        }
    }
}



2、硬件GPIO初始化及I2C读写函数

#define BOARD_I2C_PORT               I2C1
#define BOARD_I2C_IRQn               I2C1_IRQn
#define BOARD_I2C_IRQHandler         I2C1_IRQHandler
#define BOARD_I2C_FREQ               CLOCK_APB1_FREQ

/* Initialize I2C */
void app_i2c_init(void)
{
    /* Setup I2C initialization values. */
    I2C_Master_Init_Type i2c_init;
    i2c_init.ClockFreqHz = BOARD_I2C_FREQ;
    i2c_init.BaudRate = I2C_BaudRate_100K;

    /* Initialize I2C master. */
    I2C_InitMaster(BOARD_I2C_PORT, &i2c_init);

    /* The target device address needs to be configured before enabling. */
    I2C_SetTargetAddr(BOARD_I2C_PORT, APP_I2C_TARGET_ADDR);

    /* Enable I2C. */
    I2C_Enable(BOARD_I2C_PORT, true);
}

/* Write data to target device, true to writing succeed, false to writing failed. */
bool app_i2c_write(uint8_t txlen, uint8_t *txbuf)
{
    app_i2c_xfer.WaitTimes = APP_I2C_TIMEOUT_TIME;
    app_i2c_xfer.TxBuf = txbuf;
    app_i2c_xfer.TxLen = txlen;

    I2C_Enable(BOARD_I2C_PORT, true);  /* Disable I2C to clear tx fifo, and enabled I2C to perform the write operation again. */
    if ( false == I2C_MasterWriteBlocking(BOARD_I2C_PORT, &app_i2c_xfer) )
    {
        return false;
    }
    else
    {
        return true;
    }
}

/* Read data to target device, true to reading succeed, false to reading failed. */
bool app_i2c_read(uint8_t rxlen, uint8_t *rxbuf)
{
    app_i2c_xfer.WaitTimes = APP_I2C_TIMEOUT_TIME;
    app_i2c_xfer.RxBuf = rxbuf;
    app_i2c_xfer.RxLen = rxlen;

    I2C_Enable(BOARD_I2C_PORT, true);  /* Disable I2C to clear tx fifo, and enabled I2C to perform the read operation again. */
    if ( false == I2C_MasterReadBlocking(BOARD_I2C_PORT, &app_i2c_xfer) )
    {
        return false;
    }
    else
    {
        return true;
    }
}



3、传感器初始化及数据获取

/*
C1 压力灵敏度 SENS|T1
C2  压力补偿  OFF|T1
C3    温度压力灵敏度系数 TCS
C4    温度系数的压力补偿 TCO
C5    参考温度 T|REF
C6     温度系数的温度 TEMPSENS
*/
uint32_t  Cal_C[7];            //用于存放PROM中的6组数据1-6

double OFF_;
float Aux;
/*
dT 实际和参考温度之间的差异
TEMP 实际温度   
*/
uint64_t dT,TEMP;
/*
OFF 实际温度补偿
SENS 实际温度灵敏度
*/
uint64_t SENS;
uint32_t D1_Pres,D2_Temp;    // 数字压力值,数字温度值
uint32_t TEMP2,T2,OFF2,SENS2;    //温度校验值

uint32_t Pressure;                //气压
uint32_t Atmdsphere_Pressure;//大气压
uint32_t Depth;
float TEMP1;
double DEEP;
/*
* Declerations.
*/
void app_i2c_init(void);
bool app_i2c_write(uint8_t txlen, uint8_t *txbuf);
bool app_i2c_read(uint8_t rxlen, uint8_t *rxbuf);
void MS5837_init(void);
void MS583703BA_getPressure(void);

/*******************************************************************************
  * @函数名称    MS583730BA_RESET
  * @函数说明   复位MS5611
  * @输入参数   无
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
void MS583703BA_RESET(void)
{
//        IIC_Start();
//        IIC_Send_Byte(0xEC);//CSB接地,主机地址:0XEE,否则 0X77
//      IIC_Wait_Ack();
//    IIC_Send_Byte(0x1E);//发送复位命令
//      IIC_Wait_Ack();
//    IIC_Stop();   
    uint8_t txData;
    txData = 0xEC;
    app_i2c_write(1,&txData);//CSB接地,主机地址:0XEE,否则 0X77

    txData = 0x1E;
    app_i2c_write(1,&txData);    //发送复位命令
}

/*******************************************************************************
  * @函数名称    MS5611_init
  * @函数说明   初始化5611
  * @输入参数      无
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
void MS5837_init(void)
{     
    uint8_t txData,rxData,inth,intl,i;
    MS583703BA_RESET();     // Reset Device  复位MS5837
    delay_ms(20);       //复位后延时(注意这个延时是一定必要的,可以缩短但似乎不能少于20ms)


  for (i=1;i<=6;i++)
    {
        txData = 0xEC;
        app_i2c_write(1,&txData);
        txData = 0xA0 + (i*2);
        app_i2c_write(1,&txData);
        delay_us(5);
        txData = 0xEC+0x01;//进入接收模式
        app_i2c_write(1,&txData);        
        delay_us(1);
        app_i2c_read(1,&inth);
        delay_us(1);
        app_i2c_read(1,&intl);
    Cal_C = (((uint16_t)inth << 8) | intl);
    }

    for(i=0;i<5;i++)
    {
        delay_ms(1);
        MS583703BA_getPressure();   //获取大气压
    Atmdsphere_Pressure+=Pressure;   
        printf("%d\t",Pressure);               //串口输出原始数据
    }
    Atmdsphere_Pressure=Atmdsphere_Pressure/5;
    printf("Atmdsphere_Pressure:%d\r\n",Atmdsphere_Pressure);               //串口输出原始数据

}

/**************************实现函数********************************************
*函数原型:unsigned long MS561101BA_getConversion(void)
*功  能:    读取 MS5837 的转换结果
*******************************************************************************/
unsigned long MS583703BA_getConversion(uint8_t command)
{
    unsigned long conversion = 0;
    uint8_t temp[3],txData;

    txData = 0xEC;
    app_i2c_write(1,&txData);//写地址

    txData = command;
    app_i2c_write(1,&txData);    //写转换命令
    delay_ms(10);
    txData = 0xEC;
    app_i2c_write(1,&txData);    //写地址
    txData = 0x0;
    app_i2c_write(1,&txData);    //start read sequence   

    txData = 0xEC+0x01;
    app_i2c_write(1,&txData);//进入接收模式

    txData = 0x0;
    app_i2c_write(1,&txData);   

    app_i2c_read(1,&temp[0]);//带ACK的读数据  bit 23-16
    app_i2c_read(1,&temp[1]);//带ACK的读数据  bit 8-15
    app_i2c_read(1,&temp[2]);//带NACK的读数据 bit 0-7


    conversion = (unsigned long)temp[0] * 65536 + (unsigned long)temp[1] * 256 + (unsigned long)temp[2];
    return conversion;
}

/**************************实现函数********************************************
*函数原型:void MS561101BA_GetTemperature(void)
*功  能:    读取 温度转换结果
*******************************************************************************/

void MS583703BA_getTemperature(void)
{

    D2_Temp = MS583703BA_getConversion(0x58);
    delay_ms(10);
    dT=D2_Temp - (((uint32_t)Cal_C[5])*256);
    TEMP=2000+dT*((uint32_t)Cal_C[6])/8388608;
    TEMP1 = TEMP/100.0f/10000;
}

///***********************************************
//  * @brief  读取气压
//  * @param  None
//  * @retval None
//************************************************/
void MS583703BA_getPressure(void)
{
    D1_Pres= MS583703BA_getConversion(0x48);
    delay_ms(10);

    OFF_=(uint32_t)Cal_C[2]*65536+((uint32_t)Cal_C[4]*dT)/128;
    SENS=(uint32_t)Cal_C[1]*32768+((uint32_t)Cal_C[3]*dT)/256;

    if(TEMP/100<20)  // low temp
    {
        Aux = (2000-TEMP)*(2000-TEMP);
        T2 = 3*(dT*dT) /0x80000000;
        OFF2 = 1.5*Aux;
        SENS2 = 5*Aux/8;
        OFF_ = OFF_ - OFF2;
        SENS = SENS - SENS2;   

    }


     else {

         T2=2*(dT*dT)/137438953472;
        OFF2 = 1*Aux/16;
        SENS2 = 0;
        OFF_ = OFF_ - OFF2;
        SENS = SENS - SENS2;   

     }
  Pressure= ((D1_Pres*SENS/2097152-OFF_)/8192)/10;
     TEMP=(TEMP-T2)/100;
     DEEP=Pressure/9794.4/10000;
}

/*
* Functions.
*/
int main(void)
{
    BOARD_Init();
        SysTick_Init();
    printf("\r\ni2c_master_ms5837 example\r\n");

    /* Initialize I2C. */
    app_i2c_init();

    /* Setup the data to be transmitted. */
    MS5837_init();

    while (1)
    {
        //printf("press any key to write i2c-eeprom.\r\n");
        getchar();
                MS583703BA_getTemperature();
                MS583703BA_getPressure();
                printf("    Temp : %5.2lf\r\n",TEMP1);               //串口输出原始数据
                printf("    Pressure : %u\r\n\r\n\r\n",Pressure); //串口输出原始数据
                printf("    Deep : %5.6f\r\n",DEEP);         
    }
}



四. 功能测试
编译下载固件,打印输出如下:



下一步通过定时器及串口中断实现不定长数据接收来完成无线数据的透传。
————————————————
版权声明:本文为CSDN博主「极术社区」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_47569031/article/details/127440785

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

146

主题

4098

帖子

5

粉丝