基于STM32F103的MLX90614驱动

更新时间:2023-09-06 02:44:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

可以直接在STM32F103上面运行的驱动程序

$MLX90614.C

/** ****************************************************************************** * *基于STM32F103的MLX90614红外温度传感器驱动程序 * ****************************************************************************** *//* Includes ------------------------------------------------------------------*/#include"stdlib.h"#include"stm32f10x.h"//===============================================================================//#include"MLX90614.H"//-- IO Operate -#define SetBit_SDA GPIO_SetBits(GPIOB,GPIO_Pin_10)#define ClrBit_SDA GPIO_ResetBits(GPIOB,GPIO_Pin_10)#define SetBit_SCK GPIO_SetBits(GPIOB,GPIO_Pin_11)#define ClrBit_SCK GPIO_ResetBits(GPIOB,GPIO_Pin_11)#define STA_SDA GPIOB->IDR& GPIO_Pin_10#define STA_SCL GPIOB->IDR& GPIO_Pin_11//-- MLX90614 Command Mode -#define RAM#define EEPROM#define MODE#define EXITMODE#define READFLAG#define SLEEP#define RD#define WR//-- MLX90614 RAM Address -#define AMBITEMPADDR#define IR1ADDR#define IR2ADDR#define ENVITEMPADDR#define OBJ1TEMPADDR -70.01~ 382.19度#define OBJ2TEMPADDR -70.01~ 382.19度

0x00 0x20 0x60 0x61 0xf0 0xff 0x01 0x00

//对RAM进行操作//对EEPROM进行操作//进入命令模式//退出命令模式//读标志//进入睡眠模式//读操作//写操作

0x03 0x04 0x05 0x06 0x07 0x08

//周围温度//////环境温度 -40~ 125度//目标1温度,检测到的红外温度//目标2温度,检测到的红外温度

//-- MLX90614 EEPROM Address -#define TOBJMAXADDR 0x00#define TOBJMINADDR 0x01#define PWMCTRLADDR 0x02#define TARANGEADDR 0x03#define KEADDR 0x04#define CONFIGADDR 0x05#define SMBUSADDR 0x0e#define RES1ADDR 0x0f#define RES2ADDR 0x19#define ID1ADDR 0x1c#define ID2ADDR 0x1d#define ID3ADDR 0x1e

//测量温度上限设定//测量温度下限设定//PWM设定//环境温度设定//频率修正系数//配置寄存器//器件地址设定//保留//保留//ID地址1//ID地址2//ID地址3

可以直接在STM32F103上面运行的驱动程序

$MLX90614.C

#define

ID4ADDR

0x1f

//ID地址4

//-- Special Define -#define ACK_SUCCESS#define ACK_FAIL

0x01 0x00

//成功接收到应答信号//没有收到应答信号

#define

N

5

//以上宏定义可以放在头文件里面//============================================================================/** *@功能 I2C通信状态改变后的延时 *@说明无 *@参数无 *@返回值无 */ void I2C_Delay(void){ Delay_us(2);}/** *@功能产生通讯开始信号 *@说明 MLX90614在SCK=1时,检测到SDA由1到0表示通信开始 *@参数无 *@返回值无 */ void I2C_Start(void){ SetBit_SDA; SetBit_SCK; I2C_Delay(); ClrBit_SDA; I2C_Delay(); ClrBit_SCK; I2C_Delay();}/** *@功能产生通讯停止信号 *@说明 MLX90614在SCK=1时,检测到SDA由0到1表示通信结束 *@参数无 *@返回值无 */ void I2C_Stop(void){ ClrBit_SDA; ClrBit_SCK; I2C_Delay(); SetBit_SCK; I2C_Delay(); SetBit_SDA; I2C_Delay();}

可以直接在STM32F103上面运行的驱动程序

$MLX90614.C

