四汐 发表于 2024-1-13 13:21:06

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文字中声明了,大家可根据自身情况修改。


文件包含工程文件和取模工具,大家可自行下载。


取模软件的配置情况:阴码、列行式、逆向

四汐 发表于 2024-3-23 23:45:32

库函数-OLED12864-IIC/SPI-索引字库-显示GBK2312-OLEDPrintf-画点线面-OLED中英文显示 https://www.stcaimcu.com/forum.php?mod=viewthread&tid=7410 (出处: 国芯论坛-STC全球32位8051爱好者互助交流社区)
更新了,快去看看!

四汐 发表于 2024-1-13 18:16:20

写帖复制主函数的时候,不小心吧主函数里面“画正弦函数”那里注释双斜线搞没了,大家看看压缩包里面的有没有漏掉,如果出现编译报错,补一下就好了。
还有那个头文件的名称应该“OLED_12864.h”应该是之前整个工程替换的时候按错了一个键{:4_167:}导致全部的错了,不过因为是全部同时替换的,所以不影响使用,强迫症的友友可以替换自己喜欢的名字

大明狐 发表于 2024-1-14 19:51:40

{:4_225:}{:4_225:}{:4_225:}

zhuguoxin8 发表于 2024-1-15 10:42:01

{:4_180:}

芯征程 发表于 2024-1-15 13:47:19

{:4_180:}{:4_174:}

zhang32568 发表于 2024-3-18 17:26:24

正在学习中 非常感谢

xxxevery 发表于 2024-3-18 18:07:16

不错学习了

yinds 发表于 2024-3-20 05:54:51

{:4_174:}

houzi8 发表于 2024-4-27 15:32:40

{:4_174:}学习中...
页: [1] 2
查看完整版本: OLED12824-I2C/SPI协议-0.96寸/1.3寸-画点线面-带ASCII字库