1.JX90614红外测温传感器
之前想要做一期红外测温的实验,但是发现可参考的资料多是主流的MLX90614,JX90614的资料非常稀少,决定自己写驱动根据数据手册复现。该传感器使用IIC协议进行通信,通过读取数据寄存器当中的值即可获得当前的温度值(具体参考数据手册)
首先是他的电路连接,非常简单,我们采用软件IIC进行通信(任意选择两个GPIO配置为开漏输出模式即可),这里需要注意的是,该模块没有包含上拉电阻,需要在SDA、SCK与VCC之前都接上4.7K的电阻。
2.手把手复现
首先完成软件IIC接口的编写,这里使用PB11作为SDA,PB10作为SCK。
MI2C.h
#ifndef _MI2C_H
#define _MI2C_H
#include "stm32f10x.h" // Device header
#define GPIO_SDA_PORT GPIOB
#define GPIO_SDA_PIN GPIO_Pin_11
#define GPIO_SCK_PORT GPIOB
#define GPIO_SCK_PIN GPIO_Pin_10
void MI2C_Init(void);
void MI2C_W_SDA(uint8_t BitV);
void MI2C_W_SCK(uint8_t BitV);
uint8_t MI2C_R_SDA(void);
void App_I2C_Start(void);
void App_I2C_Stop(void);
void App_I2C_WriteByte(uint8_t Data);
uint8_t App_I2C_ReadByte(void);
void App_I2C_SendAck(uint8_t BitAck);
uint8_t App_I2C_ReceiveAck(void);
#endif
MI2C.c
#include "stm32f10x.h" // Device header
#include "MI2C.h"
#include "Delay.h"
//IO初始化
void MI2C_Init(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //开启GPIOB的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure); //将PB10和PB11引脚初始化为开漏输出
GPIO_SetBits(GPIOB, GPIO_Pin_10 | GPIO_Pin_11);
}
//写数据线
void MI2C_W_SDA(uint8_t BitV)
{
GPIO_WriteBit(GPIO_SDA_PORT,GPIO_SDA_PIN,(BitAction)BitV);
Delay_us(2);
}
//写时钟线
void MI2C_W_SCK(uint8_t BitV)
{
GPIO_WriteBit(GPIO_SCK_PORT,GPIO_SCK_PIN,(BitAction)BitV);
Delay_us(2);
}
//读数据线
uint8_t MI2C_R_SDA(void)
{
uint8_t Data;
Data = GPIO_ReadInputDataBit(GPIO_SDA_PORT,GPIO_SDA_PIN);
Delay_us(2);
return Data;
}
//起始位
void App_I2C_Start(void)
{
MI2C_W_SDA(1);
MI2C_W_SCK(1);
MI2C_W_SDA(0);
MI2C_W_SCK(0);
}
//停止位
void App_I2C_Stop(void)
{
MI2C_W_SDA(0);
MI2C_W_SCK(1);
MI2C_W_SDA(1);
}
//写1Byte数据
void App_I2C_WriteByte(uint8_t Data)
{
for(int i=0;i<8;i++)
{
MI2C_W_SDA((0x80>>i)&Data);
MI2C_W_SCK(1);
MI2C_W_SCK(0);
}
}
//read 1Byte Data
uint8_t App_I2C_ReadByte(void)
{
uint8_t Byte = 0x00;
MI2C_W_SDA(1);
for(int i=0;i<8;i++)
{
MI2C_W_SCK(1);
if(MI2C_R_SDA()==1)
{
Byte = Byte|(0x80>>i);
}
MI2C_W_SCK(0);
}
return Byte;
}
//发送应答
void App_I2C_SendAck(uint8_t BitAck)
{
MI2C_W_SDA(BitAck);
MI2C_W_SCK(1);
MI2C_W_SCK(0);
}
//接收应答
uint8_t App_I2C_ReceiveAck(void)
{
uint8_t Data=0;
MI2C_W_SDA(1);//主机释放总线
MI2C_W_SCK(1);
Data = MI2C_R_SDA();
MI2C_W_SCK(0);
return Data;
}
然后我们通过查数据手册知道JX90164的设备地址为0x7F,设备的初始化和运行过程如下图
另外,从寄存器的描述章节可以找到数据存储的方式
可以看到温度数据是一个24bit的数据,我们需要分别接收MSB,CSB、LSB的8bit数据,然后合成一个24bit数据,就如下面的JX90164_Get_T_Data函数所写的内容一样。
JX90164.h
#ifndef _JX90614_H
#define _JX90614_H
#include "stm32f10x.h" // Device header
#include "MI2C.h"
#include "Serial.h"
void JX90164_WriteReg(uint8_t Address,uint8_t data);
uint8_t JX90164_ReadReg(uint8_t Address);
void JX90164_Init(void);
void JX90164_Get_T_Data(int32_t* Temp);
#endif
JX90164_REG.h
#ifndef __JX90164_REG_H
#define __JX90164_REG_H
#define Soft_Reset 0x00
#define Data_ready 0x02
#define DATA1_MSB 0x10
#define DATA1_CSB 0x11
#define DATA1_LSB 0x12
#define CMD 0x30
#endif
JX90164.c
#include "stm32f10x.h" // Device header
#include "MI2C.h"
#include "Serial.h"
#include "JX90614.h"
#include "JX90614_reg.h"
#include "math.h"
#define JX90164_ADDRESS 0x7F
void JX90164_WriteReg(uint8_t Address,uint8_t data)
{
App_I2C_Start();
App_I2C_WriteByte(JX90164_ADDRESS<<1);
App_I2C_ReceiveAck();
App_I2C_WriteByte(Address);
App_I2C_ReceiveAck();
App_I2C_WriteByte(data);
App_I2C_ReceiveAck();
App_I2C_Stop();
}
uint8_t JX90164_ReadReg(uint8_t Address)
{
uint8_t data;
App_I2C_Start();
App_I2C_WriteByte(JX90164_ADDRESS<<1);
App_I2C_ReceiveAck();
App_I2C_WriteByte(Address);
App_I2C_ReceiveAck();
App_I2C_Start();
App_I2C_WriteByte(JX90164_ADDRESS<<1 | (0x01));
App_I2C_ReceiveAck();
data = App_I2C_ReadByte();
App_I2C_SendAck(1);
App_I2C_Stop();
return data;
}
void JX90164_Init(void)
{
MI2C_Init();
JX90164_WriteReg(CMD,0x00);
JX90164_WriteReg(CMD,0x08);
//JX90164_WriteReg(CMD,0x00);
}
void JX90164_Get_T_Data(int32_t* Temp)
{
uint8_t DataH,DataC,DataL;
uint8_t Flag = 0x00;
Flag = JX90164_ReadReg(Data_ready);
DataH = JX90164_ReadReg(DATA1_MSB);
DataC = JX90164_ReadReg(DATA1_CSB);
DataL = JX90164_ReadReg(DATA1_LSB);
*Temp = (DataH<<16)|(DataC<<8)|(DataL);
}
最后需要对取得的数据在除以2的14次方就可以得到室温数据。
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "mpu6050.h"
#include "MI2C.h"
#include "Serial.h"
#include "JX90614.h"
#include "math.h"
int32_t Temp;
int32_t realT;
uint8_t data_sda;
uint8_t data_sck;
int main(void)
{
/*模块初始化*/
OLED_Init(); //OLED初始化
Serial_Init();
//MI2C_Init();
JX90164_Init();
while (1)
{
data_sda = MI2C_R_SDA();
// data_sck = GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_10);
OLED_ShowString(2,1,"tempTEST");
JX90164_Get_T_Data(&Temp);
realT = Temp/(pow(2,14));
Serial_Printf("temp: %d\r\n", realT);
USART_Cmd(USART1,DISABLE);
OLED_ShowSignedNum(3, 1, realT, 5);
USART_Cmd(USART1,ENABLE);
}
}
实验结果如图
完整工程可以访问顶部链接
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_44465154/article/details/147044311
|