/** *@功能将MLX90614的工作模式从PWM模式切换

到SMBus模式 *@说明从PWM模式切换到SMBus的方法是将SCL保持至少1.44ms以上的低电平 *如果PWM没有使能就不需要发送请求命令 *@参数无 *@返回值无 */ void PwmToSMBus(void){ ClrBit_SCK; Delay_us(1500);//大于1.44ms SetBit_SCK;}/** *@功能退出睡眠模式 *@说明保持SCK高电平后,SDA持续至少33ms低电平, *在退出睡眠模式后需要间隔250ms(典型值)才输出数据。 *@参数无 *@返回值无 */ void Eixt_Sleep(void){ SetBit_SCK; SetBit_SDA; I2C_Delay(); ClrBit_SDA; Delay_ms(35);//大于33ms退出睡眠模式 SetBit_SDA; Delay_ms(260);//大于250ms开始输出数据}/** *@功能从RAM/EEPROM中读取一个字节数据 *@说明从MLX90614中的指定地址读取一个字节数据,高位在前,低位在后 *@参数 ack_nack:主机应答信号 *@返回值 dat:读取的数据 */ uint8_t I2C_ReadByte(uint8_t ack_nack){ uint8_t i=0; uint8_t dat=0; ClrBit_SCK; Delay_us(5); for(i=0;i<8;i++){ dat= dat<<1; ClrBit_SCK; Delay_us(5*N); SetBit_SCK; Delay_us(5*N); if(STA_SDA){ dat= dat| 0x01;

可以直接在STM32F103上面运行的驱动程序

$MLX90614.C

}} ClrBit_SCK; Delay_us(3*N); if(!ack_nack) ClrBit_SDA; else SetBit_SDA; Delay_us(3*N); SetBit_SCK; Delay_us(4*N); ClrBit_SCK; Delay_us(4*N); return dat;}/** *@功能向EEPROM写一个字节数据 *@说明在写完一个字节后检测MLX6014是否发送了应答信号 *@参数 dat:需要发送的字节 *@返回值 s_ack:应答信号状态 */ uint8_t I2C_WriteByte(uint8_t dat){ uint8_t i=0; uint8_t s_ack=0; ClrBit_SCK; ClrBit_SDA; I2C_Delay(); for(i=0;i<8;i++){ ClrBit_SCK; Delay_us(3*N); if(dat&0x80){ SetBit_SDA;} else{ ClrBit_SDA;} dat= dat<<1; Delay_us(4*N); SetBit_SCK; Delay_us(4*N);}//第8个时钟下降沿

//在第9个时钟上升沿,主机发送应答信号//在第9个时钟上升沿,主机发送应答信号

//改变SDA状态

//SCK上升沿写入数据

ClrBit_SCK;//第8个下降沿开始,MLX90614将SDA置为低电平供主机检测是否正确接收 SetBit_SDA; Delay_us(2*N); SetBit_SCK;//第9个上升沿后,主机检测SDA状态 if(STA_SDA)//高电平表示正确接收数据

可以直接在STM32F103上面运行的驱动程序

$MLX90614.C

{ s_ack= ACK_FAIL;} else{ s_ack= ACK_SUCCESS;} Delay_us(2*N); ClrBit_SCK; Delay_us(4*N); return s_ack;}

/** *@功能读MLX90614的RAM中内容 *@说明主要读取三个,环境温度,物体温度1,物体温度2 *器件从地址可以通过向EEPROM的SMBus地址0x0E中写入来进行设定。 *@参数 saddr:从机地址,7位地址,任何MLX90614都会对0x00地址作出反应 * cmd:存放温度的寄存器地址 *@返回值 Data:读取出来的数值 */ uint16_t I2C_ReadRAM(uint8_t saddr,uint8_t cmd){ uint16_t Data; uint8_t DataL;//接收数据低字节 uint8_t DataH;//接收数据高字节 uint8_t PEC; uint8_t retry= 10;//失败重复次数 uint8_t s_ack= 0; uint8_t Pecreg;//计算的PEC值 uint8_t buf[6];//存储已接收数据的缓存 ClrBit_SCK; while(retry--){ I2C_Start();//发送起

始位 s_ack= I2C_WriteByte((saddr<<1)|WR);//发送从机地址和Wr位 if(s_ack== ACK_SUCCESS){ s_ack= 0; s_ack= I2C_WriteByte(RAM|cmd);//发送命令,8位,RAM表示对RAM操作,cmd表示操作RAM的地址 if(s_ack== ACK_SUCCESS){ s_ack= 0; I2C_Start();//重新发送起始位 s_ack= I2C_WriteByte((saddr<<1)+1);//发送从机地址和Rd位 if(s_ack== ACK_SUCCESS){ s_ack= 0; DataL= I2C_ReadByte(1);//读数据低字节 DataH= I2C_ReadByte(1);//读数据高字节 PEC= I2C_ReadByte(1);//读数据PEC字节 DataL=RX_byte(0);//

//

可以直接在STM32F103上面运行的驱动程序

$MLX90614.C

////

DataH=RX_byte(0); PEC=RX_byte(1); I2C_Stop(); buf[5]=(saddr<<1); buf[4]=EEPROM|cmd; buf[3]=(saddr<<1)|RD; buf[2]=DataL; buf[1]=DataH; buf[0]=0; Pecreg=PEC_Cal(buf,6); if(Pecreg== PEC){ break;}} else goto stop_rr;} else goto stop_rr;} else goto stop_rr;

