OLED12824-I2C/SPI协议-0.96寸/1.3寸-画点线面-带ASCII字库
STC32G--OLED12864--I2C/SPI协议===兼容0.96(I2C/SPI)/1.3寸(I2C)===绘制点线面--带ASCII字库函数是我参考网络上大部分0.96寸OLED的资料,学习改编而来,I2C协议是通过冲哥视频学习的,特别是B站上“大明狐”老师的教学视频(十分推荐去看看,讲的很清晰易懂),对我理解OLED屏幕提供了很大的启示帮助。目前包含了8*128级缓存和1024级缓存绘制图形以及显示文字的部分(包含点、虚线、实线、矩形、圆形等等),还有通过指令写数据的方式直接显示文字的函数。
演示视频二选一:
https://v.douyin.com/iLM8nR6g/
https://www.douyin.com/video/7321033906550000923
今天刚好有空,画了一点点时间,把SPI的也搞了一下,目前发现SPI绘制的速度比IIC的快好多喔!!IIC我用STC32G实验箱测试的,SPI我用的屠龙刀测试的。IIC协议使用的引脚(实验箱)SPI使用的引脚(屠龙刀)
#ifndef __IIC_H_
#define __IIC_H_
#include "stc32g.h"
#include "stc32_stc8_usb.h"
#define IIC_MODE 1 //0:软件IIC1:硬件IIC(仅4脚)
#define IIC_PIN 0 //0:四针IIC1:七针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 DCP34
#define CSP11
// #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_CMD0 //写命令
#define OLED_DATA 1 //写数据
#define Max_Column 128
#define Max_Row 64
#define Brightness 0xFF //亮度0~255
extern char xdata WaveData;
#if OLED_GRAM_Mode == 0 //0:8*128级缓存
extern u8 OLED_GRAM; // OLED全局缓存
#elif OLED_GRAM_Mode == 1 //1:1024级缓存
extern u8 OLED_GRAM; // 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); // 显示一个字符号串
u32OLED_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"
// #defineMAIN_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 = 0xff; // OLED全局缓存
#elif OLED_GRAM_Mode == 1 //1:1024级缓存
OLED_GRAM = 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文字中声明了,大家可根据自身情况修改。
文件包含工程文件和取模工具,大家可自行下载。
取模软件的配置情况:阴码、列行式、逆向
库函数-OLED12864-IIC/SPI-索引字库-显示GBK2312-OLEDPrintf-画点线面-OLED中英文显示 https://www.stcaimcu.com/forum.php?mod=viewthread&tid=7410 (出处: 国芯论坛-STC全球32位8051爱好者互助交流社区)
更新了,快去看看! 写帖复制主函数的时候,不小心吧主函数里面“画正弦函数”那里注释双斜线搞没了,大家看看压缩包里面的有没有漏掉,如果出现编译报错,补一下就好了。
还有那个头文件的名称应该“OLED_12864.h”应该是之前整个工程替换的时候按错了一个键{:4_167:}导致全部的错了,不过因为是全部同时替换的,所以不影响使用,强迫症的友友可以替换自己喜欢的名字 {:4_225:}{:4_225:}{:4_225:}
{:4_180:} {:4_180:}{:4_174:}
正在学习中 非常感谢 不错学习了 {:4_174:} {:4_174:}学习中...
页:
[1]
2