STM32驱动MEMS数字型气体传感器(单个使用)

简介: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工程模板、外设模板、模块模板下载地址:

stm32_template: STM32F103工程模板,外设模板,模块模板。模块模板包括:DHT11温湿度传感器,OLED屏幕,DS18B20温度传感器,DS1302时钟模块,红外测温模块,RFID模块,SIM900A短信模块,OneNET入网,ADXL345三轴传感器,离线语音识别模块,语音播报模块,甲醛传感器,PM2.5模块,SG90舵机,健康检测模块,消息队列示例,链表示例,分时调度系统示例等。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿衰0110

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值