////发送停止位

//调用计算 PEC的函数

//退出循环

stop_rr: I2C_Stop();} PEC= PEC+1; Data= (DataH<<8)+ DataL; return Data;}/** *@功能 *@说明 *@参数//发送停止位,芯片接收失败

清除EEPROM指定单元的数据在向EEPROM中写入数据之前必须先清除内存单元中的数据,也就是全部写入0 saddr:从机地址 cmd:发送命令 *@返回值无 */ void I2C_ClearEEPROM(uint8_t saddr,uint8_t cmd){ uint8_t retry= 10;//失败重复次数 uint8_t s_ack= 0; ClrBit_SCK; while(retry--){ I2C_Start();//发送起始位 s_ack= I2C_WriteByte((saddr<<1)|WR);//发送从机地址和Wr位 if(s_ack== ACK_SUCCESS){ s_ack= 0; s_ack= I2C_WriteByte(EEPROM|cmd);//发送命令,8位 EPROM表示对RAM操作,cmd表示操作EEPROM的地址

可以直接在STM32F103上面运行的驱动程序

$MLX90614.C

if(s_ack== ACK_SUCCESS){ s_ack= 0; s_ack= I2C_WriteByte(0x00); if(s_ack== ACK_SUCCESS){ s_ack= 0; s_ack= I2C_WriteByte(0x00); if(s_ack== ACK_SUCCESS){ s_ack= 0; s_ack= I2C_WriteByte(0x6f); if(s_ack== ACK_SUCCESS){ I2C_Stop(); break;} else goto stop_ce;} else goto stop_ce;} else goto stop_ce;} else goto stop_ce;} else goto stop_ce; stop_ce: I2C_Stop();} Delay_ms(5);}

//发送低字节

//发送高字节

//发送PEC字节

//发送停止位//退出循环

//发送停止位,芯片接收失败//擦除完成至少等待5ms

/** *@功能 *@说明 *@参数

读EEPROM指定单元的数据从指定从机读取指定EEPROM地址的数据 saddr:从机地址 cmd:读取EEPROM地址 *@返回值 Data:读取数据 */ uint16_t I2C_ReadEEPROM(uint8_t saddr,uint8_t cmd){ uint8_t retry= 10; uint8_t s_ack; uint16_t Data; uint8_t DataL;//接收数据低字节 uint8_t DataH;//接收数据高字节 uint8_t PEC;//接收的PEC值 uint8_t Pecreg;//计算的PEC值 uint8_t buf[6];//存储已接收数据的缓存 while(retry--){

可以直接在STM32F103上面运行的驱动程序

$MLX90614.C

I2C_Start(); s_ack= I2C_WriteByte((saddr<<1)|WR); if(s_ack== ACK_SUCCESS){ s_ack= 0; s_ack= I2C_WriteByte(EEPROM|cmd); if(s_ack== ACK_SUCCESS){ s_ack= 0; I2C_Start(); s_ack= I2C_WriteByte((saddr<<1)|RD); if(s_ack== ACK_SUCCESS){ s_ack= 0; DataL= I2C_ReadByt

e(1); DataH= I2C_ReadByte(1); PEC= I2C_ReadByte(1); I2C_Stop(); buf[5]=(saddr<<1); buf[4]=EEPROM|cmd; buf[3]=(saddr<<1)|RD; buf[2]=DataL; buf[1]=DataH; buf[0]=0; Pecreg=PEC_Cal(buf,6); if(Pecreg== PEC){ break;}} else goto stop_re;} else goto stop_re;} else goto stop_re; stop_re: I2C_Stop();} Data= (DataH<<8)+ DataL; return Data;

//发送起始位//发送从机地址和Wr位

//发送命令

//重新发送起始位//发送从机地址和Rd位

//读数据低字节//读数据高字节//读数据PEC字节//发送停止位

