在本次项目中,限于空间要求我们选用了STM32F030F4作为控制芯片。这款MCU不但封装紧凑,而且自带的Flash空间也非常有限,所以我们选择了LL库实现。在本文中我们说明一下,使用LL库实现MS5536C的SPI通讯。

1MS5536C简述

  MS5536C是一个系列的高分辨率工厂校准压力传感器。该设备包括一个压阻式压力传感器和一个ADC,采用三线SPI接口。该设备以16位数据字的形式提供数字压力和温度信息。其结构图如下:

  MS5536C具有64位的单独校准的补偿系数,允许高度精确的软件补偿过程传播和温度效应。4个字的位排序组合为6个有效系数,具体如下:

  MS5536C中,压力数据是一个16为的数据,读取的时序需要在发送命令和接受数据时采用不同的时钟沿。

  MS5536C中,温度数据是一个16为的数据,读取温度数据的时序与眼里数据一样,也需要在发送命令和接受数据时采用不同的时钟沿。

  MS5536C中,修正系数是有4个字组成,其实是6个系数,前面已经介绍了它的格式,读取这几个数据的时序也需要在发送命令和接受数据时采用不同的时钟沿。字1和字3的时序图如下:

  读取字2和字4的时序图如下:

  此外,还有复位信号,担复位信号没有什么特别,只需按时序图实现就好。其时序图如下:

  关于这几个时序图的软件实现我们会在后面给出。在这里,我们可以总结一下,对于MS5536C表压传感器,在MCU发送信号时,使用时钟上升沿;在MCU接收数据时,采用时钟下降沿。

2SPI通讯配置

  MS5536C表压传感器采用的是SPI通讯,所以我们需要看看STM32F030F4中的SPI通讯。STM32F030F4中的SPI的结构如下:

  要实现SPI通讯,需要对SPI的寄存器进行配置,主要是个寄存器:SPI控制寄存器1(SPIx_CR1)和SPI控制寄存器2(SPIx_CR2)。

  SPI控制寄存器1(SPIx_CR1)的结构如下:

  在SPIx_CR1中有几位是需要配置的:SSM,SSI,SPE,BR,MSTR,CPOL,CPHA等。SSM:软件从站管理,说的简单一点就是忽略NSS引脚信号,在我们的应用中需要置位。SSI:内部从站选择,在SSM置位的情况下才有效。SPE:SPI使能,这个是必须的,但配置需要注意,在后续我们还会说明。BR:波特率控制,用于设置时钟分频。MSTR主站选择,CPOL时钟极性,CPHA时钟相位不再多说。

  SPI控制寄存器2(SPIx_CR2)的结构如下:

  在SPI控制寄存器2(SPIx_CR2)中,有FRXTH,FIFO接收阈值;DS,SPI传送数据位数需要配置。

3、软件实现

  在前面我们已经说明了SPI的配置和MS5536C表压传感器的通讯要求,接下来就根据我们的分析实现之。

  首先来看SPI的配置,有一些配置可以通过LL库提供的初始化函数来完成。这部分我们需要给予相应的参数值然后调用初始化函数。还有一部分配置需要调用相应的函数来执行。具体配置如下:

/* SPI1 初始化配置 */

static void SPI1_Init_Configuration(void)

{

/* SPI1 端口参数配置*/

LL_SPI_InitTypeDef SPI_InitStruct = {0};

LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

/* 相关外设时钟使能 */

LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_SPI1);

LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);

/**SPI1 GPIO配置:PA5   ------> SPI1_SCK

PA6   ------> SPI1_MISO

PA7   ------> SPI1_MOSI */

GPIO_InitStruct.Pin = LL_GPIO_PIN_5;

GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;

GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;

GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;

GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;

GPIO_InitStruct.Alternate = LL_GPIO_AF_0;

LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

GPIO_InitStruct.Pin = LL_GPIO_PIN_6;

GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;

GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;

GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;

GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;

GPIO_InitStruct.Alternate = LL_GPIO_AF_0;

LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

GPIO_InitStruct.Pin = LL_GPIO_PIN_7;

GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;

GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;

GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;

GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;

GPIO_InitStruct.Alternate = LL_GPIO_AF_0;

LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/* SPI1 参数配置 */

SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;

SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;

SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;

SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;

SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;

SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;

SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV256;

SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;

SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;

SPI_InitStruct.CRCPoly = 7;

LL_SPI_Init(SPI1, &SPI_InitStruct);

LL_SPI_SetRxFIFOThreshold(SPI1,LL_SPI_RX_FIFO_TH_QUARTER);

LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);

LL_SPI_EnableNSSPulseMgt(SPI1);

}

  配置成功后,控制寄存器的状态如下图所示:

  这里需要说明一下的是使能SPI,如果只在初始化时使能,最后的结果可能是一项不到的。所以最好的做法是在每次实现数据发送前,检测SPI的状态,若没使能则调用LL_SPI_Enable(SPI1)使能SPI

  关于MS5536C表压传感器,我们查看了时序图后其实很容易实现,只需要在下发命令和接收数据时,注意转换SPI的相位设定就可以了。我们在这里只列出读取温度和压力测量值的代码。

/* 读取测量数据 */

static uint16_t ReadMeasureData(MS5536cTypeDef *ms,uint16_t command)

