STM32、GD32等驱动AMG8833热成像传感器源码分享

一、AMG8833介绍

1简介

AMG8833是一种红外热像传感器,也被称为热感传感器。它可以用来检测和测量物体的热辐射,并将其转换为数字图像。AMG8833传感器可以感知的热源范围为-20°C到100°C,并能提供8x8的像素分辨率。它通过I2C接口与微控制器或单片机进行通信,并可提供实时温度图像数据。AMG8833传感器被广泛用于热成像、人体检测、温度测量等应用领域。

2、引脚图

二、原理图

三、源码

1、iic.h

c 复制代码
#ifndef _MYIIC_H
#define _MYIIC_H
#include "sys.h"

//IO方向设置
#define SDA_IN()  {GPIOG->MODER&=~(3<<(12*2));GPIOG->MODER|=0<<12*2;}	//PH5输入模式
#define SDA_OUT() {GPIOG->MODER&=~(3<<(12*2));GPIOG->MODER|=1<<12*2;}  //PH5输出模式
//IO操作
#define IIC_SCL(n)  (n?HAL_GPIO_WritePin(GPIOG,GPIO_PIN_11,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOG,GPIO_PIN_11,GPIO_PIN_RESET)) //SCL
#define IIC_SDA(n)  (n?HAL_GPIO_WritePin(GPIOG,GPIO_PIN_12,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOG,GPIO_PIN_12,GPIO_PIN_RESET)) //SDA
#define READ_SDA    HAL_GPIO_ReadPin(GPIOG,GPIO_PIN_12)  //输入SDA

//IIC所有操作函数
void IIC_Init(void);                //初始化IIC的IO口				 
void IIC_Start(void);				//发送IIC开始信号
void IIC_Stop(void);	  			//发送IIC停止信号
void IIC_Send_Byte(u8 txd);			//IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 IIC_Wait_Ack(void); 				//IIC等待ACK信号
void IIC_Ack(void);					//IIC发送ACK信号
void IIC_NAck(void);				//IIC不发送ACK信号

void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);	 
#endif

2、iic.c

c 复制代码
#include "iic.h"
#include "delay.h"


//IIC初始化
void IIC_Init(void)
{
    GPIO_InitTypeDef GPIO_Initure;
    
    __HAL_RCC_GPIOG_CLK_ENABLE();   //使能GPIOH时钟
    
    //PH4,5初始化设置
    GPIO_Initure.Pin=GPIO_PIN_11|GPIO_PIN_12;
    GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  //推挽输出
    GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
    GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;    //快速
    HAL_GPIO_Init(GPIOG,&GPIO_Initure);
    
    IIC_SDA(1);
    IIC_SCL(1);  
}

//产生IIC起始信号
void IIC_Start(void)
{
	SDA_OUT();     //sda线输出
	IIC_SDA(1);	  	  
	IIC_SCL(1);
	delay_us(4);
 	IIC_SDA(0);//START:when CLK is high,DATA change form high to low 
	delay_us(4);
	IIC_SCL(0);//钳住I2C总线,准备发送或接收数据 
}	  
//产生IIC停止信号
void IIC_Stop(void)
{
	SDA_OUT();//sda线输出
	IIC_SCL(0);
	IIC_SDA(0);//STOP:when CLK is high DATA change form low to high
 	delay_us(4);
	IIC_SCL(1); 
	IIC_SDA(1);//发送I2C总线结束信号
	delay_us(4);							   	
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	SDA_IN();      //SDA设置为输入  
	IIC_SDA(1);delay_us(1);	   
	IIC_SCL(1);delay_us(1);	 
	while(READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL(0);//时钟输出0 	   
	return 0;  
} 
//产生ACK应答
void IIC_Ack(void)
{
	IIC_SCL(0);
	SDA_OUT();
	IIC_SDA(0);
	delay_us(2);
	IIC_SCL(1);
	delay_us(2);
	IIC_SCL(0);
}
//不产生ACK应答		    
void IIC_NAck(void)
{
	IIC_SCL(0);
	SDA_OUT();
	IIC_SDA(1);
	delay_us(2);
	IIC_SCL(1);
	delay_us(2);
	IIC_SCL(0);
}					 				     
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答			  
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
	SDA_OUT(); 	    
    IIC_SCL(0);//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        IIC_SDA((txd&0x80)>>7);
        txd<<=1; 	  
		delay_us(2);   //对TEA5767这三个延时都是必须的
		IIC_SCL(1);
		delay_us(2); 
		IIC_SCL(0);	
		delay_us(2);
    }	 
} 	    
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
u8 IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
	{
        IIC_SCL(0); 
        delay_us(2);
		IIC_SCL(1);
        receive<<=1;
        if(READ_SDA)receive++;   
		delay_us(1); 
    }					 
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}

3、amg8833.h

c 复制代码
#ifndef __AMG8833_H
#define __AMG8833_H
#include "sys.h"
#include "myiic.h"