//调用计算 PEC的函数

}/** *@功能写EEPROM指定单元的数据 *@说明在向EEPROM中写入数据之前必须先清除内存单元中的数据,也就是全部写入0 *@参数 saddr:要清除数据的内存单元 *@返回值无 */ void I2C_WriteEEPROM(uint8_t saddr,uint8_t cmd,uint8_t DataL,uint8_t DataH){ uint8_t retry= 10;//失败重复次数 uint8_t s_ack= 0; uint8_t Pecreg;//存储计算所得PEC结果

可以直接在STM32F103上面运行的驱动程序

$MLX90614.C

uint8_t

buf[6];

//存储将要发送字节的缓冲器

buf[5]=0; buf[4]=saddr<<1; buf[3]=cmd; buf[2]=DataL; buf[1]=DataH; buf[0]=0; Pecreg=PEC_Cal(buf,6); ClrBit_SCK; while(retry--){ I2C_Start(); s_ack= I2C_WriteByte((saddr<<1)|WR); if(s_ack== ACK_SUCCESS){ s_ack= 0; s_ack= I2C_WriteByte(EEPROM|cmd); if(s_ack== ACK_SUCCESS){ s_ack= 0; s_ack= I2C_WriteByte(DataL); if(s_ack== ACK_SUCCESS){ s_ack= 0; s_ack= I2C_WriteByte(DataH); if(s_ack== ACK_SUCCESS){ s_ack= 0; s_ack= I2C_WriteByte(Pecreg); if(s_ack== ACK_SUCCESS){ I2C_Stop(); break;} else goto stop_we;} else goto stop_we;} else goto stop_we;} else goto stop_we;} else goto stop_we; stop_we: I2C_Stop();} Delay_ms(5);}/** *@功能 *@说明

//发送起始位//发送从机地址和Wr位

//发送命令

//发送低字节

//发送高字节

//发送PEC码

//发送停止位//退出循环

//写入之后等待5ms

计算PEC包裹校验码,根据接收的字节计算PEC码计算传入数据的PEC码

可以直接在STM32F103上面运行的驱动程序

$MLX90614.C

pec[]:传入的数据 n:传入数据个数 *@返回值 pec[0]:计算得到的PEC值 */ uint8_t PEC_Cal(uint8_t pec[],uint16_t n){ unsigned char crc[6]; unsigned char Bitposition=47; unsigned char shift; unsigned char i; unsigned char j; unsigned char temp; do{ crc[5]=0; crc[4]=0; crc[3]=0; crc[2]=0; crc[1]=0x01; crc[0]=0x07; Bitposition=47; shift=0;//在传送的字节中找出第一个“1”

*@参数

//载入 CRC数值 0x000000000107

//设置Bitposition的最大值为47

i=5;//设置最高标志位 (包裹字节标志) j=0;//字节位标志,从最低位开始 while((pec[i]&(0x80>>j))==0&& (i>0)){ Bitposition--; if(j<7){ j++;} else{ j=0x00; i--;}}//while语句结束,并找出Bitposition中为“1”的最高位位置 shift=Bitposition-8;//得到CRC数值将要左移/右移的数值“shift”//对CRC数据左移“shift”位 while(shift){ for(i=5;i<0xFF;i--){ if((crc[i-1]&0x80)&& (i>0))//核对字节的最高位的下一位是否为"1"{//是 -

当前字节+ 1 temp=1;//否 -当前字节+ 0}//实现字节之间移动“1” else{ temp=0;}

可以直接在STM32F103上面运行的驱动程序

$MLX90614.C

crc[i]<<=1; crc[i]+=temp;} shift--;}//pec和crc之间进行异或计算 for(i=0;i<=5;i++){ pec[i]^=crc[i];}}while(Bitposition>8); return pec[0];//返回计算所得的crc数值}/** *@功能设定MLX90614器件地址 *@说明器件从地址可以通过向EEPROM的SMBus地址0x0E中写入来进行设定。为了给从器件设定地址,必须先以0x00+Wr当作从地址开始,当主机发送此命令,MLX90614总是会反馈并忽略掉内部芯片编码信息。向EEPROM写入数据前需要清除原来的数据,就是向修改单元写入0x0000擦除之后需要等待5ms才可以重新写入数据修改地址时写入的地址高字节MLX90614会忽略修改之后需要重新将MLX90614的电源断开重启。 *@参数 soaddr:从机旧地址 snaddr:从机新地址 *@返回值无 */ void I2C_SetSlaveAddr(uint8_t soaddr,uint8_t snaddr){// uint8_t cmd= EEPROM|SMBUSADDR;// uint8_t DataL= snaddr;// uint8_t DataH= 0x00;// EEPROM_WRITE(snaddr,cmd,0x00,0x00);// EEPROM_WRITE(snaddr,cmd,DataL,DataH);}

本文来源:https://www.bwwdw.com/article/nbui.html

Top