MLX90614+STM32f103c8t6标准库,OLED显示。
连线:SCL ——PA8; SDA——PA9
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "mlx90614.h"
#include "stdio.h"
int main(void)
{
float Temperature = 0; //温度数据变量(浮点型)
char TempValue[80] = {0}; //温度值(字符串)
OLED_Init();
SMBus_Init();
while (1)
{
Temperature = SMBus_ReadTemp();
Delay_ms(200);
sprintf(TempValue,"%.1f", Temperature); //浮点型转换成字符串
OLED_ShowString(1,1,TempValue);//在在OLED上显示实际测量的温度
}
}
#ifndef __IIC_H
#define __IIC_H
#include "stm32f10x.h" // Device header
void MyI2C_Init(void);
void MyI2C_Start(void);
void MyI2C_Stop(void);
void MyI2C_SendByte(uint8_t Byte);
uint8_t MyI2C_ReceiveByte(void);
void MyI2C_SendAck(uint8_t AckBit);
uint8_t MyI2C_ReceiveAck(void);
#endif
IIC.C
#include "stm32f10x.h" // Device header
#include "Delay.h"
void MyI2C_W_SCL(uint8_t BitValue)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_8, (BitAction)BitValue);
Delay_us(10);
}
void MyI2C_W_SDA(uint8_t BitValue)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_9, (BitAction)BitValue);
Delay_us(10);
}
uint8_t MyI2C_R_SDA(void)
{
uint8_t BitValue;
BitValue = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_9);
Delay_us(10);
return BitValue;
}
void MyI2C_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA, GPIO_Pin_8 | GPIO_Pin_9);
}
void MyI2C_Start(void)
{
MyI2C_W_SDA(1);
MyI2C_W_SCL(1);
MyI2C_W_SDA(0);
MyI2C_W_SCL(0);
}
void MyI2C_Stop(void)
{
MyI2C_W_SDA(0);
MyI2C_W_SCL(1);
MyI2C_W_SDA(1);
}
void MyI2C_SendByte(uint8_t Byte)
{
uint8_t i;
for (i = 0; i < 8; i ++)
{
MyI2C_W_SDA(Byte & (0x80 >> i));
MyI2C_W_SCL(1);
MyI2C_W_SCL(0);
}
}
uint8_t MyI2C_ReceiveByte(void)
{
uint8_t i, Byte = 0x00;
MyI2C_W_SDA(1);
for (i = 0; i < 8; i ++)
{
MyI2C_W_SCL(1);
if (MyI2C_R_SDA() == 1){Byte |= (0x80 >> i);}
MyI2C_W_SCL(0);
}
return Byte;
}
void MyI2C_SendAck(uint8_t AckBit)
{
MyI2C_W_SDA(AckBit);
MyI2C_W_SCL(1);
MyI2C_W_SCL(0);
}
uint8_t MyI2C_ReceiveAck(void)
{
uint8_t AckBit;
MyI2C_W_SDA(1);
MyI2C_W_SCL(1);
AckBit = MyI2C_R_SDA();
MyI2C_W_SCL(0);
return AckBit;
}
#include "mlx90614.h"
/*******************************************************************************
* 函数名: SMBus_Init
* 功能: SMBus初始化
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SMBus_Init()
{
MyI2C_Init();
}
/*******************************************************************************
* 函数名: SMBus_ReadMemory
* 功能: READ DATA FROM RAM/EEPROM 从RAM和EEPROM中读取数据
* Input : slaveAddress, command
* Return : Data
* SMBus_ReadMemory(0x00, 0x07) 0x00 表示IIC设备的从地址 从0x07这个寄存器开始读取
*******************************************************************************/
u16 SMBus_ReadMemory(u8 slaveAddress, u8 command)
{
u16 data; // Data storage (DataH:DataL)
u8 Pec; // PEC byte storage
u8 DataL=0; // Low data byte storage
u8 DataH=0; // High data byte storage
u8 arr[6]; // Buffer for the sent bytes
u8 PecReg; // Calculated PEC byte storage
u8 ErrorCounter; // Defines the number of the attempts for communication with MLX90614
ErrorCounter=0x00; // Initialising of ErrorCounter
slaveAddress <<= 1; //2-7位表示从机地址 从机地址左移一位,把读写位空出来
do
{
repeat:
MyI2C_Stop(); //If slave send NACK stop comunication
--ErrorCounter; //Pre-decrement ErrorCounter
if(!ErrorCounter) //ErrorCounter=0?
{
break; //Yes,go out from do-while{}
}
MyI2C_Start(); //Start condition
MyI2C_SendByte(slaveAddress);
if(MyI2C_ReceiveAck())//Send SlaveAddress 最低位Wr=0表示接下来写命令
{
goto repeat; //Repeat comunication again
}
MyI2C_SendByte(command);
if(MyI2C_ReceiveAck()) //Send command
{
goto repeat; //Repeat comunication again
}
MyI2C_Start(); //Repeated Start condition
MyI2C_SendByte(slaveAddress+1);
if(MyI2C_ReceiveAck()) //Send SlaveAddress 最低位Rd=1表示接下来读数据
{
goto repeat; //Repeat comunication again
}
DataL = MyI2C_ReceiveByte(); //Read low data,master must send ACK
MyI2C_SendAck(ACK);
DataH = MyI2C_ReceiveByte(); //Read high data,master must send ACK
MyI2C_SendAck(ACK);
Pec = MyI2C_ReceiveByte(); //Read PEC byte, master must send NACK
MyI2C_SendAck(NACK);
MyI2C_Stop(); //Stop condition
arr[5] = slaveAddress; //
arr[4] = command; //
arr[3] = slaveAddress+1; //Load array arr
arr[2] = DataL; //
arr[1] = DataH; //
arr[0] = 0; //
PecReg=PEC_Calculation(arr);//Calculate CRC 数据校验
}
while(PecReg != Pec);//If received and calculated CRC are equal go out from do-while{}
data = (DataH<<8) | DataL; //data=DataH:DataL
return data;
}
/*******************************************************************************
* 函数名: PEC_calculation
* 功能 : 数据校验
* Input : pec[]
* Output : None
* Return : pec[0]-this byte contains calculated crc value
*******************************************************************************/
u8 PEC_Calculation(u8 pec[])
{
u8 crc[6];//存放多项式
u8 BitPosition=47;//存放所有数据最高位,6*8=48 最高位就是47位
u8 shift;
u8 i;
u8 j;
u8 temp;
do
{
/*Load pattern value 0x00 00 00 00 01 07*/
crc[5]=0;
crc[4]=0;
crc[3]=0;
crc[2]=0;
crc[1]=0x01;
crc[0]=0x07;
/*Set maximum bit position at 47 ( six bytes byte5...byte0,MSbit=47)*/
BitPosition=47;
/*Set shift position at 0*/
shift=0;
/*Find first "1" in the transmited message beginning from the MSByte byte5*/
i=5;
j=0;
while((pec[i]&(0x80>>j))==0 && i>0)
{
BitPosition--;
if(j<7)
{
j++;
}
else
{
j=0x00;
i--;
}
}/*End of while */
/*Get shift value for pattern value*/
shift=BitPosition-8;
/*Shift pattern value */
while(shift)
{
for(i=5; i<0xFF; i--)
{
if((crc[i-1]&0x80) && (i>0))
{
temp=1;
}
else
{
temp=0;
}
crc[i]<<=1;
crc[i]+=temp;
}/*End of for*/
shift--;
}/*End of while*/
/*Exclusive OR between pec and crc*/
for(i=0; i<=5; i++)
{
pec[i] ^=crc[i];
}/*End of for*/
}
while(BitPosition>8); /*End of do-while*/
return pec[0];
}
/*******************************************************************************
* 函数名: SMBus_ReadTemp
* 功能: 计算并返回温度值
* Return : SMBus_ReadMemory(0x00, 0x07)*0.02-273.15
*******************************************************************************/
float SMBus_ReadTemp(void)
{
float temp;
temp = SMBus_ReadMemory(SA, RAM_ACCESS|RAM_TOBJ1)*0.02-273.15;
return temp;
}
#ifndef __MLX90614_H
#define __MLX90614_H
#include "iic.h"
#include "stm32f10x.h" // Device header
#define ACK 0
#define NACK 1 //不应答或否定的应答
#define SA 0x00 //从机地址,单个MLX90614时地址为0x00,多个时地址默认为0x5a
#define RAM_ACCESS 0x00 //RAM access command
#define EEPROM_ACCESS 0x20 //EEPROM access command
#define RAM_TOBJ1 0x07 //To1 address in the eeprom
void SMBus_Init();
u8 PEC_Calculation(u8 pec[]);
u16 SMBus_ReadMemory(u8 slaveAddress, u8 command);
float SMBus_ReadTemp(void);
#endif