#define STATUS_OK       0x00
#define STATUS_FAIL     0x01

#define AMG88xx_PIXEL_TEMP_CONVERSION 0.25f
#define AMG88xx_THERMISTOR_CONVERSION 0.0625f
 
enum
{
	AMG88xx_PCTL = 0x00,
	AMG88xx_RST = 0x01,
	AMG88xx_FPSC = 0x02,
	AMG88xx_INTC = 0x03,
	AMG88xx_STAT = 0x04,
	AMG88xx_SCLR = 0x05,
	//0x06 reserved
	AMG88xx_AVE = 0x07,
	AMG88xx_INTHL = 0x08,
	AMG88xx_INTHH = 0x09,
	AMG88xx_INTLL = 0x0A,
	AMG88xx_INTLH = 0x0B,
	AMG88xx_IHYSL = 0x0C,
	AMG88xx_IHYSH = 0x0D,
	AMG88xx_TTHL = 0x0E,
	AMG88xx_TTHH = 0x0F,
	AMG88xx_INT_OFFSET = 0x010,
	AMG88xx_PIXEL_OFFSET = 0x80
};
 
enum power_modes{
	AMG88xx_NORMAL_MODE = 0x00,
	AMG88xx_SLEEP_MODE = 0x01,
	AMG88xx_STAND_BY_60 = 0x20,
	AMG88xx_STAND_BY_10 = 0x21
};
 
enum sw_resets {
	AMG88xx_FLAG_RESET = 0x30,
	AMG88xx_INITIAL_RESET = 0x3F
};
 
enum frame_rates {
	AMG88xx_FPS_10 = 0x00,
	AMG88xx_FPS_1 = 0x01
};
 
enum int_enables{
	AMG88xx_INT_DISABLED = 0x00,
	AMG88xx_INT_ENABLED = 0x01
};
 
enum int_modes {
	AMG88xx_DIFFERENCE = 0x00,
	AMG88xx_ABSOLUTE_VALUE = 0x01
};


void amg8833_init(uint8_t slaveAddress);
float amg8833_read_thermistor(uint8_t slaveAddress);
void amg8833_read_pixels(uint8_t slaveAddress,float *buf, uint8_t size);

#endif

4、amg8833.c

c 复制代码
#include "amg8833.h"
#include "delay.h"


//IIC写一个字节数据
uint8_t amg8833_write_1byte(uint8_t slaveAddress, uint8_t reg,uint8_t data)
{
	IIC_Start();
	IIC_Send_Byte(slaveAddress<<1);
	if(IIC_Wait_Ack())
	{
		IIC_Stop();//释放总线
		return 1;//没应答则退出
 
	}
	IIC_Send_Byte(reg);
	IIC_Wait_Ack();	
	delay_us(5);
	IIC_Send_Byte(data);
	IIC_Wait_Ack();	
	IIC_Stop();
 
	return 0;
}
 
//IIC读一个字节数据
uint8_t amg8833_read_1byte(uint8_t slaveAddress, uint8_t reg,uint8_t *data) 
{
	IIC_Start();
	IIC_Send_Byte(slaveAddress<<1);//发写命令
	if(IIC_Wait_Ack())
	{
		 IIC_Stop();//释放总线
		 return 1;//没应答则退出
	}		
	IIC_Send_Byte(reg);
	IIC_Wait_Ack();
	delay_us(5);
	IIC_Start(); 
	IIC_Send_Byte((slaveAddress<<1)|0x01);//发读命令
	IIC_Wait_Ack();
	*data = IIC_Read_Byte(0);
	IIC_Stop();
 
	return 0;
}
 
//I2C读多个字节数据
uint8_t amg8833_read_nbyte(uint8_t slaveAddress, uint8_t reg, uint8_t *buf, uint16_t len)
{
	IIC_Start();
	IIC_Send_Byte(slaveAddress<<1);//发写命令
	if(IIC_Wait_Ack()) 
	{
		IIC_Stop();//释放总线
		return 1;//没应答则退出
	}
	IIC_Send_Byte(reg);
	IIC_Wait_Ack();
	delay_us(5);
	IIC_Start(); 
	IIC_Send_Byte((slaveAddress<<1)|0x01);//发读命令
	IIC_Wait_Ack();
	while(len)
	{
		
		if(1 == len)
		{
			*buf = IIC_Read_Byte(0);
		}
		else
		{
			*buf = IIC_Read_Byte(1);
		}
		buf++;
		len--;
	}
	IIC_Stop();
 
	return STATUS_OK;
}
 
