打印
[PIC®/AVR®/dsPIC®产品]

PIC18F46K80板子驱动TN9

[复制链接]
259|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
代码:
/******************************************************************************

* 程序功能: 4脚I2C接口OLED演示例程
* CPU型号 : PIC18F46K80
* 系统时钟: 外部8M晶振经4xPLL倍频到32M
* 开发环境: MPLAB X IDE V5.20
* 编译软件: XC8 V1.41
* 烧写工具: PICKIT3/KIT3.5   ICD3等        
* 实验说明: 由于OLED不止一家生产的,每家生产的参数可能有所不同无法确保所有厂家的OLED都适用.
*           如使用的是其他厂家的OLED无法显示时需要客户自行查找原因。
*           我们也有OLED显示屏出售,直接适用于开发板并通过验证的,欢迎选购。
* 作    者:博科电子
* 更新日期:2021年12月5

*****************************************************************************/

#include <xc.h>
#include "bmp.h"
#include "oledfont.h"           

//CONFIG1L
#pragma config RETEN = OFF           // VREG Sleep Enable bit (Ultra low-power regulator is Disabled (Controlled by REGSLP bit)),禁止超低功耗稳压器
#pragma config INTOSCSEL = HIGH      // LF-INTOSC Low-power Enable bit (LF-INTOSC in High-power mode during Sleep),休眠期间 LF-INTOSC 处于高功耗模式
#pragma config SOSCSEL = DIG         // SOSC Power Selection and mode Configuration bits (Digital (SCLKI) mode),SOSC 功耗选择和模式配置位,数字 ( SCLKI)模式;使能 RC0 和 RC1 的 I/O 端口功能
#pragma config XINST = OFF           // Extended Instruction Set (Disabled),扩展指令集使能位,禁止指令集扩展和变址寻址模式 (传统模式)

// CONFIG1H
#pragma config FOSC = HS1            // Oscillator (HS oscillator (Medium power, 4 MHz - 16 MHz)),HS振荡器,中等功耗
#pragma config PLLCFG = ON           // PLL x4 Enable bit (Enabled),打开PLL功能,系统时钟4倍频,变为32MHz
#pragma config FCMEN = OFF           // Fail-Safe Clock Monitor (Disabled),禁止故障保护时钟监视器
#pragma config IESO = OFF            // Internal External Oscillator Switch Over Mode (Disabled),禁止双速启动

// CONFIG2L
#pragma config PWRTEN = OFF         // Power Up Timer (Disabled),禁止上电延时定时器
#pragma config BOREN = SBORDIS      // Brown Out Detect (Enabled in hardware, SBOREN disabled),只能由硬件使能欠压复位
#pragma config BORV = 3             // Brown-out Reset Voltage bits (1.8V),欠压复位电压选择为1.8v
#pragma config BORPWR = ZPBORMV     // BORMV Power level (ZPBORMV instead of BORMV is selected),选择ZPBORMV而不是BORMV

// CONFIG2H
#pragma config WDTEN = OFF          // Watchdog Timer (WDT disabled in hardware; SWDTEN bit disabled),关闭看门狗功能
//#pragma config WDTEN = SWDTDIS    // Watchdog Timer (WDT enabled in hardware; SWDTEN bit disabled),由硬件使能WDT,禁止SWDTEN位
#pragma config WDTPS = 256          // Watchdog Postscaler (1:256),看门狗后分频1:256,溢出时间1.024s

// CONFIG3H
#pragma config CANMX = PORTB    // ECAN Mux bit (ECAN TX and RX pins are located on RB2 and RB3, respectively),1 = CANTX 和 CANRX 引脚分别位于 RB2 和 RB3 上
#pragma config MSSPMSK = MSK7   // MSSP address masking (7 Bit address masking mode),1 = 使能 7 位地址掩码模式
#pragma config MCLRE = ON       // Master Clear Enable (MCLR Enabled, RE3 Disabled),使能MCLR复位功能

