文章目录

  • AMG8833介绍
    • 内部框图
    • 器件参数
    • 点阵的排布顺序
    • 原理图
    • 内部寄存器
      • 1、Power Control寄存器:
      • 2、Reset寄存器:
      • 4、Interrupt Control寄存器:
      • 5、Status寄存器:
      • 6、Status Clear寄存器:
      • 7、Average寄存器:
      • 8、Interrupt Level寄存器:
      • 9、Thermistor寄存器:
      • 10、Interrupt Table寄存器:
      • 11、Temperature寄存器:
  • HI3516驱动开发
  • 测试代码
  • 最终效果

AMG8833介绍

内部框图

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

器件参数

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

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

红外测温分辨率:0.25℃

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

热敏电阻分辨率:0.0625℃

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

点阵的排布顺序

从右到左、从下到上。因此右下角才是第一个点。

原理图

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的工作模式

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的数据是一次读出的,所以不用担心新的温度值和旧的温度值会混在一起。

HI3516驱动开发

为了避免麻烦,并且这里的传输数据量并不是非常大,所以直接用IO读取数据
所以如果要用其他LINUX开发板底层函数必须根据你们的板子重新编写。

/** @Description: * @Autor: YURI* @Date: 2022-01-21 17:14:06* @LastEditors: YURI* @LastEditTime: 2022-01-31 00:03:07*/
#ifndef amg8833_H
#define amg8833_H#define GPIO0_BASE_ADDR            0x120D0000
#define GPIO0_DIR_ADDR            ((GPIO0_BASE_ADDR) + (0x400))
#define GPIO0_DATA_OUT_ADDR       ((GPIO0_BASE_ADDR) + (0x000))
#define GPIO0_DATA                ((GPIO0_BASE_ADDR) + (0x3FC))#define GPIO1_BASE_ADDR             0x120D1000
#define GPIO1_DIR_ADDR            ((GPIO1_BASE_ADDR) + (0x400))
#define GPIO1_DATA_OUT_ADDR       ((GPIO1_BASE_ADDR) + (0x000))
#define GPIO1_DATA                ((GPIO1_BASE_ADDR) + (0x3FC))#define GPIO2_BASE_ADDR             0x120D2000
#define GPIO2_DIR_ADDR            ((GPIO2_BASE_ADDR) + (0x400))
#define GPIO2_DATA_OUT_ADDR       ((GPIO2_BASE_ADDR) + (0x000))
#define GPIO2_DATA                ((GPIO2_BASE_ADDR) + (0x3FC))#define GPIO3_BASE_ADDR             0x120D3000
#define GPIO3_DIR_ADDR            ((GPIO3_BASE_ADDR) + (0x400))
#define GPIO3_DATA_OUT_ADDR       ((GPIO3_BASE_ADDR) + (0x000))
#define GPIO3_DATA                ((GPIO3_BASE_ADDR) + (0x3FC))#define GPIO4_BASE_ADDR             0x120D4000
#define GPIO4_DIR_ADDR            ((GPIO4_BASE_ADDR) + (0x400))
#define GPIO4_DATA_OUT_ADDR       ((GPIO4_BASE_ADDR) + (0x000))
#define GPIO4_DATA                ((GPIO4_BASE_ADDR) + (0x3FC))#define GPIO5_BASE_ADDR             0x120D5000
#define GPIO5_DIR_ADDR            ((GPIO5_BASE_ADDR) + (0x400))
#define GPIO5_DATA_OUT_ADDR       ((GPIO5_BASE_ADDR) + (0x000))
#define GPIO5_DATA                ((GPIO5_BASE_ADDR) + (0x3FC))#define GPIO6_BASE_ADDR             0x120D6000
#define GPIO6_DIR_ADDR            ((GPIO6_BASE_ADDR) + (0x400))
#define GPIO6_DATA_OUT_ADDR       ((GPIO6_BASE_ADDR) + (0x000))
#define GPIO6_DATA                ((GPIO6_BASE_ADDR) + (0x3FC))#define GPIO7_BASE_ADDR             0x120D7000
#define GPIO7_DIR_ADDR            ((GPIO7_BASE_ADDR) + (0x400))
#define GPIO7_DATA_OUT_ADDR       ((GPIO7_BASE_ADDR) + (0x000))
#define GPIO7_DATA                ((GPIO7_BASE_ADDR) + (0x3FC))#define GPIO8_BASE_ADDR             0x120D8000
#define GPIO8_DIR_ADDR            ((GPIO8_BASE_ADDR) + (0x400))
#define GPIO8_DATA_OUT_ADDR       ((GPIO8_BASE_ADDR) + (0x000))
#define GPIO8_DATA                ((GPIO8_BASE_ADDR) + (0x3FC))#define GPIO9_BASE_ADDR             0x120D9000
#define GPIO9_DATA_OUT_ADDR       ((GPIO9_BASE_ADDR) + (0x000))
#define GPIO9_SET_DATA_ADDR       ((GPIO9_DATA_OUT_ADDR) + (0x200))
#define GPIO9_DATA                ((GPIO9_BASE_ADDR) + (0x3FC))#define GPIO10_BASE_ADDR            0x120DA000
#define GPIO10_DIR_ADDR            ((GPIO10_BASE_ADDR) + (0x400))
#define GPIO10_DATA_OUT_ADDR       ((GPIO10_BASE_ADDR) + (0x000))
#define GPIO10_DATA                ((GPIO10_BASE_ADDR) + (0x3FC))#define GPIO11_BASE_ADDR              0x120DB000
#define GPIO11_DIR_ADDR            ((GPIO11_BASE_ADDR) + (0x400))
#define GPIO11_DATA_OUT_ADDR       ((GPIO11_BASE_ADDR) + (0x000))
#define GPIO11_DATA                ((GPIO11_BASE_ADDR) + (0x3FC))
enum amg8833_pin_direction{amg8833_IN=0,amg8833_OUT=1};#define AMG8833_DELAY_TIME  4//amg8833 关键控制器
typedef struct
{volatile unsigned long *pin_mutx;   //管脚选择地址volatile unsigned long *pin_dir;    //管脚方向地址volatile unsigned long *pin_data;//控制管脚的数据组在的位置volatile int pin_index;             //管脚号
}amg8833_pin;//amg8833 硬件控制器
typedef struct
{amg8833_pin *sck;        // 时钟amg8833_pin *sda;        // 数据线amg8833_pin *inter;      // 中断线amg8833_pin *ad0;        // 地址选择
}amg8833_ctl;#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 reservedAMG88xx_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
};
#define AMG88xx_ADR    0xD0          //5脚拉低时的设备地址#endif
/** @Description: * @Autor: YURI* @Date: 2022-01-30 17:18:51* @LastEditors: YURI* @LastEditTime: 2022-01-31 00:33:38*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <linux/delay.h>
#include "amg8833.h"
amg8833_ctl amg8833;
#define DEVICE_NAME "amg8833" /*** @description: amg8833 管脚初始化* @param {unsigned long} base_addr* @param {unsigned long} mutex_addr* @param {int} mutex_select* @param {int} pin_direction* @param {int} pinindex* @param {int} pindefaultvalue* @return {*}* @author: YURI*/
static amg8833_pin* amg8833_pin_init(unsigned long base_addr,unsigned long mutex_addr,int mutex_select,int pin_direction,int pinindex,int pindefaultvalue)
{amg8833_pin* pin=(amg8833_pin*)kmalloc(sizeof(amg8833_pin),GFP_KERNEL);pin->pin_dir     = (volatile unsigned long *)ioremap(base_addr+(0x400), 32);//方向选择寄存器pin->pin_data    = (volatile unsigned long *)ioremap(base_addr+(0x3FC), 32);//数据寄存器pin->pin_mutx    = (volatile unsigned long *)ioremap(mutex_addr, 32);       //功能选择寄存器pin->pin_index   = pinindex;*(pin->pin_data)|=(pindefaultvalue<<pinindex);*(pin->pin_mutx)=mutex_select;*(pin->pin_dir )=(pin_direction<<pinindex);return pin;
}
/*** @description: amg8833 管脚恢复* @param {amg8833_pin*} pin* @return {*}* @author: YURI*/
static void amg8833_pin_uninit(amg8833_pin* pin)
{iounmap(pin->pin_data);iounmap(pin->pin_mutx);iounmap(pin->pin_dir);kfree(pin);
}
/*** @description: 改变输入输出方向* @param {amg8833_pin*} pin* @param {int} pin_direction* @return {*}* @author: YURI*/
static inline void amg8833_pin_change_direction(amg8833_pin* pin,int pin_direction)
{*(pin->pin_dir )=(pin_direction<<pin->pin_index);
}
/*** @description: 设置管脚数值* @param {amg8833_pin*} pin* @param {int} value* @return {*}* @author: YURI*/
static inline void amg8833_pin_change_value(amg8833_pin* pin,int value)
{//printk("KERNEL VALUE %d",value);if(value) *(pin->pin_data)|=(1<<(pin->pin_index));else *(pin->pin_data)&=~(1<<(pin->pin_index));
}
/*** @description: 反转管脚* @param {amg8833_pin*} pin* @return {*}* @author: YURI*/
static inline void amg8833_pin_toggle_value(amg8833_pin* pin)
{if(*(pin->pin_data)&(1<<(pin->pin_index))) *(pin->pin_data)&=~(1<<(pin->pin_index));else *(pin->pin_data)|=(1<<(pin->pin_index));
}
/*** @description: 获取管脚电平* @param {amg8833_pin*} pin* @return {*}* @author: YURI*/
static inline int amg8833_pin_get_value(amg8833_pin* pin)
{if(*(pin->pin_data)&(1<<(pin->pin_index)))return 1;else return 0;
}
/*** @description: amg8833结构体初始化,初始化所有管脚* @param {*}* @return {*}* @author: YURI*/
static void amg8833_ctl_init(void)
{amg8833.sck   =amg8833_pin_init(GPIO0_BASE_ADDR,0X112F0034,0X520,amg8833_OUT,6,0);//0_6amg8833.sda   =amg8833_pin_init(GPIO2_BASE_ADDR,0X114F0068,0X520,amg8833_OUT,3,0);//2_3amg8833.inter =amg8833_pin_init(GPIO8_BASE_ADDR,0X112F0040,0X524,amg8833_OUT,7,0);//8_7amg8833.ad0   =amg8833_pin_init(GPIO7_BASE_ADDR,0X112F0044,0X520,amg8833_OUT,0,0);//7_0
}
/*** @description: 释放硬件资源* @param {*}* @return {*}* @author: YURI*/
static void amg8833_ctl_uninit(void)
{amg8833_pin_uninit(amg8833.sck);amg8833_pin_uninit(amg8833.sda);amg8833_pin_uninit(amg8833.inter);amg8833_pin_uninit(amg8833.ad0);
}/*** @description:IIC开始信号 当SLK高电平 SDA由高变低* @param {*}* @return {*}* @author: YURI*/
void amg_iic_start(void)
{amg8833_pin_change_direction(amg8833.sda,amg8833_OUT);amg8833_pin_change_value(amg8833.sda,1);amg8833_pin_change_value(amg8833.sck,1);udelay(AMG8833_DELAY_TIME);amg8833_pin_change_value(amg8833.sda,0);udelay(AMG8833_DELAY_TIME);amg8833_pin_change_value(amg8833.sck,0);
}/*** @description:IIC结束信号 当SLK高电平 SDA由低变高* @param {*}* @return {*}* @author: YURI*/
void amg_iic_stop(void)
{amg8833_pin_change_direction(amg8833.sda,amg8833_OUT);amg8833_pin_change_value(amg8833.sck,0);amg8833_pin_change_value(amg8833.sda,0);udelay(AMG8833_DELAY_TIME);amg8833_pin_change_value(amg8833.sck,1);amg8833_pin_change_value(amg8833.sda,1);udelay(AMG8833_DELAY_TIME);
}
/*** @description: 主机SCL拉高,读取从机SDA的电平,为低电平表示产生应答* @param {*}* @return {*}* @author: YURI*/
unsigned char amg_iic_wait_ack(void)
{unsigned char ucErrTime=0;amg8833_pin_change_direction(amg8833.sda,amg8833_IN);amg8833_pin_change_value(amg8833.sda,1);udelay(AMG8833_DELAY_TIME);amg8833_pin_change_value(amg8833.sck,1);udelay(AMG8833_DELAY_TIME);while(amg8833_pin_get_value(amg8833.sda)){ucErrTime++;if(ucErrTime>250){amg_iic_stop();return 1;}}amg8833_pin_change_value(amg8833.sck,0);//时钟输出0      return 0;
}//产生ACK应答
//1.先拉低SCL,再拉低SDA
//2.拉高SCL
//3.拉低SCL
void amg_iic_ack(void)
{amg8833_pin_change_value(amg8833.sck,0);amg8833_pin_change_direction(amg8833.sda,amg8833_OUT);amg8833_pin_change_value(amg8833.sda,0);udelay(AMG8833_DELAY_TIME/2);amg8833_pin_change_value(amg8833.sck,1);udelay(AMG8833_DELAY_TIME/2);amg8833_pin_change_value(amg8833.sck,0);
}//不产生ACK应答
//1.先拉低SCL,再拉高SDA
//2.拉高SCL
//3.拉低SCL
void amg_iic_nack(void)
{amg8833_pin_change_value(amg8833.sck,0);amg8833_pin_change_direction(amg8833.sda,amg8833_OUT);amg8833_pin_change_value(amg8833.sda,1);udelay(AMG8833_DELAY_TIME/2);amg8833_pin_change_value(amg8833.sck,1);udelay(AMG8833_DELAY_TIME/2);amg8833_pin_change_value(amg8833.sck,0);
}//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void amg_iic_send_byte(unsigned char txd)
{                        unsigned char t;   amg8833_pin_change_direction(amg8833.sda,amg8833_OUT);   amg8833_pin_change_value(amg8833.sck,0);//拉低时钟开始数据传输for(t=0;t<8;t++){              if((txd&0x80)>>7)amg8833_pin_change_value(amg8833.sda,1);elseamg8833_pin_change_value(amg8833.sda,0);txd<<=1;      udelay(AMG8833_DELAY_TIME/2);  amg8833_pin_change_value(amg8833.sck,1);udelay(AMG8833_DELAY_TIME/2); amg8833_pin_change_value(amg8833.sck,0); udelay(AMG8833_DELAY_TIME/2);}
} //读1个字节,ack=1时,发送ACK,ack=0,发送nACK
unsigned char amg_iic_read_byte(void)
{unsigned char i,receive=0;amg8833_pin_change_direction(amg8833.sda,amg8833_IN);amg8833_pin_change_value(amg8833.sda,1);;udelay(4);for(i=0;i<8;i++ ){receive<<=1;amg8833_pin_change_value(amg8833.sck,0); udelay(AMG8833_DELAY_TIME);amg8833_pin_change_value(amg8833.sck,1);udelay(AMG8833_DELAY_TIME);if(amg8833_pin_get_value(amg8833.sda))receive |= 0x01;   udelay(AMG8833_DELAY_TIME); }   amg8833_pin_change_value(amg8833.sck,0);    return receive;
}
//IIC写一个字节数据
unsigned char amg_iic_write_1_byte(unsigned char SlaveAddress, unsigned char REG_Address,unsigned char 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();   udelay(5);amg_iic_send_byte(REG_data);amg_iic_wait_ack();   amg_iic_stop();return 0;
}//IIC读一个字节数据
unsigned char amg_iic_read_1_byte(unsigned char SlaveAddress, unsigned char REG_Address,unsigned char *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();udelay(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读多个字节数据
unsigned char amg_iic_read_n_byte(unsigned char SlaveAddress, unsigned char REG_Address, unsigned char *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();udelay(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 0;
}//I2C写多个字节数据
unsigned char amg_iic_write_n_byte(unsigned char SlaveAddress, unsigned char REG_Address, unsigned char *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 0;
}/*** @description: 打开操作* @param {inode} *inode* @param {file} *file* @return {*}* @author: YURI*/
static int amg8833_drv_open(struct inode *inode, struct file *file)
{amg8833_pin_change_value(amg8833.ad0,0);//enter normal modeamg_iic_write_1_byte(AMG88xx_ADR,AMG88xx_PCTL,AMG88xx_NORMAL_MODE);//software resetamg_iic_write_1_byte(AMG88xx_ADR,AMG88xx_RST,AMG88xx_INITIAL_RESET);//set to 10 FPSamg_iic_write_1_byte(AMG88xx_ADR,AMG88xx_FPSC,AMG88xx_FPS_10);return 0;
}/*** @description: 释放操作* @param {inode} *pinode* @param {file} *pfile* @return {*}* @author: YURI*/
static int amg8833_drv_release(struct inode *pinode , struct file *pfile)
{return 0;
}/*** @description: * @param {file} *file* @param {char __user} *buf* @param {size_t} count* @param {loff_t} *ppos* @return {*}* @author: YURI*/
static ssize_t amg8833_drv_read(struct file *file,  char __user *buf, size_t count, loff_t *ppos)
{uint8_t rawArray[128],i;local_irq_disable();amg_iic_read_n_byte(AMG88xx_ADR,AMG88xx_PIXEL_OFFSET,rawArray,128);local_irq_enable();copy_to_user(buf,rawArray, count);return count;
}
static int major = (-1); /* 初始化为无效值 */
static struct class *amg8833_drv_class;
static struct file_operations amg8833_drv_fops = {.owner   = THIS_MODULE,.open    = amg8833_drv_open,.release = amg8833_drv_release,.read    = amg8833_drv_read,
};/* 驱动入口函数 */
static int amg8833_drv_init(void)
{printk("KERNEL INIT amg8833 \r\n");major = register_chrdev(0, "amg8833_drv", &amg8833_drv_fops); // 注册, 告诉内核,返回值major为自动分配的主设备号amg8833_drv_class = class_create(THIS_MODULE, "amg8833drv");device_create(amg8833_drv_class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);amg8833_ctl_init();return 0;
}/* 驱动出口函数 */
static void amg8833_drv_exit(void)
{unregister_chrdev(major, "amg8833_drv"); /* 卸载驱动程序,告诉内核 */device_destroy(amg8833_drv_class, MKDEV(major, 0));class_destroy(amg8833_drv_class);amg8833_ctl_uninit();
}module_init(amg8833_drv_init);
module_exit(amg8833_drv_exit);MODULE_LICENSE("Dual BSD/GPL");

测试代码

/** @Description: * @Autor: YURI* @Date: 2022-01-30 18:34:31* @LastEditors: YURI* @LastEditTime: 2022-01-31 02:35:01*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "framebuffer.h"
#include "opencv_mat.h"
#define AMG88xx_PIXEL_TEMP_CONVERSION 0.25
using namespace cv;
#define MIN_TEMP   0
#define MAX_TEMP   30const unsigned short camColors[] = {0x480F,0x400F,0x400F,0x400F,0x4010,0x3810,0x3810,0x3810,0x3810,0x3010,0x3010,0x3010,0x2810,0x2810,0x2810,0x2810,0x2010,0x2010,0x2010,0x1810,0x1810,0x1811,0x1811,0x1011,0x1011,0x1011,0x0811,0x0811,0x0811,0x0011,0x0011,0x0011,0x0011,0x0011,0x0031,0x0031,0x0051,0x0072,0x0072,0x0092,0x00B2,0x00B2,0x00D2,0x00F2,0x00F2,0x0112,0x0132,0x0152,0x0152,0x0172,0x0192,0x0192,0x01B2,0x01D2,0x01F3,0x01F3,0x0213,0x0233,0x0253,0x0253,0x0273,0x0293,0x02B3,0x02D3,0x02D3,0x02F3,0x0313,0x0333,0x0333,0x0353,0x0373,0x0394,0x03B4,0x03D4,0x03D4,0x03F4,0x0414,0x0434,0x0454,0x0474,0x0474,0x0494,0x04B4,0x04D4,0x04F4,0x0514,0x0534,0x0534,0x0554,0x0554,0x0574,0x0574,0x0573,0x0573,0x0573,0x0572,0x0572,0x0572,0x0571,0x0591,0x0591,0x0590,0x0590,0x058F,0x058F,0x058F,0x058E,0x05AE,0x05AE,0x05AD,0x05AD,0x05AD,0x05AC,0x05AC,0x05AB,0x05CB,0x05CB,0x05CA,0x05CA,0x05CA,0x05C9,0x05C9,0x05C8,0x05E8,0x05E8,0x05E7,0x05E7,0x05E6,0x05E6,0x05E6,0x05E5,0x05E5,0x0604,0x0604,0x0604,0x0603,0x0603,0x0602,0x0602,0x0601,0x0621,0x0621,0x0620,0x0620,0x0620,0x0620,0x0E20,0x0E20,0x0E40,0x1640,0x1640,0x1E40,0x1E40,0x2640,0x2640,0x2E40,0x2E60,0x3660,0x3660,0x3E60,0x3E60,0x3E60,0x4660,0x4660,0x4E60,0x4E80,0x5680,0x5680,0x5E80,0x5E80,0x6680,0x6680,0x6E80,0x6EA0,0x76A0,0x76A0,0x7EA0,0x7EA0,0x86A0,0x86A0,0x8EA0,0x8EC0,0x96C0,0x96C0,0x9EC0,0x9EC0,0xA6C0,0xAEC0,0xAEC0,0xB6E0,0xB6E0,0xBEE0,0xBEE0,0xC6E0,0xC6E0,0xCEE0,0xCEE0,0xD6E0,0xD700,0xDF00,0xDEE0,0xDEC0,0xDEA0,0xDE80,0xDE80,0xE660,0xE640,0xE620,0xE600,0xE5E0,0xE5C0,0xE5A0,0xE580,0xE560,0xE540,0xE520,0xE500,0xE4E0,0xE4C0,0xE4A0,0xE480,0xE460,0xEC40,0xEC20,0xEC00,0xEBE0,0xEBC0,0xEBA0,0xEB80,0xEB60,0xEB40,0xEB20,0xEB00,0xEAE0,0xEAC0,0xEAA0,0xEA80,0xEA60,0xEA40,0xF220,0xF200,0xF1E0,0xF1C0,0xF1A0,0xF180,0xF160,0xF140,0xF100,0xF0E0,0xF0C0,0xF0A0,0xF080,0xF060,0xF040,0xF020,0xF800};short signed_To_unsigned(short val)
{short absVal = (val & 0x7FF);return (val & 0x800) ? 0 - absVal : absVal ;
}
opencv_mat*           mat_convert;
framebuffer *fb;
#define RGB565_RED      0xf800
#define RGB565_GREEN    0x07e0
#define RGB565_BLUE     0x001f
int main(int argc,void **argv)
{int fd,i;Mat image,show;char* filename=NULL;unsigned char buf[128];unsigned char rgbbuf[8*8*3];int color_index=0;short data[64];short recast;short converted;fb=new framebuffer("/dev/fb0");filename = (char*)argv[1];fd = open(filename, O_RDWR);//打开dev/firstdrv设备文件mat_convert=new opencv_mat(8,8);if (fd < 0)//小于0说明没有成功{printf("error, can't open %s\n", filename);return 0;}while (1){read(fd,buf,128);for(i=0; i<64; i++){unsigned char pos = i *2;recast = ((short)buf[pos + 1] << 8) | ((short)buf[pos]);        converted = signed_To_unsigned(recast) * AMG88xx_PIXEL_TEMP_CONVERSION;data[i] = converted;}    for(int j=0;j<8;j++){for(int k=0;k<8;k++){color_index= (data[8*j+k]-MIN_TEMP) *( 255/(MAX_TEMP-MIN_TEMP));if(color_index<0){rgbbuf[8*3*j+3*k]=0;rgbbuf[8*3*j+3*k+1]=0;rgbbuf[8*3*j+3*k+2]=0;}else if(color_index>255){rgbbuf[8*3*j+3*k]=0xFF;rgbbuf[8*3*j+3*k+1]=0xFF;rgbbuf[8*3*j+3*k+2]=0xFF;}else{rgbbuf[8*3*j+3*k+2]=(camColors[color_index]&RGB565_BLUE)<<3;rgbbuf[8*3*j+3*k+1]=(camColors[color_index]&RGB565_GREEN)>>3;rgbbuf[8*3*j+3*k]=(camColors[color_index]&RGB565_RED)>>8;}}     }image=mat_convert->opencv_convert(rgbbuf);resize(image,show,Size(0,0),200,130);fb->show_rgbbuffer(show.data,0,0,show.cols,show.rows);}close(fd);
}

这里我偷懒了没有自己写插值算法,而是直接使用的OpenCV的插值函数,所以如果要用,还需要移植OpenCV。

具体代码参考
git@github.com:Yueyang123/arm_media.git

最终效果

今天是除夕夜,大家过年好。

【LINUX驱动开发】AMG8833红外成像模块在HI3516上的应用相关推荐

  1. Linux驱动开发: 使用usbmon抓取usb 总线上通信的数据

    一.环境介绍 操作系统: ubuntu18.04 64位 二.usbmon使用方法 2.1 功能介绍 usbmon 即 usb monitor,是 linux 内置的 usb 抓包工具. 当前使用的是 ...

  2. Linux驱动开发庖丁解牛系列

    1.Linux驱动开发庖丁解牛之一--开发环境的建立 http://linux.chinaunix.net/bbs/thread-1042600-1-2.html 2.Linux驱动开发庖丁解牛之二- ...

  3. 嵌入式linux驱动开发之移远4G模块EC800驱动移植指南

    回顾下移远4G模块移植过程, 还是蛮简单的.一通百通,无论是其他4G模块都是一样的.这里记录下过程,分享给有需要的人.环境使用正点原子的imax6ul开发板,板子默认支持中兴和移远EC20的驱动,这里 ...

  4. Linux驱动开发(十)---树莓派输入子系统学习(红外接收)

    前文回顾 <Linux驱动开发(一)-环境搭建与hello world> <Linux驱动开发(二)-驱动与设备的分离设计> <Linux驱动开发(三)-设备树> ...

  5. 嵌入式linux驱动开发之点亮led(驱动编程思想之初体验)

    这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的 ...

  6. Linux驱动开发环境配置(内核源码树构造)

    来源:季义钦BLOG 作者:季义钦 初次接触Linux驱动程序开发,买了一本<Linux设备驱动程序>,第一件事当然就是构建开发环境了!!! 它上面有一个Hello World的列子: / ...

  7. linux驱动开发的经典书籍

    Linux驱动学习的最大困惑在于书籍的缺乏,市面上最常见的书为<linux_device_driver 3rd Edition>,这是一本很经典的书,无奈Linux的东东还是过于庞大,这本 ...

  8. Linux驱动开发必看详解神秘内核(完全转载)

    Linux驱动开发必看详解神秘内核 完全转载-链接:http://blog.chinaunix.net/uid-21356596-id-1827434.html IT168 技术文档]在开始步入Lin ...

  9. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之Pinctrl子系统和GPIO子系统的使用

    文章目录 前言 1.Pinctrl子系统 1.1.为什么有Pinctrl子系统 1.2.重要的概念 1.3.代码中怎么引用pinctrl 2.GPIO子系统 2.1.为什么有GPIO子系统 2.2.在 ...

最新文章

  1. CSS截取字符串,兼容浏览器
  2. Linux内核分析作业第二周
  3. python宏替换_#和##在宏替换中的作用
  4. 通过Java执行python文件
  5. Linux shell tips and tricks
  6. php GD库文字居中,PHP GD ttftext居中对齐
  7. dao层和service层和control_最受欢迎Java数据库访问框架(DAO层)
  8. express捕获全局异常的三种方法
  9. 内存溢出 permgen_通过增加堆内存/ Permgen空间来修复Eclipse OutOfMemory错误
  10. python3 pdf转成txt
  11. net-java-php-python-教学资源管理系统hsg修改版计算机毕业设计程序
  12. 【JAVA问题解决方案】01.EasyExcel导出数据超过Excel单表上限解决方案
  13. linux下文件恢复方法,Linux下误删文件恢复办法
  14. loading图片实现等待的动画
  15. wps斜杠日期格式_wps表格,怎样将输入的日期间隔斜线改为横线?
  16. 福利:推荐你在线码代码
  17. Synchronized关键字深度解析
  18. 如何实行互联网企业PMO项目管理体系建设和推广落地
  19. 2019 校内赛 RPG的地牢猎手(bfs+优先队列)
  20. sony xl39h android 4.3,索尼XL39h 4.3解锁教程和方法

热门文章

  1. C#读取DWG文件方法
  2. 给你一个全新的软件,你就是负责人,你怎么去开展工作
  3. 面试官最想听哪些话?
  4. Empire简介及安装
  5. Mysql安装步骤方法
  6. 倾斜摄影自动化建模成果的数据组织和单体化
  7. Redis快速入门,一篇带你系统入门,学会即加薪
  8. MNIST手写数字识别程序
  9. 在vscode编辑器中,vetur和volar冲突
  10. 给老孙做了个排班表!