STC32G--OLED12864--I2C/SPI协议 ===兼容0.96(I2C/SPI)/1.3寸(I2C) 函数是我参考网络上大部分0.96寸OLED的资料,学习改编而来,I2C协议是通过冲哥视频学习的, 特别是B站上“大明狐”老师的教学视频(十分推荐去看看,讲的很清晰易懂), 对我理解OLED屏幕提供了很大的启示帮助。
目前包含了8*128级缓存和1024级缓存绘制图形以及显示文字的部分(包含点、虚线、实线、矩形、圆形等等),还有通过指令写数据的方式直接显示文字的函数。
演示视频二选一:
今天刚好有空,画了一点点时间,把SPI的也搞了一下,目前发现SPI绘制的速度比IIC的快好多喔!! IIC我用STC32G实验箱测试的,SPI我用的屠龙刀测试的。
#ifndef __IIC_H_
#define __IIC_H_
#include "stc32g.h"
#include "stc32_stc8_usb.h"
#define IIC_MODE 1 //0:软件IIC 1:硬件IIC(仅4脚)
#define IIC_PIN 0 //0:四针IIC 1:七针IIC
#define SLAVE_24C02 0XA0
//------------------------------引脚定义------------------------------
// #if IIC_PIN == 0
// #define SCL P25
// #define SDA P24
// #elif IIC_PIN == 1
#define SCL P25
#define SDA P24
#define RES P23
#define DC P34
#define CS P11
// #endif
#ifndef __OLED12824_IIC_H_
#define __OLED12824_IIC_H_
#include "stc32g.h"
#include "stc32_stc8_usb.h"
/*选择OLED的尺寸
0:0.96寸4P/7P
1:1.30寸4P
*/
#define OLED_SIZE 1
#define OLED_GRAM_Mode 0 //0:8*128级缓存 1:1024级缓存 2:指令模式
//------------------------------变量声明------------------------------
#define SLAVE_OLED_12864 0X78 //128*64_OLED屏幕IIC地址
#define OLED_WriteCom_Addr 0x00 //从机写指令地址
#define OLED_WriteData_Addr 0x40 //从机写数据地址
#define OLED_CMD 0 //写命令
#define OLED_DATA 1 //写数据
#define Max_Column 128
#define Max_Row 64
#define Brightness 0xFF //亮度0~255
extern char xdata WaveData[128];
#if OLED_GRAM_Mode == 0 //0:8*128级缓存
extern u8 OLED_GRAM[8][128]; // OLED全局缓存
#elif OLED_GRAM_Mode == 1 //1:1024级缓存
extern u8 OLED_GRAM[1024]; // OLED全局缓存
#else //2:指令模式
#endif
//------------------------------引脚定义------------------------------
//------------------------------函数声明------------------------------
void OLED_Write_Byte(u8 dat, u8 cmd); // 写入一个字节
void OLED_Init(void); // 初始化OLED
void OLED_Set_Pos(u8 x, u8 y); // OLED设置显示位置
void OLED_Display_On(void); // 开启OLED显示
void OLED_Display_Off(void); // 关闭OLED显示
void OLED_LightSet(u8 num); // 亮度设置
void OLED_Clear(bit mode); // 清屏函数
#if OLED_GRAM_Mode == 0 || OLED_GRAM_Mode == 1 //0:8*128级缓存//1:1024级缓存
// #elif OLED_GRAM_Mode == 1
void OLED_GRAM_Clear(bit mode); // 通过缓冲数组,OLED屏幕全亮全灭
void OLED_Refresh_Gram(void); // OLED刷新显示
void OLED_RefreshPart_Gram(u8 xstart, u8 ystart, u8 width, u8 height); // OLED局部刷新显示
void OLED_DrawPoint(u8 x, u8 y, bit mode); // OLED画一个点,0:熄灭 1:点亮
void OLED_FourPoints(u8 x0, u8 y0, bit mode); // 4个像素点为一组,控制亮灭
void OLED_Mask_Gray(u8 x0, u8 y0, u8 BMP[], bit mode); // 蒙版函数,衍生于OLED_FourPoints函数
// void OLED_DrawLineG(u8 x1, u8 y1, u8 x2, u8 y2, bit mode); // OLED画一条线,0:熄灭 1:点亮
void OLED_DrawLineG_Dot(u8 x1, u8 y1, u8 x2, u8 y2, bit mode, u8 dot); // OLED画一条虚实线,0:熄灭 1:点亮
// void OLED_DrawRectangleG(u8 x1, u8 y1, u8 x2, u8 y2, bit mode); // OLED画一个矩形
void OLED_DrawFrameG(u8 x0, u8 y0, u8 x1, u8 y1, bit mode); // OLED画一个方框
void OLED_DrawBlockG(u8 x0, u8 y0, u8 x1, u8 y1, bit mode); // OLED画一个实心框
void OLED_DrawBox(u8 x0, u8 y0, u8 x1, u8 y1, u8 fill, bit mode); // OLED画空实心矩形
void OLED_DrawCircleG(u8 x, u8 y, u8 r, bit mode); // OLED画一个圆形
void OLED_DrawEllipticG(u8 x0, u8 y0, u8 R1, u8 R2, bit mode); // OLED画一个椭圆形
void OLED_DrawCircleG_Distance(u8 x0, u8 y0, u8 R, bit mode); // OLED画一个圆形(勾股定理法)
void OLED_DrawBlockCircleG_Distance(u8 x0, u8 y0, u8 R, bit mode); // OLED画一个实心圆形(勾股定理法)
void OLED_DrawCircleG_Bresenham(u8 x, u8 y, u8 r, bit mode); // OLED画一个圆形(Bresenham法)
void OLED_DrawBlockCircleG_Bresenham(u8 x, u8 y, u8 r, bit mode); // OLED画一个实心圆形(Bresenham法)
void OLED_DrawRoundRectangleG(u8 x0, u8 y0, u8 x1, u8 y1, u8 R, u8 fill, bit mode); // OLED画一个圆角矩形(Bresenham法)
void OLED_DrawWidthRoundRectangleG(u8 x0, u8 y0, u8 x1, u8 y1, u8 R, u8 width, bit mode); // OLED画一个宽边圆角矩形(Bresenham法)
void OLED_DrawSin(); // 画正弦函数
void ButtonWave(); // 按键控制显示方波
void OLED_ShowCharG(u8 x, u8 y, u8 chr, u8 charSize, u8 Is_Reverse); // 缓存显示一个字符
void OLED_ShowStringG(u8 x, u8 y, char *chr, u8 charSize, u8 Is_Reverse); // 缓存显示一个字符号串
void OLED_ShowNumG(u8 x, u8 y, u32 num, u8 len, u8 Size, u8 Is_Reverse); // 缓存显示一串数字
void OLED_ShowChineseG(u8 x, u8 y, u8 no, u8 Is_Reverse); // 缓存显示汉字
void OLED_ShowBMPG(u8 x0, u8 y0, u8 x1, u8 y1, u8 BMP[], u8 Is_Reverse); // 缓存显示BMP图片
#else //2:指令模式
#endif
void OLED_ShowChar(u8 x, u8 y, u8 chr, u8 charSize, u8 Is_Reverse); // 早指定位置显示一个字符
void OLED_ShowString(u8 x, u8 y, char *chr, u8 charSize, u8 Is_Reverse); // 显示一个字符号串
u32 OLED_Index(u8 m, u8 n); // m^n函数
void OLED_ShowNum(u8 x, u8 y, u32 num, u8 len, u8 Size, u8 Is_Reverse); // 显示一串数字
void OLED_ShowChinese(u8 x, u8 y, u8 no, u8 Is_Reverse); // 显示汉字
void OLED_ShowBMP(u8 x0, u8 y0, u8 x1, u8 y1, u8 BMP[], u8 Is_Reverse); // 显示BMP图片
#endif
主函数如下:
- <font face="新宋体"><b>#include <intrins.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
-
- #include "stc32g.h"
- #include "stc32_stc8_usb.h"
-
- #include "iic.h"
- #include "oled12824_iic.h"
- #include "oled_bmp.h"
-
- // #define MAIN_Fosc 24000000UL //ISP下载时需将工作频率设置为24MHz
-
-
-
-
- char *USER_DEVICEDESC = NULL;
- char *USER_PRODUCTDESC = NULL;
- char *USER_STCISPCMD = "@STCISP#"; //不停电自动ISP下载命令
-
- // bit TIME_10ms_flag; //10ms的标志位
-
-
- void delay_ms(u16 ms)
- {
- u16 i;
- do
- {
- i = MAIN_Fosc / 6000;
- while(--i);
- } while (--ms);
- }
-
- void sys_init(); // 函数声明
-
- void main()
- {
- //—————————————————主程序参数定义———————————————————————————//
-
- u8 i;
-
- //—————————————————主程序参数初始化—————————————————————————//
-
- sys_init(); // 使能USB功能,IO口初始化
- usb_init(); // USB初始化 //调用USB CDC初始化库函数
- EUSB = 1; // 使能USB中断
-
-
-
- EA = 1; // 总中断开
-
-
-
- while (DeviceState != DEVSTATE_CONFIGURED); // 等待USB完成配置
- delay_ms(1000);
-
- OLED_Init();
-
-
- // —————————————————主程序循环开始———————————————————//
- while (1)
- {
-
- // —————————————————以下为USB_CDC串口代码———————————————————//
- delay_ms(2); //延时等待USB稳定
- // // 当硬件接收完成上位机通过串口助手发送数据后,会自动将bUsbOutReady置1
- // // 接收的数据字节数保存在OutNumber变量中,接收的数据保存在UsbOutBuffer缓冲区
- // if (bUsbOutReady)
- // {
- // // 使用USB_SendData库函数可向上位机发送数据,这里的测试代码为将接收数据原样返回
- // // USB_SendData(UsbOutBuffer,OutNumber);
-
- // // ——————在这里写代码,单片机USB_CDC接受到数据后才会执行———————//
-
- // }
-
- // —————————————————此处开始写代码———————————————————//
-
- //—————————————————点亮一颗LED灯———————————————————//
- P40 = 0;
- P60 = 0;
- delay_ms(1000);
-
- //—————————————————点亮一排OLED灯———————————————————//
- OLED_GRAM_Clear(0);
- #if OLED_GRAM_Mode == 0 //0:8*128级缓存
- OLED_GRAM[0][0] = 0xff; // OLED全局缓存
-
- #elif OLED_GRAM_Mode == 1 //1:1024级缓存
- OLED_GRAM[0] = 0xff; // OLED全局缓存
-
- #endif
- OLED_Refresh_Gram();
- delay_ms(1000);
-
- //—————————————————一排OLED灯流水灯———————————————————//
- OLED_GRAM_Clear(0);
- for ( i = 0; i < 8; i++)
- {
- OLED_DrawPoint(0, i, 1);
- OLED_Refresh_Gram();
- OLED_DrawPoint(0, i , 0);
- OLED_Refresh_Gram();
- }
- OLED_GRAM_Clear(0);
- OLED_Refresh_Gram();
- for ( i = 0; i < 8; i++)
- {
- OLED_DrawPoint(0, i, 1);
- OLED_Refresh_Gram();
- }
- delay_ms(1000);
- //—————————————————画线———————————————————//
- OLED_GRAM_Clear(0);
- OLED_DrawPoint(0, 0, 1);
- OLED_DrawLineG_Dot(0, 3, 127, 3, 1, 1); //直线
- OLED_DrawLineG_Dot(33, 5, 78, 27, 1, 1); //斜线
- OLED_DrawLineG_Dot(22, 29, 56, 23, 1, 3); //虚斜线
- OLED_DrawLineG_Dot(0, 63, 63, 0, 1, 1); //斜率为1的斜线
- OLED_DrawLineG_Dot(0, 7, 127, 7, 1, 5);
- OLED_DrawLineG_Dot(0, 9, 127, 9, 1, 9);
- OLED_DrawLineG_Dot(0, 11, 127, 11, 1, 11);
- OLED_DrawLineG_Dot(0, 13, 127, 13, 1, 13);
- for ( i = 0; i < 64; i+=8)
- {
- OLED_DrawLineG_Dot(0, 32, 127, i, 1, 1);
- }
- delay_ms(1000);
- //—————————————————画矩形———————————————————//
- OLED_GRAM_Clear(0);
- for ( i = 0; i < 127; i+=4)
- {
- OLED_DrawFrameG(i, i / 2, 127 - i, 63 - i / 2, 1);
- OLED_Refresh_Gram();
- }
- delay_ms(1000);
- //—————————————————画实心矩形———————————————————//
- OLED_GRAM_Clear(0);
- OLED_DrawBlockG(0, 0, 10, 10, 1);
- OLED_DrawBlockG(30, 20, 70, 40, 1);
- OLED_GRAM_Clear(1);
- OLED_Refresh_Gram();
- OLED_DrawBlockG(30, 22, 70, 57, 0);
- OLED_DrawBlockG(0, 0, 127, 63, 0);
- delay_ms(1000);
- //—————————————————画呼吸矩形———————————————————//
- OLED_GRAM_Clear(0);
- for ( i = 0; i < 10; i++)
- {
- OLED_DrawFrameG(10 + i, 3 + i, 29 - i, 22 - i, 1);
- OLED_Refresh_Gram();
- }
- for ( i = 0; i < 10; i++)
- {
- OLED_DrawFrameG(19 - i, 12 - i, 20 + i, 13 + i, 0);
- OLED_Refresh_Gram();
- }
- for ( i = 0; i < 20; i++)
- {
- OLED_DrawFrameG(50 + i, 10 + i, 89 - i, 49 - i, 1);
- OLED_Refresh_Gram();
- }
- for ( i = 0; i < 20; i++)
- {
- OLED_DrawFrameG(69 - i, 29 - i, 70 + i, 30 + i, 0);
- OLED_Refresh_Gram();
- }
- delay_ms(1000);
- // —————————————————画圆形———————————————————//
- OLED_GRAM_Clear(0);
- OLED_DrawCircleG_Distance(32, 32, 30, 1);
- OLED_DrawCircleG_Bresenham(96, 32, 30, 1);
- delay_ms(1000);
- //—————————————————画实心圆形———————————————————//
- OLED_GRAM_Clear(0);
- OLED_DrawBlockCircleG_Distance(32, 32, 30, 1);
- OLED_DrawBlockCircleG_Bresenham(96, 32, 30, 1);
- delay_ms(1000);
- //—————————————————画呼吸圆形———————————————————//
- OLED_GRAM_Clear(0);
- for ( i = 0; i < 30; i++)
- {
- OLED_DrawCircleG(64, 32, i, 1);
- }
- for ( i = 0; i < 30; i++)
- {
- OLED_DrawCircleG(64, 32, 30-i, 0);
- }
- for ( i = 0; i < 20; i++)
- {
- OLED_DrawCircleG(20, 20, 19-i, 1);
- }
- for ( i = 0; i < 20; i++)
- {
- OLED_DrawCircleG(20, 20, i, 0);
- }
- delay_ms(1000);
- //—————————————————画呼吸椭圆形———————————————————//
- OLED_GRAM_Clear(0);
- OLED_DrawEllipticG(64, 32, 40, 20, 1);
- delay_ms(1000);
- OLED_DrawEllipticG(64, 32, 40, 20, 0);
- for ( i = 0; i < 30; i++)
- {
- OLED_DrawEllipticG(64, 32, 2*i, i, 1);
- }
- for ( i = 0; i < 30; i++)
- {
- OLED_DrawEllipticG(64, 32, 2*(30-i), i, 0);
- }
- delay_ms(1000);
- //—————————————————画圆角矩形———————————————————//
- OLED_GRAM_Clear(0);
- OLED_DrawRoundRectangleG(10, 5, 100, 60, 5, 0, 1);
- OLED_Refresh_Gram();
- delay_ms(1000);
- OLED_DrawRoundRectangleG(10, 5, 100, 60, 5, 1, 1);
- OLED_Refresh_Gram();
- delay_ms(1000);
- OLED_GRAM_Clear(0);
- OLED_DrawRoundRectangleG(10, 5, 100, 60, 12, 0, 1);
- OLED_Refresh_Gram();
- delay_ms(1000);
- OLED_DrawRoundRectangleG(10, 5, 100, 60, 12, 1, 1);
- OLED_Refresh_Gram();
- delay_ms(1000);
- //—————————————————画宽边圆角矩形———————————————————//
- for ( i = 0; i < 10; i++)
- {
- OLED_GRAM_Clear(0);
- OLED_DrawWidthRoundRectangleG(0+i, 0+i, 100-i, 60-i, 10, 1+i, 1);
- OLED_Refresh_Gram();
- delay_ms(1000);
- }
- delay_ms(1000);
- —————————————————画正弦函数———————————————————//
- OLED_GRAM_Clear(1);
- OLED_Refresh_Gram();
- OLED_GRAM_Clear(0);
- OLED_Refresh_Gram();
-
- OLED_ShowString(0, 0, "----SineWave----", 6, 0);
- OLED_ShowString(0, 7, "Rad=", 6, 0);
-
- OLED_ShowChinese(5, 1, 5, 1);
- OLED_ShowChinese(5, 3, 6, 1);
- OLED_ShowChinese(5, 5, 7, 1);
- OLED_ShowChinese(112, 0, 0, 0);
- OLED_ShowChinese(112, 2, 1, 0);
- OLED_ShowChinese(112, 4, 2, 0);
- OLED_ShowChinese(112, 6, 3, 0);
-
-
- while (1)
- {
- OLED_GRAM_Clear(0);
- OLED_DrawLineG_Dot(0, 32, 127, 32, 1, 1);
- OLED_DrawLineG_Dot(62, 0, 62, 63, 1, 1);
- OLED_DrawSin();
- delay_ms(1000);
- }
-
- }
-
- }
-
-
-
- void sys_init()
- {
- WTST = 0; // 设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
- EAXFR = 1; // 扩展寄存器(XFR)访问使能
- CKCON = 0; // 提高访问XRAM速度
-
- P0M1 = 0x30; P0M0 = 0x30; // 设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
- P1M1 = 0x32; P1M0 = 0x32; // 设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
- P2M1 = 0x3c; P2M0 = 0x3c; // 设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
- P3M1 = 0x50; P3M0 = 0x50; // 设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
- P4M1 = 0x3c; P4M0 = 0x3c; // 设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
- P5M1 = 0x0c; P5M0 = 0x0c; // 设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
- P6M1 = 0xff; P6M0 = 0xff; // 设置为漏极开路(实验箱加了上拉电阻到3.3V)
- P7M1 = 0x00; P7M0 = 0x00; // 设置为准双向口
-
- // P0M1 = 0x00; P0M0 = 0x00; //设置为准双向口
- // P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
- // P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
- // P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
- // P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
- // P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
- // P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
- // P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
-
- P3M0&= ~0x03; //P3.0/P3.1和USB的D-/D+共用PIN脚,
- P3M1|= 0x03;
-
- USBCON = 0X00; //USB初始化,断开USB
- USBCLK = 0X00;
- IRC48MCR = 0X00;
- delay_ms(10);
-
- // // 设置USB使用的时钟源
- IRC48MCR = 0x80; // 使能内部48M高速IRC
- while (!(IRC48MCR & 0x01)); // 等待时钟稳定
-
- USBCLK = 0x00; // 使用CDC功能需要使用这两行,HID功能禁用这两行。
- USBCON = 0x90;
- }</b></font>
复制代码
进过测试,两张缓存方式都可以实现。
特别声明:我的时钟频率移动到STC32G.H文字中声明了,大家可根据自身情况修改。
文件包含工程文件和取模工具,大家可自行下载。
取模软件的配置情况:阴码、列行式、逆向
|