// CONFIG4L
#pragma config STVREN = ON      // Stack Overflow Reset (Enabled),堆栈满/下溢导致复位
#pragma config BBSIZ = BB2K     // Boot Block Size (2K word Boot Block size),引导区大小选择2K

// CONFIG5L
#pragma config CP0 = OFF        // Code Protect 00800-01FFF (Disabled),代码保护位
#pragma config CP1 = OFF        // Code Protect 02000-03FFF (Disabled),代码保护位
#pragma config CP2 = OFF        // Code Protect 04000-05FFF (Disabled),代码保护位
#pragma config CP3 = OFF        // Code Protect 06000-07FFF (Disabled),代码保护位

// CONFIG5H
#pragma config CPB = OFF        // Code Protect Boot (Disabled),引导区不受代码保护
#pragma config CPD = OFF        // Data EE Read Protect (Disabled),数据EEPROM不受代码保护

// CONFIG6L
#pragma config WRT0 = OFF       // Table Write Protect 00800-01FFF (Disabled),写保护位
#pragma config WRT1 = OFF       // Table Write Protect 02000-03FFF (Disabled),写保护位
#pragma config WRT2 = OFF       // Table Write Protect 04000-05FFF (Disabled),写保护位
#pragma config WRT3 = OFF       // Table Write Protect 06000-07FFF (Disabled),写保护位

// CONFIG6H
#pragma config WRTC = OFF       // Config. Write Protect (Disabled),配置寄存器不受写保护
#pragma config WRTB = OFF       // Table Write Protect Boot (Disabled),引导区不受写保护
#pragma config WRTD = OFF       // Data EE Write Protect (Disabled),数据EEPROM不受写保护

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protect 00800-01FFF (Disabled),表读保护位
#pragma config EBTR1 = OFF      // Table Read Protect 02000-03FFF (Disabled),表读保护位
#pragma config EBTR2 = OFF      // Table Read Protect 04000-05FFF (Disabled),表读保护位
#pragma config EBTR3 = OFF      // Table Read Protect 06000-07FFF (Disabled),表读保护位

// CONFIG7H
#pragma config EBTRB = OFF      // Table Read Protect Boot (Disabled),引导区不受写保护


#define  u8 unsigned char
#define  u16 unsigned int
#define  u32 unsigned int
#define uchar unsigned char

//-----------------OLED定义----------------
#define OLED_CMD  0        //写命令
#define OLED_DATA 1        //写数据

#define OLED_SCL     LATCbits.LATC3      //SCL接RC3
#define OLED_SDA     LATCbits.LATC4      //SDA接RC4

#define OLED_SCL_DIR_OUT  TRISC3=0;      //scl引脚配置为输出
#define OLED_SDA_DIR_OUT  TRISC4=0;             //sda引脚配置为输出
       
#define OLED_SCL_Clr() OLED_SCL=0
#define OLED_SCL_Set() OLED_SCL=1

#define OLED_SDA_Clr() OLED_SDA=0
#define OLED_SDA_Set() OLED_SDA=1

//OLED控制用函数
void delay_ms(unsigned int ms);
void OLED_ColorTurn(u8 i);
void OLED_DisplayTurn(u8 i);
void OLED_WR_Byte(u8 dat,u8 cmd);
void OLED_Set_Pos(u8 x, u8 y);
//void OLED_Display_On(void);
//void OLED_Display_Off(void);
void OLED_Clear(void);
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 sizey);
u32 oled_pow(u8 m,u8 n);
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 sizey);
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 sizey);
void OLED_ShowChinese(u8 x,u8 y,u8 no,u8 sizey);
void OLED_DrawBMP(u8 x,u8 y,u8 sizex, u8 sizey,u8 BMP[]);
void OLED_Init(void);

void ACK_0() { RC0=0;}

void ACK_1() { RC0=1;}







#define DATA RC2