{

uint8_t txData[2];

uint8_t rxData[2];

uint16_t result=0;

txData[0]=(uint8_t)(command>>8);

txData[1]=(uint8_t)command;

ms->ReadWriteMS(txData,rxData,2);

ms->Delayms(23);

ms->SetPhase(false);

ms->Delayms(10);

txData[0]=0x00;

txData[1]=0x00;

ms->ReadWriteMS(txData,rxData,2);

result=(rxData[0]<<8)+rxData[1];

ms->SetPhase(true);

ms->Delayms(10);

return result;

}

  对于读取校准数据,读取寄存器,软件复位等都只需按时序图实现就可以了,这里不再详述。

4、总结

  我们已经基于LL库实现了STM32F030F4和MS5536C表压传感器的代码,将其下在到目标板,监视器结果正确,如下图所示:

 欢迎关注:

STM32F0使用LL库实现MS5536C通讯的更多相关文章

  1. STM32F0使用LL库实现Modbus通讯

    在本次项目中,限于空间要求我们选用了STM32F030F4作为控制芯片.这款MCU不但封装紧凑,而且自带的Flash空间也非常有限,所以我们选择了LL库实现.本篇将说明基于LL实现USART通讯. 1 ...

  2. STM32F0使用LL库实现SHT70通讯

    在本次项目中,限于空间要求我们选用了STM32F030F4作为控制芯片.这款MCU不但封装紧凑,而且自带的Flash空间也非常有限,所以我们选择了LL库实现.本篇我们将基于LL库采用模拟I2C接口的方 ...

  3. C/C++ 用libcurl库进行http通讯网络编程

    C/C++ 用libcurl库进行http通讯网络编程 目录索引: 一.LibCurl基本编程框架 二.一些基本的函数 三.curl_easy_setopt函数部分选项介绍 四.curl_easy_p ...

  4. C++ 用libcurl库进行http通讯网络编程 【转】

    http://www.cnblogs.com/moodlxs/archive/2012/10/15/2724318.html C++ 用libcurl库进行http通讯网络编程 目录索引: 一.Lib ...

  5. C++ 用libcurl库进行http通讯网络编程

    使用libcurl完成http通讯,很方便而且是线程安全,转载一篇比较好的入门文章 转载自 http://www.cnblogs.com/moodlxs/archive/2012/10/15/2724 ...

  6. C++ 用libcurl库进行http通讯网络编程(转)

    转载:http://www.cnblogs.com/moodlxs/archive/2012/10/15/2724318.html 目录索引: 一.LibCurl基本编程框架 二.一些基本的函数 三. ...

  7. C++ 用libcurl库进行http通讯网络编程[转]

    http://www.cnblogs.com/moodlxs/archive/2012/10/15/2724318.html 目录索引: 一.LibCurl基本编程框架 二.一些基本的函数 三.cur ...

  8. (4)STM32使用HAL库实现串口通讯——理论讲解

    一.查询模式 1. 二.中断模式 1.中断接收. 1.1先看中断接收的流程(以 USART2 为例) 在启动文件中找到中断向量 USART2_IRQHandler 找到USART2_IRQHandle ...

  9. STM32F0使用LL库实现PWM输出

    在本次项目中,限于空间要求我们选用了STM32F030F4作为控制芯片.这款MCU不但封装紧凑,而且自带的Flash空间也非常有限,所以我们选择了LL库实现.本文我们将说明如何通过LL库实现PWM信号 ...

随机推荐

  1. 进程与线程的通信机制----Queue

    进程运行时候变量是隔离的,线程间共享全局变量. 进程: from multiprocessing import Process from threading import Thread def get ...

  2. Mysql完整约束性

    一.介绍 约束条件与数据类型的宽度一样,都是可选参数 作用:用于保证数据的完整性和一致性主要分为: PRIMARY KEY (PK) 标识该字段为该表的主键,可以唯一的标识记录 FOREIGN KEY ...

  3. 控制结构(8): 线性化(linearization)

    // 上一篇:管道(pipeline) // 下一篇:程序计数器(PC) "编程语言不过是一个工具,什么语言都一样","编程语言能改变人的思维,不同的语言会带给你不同的思 ...

  4. 使用Gradle构建web工程配置详解

  5. MySQL中的float和decimal类型有什么区别

    decimal 类型可以精确地表示非常大或非常精确的小数.大至 1028(正或负)以及有效位数多达 28 位的数字可以作为 decimal类型存储而不失其精确性.该类型对于必须避免舍入错误的应用程序( ...

  6. vue.js实战——splice使用

    Vue在检测到数组变化时,并不是直接重新渲染整个列表,而是最大化地复用DOM元素.替换的数组中含有相同元素的项不会被重新渲染,因此可以大胆地用新数组来替换就数组,不用担心性能问题. 需要注意的是,以下 ...

  7. 4月11日java多线程4

    继昨天学习了线程池之后,今天学习了多线程内的锁Lock. 定义方法: ReentrantLock queueLock = new ReentrantLock(); //可重入锁 ReentrantRe ...

  8. UOJ10 UTR #1 pyx的难题(堆)

    显然优先级越高完成的越早,二分答案后用堆模拟就是O(nlog2n)的.考虑去一个log.先固定特殊题的优先级为最低,模拟一遍.这样在特殊题被扔过来到T的这段时间内,如果将特殊题的优先级提高至超过这其中 ...

  9. codeforces选做

    收录了最近本人完成的一部分codeforces习题,不定期更新 codeforces 1132E Knapsack 注意到如果只使用某一种物品,那么这八种物品可以达到的最小相同重量为\(840\) 故 ...

  10. cobbler批量安装操作

    打开mirrors.aliyun.com/epel http://mirrors.aliyun.com/epel/epel-release-latest-6.noarch.rpm rpm -ivh h ...