MLX90614测温模块+OLED显示
功能描述
MLX90614测量温度,得出的温度值在0.96 OLED屏上动态显示。
程序代码(基于STM32F103ZET6)
mlx90614
mlx90614.h
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MLX90614_H
#define __MLX90614_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
/* Exported types ------------------------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
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
/*********************************END OF FILE*********************************/
mlx90614.c
/* Includes ------------------------------------------------------------------*/
#include "mlx90614.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define ACK 0
#define NACK 1
#define SA 0x00 //Slave address ??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
#define SMBUS_PORT GPIOB
#define SMBUS_SCK GPIO_Pin_6
#define SMBUS_SDA GPIO_Pin_7
#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 //??????
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/*******************************************************************************
* Function Name : SMBus_Init
* Description : SMBus???
* Input : None
* Output : None
* Return : None
*******************************************************************************/
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();
}
/*******************************************************************************
* Function Name : SMBus_StartBit
* Description : Generate START condition on SMBus
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SMBus_StartBit(void)
{
SMBUS_SDA_H(); // Set SDA line
SMBus_Delay(1); // Wait a few microseconds
SMBUS_SCK_H(); // Set SCL line
SMBus_Delay(5); // Generate bus free time between Stop
SMBUS_SDA_L(); // Clear SDA line
SMBus_Delay(10); // Hold time after (Repeated) Start
// Condition. After this period, the first clock is generated.
//(Thd:sta=4.0us min)
SMBUS_SCK_L(); // Clear SCL line
SMBus_Delay(2); // Wait a few microseconds
}
/*******************************************************************************
* Function Name : SMBus_StopBit
* Description : Generate STOP condition on SMBus
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SMBus_StopBit(void)
{
SMBUS_SCK_L(); // Clear SCL line
SMBus_Delay(5); // Wait a few microseconds
SMBUS_SDA_L(); // Clear SDA line
SMBus_Delay(5); // Wait a few microseconds
SMBUS_SCK_H(); // Set SCL line
SMBus_Delay(10); // Stop condition setup time(Tsu:sto=4.0us min)
SMBUS_SDA_H(); // Set SDA line
}
/*******************************************************************************
* Function Name : SMBus_SendByte
* Description : Send a byte on SMBus
* Input : Tx_buffer
* Output : None
* Return : None
*******************************************************************************/
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 SDA
Tx_buffer<<=1; // Get next bit for checking
}
Ack_bit=SMBus_ReceiveBit(); // Get acknowledgment bit
return Ack_bit;
}
/*******************************************************************************
* Function Name : SMBus_SendBit
* Description : Send a bit on SMBus
* Input : bit_out
* Output : None
* Return : None
*******************************************************************************/
void SMBus_SendBit(u8 bit_out)
{
if(bit_out==0)
{
SMBUS_SDA_L();
}
else
{
SMBUS_SDA_H();
}
SMBus_Delay(2); // Tsu:dat = 250ns minimum
SMBUS_SCK_H(); // Set SCL line
SMBus_Delay(10); // High Level of Clock Pulse
SMBUS_SCK_L(); // Clear SCL line
SMBus_Delay(10); // Low Level of Clock Pulse
// SMBUS_SDA_H(); // Master release SDA line ,
return;
}
/*******************************************************************************
* Function Name : SMBus_ReceiveBit
* Description : Receive a bit on SMBus
* Input : None
* Output : None
* Return : Ack_bit
*******************************************************************************/
u8 SMBus_ReceiveBit(void)
{
u8 Ack_bit;
SMBUS_SDA_H(); //?????????,????
SMBUS_SCK_H(); // Set SCL line
SMBus_Delay(2); // High Level of Clock Pulse
if (SMBUS_SDA_PIN())
{
Ack_bit=1;
}
else
{
Ack_bit=0;
}
SMBUS_SCK_L(); // Clear SCL line
SMBus_Delay(4); // Low Level of Clock Pulse
return Ack_bit;
}
/*******************************************************************************
* Function Name : SMBus_ReceiveByte
* Description : Receive a byte on SMBus
* Input : ack_nack
* Output : None
* Return : RX_buffer
*******************************************************************************/
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_buffer
RX_buffer |=0x01;
}
else
{
RX_buffer <<= 1; // If the bit is LOW save 0 in RX_buffer
RX_buffer &=0xfe;
}
}
SMBus_SendBit(ack_nack); // Sends acknowledgment bit
return RX_buffer;
}
/*******************************************************************************
* Function Name : SMBus_Delay
* Description : ?? ?????1us
* Input : time
* Output : None
* Return : None
*******************************************************************************/
void SMBus_Delay(u16 time)
{
u16 i, j;
for (i=0; i<4; i++)
{
for (j=0; j<time; j++);
}
}
/*******************************************************************************
* Function Name : SMBus_ReadMemory
* Description : READ DATA FROM RAM/EEPROM
* Input : slaveAddress, command
* Output : None
* Return : Data
*******************************************************************************/
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:
SMBus_StopBit(); //If slave send NACK stop comunication
--ErrorCounter; //Pre-decrement ErrorCounter
if(!ErrorCounter) //ErrorCounter=0?
{
break; //Yes,go out from do-while{}
}
SMBus_StartBit(); //Start condition
if(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 condition
if(SMBus_SendByte(slaveAddress+1)) //Send SlaveAddress ???Rd=1????????
{
goto repeat; //Repeat comunication again
}
DataL = SMBus_ReceiveByte(ACK); //Read low data,master must send ACK
DataH = SMBus_ReceiveByte(ACK); //Read high data,master must send ACK
Pec = SMBus_ReceiveByte(NACK); //Read PEC byte, master must send NACK
SMBus_StopBit(); //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;
}
/*******************************************************************************
* Function Name : PEC_calculation
* Description : Calculates the PEC of received bytes
* Input : pec[]
* Output : None
* Return : pec[0]-this byte contains calculated crc value
*******************************************************************************/
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];
}
/*******************************************************************************
* Function Name : SMBus_ReadTemp
* Description : Calculate and return the temperature
* Input : None
* Output : None
* Return : SMBus_ReadMemory(0x00, 0x07)*0.02-273.15
*******************************************************************************/
float SMBus_ReadTemp(void)
{
return SMBus_ReadMemory(SA, RAM_ACCESS|RAM_TOBJ1)*0.02-273.15;
}
/*********************************END OF FILE*********************************/
oled
oled.h
#ifndef __OLED_H
#define __OLED_H
#include "sys.h"
/**************************************************************************
作者:平衡小车之家
我的淘宝小店:http://shop114407458.taobao.com/
**************************************************************************/
#define PRI_BUF 300 //OLED显示的最长字符串
#define Brightness 0x0F //OLED亮度
#define X_WIDTH 128 //OLED宽度
#define Y_WIDTH 64 //OLEDgap都
//-----------------OLED端口定义----------------
#define OLED_RST_Clr() PCout(5)=0 //RST
#define OLED_RST_Set() PCout(5)=1 //RST
#define OLED_RS_Clr() PAout(7)=0 //DC
#define OLED_RS_Set() PAout(7)=1 //DC
#define OLED_SCLK_Clr() PBout(11)=0 //SCL
#define OLED_SCLK_Set() PBout(11)=1 //SCL
#define OLED_SDIN_Clr() PBout(1)=0 //SDA
#define OLED_SDIN_Set() PBout(1)=1 //SDA
#define OLED_CMD 0 //写命令
#define OLED_DATA 1 //写数据
//OLED控制用函数
void OLED_Init(void);
void OLEDPritnf(const char* format, ...);
void OLED_Show_Position(u8 x,u8 y,char* format, ...);
void OLED_Draw_BMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1, const unsigned char BMP[]);
void OLED_P16x16Ch(unsigned char x, unsigned char y, unsigned char n );
void OLED_P8x16CharPutc(unsigned char* x, unsigned char* y,unsigned char ch);
void OLED_P6x8CharPutc(unsigned char* x, unsigned char* y,unsigned char ch);
void OLED_P8x16Str(unsigned char x, unsigned char y,unsigned char ch[]);
void OLED_P8x16Char(unsigned char x, unsigned char y,unsigned char ch);
void OLED_P6x8Char(unsigned char ch);
void OLED_CLS(void);
void OLED_Fill(unsigned char bmp_dat);
void OLED_Set_Pos(unsigned char x, unsigned char y) ;
void OLED_Display_Off(void);
void OLED_Display_On(void);
void OLED_16x16CN(u8 x,u8 y,u8 N);
void OLED_16x32(u8 x, u8 y, u8 ch);
void OLED_8x16Str(u8 x, u8 y, u8 ch);
#endif
oled.c
/**
OLED_Show_Position(80,2,"Vc:%d",90);
OLED_Show_Position(0,6,"-->:HUNAN UNIVERSITY OF ARTS AND SCIENCE");
***/
#include "oled.h"
#include "sys.h"
#include "stdlib.h"
#include "oledfont.h"
#include "delay.h"
#include <stm32f10x.h>
#include "usart.h"
#include "stdarg.h"
#include "stdio.h"
#include "string.h"
volatile u8 Flag_clear = 1;
//*******************OLED写数据
void OLED_WrDat(unsigned char dat)
{
u8 i;
OLED_RS_Set(); //D/C 置1写数据
for(i=0;i<8;i++)
{
OLED_SCLK_Clr();
if(dat&0x01)
OLED_SDIN_Set();
else
OLED_SDIN_Clr();
OLED_SCLK_Set();
dat>>=1;
}
OLED_RS_Set();
}
//*******************OLED写命令
void OLED_WrCmd(unsigned char cmd)
{
u8 i;
OLED_RS_Clr(); //D/C 置0写命令
for(i=0;i<8;i++)
{
OLED_SCLK_Clr();
if(cmd&0x80)
OLED_SDIN_Set();
else
OLED_SDIN_Clr();
OLED_SCLK_Set();
cmd<<=1;
}
OLED_RS_Set();
}
//开启OLED显示
void OLED_Display_On(void)
{
OLED_WrCmd(0X8D); //SET DCDC命令
OLED_WrCmd(0X14); //DCDC ON
OLED_WrCmd(0XAF); //DISPLAY ON
}
//关闭OLED显示
void OLED_Display_Off(void)
{
OLED_WrCmd(0X8D); //SET DCDC命令
OLED_WrCmd(0X10); //DCDC OFF
OLED_WrCmd(0XAE); //DISPLAY OFF
}
//OLED 设置坐标
void OLED_Set_Pos(unsigned char x, unsigned char y)
{
OLED_WrCmd(0xb0+(7-y));
OLED_WrCmd(((x&0xf0)>>4)|0x10);
OLED_WrCmd((x&0x0f)|0x01);
}
//OLED填充
void OLED_Fill(unsigned char bmp_dat)
{
unsigned char y,x;
for(y=0;y<8;y++)
{
OLED_WrCmd(0xb0+y);
OLED_WrCmd(0x01);
OLED_WrCmd(0x10);
for(x=0;x<X_WIDTH;x++)
OLED_WrDat(bmp_dat);
}
}
//OLED复位
void OLED_CLS(void)
{
unsigned char y,x;
for(y=0;y<8;y++)
{
OLED_WrCmd(0xb0+y);
OLED_WrCmd(0x01);
OLED_WrCmd(0x10);
for(x=0;x<X_WIDTH;x++)
OLED_WrDat(0);
}
}
//功能描述:显示6*8一组标准ASCII字符串 显示的坐标(x,y),y为页范围0~7
void OLED_P6x8Char(unsigned char ch)
{
unsigned char c=0, i;
c = ch - 32;
for(i=0;i<6;i++)
OLED_WrDat(F6x8[c][i]);
}
//功能描述:显示8*16一组标准ASCII字符串 显示的坐标(x,y),y为页范围0~7
void OLED_P8x16Char(unsigned char x, unsigned char y,unsigned char ch)
{
unsigned char c=0,i=0;
c =ch-32;
OLED_Set_Pos(x,y);
for(i=0;i<8;i++)
OLED_WrDat(F8X16[c][i]);
OLED_Set_Pos(x,y+1);
for(i=0;i<8;i++)
OLED_WrDat(F8X16[c][i+8]);
}
//功能描述:显示8*16一组标准ASCII字符串 显示的坐标(x,y),y为页范围0~7
void OLED_P8x16Str(unsigned char x, unsigned char y,unsigned char ch[])
{
unsigned char c=0,i=0,j=0;
while (ch[j]!='\0')
{
c =ch[j]-32;
if(x>120){x=0;y++;}
OLED_Set_Pos(x,y);
for(i=0;i<8;i++)
OLED_WrDat(F8X16[c][i]);
OLED_Set_Pos(x,y+1);
for(i=0;i<8;i++)
OLED_WrDat(F8X16[c][i+8]);
x+=8;
j++;
}
}
/**
* @brief OLEDPritnf(...)服务子函数,显示6*8一组标准ASCII字符串 显示的坐标(x,y)
* @param x:0~120, y:0~7, ch:ASCII
* @retval None
*/
void OLED_P6x8CharPutc(unsigned char* x, unsigned char* y,unsigned char ch)
{
unsigned char c=0,i=0;
if(*x > 120) //判断横轴是否超出界限(120),如果超出则纵轴换行
{
*x = 0;
(*y) += 1;
}
if(*y > 7) //判断纵轴是否超出界限(6),如果超出则清屏
{
*y = 0;
OLED_Fill(0x00); //初始清屏
}
switch(ch)
{
case '\r': //回车
{
*x = 0;
return;
}
case '\n': //换行
{
(*y) += 1;
return;
}
case '\t': //TAB
{
(*x) += 24;
return;
}
default : //通用字符显示
{
c = ch - 32;
OLED_Set_Pos(*x,*y);
for(i=0;i<6;i++)
OLED_WrDat(F6x8[c][i]);
(*x) += 6;
break;
}
}
}
/**
* @brief OLEDPritnf(...)服务子函数,显示8*16一组标准ASCII字符串 显示的坐标(x,y)
* @param x:0~120, y:0/2/4/6, ch:ASCII
* @retval None
*/
void OLED_P8x16CharPutc(unsigned char* x, unsigned char* y,unsigned char ch)
{
unsigned char c=0,i=0;
if(*x > 120) //判断横轴是否超出界限(120),如果超出则纵轴换行
{
*x = 0;
(*y) += 2;
}
if(*y > 6) //判断纵轴是否超出界限(6),如果超出则清屏
{
*y = 0;
OLED_Fill(0x00); //初始清屏
}
switch(ch)
{
case '\r': //回车
{
*x = 0;
return;
}
case '\n': //换行
{
(*y) += 2;
return;
}
case '\t': //TAB
{
(*x) += 32;
return;
}
default : //通用字符显示
{
c = ch-32;
OLED_Set_Pos(*x,*y);
for(i=0;i<8;i++)
OLED_WrDat(F8X16[c][i]);
OLED_Set_Pos(*x,(*y)+1);
for(i=0;i<8;i++)
OLED_WrDat(F8X16[c][i+8]);
(*x) += 8;
break;
}
}
}
//功能描述:显示16*16点阵 显示的坐标(x,y),y为页范围0~7
//void OLED_P16x16Ch(unsigned char x, unsigned char y, unsigned char n )
//{ //x为横向坐标(汉字+17一个字),y为列向坐标(汉字+2一个字),n为字库索引
// unsigned char wm=0;
// OLED_Set_Pos(x , y);
// for(wm = 0;wm < 16;wm++)
// {
// OLED_WrDat(F16x16[n][wm]);
// }
// OLED_Set_Pos(x,y + 1);
// for(;wm < 32;wm++)
// {
// OLED_WrDat(F16x16[n][wm]);
// }
//}
//功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7
void OLED_Draw_BMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1, const unsigned char BMP[])
{
unsigned int j=0;
unsigned char x,y;
if(y1%8==0) y=y1/8;
else y=y1/8+1;
for(y=y0;y<y1;y++)
{
OLED_Set_Pos(x0,y);
for(x=x0;x<x1;x++)
{
OLED_WrDat(BMP[j++]);
delay_us(1);
}
}
}
//初始化OLED
void OLED_Init(void)
{
// GPIO_InitTypeDef GPIO_InitStructure;
// RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);//使能PORTC时钟
// //GPIO初始化设置
// GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
// GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
// GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
// GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化
//
// RCC->AHB1ENR|=1<<2;//使能PORTC时钟
// GPIO_Set(GPIOC,PIN0|PIN13|PIN14|PIN15,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);
RCC->APB2ENR|=1<<2; //使能PORTA时钟
RCC->APB2ENR|=1<<3; //使能PORTB时钟
RCC->APB2ENR|=1<<4; //使能PORTC时钟
//RCC->APB2ENR|=1<<0; //使能AFIO时钟
GPIOA->CRL&=0X0FFFFFFF; //A7
GPIOA->CRL|=0X20000000;
GPIOB->CRH&=0XFFFF0FFF; //B11
GPIOB->CRH|=0X00002000;
GPIOB->CRL&=0XFFFFFF0F; //B1
GPIOB->CRL|=0X00000020;
GPIOC->CRL&=0XFF0FFFFF;
GPIOC->CRL|=0X00200000;//C5
OLED_RST_Clr();
delay_ms(100);
OLED_RST_Set();
OLED_WrCmd(0xAE); //关闭显示
OLED_WrCmd(0xD5); //设置时钟分频因子,震荡频率
OLED_WrCmd(80); //[3:0],分频因子;[7:4],震荡频率
OLED_WrCmd(0xA8); //设置驱动路数
OLED_WrCmd(0X3F); //默认0X3F(1/64)
OLED_WrCmd(0xD3); //设置显示偏移
OLED_WrCmd(0X00); //默认为0
OLED_WrCmd(0x40); //设置显示开始行 [5:0],行数.
OLED_WrCmd(0x8D); //电荷泵设置
OLED_WrCmd(0x14); //bit2,开启/关闭
OLED_WrCmd(0x20); //设置内存地址模式
OLED_WrCmd(0x02); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;
OLED_WrCmd(0xA1); //段重定义设置,bit0:0,0->0;1,0->127;
OLED_WrCmd(0xC0); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数
OLED_WrCmd(0xDA); //设置COM硬件引脚配置
OLED_WrCmd(0x12); //[5:4]配置
OLED_WrCmd(0x81); //对比度设置
OLED_WrCmd(0xEF); //1~255;默认0X7F (亮度设置,越大越亮)
OLED_WrCmd(0xD9); //设置预充电周期
OLED_WrCmd(0xf1); //[3:0],PHASE 1;[7:4],PHASE 2;
OLED_WrCmd(0xDB); //设置VCOMH 电压倍率
OLED_WrCmd(0x30); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;
OLED_WrCmd(0xA4); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
OLED_WrCmd(0xA6); //设置显示方式;bit0:1,反相显示;0,正常显示
OLED_WrCmd(0xAF); //开启显示
OLED_Fill(0x00);
OLED_Set_Pos(0,0);
}
/**
* @brief OLED格式输出显示函数
* @param 例子:"OLEDPritnf(0, "i=%.1f,i*2=%d\r\n",-0.23, i*2)"
* @retval None
*/
uint8_t OLED_buf[PRI_BUF];
void OLEDPritnf(const char* format, ...)
{
uint16_t i,j;
va_list ap;
static unsigned char x = 0, y = 0;
// if(Flag_clear == 1)
// {
// x = 0;
// y = 0;
// OLED_Fill(0x00); //清屏
// Flag_clear = 0;
// }
OLED_Fill(0x00); //清屏
va_start(ap,format);
vsprintf((char*)OLED_buf,format,ap);
va_end(ap);
i=strlen((const char*)OLED_buf); //此次发送数据的长度
for(j=0;j<i;j++) //循环发送数据
{
OLED_P6x8CharPutc(&x, &y, OLED_buf[j]);
}
}
//固定位置显示数字或字符
void OLED_Show_Position(u8 x,u8 y,char* format, ...)
{
uint16_t i,j;
va_list ap;
va_start(ap,format);
vsprintf((char*)OLED_buf,format,ap);
va_end(ap);
i=strlen((char*)OLED_buf); //此次发送数据的长度
for(j=0;j<i;j++) //循环发送数据
{
//OLED_P6x8CharPutc(&x, &y, OLED_buf[j]);
OLED_P8x16CharPutc(&x, &y, OLED_buf[j]);
}
}
void OLED_8x16Str(u8 x, u8 y, u8 ch)
{
u8 i=0;
if(x>120)
{
x=0;y++;
}
OLED_Set_Pos(x,y);
for(i=0;i<8;i++)
{
OLED_WrDat(MyF8X16[ch*16+i]);
}
OLED_Set_Pos(x,y+1);
for(i=0;i<8;i++)
{
OLED_WrDat(MyF8X16[ch*16+i+8]);
}
}
void OLED_16x16CN(u8 x,u8 y,u8 N)//显示16*16的坐标(x,y),y为页范围0~7
{
u8 i=0;
u32 adder=32*N;
OLED_Set_Pos(x,y);
for(i=0;i<16;i++)
{
OLED_WrDat(F16x16[adder]);
adder+=1;
}
OLED_Set_Pos(x,y+1);
for(i=0;i<16;i++)
{
OLED_WrDat(F16x16[adder]);
adder+=1;
}
}
void OLED_16x32(u8 x, u8 y, u8 ch)//显示8*16的坐标(x,y),y为页范围0~7
{
u8 i=0;
if(x>120)
{
x=0;y++;
}
OLED_Set_Pos(x,y);
for(i=0;i<16;i++)
{
OLED_WrDat(F16X32[ch*64+i]);
}
OLED_Set_Pos(x,y+1);
for(i=0;i<16;i++)
{
OLED_WrDat(F16X32[ch*64+i+16]);
}
OLED_Set_Pos(x,y+2);
for(i=0;i<16;i++)
{
OLED_WrDat(F16X32[ch*64+i+32]);
}
OLED_Set_Pos(x,y+3);
for(i=0;i<16;i++)
{
OLED_WrDat(F16X32[ch*64+i+48]);
}
}
float2string(浮点型转字符串)
float2string.h
#ifndef __FLOAT2STRING_H
#define __FLOAT2STRING_H
#include "sys.h"
uint8_t* Float2String(uint8_t* s_buff, float num, uint8_t accuracy);
#endif
float2string.c
#include "float2string.h"
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] 单精度浮点数转字符串
* @param num:待转换的单精度浮点数
accuracy:转换精度
[url=home.php?mod=space&uid=2583231]@arg[/url] 精度值取大于7时无效
* @retval 转换完成的字符串首地址
@arg result[]
*/
uint8_t* Float2String(uint8_t* s_buff, float num, uint8_t accuracy) //ps:C标准输入输出库内有sprintf(...)浮点ect.数转字符串函数
{
uint32_t integer = 0; //整数
uint32_t decimal = 0; //小数
uint8_t num_temp = 0; //按位转换的结果缓冲
uint32_t multi_dec = 1; //小数倍乘
uint8_t point = 0; //转换结果下标
uint8_t trans_len = 0; //按位转换的结果长度
uint8_t trans_temp[300]; //按位转换的结果数组缓冲
uint8_t accuracy_temp = accuracy; //转换精度备份
if (num < 0)
{
/* 若num小于零,前填零 */
num = -num;
s_buff[point] = '-';
point++;
}
integer = (uint16_t) num; //取整数部分
while (accuracy--)
{
multi_dec *= 10; //取小数精度倍乘
}
decimal = (uint16_t)(multi_dec * (num - integer + 0.000001f)); //取小数部分
if (integer)
{
while (integer)
{
/* 将整数部分转换为倒位数组 */
num_temp = integer % 10;
trans_temp[trans_len] = num_temp + 48;
integer = (integer - num_temp) / 10;
trans_len++;
}
point += trans_len;
}
else
{
s_buff[point] = '0';
point++;
}
for (; trans_len > 0; trans_len--)
{
/* 将倒位数组内容存放到转换结果 */
s_buff[point - trans_len] = trans_temp[trans_len - 1];
}
if (decimal)
{
s_buff[point] = '.'; //补小数点
trans_len = 0;
while (decimal)
{
/* 将小数部分转换为倒位数组 */
num_temp = decimal % 10;
trans_temp[trans_len] = num_temp + 48;
decimal = (decimal - num_temp) / 10;
trans_len++;
}
while (trans_len < accuracy_temp)
{
/* 补零 */
trans_temp[trans_len] = '0';
trans_len++;
}
point += (trans_len + 1);
}
else
{
s_buff[point] = 0;
return s_buff;
}
for (; trans_len > 0; trans_len--)
{
/* 将倒位数组内容存放到转换结果 */
s_buff[point - trans_len] = trans_temp[trans_len - 1];
}
s_buff[point] = 0;
return s_buff;
}
led
led.h
#ifndef __LED_H
#define __LED_H
#include "sys.h"
#define LED0 PBout(5)// PB5
#define LED1 PEout(5)// PE5
void LED_Init(void);//初始化
#endif
led.c
#include "led.h"
//初始化PB5和PE5为输出口.并使能这两个口的时钟
//LED IO初始化
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能PB,PE端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB.5
GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 端口配置, 推挽输出
GPIO_Init(GPIOE, &GPIO_InitStructure); //推挽输出 ,IO口速度为50MHz
GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高
}
main.c
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "oled.h"
#include "mlx90614.h"
#include "stdio.h"
#include "string.h"
#include "float2string.h"
int main(void)
{
float temp;
uint8_t buffer[300];
uint8_t i,k,m;
delay_init(); //延时函数初始化
OLED_Init();
uart_init(115200); //串口初始化为115200
SMBus_Init();
while(1)
{
// OLED_16x16CN(0, 0, 37);//脚
// OLED_16x16CN(16, 0, 28);//下
// OLED_16x16CN(32, 0, 38);//的
// OLED_16x16CN(48, 0, 39);//路
// OLED_16x16CN(64, 0, 44);//,
// OLED_16x16CN(80, 0, 40);//天
// OLED_16x16CN(96, 0, 41);//翻
// OLED_16x16CN(112, 0, 42);//地
// OLED_16x16CN(0, 2, 43);//覆
//OLED_Show_Position(0,4,"Mat Jenin");
//OLED_8x16Str(66, 2, 24);//%
for(i=0;i<=10;i++)
{
//OLED_Show_Position(0,4,"%d\r\n",i);
//OLEDPritnf("%d\r\n",i);
}
temp = SMBus_ReadTemp();
printf("1111\n");
printf("temp = %f\n",temp);
//OLED_Show_Position(0,0,"temp=");
OLED_Show_Position(0,0,"temp:");
sprintf((char*)buffer,"%.3f",temp);
k=strlen((char*)buffer); //此次发送数据的长度
for(m=0;m<k;m++) //循环发送数据
{
OLED_Show_Position(0,2,Float2String(buffer, temp, 1));
}
delay_ms(2500);
OLED_Fill(0x00); //清屏
}
}