用STM32F030F4的SPI总线获取BMP280的气压和温度

1.用STM32Cube MX生成SPI总线的初始化函数


static void BMP280_SPI_Init(void)
{
  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 Configuration  
  PA5   ------> SPI1_SCK
  PA6   ------> SPI1_MISO
  PA7   ------> SPI1_MOSI 
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_4;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  
  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 parameter configuration*/
  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_HIGH;
  SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;//:第二个边沿开始
  
  
  SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
  SPI_InitStruct.BaudRate =  LL_SPI_BAUDRATEPRESCALER_DIV32; 
  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); //设置触发RXNE事件的RXFIFO阈值,这里设置为一个字节
  LL_SPI_Enable(SPI1);
}

2.根据BMP280的时序图,编写读写函数
时序图:
用STM32F030F4的SPI总线获取BMP280的气压和温度_第1张图片
有图片可知spi的模式为11:即是时钟极性CPOL: 即SPI空闲时,时钟信号SCLK的电平(1:空闲时高电平; 0:空闲时低电平),时钟相位CPHA: 即SPI在SCLK第几个边沿开始采样(0:第一个边沿开始; 1:第二个边沿开始)。
由图可以,第一个字节字节为控制字节,因为SPI是全双工的,有发必有会,由图可知,控制字节所回的数据是无效的。
所以读写代码如下

static void WriteBmp280(uint8_t addr, uint8_t data)
{
	BMP280_CS_ENABLE;

	LL_SPI_TransmitData8(SPI1, addr & ~0x80);
	while (!LL_SPI_IsActiveFlag_TXE(SPI1))
	{
	}
	while (!LL_SPI_IsActiveFlag_RXNE(SPI1))
	{
	}
	(void)LL_SPI_ReceiveData8(SPI1);

	LL_SPI_TransmitData8(SPI1, data);
	while (!LL_SPI_IsActiveFlag_TXE(SPI1))
	{
	}
	while (!LL_SPI_IsActiveFlag_RXNE(SPI1))
	{
	}
	(void)LL_SPI_ReceiveData8(SPI1);

	BMP280_CS_DISENABLE;
}
static uint8_t ReadBmp280(uint8_t addr)
{
	uint8_t data;
	BMP280_CS_ENABLE;

	LL_SPI_TransmitData8(SPI1, (0x80 | addr));
	while (!LL_SPI_IsActiveFlag_TXE(SPI1))
	{
	}
	while (!LL_SPI_IsActiveFlag_RXNE(SPI1))
	{
	}
	(void)LL_SPI_ReceiveData8(SPI1);

	LL_SPI_TransmitData8(SPI1, 0x00);
	while (!LL_SPI_IsActiveFlag_TXE(SPI1))
	{
	}
	while (!LL_SPI_IsActiveFlag_RXNE(SPI1))
	{
	}
	data = LL_SPI_ReceiveData8(SPI1);

	BMP280_CS_DISENABLE;
	return data;
}
static int16_t ReadBmp280Dig_P(uint8_t addr)
{
	uint8_t MSB, LSB;
	LSB = ReadBmp280(addr);
	MSB = ReadBmp280(addr + 1);
	return ((int16_t)((MSB << 8) | LSB));
}

3.根据手册里的公式获取气压以及温度的数据

手册里的公式:
用STM32F030F4的SPI总线获取BMP280的气压和温度_第2张图片
寄存器表:
用STM32F030F4的SPI总线获取BMP280的气压和温度_第3张图片

static int32_t GetBmp280(void)
{
	int32_t adc_T;
	int32_t adc_P;
	int32_t var1;
	int32_t var2;
	int32_t t_fine;
	int32_t T;
	int32_t p;
	adc_T = (ReadBmp280(BMP280_TEMP_MSB) << 12 | ReadBmp280(BMP280_TEMP_LSB) << 4 | ReadBmp280(BMP280_TEMP_XLSB) >> 4);
	adc_P = (ReadBmp280(BMP280_PRESS_MSB) << 12 | ReadBmp280(BMP280_PRESS_LSB) << 4 | ReadBmp280(BMP280_PRESS_XLSB) >> 4);
	var1 = (((double)adc_T) / 16384.0 - ((double)DIG_T1) / 1024.0) * ((double)DIG_T2);
	var2 = ((((double)adc_T) / 131072.0 - ((double)DIG_T1) / 8192.0) * (((double)adc_T) / 131072.0 - ((double)DIG_T1) / 8192.0)) * ((double)DIG_T3);
	t_fine = (uint32_t)(var1 + var2);
	T = t_fine / 5120;
	(void)T;//本系统中不需要温度,故舍去

	var1 = ((double)t_fine / 2.0) - 64000.0;
	var2 = var1 * var1 * ((double)DIG_P6) / 32768.0;
	var2 = var2 + var1 * ((double)DIG_P5) * 2.0;
	var2 = (var2 / 4.0) + (((double)DIG_P4) * 65536.0);
	var1 = (((double)DIG_P3) * var1 * var1 / 524288.0 + ((double)DIG_P2) * var1) / 524288.0;
	var1 = (1.0 + var1 / 32768.0) * ((double)DIG_P1);
	p = 1048576.0 - (double)adc_P;
	p = (p - (var2 / 4096.0)) * 6250.0 / var1;
	var1 = ((double)DIG_P9) * p * p / 2147483648.0;
	var2 = p * ((double)DIG_P8) / 32768.0;
	p = p + (var1 + var2 + (DIG_P7)) / 16.0;
	return p;
}

你可能感兴趣的:(单片机)