可以看到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脚接一个电容。
设置AMG8833的工作模式
进行软复位。
有两种复位方式:
Flag Reset会清除Status寄存器(0x04)、中断标志、中断表(0x10~0x17)
Initial Reset会复位标志,并使AMG8833的参数恢复初始。
3、Frame Rate寄存器:设定帧率
bit0: Setting Frame Mode
1: 1FPS
0: 10FPS
配置中断功能
bit1: INTMOD
1: Absolute Value Interrupt Mode
0: Difference Interrupt Mode
bit0: INTEN
1: INT 引脚输出使能
0: INT 引脚禁止输出(保持高阻状态)
溢出标志和中断标志
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)
清除溢出标志和中断标志
bit3: OVT_CLR
1: 清除热敏电阻温度输出溢出标志
bit2: OVS_CLR
1: 清除红外温度输出溢出标志
bit1: INTCLR
1: 清除中断标志
设置移动平均输出模式
bit5: MAMOD
1::Twice moving average Output Mode
0:No moving average
设置发生中断的上限值、下限值、迟滞值。
INT_LVL_H [11:0]:中断上限值,当温度高于此值,输出中断并且设置Interrupt Table寄存器。
INT_LVL_L [11:0]:中断下限值,当温度低于此值,输出中断并且设置Interrupt Table寄存器。
INT_HYS [11:0]:设置上限值、下限值的迟滞值,类似于施密特触发器。
上述3个数据都是12位数据。最高位为符号位,值为0表示正,值为1表示负。步进值为0.25℃。
热敏电阻测量的温度值
有12位数据。最高位为符号位,值为0表示正,值为1表示负。步进值为0.0625℃。举例如下:
显示哪一个像素点发生了中断
当64个像素点中的某一个点的温度值高于或低于了Interrupt Level寄存器中设置的上下限,就会在Interrupt Table寄存器的对应位设置值。值为1代表发生了中断,0表示没有。
红外点阵测量的温度值
有12位数据。最高位为符号位,值为0表示正,值为1表示负。步进值为0.25℃。举例如下:
0x80和0x81保存的是第一个像素的温度值,1-64像素对应地址为0x80~0xFF。
注:
(1)1 - 64像素(0x80~0xFF)的温度值是一起更新的,不需要任何指令。
(2)0x80~0xFF的数据是一次读出的,所以不用担心新的温度值和旧的温度值会混在一起。
为了避免麻烦,并且这里的传输数据量并不是非常大,所以直接用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 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 }; #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_6 amg8833.sda =amg8833_pin_init(GPIO2_BASE_ADDR,0X114F0068,0X520,amg8833_OUT,3,0);//2_3 amg8833.inter =amg8833_pin_init(GPIO8_BASE_ADDR,0X112F0040,0X524,amg8833_OUT,7,0);//8_7 amg8833.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); else amg8833_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 mode amg_iic_write_1_byte(AMG88xx_ADR,AMG88xx_PCTL,AMG88xx_NORMAL_MODE); //software reset amg_iic_write_1_byte(AMG88xx_ADR,AMG88xx_RST,AMG88xx_INITIAL_RESET); //set to 10 FPS amg_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 30 const 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。
具体代码参考
Github
今天是除夕夜,大家过年好。