MLX90614测温+OLED显示


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); //清屏
    }
}

文章作者: Mat Jenin
文章链接: http://matjenin.xyz
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Mat Jenin !
  目录