#define CLOCK RC5







float Temp;

float Temp1,Temp2;

unsigned char ReadData[5];

//float  a,b;



//-----------------------------------------------------------------------------------------

//????:Delay()

//?    ?:?????

//-----------------------------------------------------------------------------------------

void Delay(unsigned char us)

{

    uchar i;

    while(--us)

    {

        for(i=0;i<50;i++);

    }

}



//-----------------------------------------------------------------------------------------

//????:Delayms()

//-----------------------------------------------------------------------------------------

void Delayms(unsigned int ims)

{

    unsigned int i,j;

    for(i=0;i<ims;i++)

         for(j=0;j<65;j++)

         {

            Delay(1);

     }

}

void TN_IRACK_EN(void)

{

    ACK_0();

    Delay(1);

}





void TN_IRACK_UN(void)

{

    ACK_1();

    Delay(1);

}





void TN_ReadData(unsigned char Flag)

{

    unsigned char i,j,k,BitState=0;

    for(k=0;k<7;k++)

    {

        for(j=0;j<5;j++)

         {

            for(i=0;i<8;i++)

            {

                while(1)

                {

                     if(CLOCK==0)

                        break;

                    Delay(1);

                }

                Delay(1);

                if(DATA==1)

                     BitState=1;

                else

                    BitState=0;

                ReadData[j]= ReadData[j]<<1;

                ReadData[j]= ReadData[j]|BitState;

                Delay(1);

                while(1)

                {

                    if(CLOCK==1)

                        break;

                    Delay(1);

                }

            }

         }

         if(ReadData[0]==Flag)

            k=8;

    }

    TN_IRACK_UN();

}

float TN_GetData(unsigned char X)

{



    TN_ReadData(X);

    Temp=(ReadData[1]<<8)|ReadData[2];

    Temp=(float)Temp/16.00-273.15;

    return Temp;

}

float TN_GetTemp(unsigned char mode)

{



    float T;



    {

         TN_IRACK_UN();

            TN_IRACK_EN();

         if(mode==0)

         {

            T=TN_GetData(0x4c);



         }

         else

        {

            T=TN_GetData(0x66);



        }

    }



    return T;

}

void main(void)
{       
    uchar a,b,c,d;
    u16 i,j;
   
    ANCON1=0x00;            //PORTB带模拟输入功能的引脚全部配置为数字IO
    TRISC0=0;
    TRISC2=1;
    TRISC5=1;
   
        OLED_Init();//初始化OLED
        OLED_ColorTurn(0);//0正常显示,1 反色显示
    OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示
   
    OLED_ShowChinese(0,0,7,16);//中
    OLED_ShowChinese(18,0,8,16);//中
    OLED_ShowChinese(36,0,11,16);//中
    OLED_ShowChinese(54,0,12,16);//中
   
    OLED_ShowChinese(0,4,9,16);//中
    OLED_ShowChinese(18,4,10,16);//中
    OLED_ShowChinese(36,4,11,16);//中
    OLED_ShowChinese(54,4,12,16);//中
   
        while(1)
        {               
               
                //OLED_Clear();
                Temp1=TN_GetTemp(0);
        i=(u16)(Temp1*100);
        a=(uchar)(i/1000);
        b=(uchar)(i%1000/100);
        c=(uchar)(i%100/10);
        d=(uchar)(i%10);
        OLED_ShowChar(76,0,a+48,16);
        OLED_ShowChar(84,0,b+48,16);
        OLED_ShowChar(92,0,'.',16);
        OLED_ShowChar(100,0,c+48,16);
        OLED_ShowChar(108,0,d+48,16);
        Temp2=TN_GetTemp(1);  
        j=(u16)(Temp2*100);
        a=(uchar)(j/1000);
        b=(uchar)(j%1000/100);
        c=(uchar)(j%100/10);
        d=(uchar)(j%10);
        OLED_ShowChar(76,4,a+48,16);
        OLED_ShowChar(84,4,b+48,16);
        OLED_ShowChar(92,4,'.',16);
        OLED_ShowChar(100,4,c+48,16);
        OLED_ShowChar(108,4,d+48,16);
                delay_ms(2000);      
               
        }                 
}


