打印
[应用相关]

AMG8833的使用与stm32驱动代码

[复制链接]
908|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主

一、介绍

1、内部框图

        可以看到AMG8833的内部有红外点阵测温,并且还带有一个热敏电阻。使用同一个ADC进行采样,然后送给Control。


使用特权

评论回复
沙发
xiaoqizi|  楼主 | 2021-6-4 14:52 | 只看该作者

2、器件参数

测温点数:64(8x8的矩阵)

帧率:10帧每秒或1帧每秒

红外测温分辨率:0.25℃

热敏电阻测量温度范围:-20℃~80℃

热敏电阻分辨率:0.0625℃

红外测温的准确度:High gain误差在2.5℃以内;Low gain误差在3℃以内。


使用特权

评论回复
板凳
xiaoqizi|  楼主 | 2021-6-4 14:52 | 只看该作者

3、点阵的排布顺序是:从右到左、从下到上。因此右下角才是第一个点。


使用特权

评论回复
地板
xiaoqizi|  楼主 | 2021-6-4 14:52 | 只看该作者

4、视角是水平60度、垂直60度。


使用特权

评论回复
5
xiaoqizi|  楼主 | 2021-6-4 14:53 | 只看该作者
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脚接一个电容。


使用特权

评论回复
6
xiaoqizi|  楼主 | 2021-6-4 14:53 | 只看该作者

二、寄存器

1、Power Control寄存器:设置AMG8833的工作模式

工作模式有4种:

模式之间的转换关系:

注:

(1)在休眠模式中进行的写操作只有在进入正常模式后才生效。

(2)在休眠模式中读操作是无效的。


使用特权

评论回复
7
xiaoqizi|  楼主 | 2021-6-4 14:53 | 只看该作者

2、Reset寄存器:进行软复位。

有两种复位方式:

        Flag Reset会清除Status寄存器(0x04)、中断标志、中断表(0x10~0x17)

        Initial Reset会复位标志,并使AMG8833的参数恢复初始。


使用特权

评论回复
8
xiaoqizi|  楼主 | 2021-6-4 14:54 | 只看该作者

3、Frame Rate寄存器:设定帧率

bit0: Setting Frame Mode
1: 1FPS
0: 10FPS


使用特权

评论回复
9
xiaoqizi|  楼主 | 2021-6-4 14:54 | 只看该作者
4、Interrupt Control寄存器:配置中断功能



bit1: INTMOD
1: Absolute Value Interrupt Mode
0: Difference Interrupt Mode
bit0: INTEN
1: INT 引脚输出使能
0: INT 引脚禁止输出(保持高阻状态)


使用特权

评论回复
10
xiaoqizi|  楼主 | 2021-6-4 14:54 | 只看该作者
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)


使用特权

评论回复
11
xiaoqizi|  楼主 | 2021-6-4 14:54 | 只看该作者

6、Status Clear寄存器:清除溢出标志和中断标志

bit3: OVT_CLR
1: 清除热敏电阻温度输出溢出标志
bit2: OVS_CLR
1: 清除红外温度输出溢出标志
bit1: INTCLR
1: 清除中断标志


使用特权

评论回复
12
xiaoqizi|  楼主 | 2021-6-4 14:55 | 只看该作者

7、Average寄存器:设置移动平均输出模式

bit5: MAMOD
1::Twice moving average Output Mode

0:No moving average


使用特权

评论回复
13
xiaoqizi|  楼主 | 2021-6-4 14:55 | 只看该作者
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℃。


使用特权

评论回复
14
xiaoqizi|  楼主 | 2021-6-4 14:55 | 只看该作者

9、Thermistor寄存器:热敏电阻测量的温度值

有12位数据。最高位为符号位,值为0表示正,值为1表示负。步进值为0.0625℃。举例如下:


使用特权

评论回复
15
xiaoqizi|  楼主 | 2021-6-4 14:56 | 只看该作者
10、Interrupt Table寄存器:显示哪一个像素点发生了中断



        当64个像素点中的某一个点的温度值高于或低于了Interrupt Level寄存器中设置的上下限,就会在Interrupt Table寄存器的对应位设置值。值为1代表发生了中断,0表示没有。


使用特权

评论回复
16
xiaoqizi|  楼主 | 2021-6-4 14:56 | 只看该作者
11、Temperature寄存器:红外点阵测量的温度值



有12位数据。最高位为符号位,值为0表示正,值为1表示负。步进值为0.25℃。举例如下:



        0x80和0x81保存的是第一个像素的温度值,1~64像素对应地址为0x80~0xFF。

注:

(1)1~64像素(0x80~0xFF)的温度值是一起更新的,不需要任何指令。

(2)0x80~0xFF的数据是一次读出的,所以不用担心新的温度值和旧的温度值会混在一起。


使用特权

评论回复
17
xiaoqizi|  楼主 | 2021-6-4 14:57 | 只看该作者

三、寄存器总表

。。。


使用特权

评论回复
18
xiaoqizi|  楼主 | 2021-6-4 14:57 | 只看该作者
四、驱动代码

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



使用特权

评论回复
19
xiaoqizi|  楼主 | 2021-6-4 14:58 | 只看该作者
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;
}


使用特权

评论回复
20
xiaoqizi|  楼主 | 2021-6-4 14:58 | 只看该作者
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


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

76

主题

4030

帖子

3

粉丝