本文主要是介绍STM32读取MLX90614模块温度,并在OLED屏幕上显示,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
mlx90614驱动代码来源于网络,OLED驱动代码来源于江协科技,侵权删
本文使用硬件:STM32F103C8T6最小系统板、IIC协议0.96寸OLED屏幕显示、mlx90614红外测温模块。
实现功能:在OLED上显示出mlx90614采集到的温度,精确到小数点后两位。
mlx.c
#include "stm32f10x.h" // Device header
#include "Delay.h"#include "mlx.h"
#define ACK 0
#define NACK 1
#define SA 0x00
#define RAM_ACCESS 0x00
#define EEPROM_ACCESS 0x20
#define RAM_TOBJ1 0x07 #define SMBUS_PORT GPIOB
#define SMBUS_SCK GPIO_Pin_15
#define SMBUS_SDA GPIO_Pin_14#define RCC_APB2Periph_SMBUS_PORT RCC_APB2Periph_GPIOB#define SMBUS_SCK_H() SMBUS_PORT->BSRR = SMBUS_SCK
#define SMBUS_SCK_L() SMBUS_PORT->BRR = SMBUS_SCK
#define SMBUS_SDA_H() SMBUS_PORT->BSRR = SMBUS_SDA
#define SMBUS_SDA_L() SMBUS_PORT->BRR = SMBUS_SDA#define SMBUS_SDA_PIN() SMBUS_PORT->IDR & SMBUS_SDA void SMBus_StartBit(void)
{SMBUS_SDA_H(); // Set SDA lineSMBus_Delay(8); // Wait a few microsecondsSMBUS_SCK_H(); // Set SCL lineSMBus_Delay(8); // Generate bus free time between StopSMBUS_SDA_L(); // Clear SDA lineSMBus_Delay(8); // Hold time after (Repeated) Start// Condition. After this period, the first clock is generated.//(Thd:sta=4.0us min)SMBUS_SCK_L(); // Clear SCL lineSMBus_Delay(8); // Wait a few microseconds
}void SMBus_StopBit(void)
{SMBUS_SCK_L(); // Clear SCL lineSMBus_Delay(8); // Wait a few microsecondsSMBUS_SDA_L(); // Clear SDA lineSMBus_Delay(8); // Wait a few microsecondsSMBUS_SCK_H(); // Set SCL lineSMBus_Delay(8); // Stop condition setup time(Tsu:sto=4.0us min)SMBUS_SDA_H(); // Set SDA line
}u8 SMBus_SendByte(u8 Tx_buffer)
{u8 Bit_counter;u8 Ack_bit;u8 bit_out;for(Bit_counter=8; Bit_counter; Bit_counter--){if (Tx_buffer&0x80){bit_out=1; // If the current bit of Tx_buffer is 1 set bit_out}else{bit_out=0; // else clear bit_out}SMBus_SendBit(bit_out); // Send the current bit on SDATx_buffer<<=1; // Get next bit for checking}Ack_bit=SMBus_ReceiveBit(); // Get acknowledgment bitreturn Ack_bit;
}void SMBus_SendBit(u8 bit_out)
{if(bit_out==0){SMBUS_SDA_L();}else{SMBUS_SDA_H();}SMBus_Delay(6); // Tsu:dat = 250ns minimumSMBUS_SCK_H(); // Set SCL lineSMBus_Delay(8); // High Level of Clock PulseSMBUS_SCK_L(); // Clear SCL lineSMBus_Delay(8); // Low Level of Clock Pulsereturn;
}u8 SMBus_ReceiveBit(void)
{u8 Ack_bit;SMBUS_SDA_H(); SMBus_Delay(6); // High Level of Clock PulseSMBUS_SCK_H(); // Set SCL lineSMBus_Delay(8); // High Level of Clock Pulseif (SMBUS_SDA_PIN()){Ack_bit=1;}else{Ack_bit=0;}SMBUS_SCK_L(); // Clear SCL lineSMBus_Delay(8); // Low Level of Clock Pulsereturn Ack_bit;
}u8 SMBus_ReceiveByte(u8 ack_nack)
{u8 RX_buffer;u8 Bit_Counter;for(Bit_Counter=8; Bit_Counter; Bit_Counter--){if(SMBus_ReceiveBit()) // Get a bit from the SDA line{RX_buffer <<= 1; // If the bit is HIGH save 1 in RX_bufferRX_buffer |=0x01;}else{RX_buffer <<= 1; // If the bit is LOW save 0 in RX_bufferRX_buffer &=0xfe;}}SMBus_SendBit(ack_nack); // Sends acknowledgment bitreturn RX_buffer;
}void SMBus_Delay(u16 time)
{u16 i, j;for (i=0; i<5; i++){for (j=0; j<time; j++);}
}void SMBus_Init()
{GPIO_InitTypeDef GPIO_InitStructure;/* Enable SMBUS_PORT clocks */RCC_APB2PeriphClockCmd(RCC_APB2Periph_SMBUS_PORT, ENABLE);/*??SMBUS_SCK?SMBUS_SDA????????*/GPIO_InitStructure.GPIO_Pin = SMBUS_SCK | SMBUS_SDA;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(SMBUS_PORT, &GPIO_InitStructure);SMBUS_SCK_H();SMBUS_SDA_H();
}u16 SMBus_ReadMemory(u8 slaveAddress, u8 command)
{u16 data; // Data storage (DataH:DataL)u8 Pec; // PEC byte storageu8 DataL=0; // Low data byte storageu8 DataH=0; // High data byte storageu8 arr[6]; // Buffer for the sent bytesu8 PecReg; // Calculated PEC byte storageu8 ErrorCounter; // Defines the number of the attempts for communication with MLX90614ErrorCounter=0x00; // Initialising of ErrorCounterslaveAddress <<= 1; //2-7???????do{
repeat:SMBus_StopBit(); //If slave send NACK stop comunication--ErrorCounter; //Pre-decrement ErrorCounterif(!ErrorCounter) //ErrorCounter=0?{break; //Yes,go out from do-while{}}SMBus_StartBit(); //Start conditionif(SMBus_SendByte(slaveAddress))//Send SlaveAddress ???Wr=0????????{goto repeat; //Repeat comunication again}if(SMBus_SendByte(command)) //Send command{goto repeat; //Repeat comunication again}SMBus_StartBit(); //Repeated Start conditionif(SMBus_SendByte(slaveAddress+1)) //Send SlaveAddress ???Rd=1????????{goto repeat; //Repeat comunication again}DataL = SMBus_ReceiveByte(ACK); //Read low data,master must send ACKDataH = SMBus_ReceiveByte(ACK); //Read high data,master must send ACKPec = SMBus_ReceiveByte(NACK); //Read PEC byte, master must send NACKSMBus_StopBit(); //Stop conditionarr[5] = slaveAddress; //arr[4] = command; //arr[3] = slaveAddress+1; //Load array arrarr[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:DataLreturn data;
}u8 PEC_Calculation(u8 pec[])
{u8 crc[6];u8 BitPosition=47;u8 shift;u8 i;u8 j;u8 temp;do{/*Load pattern value 0x000000000107*/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];
}float SMBus_ReadTemp(void)
{ return (SMBus_ReadMemory(SA, RAM_ACCESS|RAM_TOBJ1)*0.02-273.15);
}
mlx.h
#ifndef __MLX_H
#define __MLX_H#include "stm32f10x.h"
void SMBus_StartBit(void);
void SMBus_StopBit(void);
void SMBus_SendBit(u8);
u8 SMBus_SendByte(u8);
u8 SMBus_ReceiveBit(void);
u8 SMBus_ReceiveByte(u8);
void SMBus_Delay(u16);
void SMBus_Init(void);
u16 SMBus_ReadMemory(u8, u8);
u8 PEC_Calculation(u8*);
float SMBus_ReadTemp(void); //获取温度值
#endif
main.c
#include "stm32f10x.h"
#include "Delay.h"
#include "OLED.h"
#include "mlx.h"int main(void)
{float temper;OLED_Init();SMBus_Init();OLED_ShowString(1, 1, "T:");OLED_ShowString(1, 5, ".");while(1){temper = SMBus_ReadTemp();OLED_ShowNum(1, 3, temper, 2); //显示温度整数OLED_ShowNum(1, 6, (unsigned long)(temper*100)%100, 2); //显示小数点后两位的温度Delay_ms(500);}}
实物效果图:
工程文件百度网盘链接:链接:https://pan.baidu.com/s/18gQPZKej-pdFgj-ZpxWswg
提取码:1234
这篇关于STM32读取MLX90614模块温度,并在OLED屏幕上显示的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!