//I2C写多个字节数据
uint8_t amg8833_write_nbyte(uint8_t slaveAddress, uint8_t reg, uint8_t *buf, uint16_t len)
{
	IIC_Start();
	IIC_Send_Byte(slaveAddress<<1);//发写命令
	if(IIC_Wait_Ack()) 
	{
		IIC_Stop();//释放总线
		return 1;//没应答则退出
	}
	IIC_Send_Byte(reg);
	IIC_Wait_Ack();
	while(len--)
	{
		IIC_Send_Byte(*buf++);
		IIC_Wait_Ack();
	}
	IIC_Stop();
 
	return STATUS_OK;
}

 
void amg8833_init(uint8_t slaveAddress)
{
	uint8_t read = 0xaa;
	//enter normal mode
	amg8833_write_1byte(slaveAddress,AMG88xx_PCTL,AMG88xx_NORMAL_MODE);
	
	//software reset
	amg8833_write_1byte(slaveAddress,AMG88xx_RST,AMG88xx_INITIAL_RESET);
	
	//set to 10 FPS
	amg8833_write_1byte(slaveAddress,AMG88xx_FPSC,AMG88xx_FPS_10);
	
	amg8833_read_1byte(slaveAddress, AMG88xx_FPSC,&read);
	
	printf("write = 0x%02x  read = 0x%02x\r\n", AMG88xx_FPS_10,read);
}
 
float signed_mag12_to_float(uint16_t val)
{
	//take first 11 bits as absolute val
	uint16_t absVal = (val & 0x7FF);
	
	return (val & 0x800) ? 0 - (float)absVal : (float)absVal ;
}
 
float amg8833_read_thermistor(uint8_t slaveAddress)
{
	uint8_t raw[2];
	uint16_t recast;
	
	amg8833_read_nbyte(slaveAddress,AMG88xx_TTHL, raw, 2);
	recast = ((uint16_t)raw[1] << 8) | ((uint16_t)raw[0]);
	return signed_mag12_to_float(recast) * AMG88xx_THERMISTOR_CONVERSION;
}
 
void amg8833_read_pixels(uint8_t slaveAddress,float *buf, uint8_t size)
{
	uint16_t recast;
	float converted;
	uint8_t rawArray[128],i;
	
	amg8833_read_nbyte(slaveAddress,AMG88xx_PIXEL_OFFSET,rawArray,128);
	
	for(i=0; i<size; i++)
	{
		uint8_t pos = i << 1;
		recast = ((uint16_t)rawArray[pos + 1] << 8) | ((uint16_t)rawArray[pos]);        
		
		converted = signed_mag12_to_float(recast) * AMG88xx_PIXEL_TEMP_CONVERSION;
		buf[i] = converted;
	}
}

四、使用方法

c 复制代码
#include "sys.h" 
#include "usart.h" 
#include "delay.h" 
#include "led.h"
#include "mpu.h"
#include "amg8833.h"

int main(void)
{
	uint8_t slaveAddress = 0x69;

	float pixTempture[8][8];
	uint8_t i,j;
	
	Cache_Enable();					//打开L1-Cache
	HAL_Init();				        //初始化HAL库
	Stm32_Clock_Init(160,5,2,4);	//设置时钟,400Mhz
	delay_init(400);				//延时初始化
	uart_init(115200);				//串口初始化
	led_init();						//初始化LED时钟
	MPU_Memory_Protection();		//保护相关存储区域
	
	IIC_Init();
	
	amg8833_init(slaveAddress);
	
  
	while(1)
	{
		amg8833_read_pixels(slaveAddress,&pixTempture[0][0], 64);
		
		for(i=0;i<8;i++)
		{
			for(j=0;j<8;j++)
			{
				printf("%.2f    ",pixTempture[i][j]);
			}
			printf("\r\n");
		}
		printf("\r\n");
		printf("\r\n");
		toggle_g_led();
		delay_ms(1000);		
	} 
}

五、工程源码

点击下载

相关推荐
蓝斯49713 小时前
从.到实现一个Windows上的虚拟hid键盘设备
windows·单片机·计算机外设
熙芯XiChip14 小时前
硬实时与软实时RTOS核心区别
嵌入式硬件
伟大的前程14 小时前
unsigned int 定义的变量 在 电脑的 64 位系统中 和 32 位 cortex-m0 和 8 位的 51 单片机
单片机·嵌入式硬件
小渔村的拉线工14 小时前
1.HPM6E80 解析芯片整体工作原理和存储架构
单片机·嵌入式硬件·mcu·架构·hpm6e80
熙芯XiChip15 小时前
CAN与CANopen的本质区别
单片机
lilihewo16 小时前
Altium Designer 封装库的创建(分享pcb 3D封装库)
嵌入式硬件·51单片机
神罚天下ET16 小时前
典型arm位单片机启动流程(从上电到main.c)
c语言·arm开发·单片机
碧海银沙音频科技研究院17 小时前
蓝牙耳机使用WSDF5361锂保芯片进入船运模式实现方法
嵌入式硬件·算法
Zevalin爱灰灰18 小时前
模拟信号链电路——基于TL431的电压基准电路
单片机·嵌入式硬件
csdn杰哥19 小时前
瑞萨单片机开发教程[二十七] DTC 外部中断触发传输实验
单片机·嵌入式硬件·mongodb·瑞萨·ra6m5