void delay_ms(unsigned int ms)
{                        
        unsigned int a;
        while(ms)
        {
                a=1800;
                while(a--);
                ms--;
        }
        return;
}


//反显函数
void OLED_ColorTurn(u8 i)
{
        if(i==0)
                {
                        OLED_WR_Byte(0xA6,OLED_CMD);//正常显示
                }
        if(i==1)
                {
                        OLED_WR_Byte(0xA7,OLED_CMD);//反色显示
                }
}


//屏幕旋转180度
void OLED_DisplayTurn(u8 i)
{
        if(i==0)
                {
                        OLED_WR_Byte(0xC8,OLED_CMD);//正常显示
                        OLED_WR_Byte(0xA1,OLED_CMD);
                }
        if(i==1)
                {
                        OLED_WR_Byte(0xC0,OLED_CMD);//反转显示
                        OLED_WR_Byte(0xA0,OLED_CMD);
                }
}



//延时
void IIC_delay(void)
{
        u8 t=1;
        while(t--);
}


//起始信号
void I2C_Start(void)
{
        OLED_SDA_Set();
        OLED_SCL_Set();
        IIC_delay();
        OLED_SDA_Clr();
        IIC_delay();
        OLED_SCL_Clr();
         
}


//结束信号
void I2C_Stop(void)
{
        OLED_SDA_Clr();
        OLED_SCL_Set();
        IIC_delay();
        OLED_SDA_Set();
}


//等待信号响应
void I2C_WaitAck(void) //测数据信号的电平
{
        OLED_SDA_Set();
        IIC_delay();
        OLED_SCL_Set();
        IIC_delay();
        OLED_SCL_Clr();
        IIC_delay();
}


//写入一个字节
void Send_Byte(u8 dat)
{
        u8 i;
        for(i=0;i<8;i++)
        {
                OLED_SCL_Clr();//将时钟信号设置为低电平
                if(dat&0x80)//将dat的8位从最高位依次写入
                {
                        OLED_SDA_Set();
    }
                else
                {
                        OLED_SDA_Clr();
    }
                IIC_delay();
                OLED_SCL_Set();
                IIC_delay();
                OLED_SCL_Clr();
                dat<<=1;
  }
}


//发送一个字节
//向SSD1306写入一个字节。
//mode:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat,u8 mode)
{
        I2C_Start();
        Send_Byte(0x78);
        I2C_WaitAck();
        if(mode){Send_Byte(0x40);}
  else{Send_Byte(0x00);}
        I2C_WaitAck();
        Send_Byte(dat);
        I2C_WaitAck();
        I2C_Stop();
}


//坐标设置

void OLED_Set_Pos(u8 x, u8 y)
{
        OLED_WR_Byte(0xb0+y,OLED_CMD);
        OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
        OLED_WR_Byte((x&0x0f),OLED_CMD);
}             

/*
//开启OLED显示   
void OLED_Display_On(void)
{
        OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
        OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ON
        OLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON
}


//关闭OLED显示     
void OLED_Display_Off(void)
{
        OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
        OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFF
        OLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
}                                            
*/

//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!          
void OLED_Clear(void)  
{  
        u8 i,n;                    
        for(i=0;i<8;i++)  
        {  
                OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)
                OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置?列低地址
                OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置?列高地址   
                for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA);
        } //更新显示
}


