简介:STM32F103C8T6驱动MEMS数字型气体传感器(单个使用)源码介绍。
开发平台:KEIL ARM
MCU型号:STM32F103C8T6
传感器型号:精讯畅通MEMS系列数字型气体传感器
特别提示:驱动内可能使用了某些其他组件,比如delay等,在文末外设模板下载地址内有。
1积分源码下载地址在文末!!!
接口图:
使用举例:
#include <stdio.h>
#include "MEMS.h"
int main()
{
uint16_t mems_val;
MEMS_CH2O_init(); // 初始化
while(1) {
mems_val = MEMS_CH2O_read(); // 读取
printf("mems read ppm:%d\n", mems_val);
delayMs(1000);
}
}
驱动源码:
IIC.c
#include "IIC.h"
#define IIC_SDA_PORT GPIOA
#define IIC_SDA_CLK (RCC_APB2Periph_GPIOA)
#define IIC_SDA_PIN GPIO_Pin_7
#define IIC_SCL_PORT GPIOB
#define IIC_SCL_CLK (RCC_APB2Periph_GPIOB)
#define IIC_SCL_PIN GPIO_Pin_0
#define IIC_SCL_OUT_1 IIC_SCL_PORT->BSRR = (uint32_t)IIC_SCL_PIN // 置1
#define IIC_SCL_OUT_0 IIC_SCL_PORT->BRR = (uint32_t)IIC_SCL_PIN
#define IIC_SDA_OUT_1 IIC_SDA_PORT->BSRR = (uint32_t)IIC_SDA_PIN // 置1
#define IIC_SDA_OUT_0 IIC_SDA_PORT->BRR = (uint32_t)IIC_SDA_PIN
#define IIC_SDA_IN() ((IIC_SDA_PORT->IDR & IIC_SDA_PIN) != 0)
/**
* @brief IIC延时
* @param None
* @retval None
*/
static void IIC_Delay(void)
{
uint16_t i;
/*
下面的时间是通过逻辑分析仪测试得到的。
工作条件:CPU主频72MHz ,MDK编译环境,1级优化
循环次数为10时,SCL频率 = 205KHz
循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us
循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us
*/
for (i = 0; i < 400; i++);
}
/**
* @brief SDA输出方向配置
* @param None
* @retval None
*/
void Set_IIC_SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(IIC_SDA_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin=IIC_SDA_PIN;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
GPIO_Init(IIC_SDA_PORT,&GPIO_InitStructure);
}
/**
* @brief SDA输入方向配置
* @param None
* @retval None
*/
void Set_IIC_SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(IIC_SDA_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin=IIC_SDA_PIN;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(IIC_SDA_PORT,&GPIO_InitStructure);
}
/**
* @brief 模拟IIC初始化
* @param None
* @retval None
*/
void IIC_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(IIC_SDA_CLK | IIC_SCL_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = IIC_SCL_PIN;
GPIO_Init(IIC_SCL_PORT, &GPIO_InitStructure);
IIC_stop();
}
/**
* @brief 模拟IIC起始信号
* @param None
* @retval None
*/
void IIC_start()
{
Set_IIC_SDA_OUT();
IIC_SCL_OUT_1;
IIC_SDA_OUT_1;
IIC_Delay();
IIC_SDA_OUT_0;
IIC_Delay();
IIC_SCL_OUT_0;
IIC_Delay();
}
/**
* @brief 模拟IIC停止信号
* @param None
* @retval None
*/
void IIC_stop()
{
Set_IIC_SDA_OUT();
IIC_SCL_OUT_1;
IIC_SDA_OUT_0;
IIC_Delay();
IIC_SDA_OUT_1;
}
/**
* @brief 模拟IIC主机应答
* @param None
* @retval None
*/
void IIC_ack()
{
Set_IIC_SDA_OUT();
IIC_SDA_OUT_0;
IIC_Delay();
IIC_SCL_OUT_1;
IIC_Delay();
IIC_SCL_OUT_0;
IIC_Delay();
IIC_SDA_OUT_1;
}
/**
* @brief 模拟IIC主机不应答
* @param None
* @retval None
*/
void IIC_noack()
{
Set_IIC_SDA_OUT();
IIC_SDA_OUT_1;
IIC_Delay();
IIC_SCL_OUT_1;
IIC_Delay();
IIC_SCL_OUT_0;
IIC_Delay();
}
/**
* @brief 模拟IIC等待从机应答
* @param None
* @retval 1: 接收应答失败 0: 接收应答成功
*/
uint8_t IIC_wait_ack()
{
uint8_t rec = 0;
Set_IIC_SDA_OUT();
IIC_SDA_OUT_1;
IIC_Delay();
Set_IIC_SDA_IN();
IIC_SCL_OUT_1;
IIC_Delay();
rec = IIC_SDA_IN();
IIC_SCL_OUT_0;
IIC_Delay();
return rec;
}
/**
* @brief 模拟IIC发送一个字节
* @param None
* @retval None
*/
void IIC_send_byte(uint8_t txd)
{
uint8_t i=0;
Set_IIC_SDA_OUT();
for(i=0;i<8;i++)
{
if(txd&0x80) IIC_SDA_OUT_1;
else IIC_SDA_OUT_0;
IIC_Delay();
IIC_SCL_OUT_1;
IIC_Delay(); // 发送数据
IIC_SCL_OUT_0;
if(i == 7) IIC_SDA_OUT_1; // 最后一位数据发送完要释放SDA总线
txd <<= 1;
IIC_Delay();
}
}
/**
* @brief 模拟IIC读取一个字节
* @param ack: 0,读完不产生应答 1,读完产生应答
* @retval 返回读取到的字节
*/
uint8_t IIC_read_byte(uint8_t ack)
{
uint8_t i,receive=0;
Set_IIC_SDA_IN();
for(i=0;i<8;i++)
{
receive <<= 1;
IIC_SCL_OUT_1;
IIC_Delay();
if(IIC_SDA_IN()) receive++; // 连续读取八位
IIC_SCL_OUT_0;
IIC_Delay();
}
if(!ack) IIC_noack();
else IIC_ack();
return receive; // 返回读取到的字节
}
IIC.h
#ifndef __IIC_H
#define __IIC_H
#include "main.h"
void Set_IIC_SDA_OUT(void);
void Set_IIC_SDA_IN(void);
void IIC_init(void);
void IIC_start(void);
void IIC_stop(void);
void IIC_ack(void);
void IIC_noack(void);
uint8_t IIC_wait_ack(void);
void IIC_send_byte(uint8_t txd);
uint8_t IIC_read_byte(uint8_t ack);
#endif
MEMS.c
#include "MEMS.h"
#include "IIC.h"
/**
* @brief MEMS数字甲醛传感器IIC端口初始化
* @param None
* @retval None
*/
void MEMS_CH2O_init(void)
{
IIC_init(); // iic延时计数400
}
/**
* @brief 读取MEMS数字甲醛传感器检测浓度
* @param None
* @retval 返回读取到的数据 2字节 0-100ppm 正常<=2
*/
uint16_t MEMS_CH2O_read(void)
{
uint8_t recHigh = 0,recLow = 0;
IIC_start();
IIC_send_byte(MEMS_CH2O_wrAddr); // slave address + write cmd
if(IIC_wait_ack()) return 0xFFFF;
IIC_send_byte(0xA1); // read cmd
if(IIC_wait_ack()) return 0xFFFE;
IIC_start();
IIC_send_byte(MEMS_CH2O_rdAddr); // slave address + read cmd
if(IIC_wait_ack()) return 0xFFFD;
recHigh = IIC_read_byte(1);
recLow = IIC_read_byte(0);
IIC_stop();
return (uint16_t)recHigh << 8 | recLow;
}
MEMS.h
#ifndef __MEMS_H
#define __MEMS_H
#include "main.h"
#define MEMS_CH2O_wrAddr 0x54
#define MEMS_CH2O_rdAddr 0x55
void MEMS_CH2O_init(void);
uint16_t MEMS_CH2O_read(void);
#endif
驱动下载地址:
https://download.csdn.net/download/m0_50669075/87672784
STM32工程模板、外设模板、模块模板下载地址: