首页 > 其他分享 >STM32模拟IIC读取ACD10红外二氧化碳数据

STM32模拟IIC读取ACD10红外二氧化碳数据

时间:2024-03-13 09:29:05浏览次数:25  
标签:SCL ACD10 引脚 void STM32 SDA IIC GPIO

引脚介绍
ACD10通过IIC来通信我们使用下图右边四个引脚就可以了,系统默认模式为IIC通信方式,他也支持USART串口通信不过需要配置pin5引脚(低电平)。

模拟IIC通信配置比较简单,在单片机上面随便找两个引脚就可以。用来配置SDA数据与SCL时钟引脚。

读取数据命令

官方给我们命令行列表也有很多,我们要读取数据使用第一个功能读取CO2的浓度就可以了

iic.c iic.h

下面为模拟IIC的代码已经宏定义

#ifndef __IIC_H
#define	__IIC_H
需要使用到的宏定义

#define ACD10_GPIO GPIOA
#define SDA_PIN GPIO_Pin_4   //这里定义的引脚以及 相关代码中所使用的都是这两个
#define SCL_PIN GPIO_Pin_5    //直接配置成自己选中的引脚即可使用  

#define I2C1_OwnAddress 0x54  //数据手册的地址码
#define SDA_High 	GPIO_SetBits(ACD10_GPIO,SDA_PIN) //拉高数据线
#define SDA_Low 	GPIO_ResetBits(ACD10_GPIO,SDA_PIN) 
#define SCL_High 	GPIO_SetBits(ACD10_GPIO,SCL_PIN) //拉高时钟线
#define SCL_Low 	GPIO_ResetBits(ACD10_GPIO,SCL_PIN) 

void IIC_Start(void);
void IIC_Stop(void);
void IIC_SendACK(int ack);
int IIC_RecvACK(void);
void IIC_SendByte(u8 dat);
u8 IIC_DataByte(void);


//初始化引脚  以及更改切换模式
void SDA_Gpio_init(int flag);
void Acd10_Config(void);

#endif

IIC.c代码 

#include "iic.h"

//起始信号
void IIC_Start(void)
{
	SDA_Gpio_init(1);//更改写模式
	SDA_High;
	SCL_High;
	Delay_us(4);
	SDA_Low;
	Delay_us(4);
	SCL_Low;
	
}

//停止信号
void IIC_Stop(void)
{
	SDA_Gpio_init(1);//更改写模式
	SDA_Low;
	SCL_High;
	Delay_us(4);
	SDA_High;
	Delay_us(4);
}

//发送应答信号 入口参数:ack(0:ACK   1:NAK)
void IIC_SendACK(int ack)
{
	SDA_Gpio_init(1);//更改写模式
	SCL_Low;
	if(ack == 1)   //写应答信号
		SDA_High;
	else if(ack == 0)
		SDA_Low; 
	else
		return;	
	
	SCL_High;
	Delay_us(4);
	SCL_Low;
	Delay_us(4);

}

//接收应答信号
int IIC_RecvACK(void)
{
	uint16_t mcy = 0;
	
	SDA_Gpio_init(0);
	
	SCL_High;
	Delay_us(4);
	if(GPIO_ReadInputDataBit(ACD10_GPIO,SDA_PIN)==1)//读应答信号
		mcy = 1 ;  
  else
    mcy = 0 ;
	SCL_Low;                    //拉低时钟线
  Delay_us(4);                 //延时
	SDA_Gpio_init(1);
  return mcy;
}

//向IIC总线发送一个直接数据
void IIC_SendByte(u8 dat)
{
	SDA_Gpio_init(1);
	for(u8 i=0;i<8;i++)
	{
		if(0x80 & dat)
			SDA_High;
		else
			SDA_Low;
		dat<<=1;
		
		SCL_High;
		Delay_us(4);
		SCL_Low;
		Delay_us(4);	
	}
}

