|
|
以下是基于 STM32F103 系列 MCU 的 WF282A 完整接口配置代码,包含 I2C/SPI 底层驱动、传感器初始化、数据读取、校准参数写入等全功能片段,代码可直接移植,适配 Keil MDK 开发环境。
一、通用头文件定义(wf282a.h)
- <font face="宋体">#ifndef __WF282A_H
- #define __WF282A_H
- #include "stm32f10x.h"
- #include "delay.h"
- /************************** 引脚定义 **************************/
- // I2C模式(默认使用I2C1)
- #define WF282A_I2C I2C1
- #define WF282A_I2C_CLK RCC_APB1Periph_I2C1
- #define WF282A_I2C_SCL_PIN GPIO_Pin_6
- #define WF282A_I2C_SCL_PORT GPIOB
- #define WF282A_I2C_SCL_CLK RCC_APB2Periph_GPIOB
- #define WF282A_I2C_SDA_PIN GPIO_Pin_7
- #define WF282A_I2C_SDA_PORT GPIOB
- #define WF282A_I2C_SDA_CLK RCC_APB2Periph_GPIOB
- // SPI模式(默认使用SPI1)
- #define WF282A_SPI SPI1
- #define WF282A_SPI_CLK RCC_APB2Periph_SPI1
- #define WF282A_SPI_SCK_PIN GPIO_Pin_5
- #define WF282A_SPI_SCK_PORT GPIOA
- #define WF282A_SPI_SCK_CLK RCC_APB2Periph_GPIOA
- #define WF282A_SPI_MOSI_PIN GPIO_Pin_7
- #define WF282A_SPI_MOSI_PORT GPIOA
- #define WF282A_SPI_MOSI_CLK RCC_APB2Periph_GPIOA
- #define WF282A_SPI_MISO_PIN GPIO_Pin_6
- #define WF282A_SPI_MISO_PORT GPIOA
- #define WF282A_SPI_MISO_CLK RCC_APB2Periph_GPIOA
- #define WF282A_SPI_CS_PIN GPIO_Pin_4
- #define WF282A_SPI_CS_PORT GPIOA
- #define WF282A_SPI_CS_CLK RCC_APB2Periph_GPIOA
- /************************** 设备参数 **************************/
- // I2C地址(CS接3.3V为0x77,接GND为0x76,左移1位适配STM32 I2C地址格式)
- #define WF282A_I2C_ADDR (0x77 << 1)
- // SPI指令宏
- #define WF282A_SPI_READ_CMD 0x80 // 读操作位(最高位1)
- /************************** 寄存器地址 **************************/
- #define WF282A_REG_PRESS_MSB 0x00 // 气压数据高8位
- #define WF282A_REG_PRESS_MID 0x01 // 气压数据中8位
- #define WF282A_REG_PRESS_LSB 0x02 // 气压数据低8位
- #define WF282A_REG_TEMP_MSB 0x04 // 温度数据高8位
- #define WF282A_REG_TEMP_MID 0x05 // 温度数据中8位
- #define WF282A_REG_TEMP_LSB 0x06 // 温度数据低8位
- #define WF282A_REG_CTRL 0x10 // 控制寄存器
- #define WF282A_REG_CALIB_OFFSET 0x18 // 校准偏移寄存器
- #define WF282A_REG_TEMP_COMP 0x1C // 温度补偿寄存器
- #define WF282A_REG_ID 0x20 // 设备ID寄存器
- /************************** 控制寄存器配置 **************************/
- #define WF282A_CTRL_NORMAL_MODE 0x01 // 正常工作模式
- #define WF282A_CTRL_LOW_POWER 0x02 // 低功耗模式
- #define WF282A_CTRL_FILTER_EN 0x04 // 启用数字滤波
- #define WF282A_CTRL_SAMPLE_1HZ 0x00 // 1Hz采样率
- #define WF282A_CTRL_SAMPLE_10HZ 0x10 // 10Hz采样率
- #define WF282A_CTRL_SAMPLE_100HZ 0x20 // 100Hz采样率
- /************************** 函数声明 **************************/
- // I2C接口函数
- void WF282A_I2C_Init(void);
- uint8_t WF282A_I2C_ReadByte(uint8_t reg_addr);
- void WF282A_I2C_WriteByte(uint8_t reg_addr, uint8_t data);
- void WF282A_I2C_ReadBytes(uint8_t reg_addr, uint8_t len, uint8_t *buf);
- void WF282A_I2C_WriteBytes(uint8_t reg_addr, uint8_t len, uint8_t *buf);
- // SPI接口函数
- void WF282A_SPI_Init(void);
- void WF282A_SPI_CS_Enable(void);
- void WF282A_SPI_CS_Disable(void);
- uint8_t WF282A_SPI_ReadWriteByte(uint8_t tx_data);
- uint8_t WF282A_SPI_ReadByte(uint8_t reg_addr);
- void WF282A_SPI_WriteByte(uint8_t reg_addr, uint8_t data);
- // 传感器核心函数
- uint8_t WF282A_Check_ID(void); // 检测设备ID
- void WF282A_Init(uint8_t mode); // 初始化传感器(mode:工作模式)
- float WF282A_Read_Pressure(void); // 读取气压值(Pa)
- float WF282A_Read_Temperature(void); // 读取温度值(℃)
- void WF282A_Write_Calib_Offset(int16_t offset); // 写入校准偏移量
- void WF282A_Write_Temp_Comp(uint8_t comp); // 写入温度补偿系数
- #endif</font>
复制代码 二、I2C 接口驱动实现(wf282a_i2c.c)- <font face="宋体">#include "wf282a.h"
- /************************** I2C底层初始化 **************************/
- void WF282A_I2C_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
- I2C_InitTypeDef I2C_InitStruct;
- // 使能时钟
- RCC_APB2PeriphClockCmd(WF282A_I2C_SCL_CLK | WF282A_I2C_SDA_CLK, ENABLE);
- RCC_APB1PeriphClockCmd(WF282A_I2C_CLK, ENABLE);
- // 配置SCL引脚(复用开漏输出)
- GPIO_InitStruct.GPIO_Pin = WF282A_I2C_SCL_PIN;
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(WF282A_I2C_SCL_PORT, &GPIO_InitStruct);
- // 配置SDA引脚(复用开漏输出)
- GPIO_InitStruct.GPIO_Pin = WF282A_I2C_SDA_PIN;
- GPIO_Init(WF282A_I2C_SDA_PORT, &GPIO_InitStruct);
- // 配置I2C参数
- I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
- I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
- I2C_InitStruct.I2C_OwnAddress1 = 0x00; // 主机无地址
- I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
- I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
- I2C_InitStruct.I2C_ClockSpeed = 400000; // 400KHz高速模式
- I2C_Init(WF282A_I2C, &I2C_InitStruct);
- // 使能I2C
- I2C_Cmd(WF282A_I2C, ENABLE);
- }
- /************************** I2C单字节读取 **************************/
- uint8_t WF282A_I2C_ReadByte(uint8_t reg_addr)
- {
- uint8_t data = 0;
- // 等待I2C总线空闲
- while(I2C_GetFlagStatus(WF282A_I2C, I2C_FLAG_BUSY));
- // 发送起始信号
- I2C_GenerateSTART(WF282A_I2C, ENABLE);
- while(!I2C_CheckEvent(WF282A_I2C, I2C_EVENT_MASTER_MODE_SELECT));
- // 发送设备地址+写操作
- I2C_Send7bitAddress(WF282A_I2C, WF282A_I2C_ADDR, I2C_Direction_Transmitter);
- while(!I2C_CheckEvent(WF282A_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
- // 发送寄存器地址
- I2C_SendData(WF282A_I2C, reg_addr);
- while(!I2C_CheckEvent(WF282A_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
- // 发送重复起始信号
- I2C_GenerateSTART(WF282A_I2C, ENABLE);
- while(!I2C_CheckEvent(WF282A_I2C, I2C_EVENT_MASTER_MODE_SELECT));
- // 发送设备地址+读操作
- I2C_Send7bitAddress(WF282A_I2C, WF282A_I2C_ADDR, I2C_Direction_Receiver);
- while(!I2C_CheckEvent(WF282A_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
- // 关闭应答,准备接收
- I2C_AcknowledgeConfig(WF282A_I2C, DISABLE);
- I2C_GenerateSTOP(WF282A_I2C, ENABLE); // 发送停止信号
- // 读取数据
- while(!I2C_CheckEvent(WF282A_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED));
- data = I2C_ReceiveData(WF282A_I2C);
- // 重新使能应答
- I2C_AcknowledgeConfig(WF282A_I2C, ENABLE);
- return data;
- }
- /************************** I2C单字节写入 **************************/
- void WF282A_I2C_WriteByte(uint8_t reg_addr, uint8_t data)
- {
- // 等待I2C总线空闲
- while(I2C_GetFlagStatus(WF282A_I2C, I2C_FLAG_BUSY));
- // 发送起始信号
- I2C_GenerateSTART(WF282A_I2C, ENABLE);
- while(!I2C_CheckEvent(WF282A_I2C, I2C_EVENT_MASTER_MODE_SELECT));
- // 发送设备地址+写操作
- I2C_Send7bitAddress(WF282A_I2C, WF282A_I2C_ADDR, I2C_Direction_Transmitter);
- while(!I2C_CheckEvent(WF282A_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
- // 发送寄存器地址
- I2C_SendData(WF282A_I2C, reg_addr);
- while(!I2C_CheckEvent(WF282A_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
- // 发送写入数据
- I2C_SendData(WF282A_I2C, data);
- while(!I2C_CheckEvent(WF282A_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
- // 发送停止信号
- I2C_GenerateSTOP(WF282A_I2C, ENABLE);
- }
- /************************** I2C多字节读取 **************************/
- void WF282A_I2C_ReadBytes(uint8_t reg_addr, uint8_t len, uint8_t *buf)
- {
- uint8_t i = 0;
- if(len == 0 || buf == NULL) return;
- // 等待I2C总线空闲
- while(I2C_GetFlagStatus(WF282A_I2C, I2C_FLAG_BUSY));
- // 发送起始信号
- I2C_GenerateSTART(WF282A_I2C, ENABLE);
- while(!I2C_CheckEvent(WF282A_I2C, I2C_EVENT_MASTER_MODE_SELECT));
- // 发送设备地址+写操作
- I2C_Send7bitAddress(WF282A_I2C, WF282A_I2C_ADDR, I2C_Direction_Transmitter);
- while(!I2C_CheckEvent(WF282A_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
- // 发送寄存器地址
- I2C_SendData(WF282A_I2C, reg_addr);
- while(!I2C_CheckEvent(WF282A_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
- // 发送重复起始信号
- I2C_GenerateSTART(WF282A_I2C, ENABLE);
- while(!I2C_CheckEvent(WF282A_I2C, I2C_EVENT_MASTER_MODE_SELECT));
- // 发送设备地址+读操作
- I2C_Send7bitAddress(WF282A_I2C, WF282A_I2C_ADDR, I2C_Direction_Receiver);
- while(!I2C_CheckEvent(WF282A_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
- // 读取多字节数据
- for(i=0; i<len; i++)
- {
- if(i == len-1)
- {
- // 最后一个字节,关闭应答并发送停止信号
- I2C_AcknowledgeConfig(WF282A_I2C, DISABLE);
- I2C_GenerateSTOP(WF282A_I2C, ENABLE);
- }
- while(!I2C_CheckEvent(WF282A_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED));
- buf[i] = I2C_ReceiveData(WF282A_I2C);
- }
- // 重新使能应答
- I2C_AcknowledgeConfig(WF282A_I2C, ENABLE);
- }
- /************************** I2C多字节写入 **************************/
- void WF282A_I2C_WriteBytes(uint8_t reg_addr, uint8_t len, uint8_t *buf)
- {
- uint8_t i = 0;
- if(len == 0 || buf == NULL) return;
- // 等待I2C总线空闲
- while(I2C_GetFlagStatus(WF282A_I2C, I2C_FLAG_BUSY));
- // 发送起始信号
- I2C_GenerateSTART(WF282A_I2C, ENABLE);
- while(!I2C_CheckEvent(WF282A_I2C, I2C_EVENT_MASTER_MODE_SELECT));
- // 发送设备地址+写操作
- I2C_Send7bitAddress(WF282A_I2C, WF282A_I2C_ADDR, I2C_Direction_Transmitter);
- while(!I2C_CheckEvent(WF282A_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
- // 发送寄存器地址
- I2C_SendData(WF282A_I2C, reg_addr);
- while(!I2C_CheckEvent(WF282A_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
- // 发送多字节数据
- for(i=0; i<len; i++)
- {
- I2C_SendData(WF282A_I2C, buf[i]);
- while(!I2C_CheckEvent(WF282A_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
- }
- // 发送停止信号
- I2C_GenerateSTOP(WF282A_I2C, ENABLE);
- }</font>
复制代码
三、SPI 接口驱动实现(wf282a_spi.c)
- <font face="宋体">#include "wf282a.h"
- /************************** SPI底层初始化 **************************/
- void WF282A_SPI_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
- SPI_InitTypeDef SPI_InitStruct;
- // 使能时钟
- RCC_APB2PeriphClockCmd(WF282A_SPI_SCK_CLK | WF282A_SPI_MOSI_CLK |
- WF282A_SPI_MISO_CLK | WF282A_SPI_CS_CLK, ENABLE);
- RCC_APB2PeriphClockCmd(WF282A_SPI_CLK, ENABLE);
- // 配置SCK引脚(复用推挽输出)
- GPIO_InitStruct.GPIO_Pin = WF282A_SPI_SCK_PIN;
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(WF282A_SPI_SCK_PORT, &GPIO_InitStruct);
- // 配置MOSI引脚(复用推挽输出)
- GPIO_InitStruct.GPIO_Pin = WF282A_SPI_MOSI_PIN;
- GPIO_Init(WF282A_SPI_MOSI_PORT, &GPIO_InitStruct);
- // 配置MISO引脚(浮空输入)
- GPIO_InitStruct.GPIO_Pin = WF282A_SPI_MISO_PIN;
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(WF282A_SPI_MISO_PORT, &GPIO_InitStruct);
- // 配置CS引脚(推挽输出)
- GPIO_InitStruct.GPIO_Pin = WF282A_SPI_CS_PIN;
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(WF282A_SPI_CS_PORT, &GPIO_InitStruct);
- // 初始拉高CS引脚
- WF282A_SPI_CS_Disable();
- // 配置SPI参数
- SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
- SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
- SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
- SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low; // 时钟极性:低电平空闲
- SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge; // 第一个边沿采样
- SPI_InitStruct.SPI_NSS = SPI_NSS_Soft; // 软件控制NSS
- SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; // 1MHz(72/16=4.5MHz,可调整)
- SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB; // 高位先行
- SPI_InitStruct.SPI_CRCPolynomial = 7;
- SPI_Init(WF282A_SPI, &SPI_InitStruct);
- // 使能SPI
- SPI_Cmd(WF282A_SPI, ENABLE);
- }
- /************************** SPI片选控制 **************************/
- void WF282A_SPI_CS_Enable(void)
- {
- GPIO_ResetBits(WF282A_SPI_CS_PORT, WF282A_SPI_CS_PIN);
- delay_us(1); // 延时确保片选稳定
- }
- void WF282A_SPI_CS_Disable(void)
- {
- delay_us(1);
- GPIO_SetBits(WF282A_SPI_CS_PORT, WF282A_SPI_CS_PIN);
- }
- /************************** SPI单字节读写 **************************/
- uint8_t WF282A_SPI_ReadWriteByte(uint8_t tx_data)
- {
- // 等待发送缓冲区为空
- while(SPI_I2S_GetFlagStatus(WF282A_SPI, SPI_I2S_FLAG_TXE) == RESET);
- // 发送数据
- SPI_I2S_SendData(WF282A_SPI, tx_data);
- // 等待接收缓冲区非空
- while(SPI_I2S_GetFlagStatus(WF282A_SPI, SPI_I2S_FLAG_RXNE) == RESET);
- // 返回接收数据
- return SPI_I2S_ReceiveData(WF282A_SPI);
- }
- /************************** SPI单字节读取 **************************/
- uint8_t WF282A_SPI_ReadByte(uint8_t reg_addr)
- {
- uint8_t data = 0;
- WF282A_SPI_CS_Enable(); // 拉低CS
- // 发送寄存器地址+读操作位
- WF282A_SPI_ReadWriteByte(reg_addr | WF282A_SPI_READ_CMD);
- // 读取数据
- data = WF282A_SPI_ReadWriteByte(0xFF);
- WF282A_SPI_CS_Disable(); // 拉高CS
- return data;
- }
- /************************** SPI单字节写入 **************************/
- void WF282A_SPI_WriteByte(uint8_t reg_addr, uint8_t data)
- {
- WF282A_SPI_CS_Enable(); // 拉低CS
- // 发送寄存器地址(写操作位为0)
- WF282A_SPI_ReadWriteByte(reg_addr & ~WF282A_SPI_READ_CMD);
- // 写入数据
- WF282A_SPI_ReadWriteByte(data);
- WF282A_SPI_CS_Disable(); // 拉高CS
- }</font>
复制代码
|
|