//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63                                 
//sizey:选择字体 6x8  8x16
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 sizey)
{             
        u8 c=0,sizex=sizey/2;
        u16 i=0,size1;
        if(sizey==8)size1=6;
        else size1=(sizey/8+((sizey%8)?1:0))*(sizey/2);
        c=chr-' ';//得到偏移后的值
        OLED_Set_Pos(x,y);
        for(i=0;i<size1;i++)
        {
                if(i%sizex==0&&sizey!=8) OLED_Set_Pos(x,y++);
                if(sizey==8) OLED_WR_Byte(asc2_0806[c][i],OLED_DATA);//6X8字号
                else if(sizey==16) OLED_WR_Byte(asc2_1608[c][i],OLED_DATA);//8x16字号
//                else if(sizey==xx) OLED_WR_Byte(asc2_xxxx[c][i],OLED_DATA);//用户添加字号
                else return;
        }
}


//m^n函数
u32 oled_pow(u8 m,u8 n)
{
        u32 result=1;         
        while(n--)result*=m;   
        return result;
}                                  


//显示数字
//x,y :起点坐标
//num:要显示的数字
//len :数字的位数
//sizey:字体大小                  
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 sizey)
{                
        u8 t,temp,m=0;
        u8 enshow=0;
        if(sizey==8)m=2;
        for(t=0;t<len;t++)
        {
                temp=(num/oled_pow(10,len-t-1))%10;
                if(enshow==0&&t<(len-1))
                {
                        if(temp==0)
                        {
                                OLED_ShowChar(x+(sizey/2+m)*t,y,' ',sizey);
                                continue;
                        }else enshow=1;
                }
                 OLED_ShowChar(x+(sizey/2+m)*t,y,temp+'0',sizey);
        }
}


//显示一个字符号串
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 sizey)
{
        u8 j=0;
        while (chr[j]!='\0')
        {               
                OLED_ShowChar(x,y,chr[j++],sizey);
                if(sizey==8)x+=6;
                else x+=sizey/2;
        }
}


//显示汉字
void OLED_ShowChinese(u8 x,u8 y,u8 no,u8 sizey)
{
        u16 i,size1=(sizey/8+((sizey%8)?1:0))*sizey;
        for(i=0;i<size1;i++)
        {
                if(i%sizey==0) OLED_Set_Pos(x,y++);
                if(sizey==16) OLED_WR_Byte(Hzk[no][i],OLED_DATA);//16x16字号
//                else if(sizey==xx) OLED_WR_Byte(xxx[c][i],OLED_DATA);//用户添加字号
                else return;
        }                               
}


//显示图片
//x,y显示坐标
//sizex,sizey,图片长宽
//BMP:要显示的图片
void OLED_DrawBMP(u8 x,u8 y,u8 sizex, u8 sizey,u8 BMP[])
{        
  u16 j=0;
        u8 i,m;
        sizey=sizey/8+((sizey%8)?1:0);
        for(i=0;i<sizey;i++)
        {
                OLED_Set_Pos(x,i+y);
    for(m=0;m<sizex;m++)
                {      
                        OLED_WR_Byte(BMP[j++],OLED_DATA);                   
                }
        }
}



//初始化                                    
void OLED_Init(void)
{
    OLED_SCL_DIR_OUT;
    OLED_SDA_DIR_OUT;
    delay_ms(200);
        OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
        OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
        OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
        OLED_WR_Byte(0x40,OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
        OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
        OLED_WR_Byte(0xCF,OLED_CMD); // Set SEG Output Current Brightness
        OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
        OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
        OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display
        OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
        OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
        OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset        Shift Mapping RAM Counter (0x00~0x3F)
        OLED_WR_Byte(0x00,OLED_CMD);//-not offset
        OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
        OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
        OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
        OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
        OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
        OLED_WR_Byte(0x12,OLED_CMD);
        OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
        OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
        OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
        OLED_WR_Byte(0x02,OLED_CMD);//
        OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
        OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
        OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
        OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)
        OLED_Clear();
        OLED_WR_Byte(0xAF,OLED_CMD); /*display ON*/
}

       
效果图



温度值显示有些模糊。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

347

主题

3092

帖子

7

粉丝