//在IIC总线接收一个字节数据
u8 IIC_DataByte(void)
{
  u8 i;
  u8 dat = 0;  //dat是存放接收到的一个字节的数据


	SDA_High;//使能内部上拉,准备读取数据,
	Delay_us(2);
  for (i=0; i<8; i++)         //8位计数器
  {
    dat <<= 1;       //循环8次,每次接收一个位,8次之后完成一个字节数据的接收
    SCL_High;               //拉高时钟线
    Delay_us(4);             //延时
		dat	|= GPIO_ReadInputDataBit(ACD10_GPIO,SDA_PIN);//读取SDA引脚的电平,如果是高电平,就是传输“1” 
		
		SCL_Low;                //拉低时钟线
    Delay_us(4);          //延时
  }		
  SDA_High;
  return dat;
}

void Acd10_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_InitStruct.GPIO_Pin  = SDA_PIN | SCL_PIN;
	GPIO_InitStruct.GPIO_Speed= GPIO_Speed_50MHz;
	GPIO_Init(ACD10_GPIO, &GPIO_InitStruct);
	
}

//读写模式的更改
void SDA_Gpio_init(int flag)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStruct.GPIO_Pin = SDA_PIN;
	if(flag == 1)
	{//开漏输出
		GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;//开漏
	}
	else if(flag == 0)
	{//上拉输入
		GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;//上拉
	}
	GPIO_Init(ACD10_GPIO,&GPIO_InitStruct);
}

 以上为iic的配置

下面是封装一个获取数据的函数


u8 buf[6] = {0} , CRC_buf[3]; u16 CO2 , TEM;
//读取指令
uint8_t Acd10_Read(void)
{
		//向从设备发送
	IIC_Start();
	IIC_SendByte(I2C1_OwnAddress);		//发送设备地址

	if(IIC_RecvACK()==1)
		return 1;
	IIC_SendByte(0x03);								//发送高字节
	if(IIC_RecvACK()==1)
		return 1;
	IIC_SendByte(0x00);								//发送低字节
	if(IIC_RecvACK()==1)
		return 1;
	IIC_Stop();
	
    //这里的延时极为重要,需要给一定的时间在进行发送起始信号,不然会接收不到从机的应答
    Delay_ms(10);
	//接收信息
	//发送起始信号与地址
	IIC_Start();
	IIC_SendByte(I2C1_OwnAddress+1); //读取地址为0x55 在发送的地址加1就可以了
	//判断是否应答
	if(IIC_RecvACK()==1)
		return 1;
	
/*因为要接收9次数据所以直接使用了for 省的我们来回发送应答信号了,每接收两个字节数据我们就需要接收一个CRC,所有上面定义了两个数组 一个用来接收我们co2和tem数据 一个用来接收crc校验。
*/
	for(u8 i=0;i<6;i++)
	{
		buf[i] = IIC_DataByte(); 
		IIC_SendACK(0);       //接收一次需要发送一个应答信号
		Delay_us(2);
		if((i+1)%2 == 0)
		{
			CRC_buf[(i+1)/2-1] = IIC_DataByte(); 
			if(i==5)
				IIC_SendACK(1);//判断是否为最后一次接收,如果是发送接收完毕的应答信号
			else
				IIC_SendACK(0);
		}
	}
	IIC_Stop();
//判断CRC 我们获取到的数据是否正确
	if((Calc_CRC8(buf,2)!=CRC_buf[0])||(Calc_CRC8(buf+2,2)!=CRC_buf[1])||(Calc_CRC8(buf+4,2)!=CRC_buf[2]))
		return 2;//CRC校验出错
	CO2 = (u16)((((u16)buf[0])<<24) | (((u16)buf[1])<<16) |
	(((u16)buf[2])<<8) | ((u16)buf[3]));
	TEM = buf[4] * 256 + buf[5];
	return 0;

}


//CRC校验函数,这个在官方例程中给到了,直接拿来用
u8 Calc_CRC8(unsigned char *data, unsigned char Num)
{
	unsigned char bit, byte, crc=0xFF;
	for(byte=0; byte<Num; byte++)
	{
		crc^=(data[byte]);
		for(bit=8;bit>0;--bit)
		{
			if(crc&0x80) crc=(crc<<1)^0x31;
			else crc=(crc<<1);
		}
	}
	return crc;
}

标签:SCL,ACD10,引脚,void,STM32,SDA,IIC,GPIO
From: https://blog.csdn.net/w1094598477/article/details/136630085

相关文章

  • 基于STM32F103C8T6单片机学习(江科大版本)
    学习内容1:用库函数来控制IO输出控制LED闪烁,LED流水灯,蜂鸣器主要用到GPIO_unit()函数配置GPIO口和RCC外设时钟控制函数,GPIO的写函数,setbitsresitbits,write等函数 1.led闪烁1.文件配置LED闪烁硬件电路图​​​​​ 首先打开文件管理器,在STM32>工程项目文件......
  • 在stm32f767中使用fmc外挂dram
    `uint16_tbuf[6]attribute((at(0xd0000000)))={0};//将缓冲数组分配到外部dram中。voidTestDram(void){uint16_txxx[6]={0x1111,0x2222,0x3333,0x4444,0x5555,0x6666};for(inti=0;i<5;i++){buf[i]=xxx[i];}for(inti=0;i<5;i++){ if(xxx[i]!......
  • stm32 TIM输出比较(OC) PWM
    stm32P6-4 05:00  ([6-4]PWM驱动LED呼吸灯&PWM驱动舵机&PWM驱动直流电机_哔哩哔哩_bilibili)1.stm32f10x.tim.h部分头文件讲解voidTIM_DeInit(TIM_TypeDef*TIMx);​​​​​​​voidTIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef*TIM_TimeBaseInitStruct......
  • STM32 LwIP学习过程问题总结(一):LwIP ping不通,抓包发现ICMP校验和为0x0000
    一、问题今天在将之前的STM32LwIP1.4.1版本程序移植到2.1.2版本上时,发现ping不同,但是开发板有ICMP回复包,黄颜色警告checksum为0x0000。说明LwIP移植应该是没问题,数据处理这一块出错了。 在网上找了下相关的错误,ST论坛有个问题和我这个一样。HardwareIPv4checksumonanST......
  • STM32标准库通用定时器输出比较
    STM32标准库通用定时器输出比较1.初始化voidTIM2_Init(){ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//使能TIM2时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA时钟 GPIO_InitTypeDefGPIO_InitSt......
  • STM32标准库通用定时器输入捕获
    STM32标准库定时器输入捕获1.输入捕获介绍输入捕获为STM32定时器的一个功能,可以用来测量输入信号的频率和占空比。具体原理:当输入信号经过比较捕获通道时,STM32会依据通道的极性设置决定是否触发捕获中断TIM_IT_CCx。此时定时器会将当前计数值TIMx->CNT的值保存在TIMx->CCRx中,通......
  • STM32移植完FATFS的ROM不够解决方法
    1.移植完FatFs之后会有语言包的支持,在map文件中也可以查看到也就是cc936.c这个文件现在cc936占用ROM大约为175030,在本项目中不需要中文支持所以取消掉即可,取消方法如下第一种方法(通过CubeMX配置的代码)不要使能中文文件名称就好了,记得改这个 第二种方法(库函数或者HAL库没有......
  • 45. 跳跃游戏 IIc
    暴力DFS超时了。先放着把。intmin;voiddfs(int*nums,intnumsSize,intindex,intcount){if(index>=numsSize-1){if(count<min)min=count;return;}for(inti=nums[index];i>0;i--){dfs(nums,numsSize,index+i,count+1);......
  • IIC
    IICIIC总线结构图IIC协议时序软件模拟IIC协议示例代码起始信号voidiic_start(void){/*SCL为高电平期间,SDA从高电平往低电平跳变*/IIC_SDA(1); IIC_SCL(1);iic_delay(); IIC_SDA(0); iic_delay();IIC_SCL(0); iic_delay();......
  • STM32的3种启动模式
    STM32的3种启动模式STM32启动模式介绍各种模式介绍boot0=0Flashmemory启动方式启动地址:0x08000000是STM32内置的Flash,一般我们使用JTAG或者SWD模式下载程序时,就是下载到这个里面,重启后也直接从这启动程序。基本上都是采用这种模式。boot0=1;boot1=0System......