- /******************************************************************************
- * 程序功能: 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*/
- }
-
效果图
温度值显示有些模糊。