一、介绍
1、内部框图
可以看到AMG8833的内部有红外点阵测温,并且还带有一个热敏电阻。使用同一个ADC进行采样,然后送给Control。
2、器件参数
测温点数:64(8x8的矩阵)
帧率:10帧每秒或1帧每秒
红外测温分辨率:0.25℃
热敏电阻测量温度范围:-20℃~80℃
热敏电阻分辨率:0.0625℃
红外测温的准确度:High gain误差在2.5℃以内;Low gain误差在3℃以内。
3、点阵的排布顺序是:从右到左、从下到上。因此右下角才是第一个点。
4、视角是水平60度、垂直60度。
5、原理图
2脚和3脚是IIC通信引脚,最大速度400K。
4脚是中断引脚,如果INT control寄存器中激活了中断功能,当发生中断,此引脚会拉低。
5脚是IIC设备地址选择脚。拉低,设备地址为110 1000,即0x68。拉高,设备地址为110 1001,即0x69。
设备地址占据高7位,最低位是读写位,0表示写,1表示读。所以当5脚拉低,进行写操作时,8位数据为:1101
0000,即0xD0,读操作时,8位数据为:1101 0001,即0xD1。
6脚为地。
9脚和13脚为VDD,可以3.3V或5V供电。
10脚接一个电容和电阻。
12脚接一个电容。
二、寄存器
1、Power Control寄存器:设置AMG8833的工作模式
工作模式有4种:
模式之间的转换关系:
注:
(1)在休眠模式中进行的写操作只有在进入正常模式后才生效。
(2)在休眠模式中读操作是无效的。
2、Reset寄存器:进行软复位。
有两种复位方式:
Flag Reset会清除Status寄存器(0x04)、中断标志、中断表(0x10~0x17)
Initial Reset会复位标志,并使AMG8833的参数恢复初始。
3、Frame Rate寄存器:设定帧率
bit0: Setting Frame Mode
1: 1FPS
0: 10FPS
4、Interrupt Control寄存器:配置中断功能
bit1: INTMOD
1: Absolute Value Interrupt Mode
0: Difference Interrupt Mode
bit0: INTEN
1: INT 引脚输出使能
0: INT 引脚禁止输出(保持高阻状态)
5、Status寄存器:溢出标志和中断标志
bit3: OVF_THS
1: 热敏电阻温度输出溢出标志
(Value of Thermistor (0x0E、0x0F) : 0xFFF)
bit2: OVF_IRS
1: 红外温度输出溢出标志
(Value of Temperature Register(0x80~0xFF): 0xFFF)
bit1: INTF
1: 发生中断标志
(Value of Interrupt Table Register(0x10~0x17): Except for 0x00)
6、Status Clear寄存器:清除溢出标志和中断标志
bit3: OVT_CLR
1: 清除热敏电阻温度输出溢出标志
bit2: OVS_CLR
1: 清除红外温度输出溢出标志
bit1: INTCLR
1: 清除中断标志
7、Average寄存器:设置移动平均输出模式
bit5: MAMOD
1::Twice moving average Output Mode
0:No moving average
8、Interrupt Level寄存器:设置发生中断的上限值、下限值、迟滞值。
INT_LVL_H [11:0]:中断上限值,当温度高于此值,输出中断并且设置Interrupt Table寄存器。
INT_LVL_L [11:0]:中断下限值,当温度低于此值,输出中断并且设置Interrupt Table寄存器。
INT_HYS [11:0]:设置上限值、下限值的迟滞值,类似于施密特触发器。
上述3个数据都是12位数据。最高位为符号位,值为0表示正,值为1表示负。步进值为0.25℃。
9、Thermistor寄存器:热敏电阻测量的温度值
有12位数据。最高位为符号位,值为0表示正,值为1表示负。步进值为0.0625℃。举例如下:
10、Interrupt Table寄存器:显示哪一个像素点发生了中断
当64个像素点中的某一个点的温度值高于或低于了Interrupt Level寄存器中设置的上下限,就会在Interrupt
Table寄存器的对应位设置值。值为1代表发生了中断,0表示没有。
11、Temperature寄存器:红外点阵测量的温度值
有12位数据。最高位为符号位,值为0表示正,值为1表示负。步进值为0.25℃。举例如下:
0x80和0x81保存的是第一个像素的温度值,1~64像素对应地址为0x80~0xFF。
注:
(1)1~64像素(0x80~0xFF)的温度值是一起更新的,不需要任何指令。
(2)0x80~0xFF的数据是一次读出的,所以不用担心新的温度值和旧的温度值会混在一起。
三、寄存器总表
。。。
四、驱动代码
1、AMG_IIC.h
#ifndef __AMG_I2C_H #define __AMG_I2C_H #include "stdint.h" #include "sys.h"
#include "delay.h" #define AMG_SDA_RCC RCC_APB2Periph_GPIOB #define AMG_SDA_PIN
GPIO_Pin_7 #define AMG_SDA_IOx GPIOB #define AMG_SCL_RCC RCC_APB2Periph_GPIOB
#define AMG_SCL_PIN GPIO_Pin_6 #define AMG_SCL_IOx GPIOB #define AMG_SDA_IN()
{GPIOB->CRL&=0x0FFFFFFF;GPIOB->CRL|=8<<28;} #define AMG_SDA_OUT()
{GPIOB->CRL&=0x0FFFFFFF;GPIOB->CRL|=3<<28;} #define AMG_IIC_SCL PBout(6) //SCL
#define AMG_IIC_SDA PBout(7) //SDA #define AMG_READ_SDA PBin(7) //输入SDA #define
AMG88xx_ADR 0xD0 //5脚拉低时的设备地址 //Status #define STATUS_OK 0x00 #define
STATUS_FAIL 0x01 void AMG8833_IIC_Init(void); u8 AMG_IIC_Write_1Byte(u8
SlaveAddress, u8 REG_Address,u8 REG_data); u8 AMG_IIC_Read_1Byte(u8
SlaveAddress, u8 REG_Address,u8 *REG_data); uint8_t AMG_I2C_Read_nByte(uint8_t
SlaveAddress, uint8_t REG_Address, uint8_t *buf, uint16_t len); #endif
2、AMG_IIC.c
#include "AMG_IIC.h" void AMG8833_IIC_Init(void) { GPIO_InitTypeDef
GPIO_InitStructure; RCC_APB2PeriphClockCmd( AMG_SDA_RCC, ENABLE );
GPIO_InitStructure.GPIO_Pin = AMG_SDA_PIN; //端口配置 GPIO_InitStructure.GPIO_Mode
= GPIO_Mode_Out_PP ; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//50Mhz速度 GPIO_Init(AMG_SDA_IOx, &GPIO_InitStructure); RCC_APB2PeriphClockCmd(
AMG_SCL_RCC, ENABLE ); GPIO_InitStructure.GPIO_Pin = AMG_SCL_PIN; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50Mhz速度
GPIO_Init(AMG_SCL_IOx, &GPIO_InitStructure);
GPIO_SetBits(AMG_SDA_IOx,AMG_SDA_PIN);//SDA输出高
GPIO_SetBits(AMG_SCL_IOx,AMG_SCL_PIN);//SCL输出高 } void AMG_IIC_Start(void) {
AMG_SDA_OUT();//sda线输出 AMG_IIC_SDA=1; AMG_IIC_SCL=1; delay_us(4);
AMG_IIC_SDA=0;//START:when CLK is high,DATA change form high to low
delay_us(4); AMG_IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 } //产生IIC停止信号 void
AMG_IIC_Stop(void) { AMG_SDA_OUT();//sda线输出 AMG_IIC_SCL=0;
AMG_IIC_SDA=0;//STOP:when CLK is high DATA change form low to high delay_us(4);
AMG_IIC_SCL=1; AMG_IIC_SDA=1;//发送I2C总线结束信号 delay_us(4); } u8
AMG_IIC_Wait_Ack(void) { u8 ucErrTime=0; AMG_SDA_IN(); //SDA设置为输入
AMG_IIC_SDA=1;delay_us(1); AMG_IIC_SCL=1;delay_us(1); while(AMG_READ_SDA) {
ucErrTime++; if(ucErrTime>250) { AMG_IIC_Stop(); return 1; } }
AMG_IIC_SCL=0;//时钟输出0 return 0; } //产生ACK应答 void AMG_IIC_Ack(void) {
AMG_IIC_SCL=0; AMG_SDA_OUT(); AMG_IIC_SDA=0; delay_us(2); AMG_IIC_SCL=1;
delay_us(2); AMG_IIC_SCL=0; } //不产生ACK应答 void AMG_IIC_NAck(void) {
AMG_IIC_SCL=0; AMG_SDA_OUT(); AMG_IIC_SDA=1; delay_us(2); AMG_IIC_SCL=1;
delay_us(2); AMG_IIC_SCL=0; } //IIC发送一个字节 //返回从机有无应答 //1,有应答 //0,无应答 void
AMG_IIC_Send_Byte(u8 txd) { u8 t; AMG_SDA_OUT(); AMG_IIC_SCL=0;//拉低时钟开始数据传输
for(t=0;t<8;t++) { if((txd&0x80)>>7) AMG_IIC_SDA=1; else AMG_IIC_SDA=0;
txd<<=1; delay_us(2); AMG_IIC_SCL=1; delay_us(2); AMG_IIC_SCL=0; delay_us(2); }
} //读1个字节,ack=1时,发送ACK,ack=0,发送nACK u8 AMG_IIC_Read_Byte(void) { unsigned char
i,receive=0; AMG_SDA_IN(); //SDA设置为输入 AMG_IIC_SDA = 1; delay_us(4);
for(i=0;i<8;i++ ) { receive<<=1; AMG_IIC_SCL=0; delay_us(4); AMG_IIC_SCL=1;
delay_us(4); if(AMG_READ_SDA) receive |= 0x01; delay_us(4); //1 } AMG_IIC_SCL =
0; return receive; } //IIC写一个字节数据 u8 AMG_IIC_Write_1Byte(u8 SlaveAddress, u8
REG_Address,u8 REG_data) { AMG_IIC_Start(); AMG_IIC_Send_Byte(SlaveAddress);
if(AMG_IIC_Wait_Ack()) { AMG_IIC_Stop();//释放总线 return 1;//没应答则退出 }
AMG_IIC_Send_Byte(REG_Address); AMG_IIC_Wait_Ack(); delay_us(5);
AMG_IIC_Send_Byte(REG_data); AMG_IIC_Wait_Ack(); AMG_IIC_Stop(); return 0; }
//IIC读一个字节数据 u8 AMG_IIC_Read_1Byte(u8 SlaveAddress, u8 REG_Address,u8
*REG_data) { AMG_IIC_Start(); AMG_IIC_Send_Byte(SlaveAddress);//发写命令
if(AMG_IIC_Wait_Ack()) { AMG_IIC_Stop();//释放总线 return 1;//没应答则退出 }
AMG_IIC_Send_Byte(REG_Address); AMG_IIC_Wait_Ack(); delay_us(5);
AMG_IIC_Start(); AMG_IIC_Send_Byte(SlaveAddress|0x01);//发读命令
AMG_IIC_Wait_Ack(); *REG_data = AMG_IIC_Read_Byte(); AMG_IIC_Stop(); return 0;
} //I2C读多个字节数据 uint8_t AMG_I2C_Read_nByte(uint8_t SlaveAddress, uint8_t
REG_Address, uint8_t *buf, uint16_t len) { AMG_IIC_Start();
AMG_IIC_Send_Byte(SlaveAddress);//发写命令 if(AMG_IIC_Wait_Ack()) {
AMG_IIC_Stop();//释放总线 return 1;//没应答则退出 } AMG_IIC_Send_Byte(REG_Address);
AMG_IIC_Wait_Ack(); delay_us(5); AMG_IIC_Start();
AMG_IIC_Send_Byte(SlaveAddress|0x01);//发读命令 AMG_IIC_Wait_Ack(); while(len) {
*buf = AMG_IIC_Read_Byte(); if(1 == len) { AMG_IIC_NAck(); } else {
AMG_IIC_Ack(); } buf++; len--; } AMG_IIC_Stop(); return STATUS_OK; }
//I2C写多个字节数据 uint8_t AMG_I2C_Write_nByte(uint8_t SlaveAddress, uint8_t
REG_Address, uint8_t *buf, uint16_t len) { AMG_IIC_Start();
AMG_IIC_Send_Byte(SlaveAddress);//发写命令 if(AMG_IIC_Wait_Ack()) {
AMG_IIC_Stop();//释放总线 return 1;//没应答则退出 } AMG_IIC_Send_Byte(REG_Address);
AMG_IIC_Wait_Ack(); while(len--) { AMG_IIC_Send_Byte(*buf++);
AMG_IIC_Wait_Ack(); } AMG_IIC_Stop(); return STATUS_OK; }
3、AMG8833.h
#ifndef __AMG8833_H #define __AMG8833_H #include "AMG_IIC.h" #define
AMG88xx_PIXEL_TEMP_CONVERSION 0.25 #define AMG88xx_THERMISTOR_CONVERSION 0.0625
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(void); float AMG88xx_ReadThermistor(void); void
amg88xx_readPixels(float *buf, uint8_t size); #endif
4、AMG8833.c
#include "AMG8833.h" void AMG8833_Init(void) { AMG8833_IIC_Init(); //IIC初始化
//enter normal mode
AMG_IIC_Write_1Byte(AMG88xx_ADR,AMG88xx_PCTL,AMG88xx_NORMAL_MODE); //software
reset AMG_IIC_Write_1Byte(AMG88xx_ADR,AMG88xx_RST,AMG88xx_INITIAL_RESET); //set
to 10 FPS AMG_IIC_Write_1Byte(AMG88xx_ADR,AMG88xx_FPSC,AMG88xx_FPS_10); } float
signedMag12ToFloat(uint16_t val) { //take first 11 bits as absolute val
uint16_t absVal = (val & 0x7FF); return (val & 0x800) ? 0 - (float)absVal :
(float)absVal ; } float AMG88xx_ReadThermistor(void) { uint8_t raw[2]; uint16_t
recast; AMG_I2C_Read_nByte(AMG88xx_ADR,AMG88xx_TTHL, raw, 2); recast =
((uint16_t)raw[1] << 8) | ((uint16_t)raw[0]); return signedMag12ToFloat(recast)
* AMG88xx_THERMISTOR_CONVERSION; } void amg88xx_readPixels(float *buf, uint8_t
size) { uint16_t recast; float converted; uint8_t rawArray[128],i;
AMG_I2C_Read_nByte(AMG88xx_ADR,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 = signedMag12ToFloat(recast) *
AMG88xx_PIXEL_TEMP_CONVERSION; buf[i] = converted; } }