找回密码
 立即注册
查看: 159|回复: 1

库函数-OLED12864-IIC/SPI-索引字库-显示GBK2312-OLEDPrintf-画点线面-OLED中英文显示

[复制链接]
  • TA的每日心情
    奋斗
    昨天 13:40
  • 签到天数: 78 天

    [LV.6]常住居民II

    4

    主题

    44

    回帖

    525

    积分

    高级会员

    积分
    525
    发表于 2024-3-23 23:37:35 | 显示全部楼层 |阅读模式
    本帖最后由 四汐 于 2024-3-23 23:42 编辑

    库函数-OLED12864-IIC/SPI-索引字库-显示GBK2312-OLEDPrintf-画点线面-OLED中英文显示-自动换行显示-兼容0.96/1.3寸屏

    近期,无意间看到官网上的库函数(有时候缘分就是这么巧妙),于是便下载下来看了一下。不看不知道,一看吓一跳!!!

    简言之就是,原本写代码需要配置寄存器的时候,得不断地翻用户手册,看看各种配置需要怎么设置,才可以开始写代码。
    看了库函数之后,发现直接可以使用结构体配置,各种参数配置也是一目了然,实在不理解再翻手册也可以很容易看明白,而且还配有示例程序,结合则看,很快就可以入手。
    看了库函数,对我这种小白而言,真的有很多值得学习的地方,推荐大家也可以看看学习学习。话不多说,贴完我要搞毕设找工作去咯,不然就完蛋了。
    截图202403232258049058.jpg

    言归正传,我曾经在论坛上分享过一篇关于使用IIC/SPI协议驱动OLED12864屏幕的文章。(懒得贴了,时代在进步!)
    现在,我使用库函数重写了一遍驱动函数,伴随着ISP工具新增取模工具,我也更新一些新的显示函数。
    这里以IIC的版本展示吧,留言下载,有问题请留言喔!!


    旧版本演示视频:
    https://www.douyin.com/user/self?modal_id=7321033906550000923&showTab=post
    新增函数演示视频:
    https://www.douyin.com/user/self?modal_id=7345036745228045568&showTab=post

    (本来想试试上传本地视频,结果视频太大了哈哈哈,还是贴连接叭)


    代码附件在这里:
    3_001_OLED12864(官方库函Shu版本).zip (3.96 MB, 下载次数: 20)



    主函数贴上:
    1. //ISP下载时需将工作频率设置在"config.h"文件中
    2. #include "config.h"
    3. #include "sys.h"
    4. //#include "stc32_stc8_usb.h"
    5. #include "gpio_init.h"
    6. #include "oled12864_iic.h"
    7. // char *USER_DEVICEDESC = NULL;
    8. // char *USER_PRODUCTDESC = NULL;
    9. // char *USER_STCISPCMD = "@STCISP#";       //不停电自动ISP下载命令
    10. void main()
    11. {
    12. //—————————————————主程序参数定义———————————————————————————//
    13. //—————————————————主程序参数初始化—————————————————————————//
    14. sys_init(); // 使能USB功能,IO口初始化
    15. // usb_init(); // USB初始化     //调用USB CDC初始化库函数
    16. // EUSB = 1;   // 使能USB中断
    17. EA = 1;     // 总中断开
    18. //while (DeviceState != DEVSTATE_CONFIGURED); // 等待USB完成配置
    19. //delay_ms(1000);
    20. GPIO_config();
    21. OLED_Init();
    22. // —————————————————主程序循环开始———————————————————//
    23. while (1)
    24. {
    25.    
    26.     // —————————————————以下为USB_CDC串口代码———————————————————//
    27.     // delay_ms(2);        //延时等待USB稳定
    28.     // // 当硬件接收完成上位机通过串口助手发送数据后,会自动将bUsbOutReady置1
    29.     // // 接收的数据字节数保存在OutNumber变量中,接收的数据保存在UsbOutBuffer缓冲区
    30.     // if (bUsbOutReady)
    31.     // {
    32.     //     // 使用USB_SendData库函数可向上位机发送数据,这里的测试代码为将接收数据原样返回
    33.     //     USB_SendData(UsbOutBuffer,OutNumber);
    34.     //     //处理完成接收的数据后,调用usb_OUT_done准备接收下一笔数据
    35.         //         usb_OUT_done();  
    36.     //     // ——————在这里写代码,单片机USB_CDC接受到数据后才会执行———————//
    37.         
    38.     // }
    39.     // —————————————————此处开始写代码———————————————————//
    40.     // —————————————————OLED_IIC代码测试———————————————————//
    41.         OLED_Printf(0,0,16,"Welcome to my OLED display program!!!");
    42.     delay_ms(5000);
    43.     OLED_Test_Show();
    44. }
    45. }
    复制代码


    iic.c(部分)贴上:
    1. #include "iic.h"
    2. //------------------------------变量定义------------------------------
    3. //------------------------------函数定义------------------------------
    4. #ifdef Hardware_IIC
    5. /**
    6. * @name IIC_config
    7. * @brief 硬件IIC配置
    8. * @version 版本:v1.0
    9. * @date 日期:2024-3-23
    10. * @author 作者:
    11. * @note 注释:
    12. */
    13. void IIC_Hardware_config()
    14. {
    15.     I2C_InitTypeDef I2C_InitStructure;
    16.     // 作主机设置
    17.     I2C_InitStructure.I2C_Mode      = I2C_Mode_Master;            //主从选择   I2C_Mode_Master, I2C_Mode_Slave
    18.         I2C_InitStructure.I2C_Enable    = ENABLE;                            //I2C功能使能,   ENABLE, DISABLE
    19.         I2C_InitStructure.I2C_MS_WDTA   = DISABLE;                            //主机使能自动发送,  ENABLE, DISABLE
    20.         I2C_InitStructure.I2C_Speed     = 63;                                    //总线速度=Fosc/2/(Speed*2+4),      0~63
    21.         I2C_Init(&I2C_InitStructure);
    22.         NVIC_I2C_Init(I2C_Mode_Master,DISABLE,Priority_0);                //主从模式, I2C_Mode_Master, I2C_Mode_Slave; 中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
    23.     // 作从机设置
    24.     // I2C_InitStructure.I2C_Mode      = I2C_Mode_Slave;                //主从选择   I2C_Mode_Master, I2C_Mode_Slave
    25.         // I2C_InitStructure.I2C_Enable    = ENABLE;                                //I2C功能使能,   ENABLE, DISABLE
    26.         // I2C_InitStructure.I2C_SL_MA     = ENABLE;                                //使能从机地址比较功能,   ENABLE, DISABLE
    27.         // I2C_InitStructure.I2C_SL_ADR    = 0x2d;                                        //从机设备地址,  0~127  (0x2d<<1 = 0x5a)
    28.         // I2C_Init(&I2C_InitStructure);
    29.         // NVIC_I2C_Init(I2C_Mode_Slave,I2C_ESTAI|I2C_ERXI|I2C_ETXI|I2C_ESTOI,Priority_0);        //主从模式, I2C_Mode_Master, I2C_Mode_Slave; 中断使能, I2C_ESTAI/I2C_ERXI/I2C_ETXI/I2C_ESTOI/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
    30.         I2C_SW(I2C_P24_P25);                                        //I2C_P14_P15,I2C_P24_P25,I2C_P76_P77,I2C_P33_P32
    31. }
    32. /**
    33. * @name Wait
    34. * @brief 等待主机模式I2C控制器执行完成I2CMSCR
    35. * @version 版本:v1.0
    36. * @date 日期:2024
    37. * @author 作者:
    38. * @note 注释:
    39. */
    40. void Wait(void)
    41. {
    42.         while (!(I2CMSST & 0x40));
    43.         I2CMSST &= ~0x40;
    44. }
    45. 。。。。。。(中间有点长,省略了)
    46. //---------------------功能函数---------------------
    47. /**
    48. * @name IIC_WriteNbyte
    49. * @brief IIC写入连续的几个字节
    50. * @param slave: 选择哪一个从机的地址
    51. * @param mem_addr: 数据的地址
    52. * @param p: 数据内容,写入数据存储位置
    53. * @param number: 写入几个数据
    54. * @return 无
    55. * @version 版本:v1.0
    56. * @date 日期:2024-3-23
    57. * @author 作者:汐
    58. * @note 注释:DeviceAddress,WordAddress,First Data Address,Byte lenth
    59. */
    60. void IIC_WriteNbyte_Hard(u8 slave, u8 mem_addr, u8 *p, u8 number)
    61. {
    62.         Start();                                //发送起始命令
    63.         SendData(slave);                     //发送设备地址+写命令
    64.         RecvACK();
    65.         SendData(mem_addr);                     //发送存储地址
    66.         RecvACK();
    67.         do
    68.         {
    69.                 SendData(*p++);
    70.                 RecvACK();
    71.         }
    72.         while(--number);
    73.         Stop();   
    74. }
    75. /**
    76. * @name IIC_ReadNbyte
    77. * @brief IIC读取连续的几个字节
    78. * @param slave: 选择哪一个从机的地址
    79. * @param mem_addr: 要读的数据的地址
    80. * @param p: 数据,取数据存储位置
    81. * @param number: 写入几个数据
    82. * @return
    83. * @version 版本:v1.0
    84. * @date 日期:2024-3-23
    85. * @author 作者:汐
    86. * @note 注释:发送开始命令->发送器件地址(写)->发送数据地址->发送开始命令->发送器件地址(读)->读数据
    87. * DeviceAddress,WordAddress,First Data Address,Byte lenth
    88. */
    89. void IIC_ReadNbyte_Hard(u8 slave, u8 mem_addr, u8 *p, u8 number)
    90. {
    91.         Start();                                //发送起始命令
    92.         SendData(slave);                     //发送设备地址+写命令
    93.         RecvACK();
    94.         SendData(mem_addr);                     //发送存储地址
    95.         RecvACK();
    96.         Start();                                //发送起始命令
    97.         SendData(slave|1);                   //发送设备地址+读命令
    98.         RecvACK();
    99.         do
    100.         {
    101.                 *p = RecvData();
    102.                 p++;
    103.                 if(number != 1) SendACK();          //send ACK
    104.         }
    105.         while(--number);
    106.         SendNAK();                              //send no ACK        
    107.         Stop();                                 //发送停止命令
    108. }
    109. #endif
    110. #ifdef Software_IIC
    111. /**
    112. * @name IIC_Software_config
    113. * @brief 软件IIC设置配置
    114. * @version 版本:v1.0
    115. * @date 日期:2024
    116. * @author 作者:
    117. * @note 注释:
    118. */
    119. void IIC_Software_config()
    120. {
    121.         #if     IIC_PIN == 0        //4P
    122.     SCL = 1;
    123.     SDA = 1;
    124.     #elif   IIC_PIN == 1        //7P
    125.     SCL = 1;
    126.     SDA = 1;
    127.     RES = 1;
    128.     DC = 0;
    129.     CS = 0;
    130.     #endif
    131. }
    复制代码


    iic.h贴上:
    1. #ifndef __IIC_H_
    2. #define __IIC_H_
    3. #include "config.h"
    4. #include "STC32G_I2C.h"
    5. #include "STC32G_NVIC.h"
    6. #include "STC32G_Switch.h"
    7. #define IIC_MODE 0          // 0: 软件IIC 1:硬件IIC
    8. #define IIC_PIN  0          // 0:四针IIC  1:七针IIC(OLED)
    9. //#define Hardware_IIC        // 硬件IIC开关
    10. #define Software_IIC        // 软件IIC开关
    11. //------------------------------引脚定义------------------------------
    12. #ifdef Software_IIC
    13. #if     IIC_PIN == 0
    14. #define SCL P25         //时钟线
    15. #define SDA P24         //数据线
    16. #elif   IIC_PIN == 1
    17. #define SCL P25
    18. #define SDA P24
    19. #define RES P23
    20. #define DC  P34
    21. #define CS  P11
    22. #endif
    23. #endif
    24. //------------------------------变量声明------------------------------
    25. // typedef struct
    26. // {
    27. //         u8        IIC_SDA;                                // IIC数据线
    28. //         u8        IIC_SCL;                                // IIC时钟线
    29. // } IIC_Soft_InitTypeDef;
    30. //------------------------------函数声明------------------------------
    31. #ifdef Hardware_IIC
    32. void IIC_Hardware_config();
    33. void IIC_WriteNbyte_Hard(u8 slave, u8 mem_addr, u8 *p, u8 number);
    34. void IIC_ReadNbyte_Hard(u8 slave, u8 mem_addr, u8 *p, u8 number);
    35. #endif
    36. #ifdef Software_IIC
    37. void IIC_Software_config();
    38. void IIC_WriteNbyte_Soft(u8 dev_addr, u8 mem_addr, u8 *p, u8 number);
    39. void IIC_ReadNbyte_Soft(u8 dev_addr, u8 mem_addr, u8 *p, u8 number);
    40. #endif
    41. #endif
    复制代码


    oled12864_iic.c贴上:
    1. 额。。。算了这个真的超级长,就贴新增的函数吧。
    复制代码
    不知道为什么贴不上来,这样子贴试试

    oled12864_iic.h贴上:
    1. #ifndef __OLED12864_IIC_H_
    2. #define __OLED12864_IIC_H_
    3. #include "config.h"
    4. #include "iic.h"
    5. /*选择OLED的尺寸
    6.     0:0.96寸4P/7P
    7.     1:1.30寸4P
    8. */
    9. #define OLED_SIZE   1               
    10. #define OLED_GRAM_Mode 1            //0:8*128级缓存 1:1024级缓存 2:指令模式
    11. //------------------------------变量声明------------------------------
    12. #define SLAVE_OLED_12864    0X78    //128*64_OLED屏幕IIC地址
    13. #define OLED_WriteCom_Addr        0x00        //从机写指令地址
    14. #define OLED_WriteData_Addr        0x40        //从机写数据地址
    15. #define OLED_CMD  0        //写命令
    16. #define OLED_DATA 1        //写数据
    17. #define Max_Column                        128
    18. #define Max_Row                                64
    19. #define        Brightness                        0xFF    //亮度0~255
    20. extern char xdata WaveData[128];
    21. #if     OLED_GRAM_Mode == 0             //0:8*128级缓存
    22.     extern u8 OLED_GRAM[8][128];         // OLED全局缓存
    23. #elif   OLED_GRAM_Mode == 1             //1:1024级缓存
    24.     extern u8 OLED_GRAM[1024];           // OLED全局缓存
    25. #else                                   //2:指令模式
    26. #endif
    27. //------------------------------引脚定义------------------------------
    28. //------------------------------函数声明------------------------------
    29. void OLED_Write_Byte(u8 dat, u8 cmd);               // 写入一个字节
    30. void OLED_Init(void);                               // 初始化OLED
    31. void OLED_Set_Pos(u8 x, u8 y);                      // OLED设置显示位置
    32. void OLED_Display_On(void);                         // 开启OLED显示
    33. void OLED_Display_Off(void);                        // 关闭OLED显示
    34. void OLED_LightSet(u8 num);                         // 亮度设置
    35. void OLED_Clear(bit mode);                          // 清屏函数
    36. #if     OLED_GRAM_Mode == 0 || OLED_GRAM_Mode == 1           //0:8*128级缓存//1:1024级缓存
    37. // #elif   OLED_GRAM_Mode == 1            
    38.     void OLED_GRAM_Clear(bit mode);                                         // 通过缓冲数组,OLED屏幕全亮全灭
    39.     void OLED_Refresh_Gram(void);                                           // OLED刷新显示
    40.     void OLED_RefreshPart_Gram(u8 xstart, u8 ystart, u8 width, u8 height);  // OLED局部刷新显示
    41.     void OLED_DrawPoint(u8 x, u8 y, bit mode);                              // OLED画一个点,0:熄灭 1:点亮
    42.     void OLED_FourPoints(u8 x0, u8 y0, bit mode);                           // 4个像素点为一组,控制亮灭
    43.     void OLED_Mask_Gray(u8 x0, u8 y0, u8 BMP[], bit mode);                  // 蒙版函数,衍生于OLED_FourPoints函数
    44.     // void OLED_DrawLineG(u8 x1, u8 y1, u8 x2, u8 y2, bit mode);              // OLED画一条线,0:熄灭 1:点亮
    45.     void OLED_DrawLineG_Dot(u8 x1, u8 y1, u8 x2, u8 y2, bit mode, u8 dot);  // OLED画一条虚实线,0:熄灭 1:点亮
    46.     // void OLED_DrawRectangleG(u8 x1, u8 y1, u8 x2, u8 y2, bit mode);         // OLED画一个矩形
    47.     void OLED_DrawFrameG(u8 x0, u8 y0, u8 x1, u8 y1, bit mode);             // OLED画一个方框
    48.     void OLED_DrawBlockG(u8 x0, u8 y0, u8 x1, u8 y1, bit mode);             // OLED画一个实心框
    49.     void OLED_DrawBox(u8 x0, u8 y0, u8 x1, u8 y1, u8 fill, bit mode);       // OLED画空实心矩形
    50.     void OLED_DrawCircleG(u8 x, u8 y, u8 r, bit mode);                      // OLED画一个圆形
    51.     void OLED_DrawEllipticG(u8 x0, u8 y0, u8 R1, u8 R2, bit mode);          // OLED画一个椭圆形
    52.     void OLED_DrawCircleG_Distance(u8 x0, u8 y0, u8 R, bit mode);           // OLED画一个圆形(勾股定理法)
    53.     void OLED_DrawBlockCircleG_Distance(u8 x0, u8 y0, u8 R, bit mode);      // OLED画一个实心圆形(勾股定理法)
    54.     void OLED_DrawCircleG_Bresenham(u8 x, u8 y, u8 r, bit mode);            // OLED画一个圆形(Bresenham法)
    55.     void OLED_DrawBlockCircleG_Bresenham(u8 x, u8 y, u8 r, bit mode);       // OLED画一个实心圆形(Bresenham法)
    56.     void OLED_DrawRoundRectangleG(u8 x0, u8 y0, u8 x1, u8 y1, u8 R, u8 fill, bit mode);       // OLED画一个圆角矩形(Bresenham法)
    57.     void OLED_DrawWidthRoundRectangleG(u8 x0, u8 y0, u8 x1, u8 y1, u8 R, u8 width, bit mode); // OLED画一个宽边圆角矩形(Bresenham法)
    58.     void OLED_DrawSin();                                                        // 画正弦函数
    59.     void ButtonWave();                                                          // 按键控制显示方波
    60.     void OLED_ShowCharG(u8 x, u8 y, u8 chr, u8 charSize, u8 Is_Reverse);        // 缓存显示一个字符
    61.     void OLED_ShowStringG(u8 x, u8 y, char *chr, u8 charSize, u8 Is_Reverse);   // 缓存显示一个字符号串
    62.     void OLED_ShowNumG(u8 x, u8 y, u32 num, u8 len, u8 Size, u8 Is_Reverse);    // 缓存显示一串数字
    63.     void OLED_ShowChineseG(u8 x, u8 y, u8 no, u8 Is_Reverse);                   // 缓存显示汉字
    64.     void OLED_ShowBMPG(u8 x0, u8 y0, u8 x1, u8 y1, u8 BMP[], u8 Is_Reverse);    // 缓存显示BMP图片
    65. #else                                   //2:指令模式
    66. #endif
    67.     void OLED_ShowChar(u8 x, u8 y, u8 chr, u8 charSize, u8 Is_Reverse);         // 早指定位置显示一个字符
    68.     void OLED_ShowString(u8 x, u8 y, char *chr, u8 charSize, u8 Is_Reverse);    // 显示一个字符号串
    69.     u32  OLED_Index(u8 m, u8 n);                                                // m^n函数
    70.     void OLED_ShowNum(u8 x, u8 y, u32 num, u8 len, u8 Size, u8 Is_Reverse);     // 显示一串数字
    71.     void OLED_ShowChinese(u8 x, u8 y, u8 no, u8 Is_Reverse);                    // 显示汉字
    72.     void OLED_ShowBMP(u8 x0, u8 y0, u8 x1, u8 y1, u8 BMP[], u8 Is_Reverse);     // 显示BMP图片
    73.     void OLED_ShowGBK2312(u8 x, u8 y, char *GBK, u8 Is_Reverse);                  // 显示一个汉字
    74.     void OLED_Showstr_CN_EN(u8 x, u8 y, char *str, u8 Is_Reverse);                // 显示一串中英文
    75.     void OLED_Printf(u8 x, u8 y, u8 Size, char *format, ...);
    76. void OLED_Test_Show();
    77. #endif
    复制代码


    ———————————————————————人家是有底线的!!!!!—————————————————————————

    回复 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    昨天 13:40
  • 签到天数: 78 天

    [LV.6]常住居民II

    4

    主题

    44

    回帖

    525

    积分

    高级会员

    积分
    525
     楼主| 发表于 2024-3-23 23:43:04 | 显示全部楼层
    算了,贴在这里吧

    void OLED_Showstr_CN_EN(u8 x, u8 y, char *str, u8 Is_Reverse)    //显示一串中英文
    {
        u8 pGBK = 0;
        u8 pIndex;
        u8 xdata i, j, k = 0;
        u8 SingleChinese[OLED_CHN_CHAR_WIDTH + 1] = {0};
        u8 px = x + k;

        for (i = 0; str != '\0'; i++)
        {
            if ( (str < 127) && (str >= ' ') )
            {
                OLED_ShowChar(px, y, str, 16, Is_Reverse);
                px += 8;
                // 自动换行
                if (px > 120)
                {
                    px = 0;
                    y = y + 2;
                    delay_oled_ms(500);
                    if (y > 7)
                    {
                        y = 0;
                    }
                }
            }
            else
            {
                SingleChinese[pGBK] = str;           // 提取汉字串数据到单个汉字数组
                pGBK++;                                 // 计次自增

                /*当提取次数到达汉字长度时,即代表提取到了一个完整的汉字*/
                if (pGBK >= OLED_CHN_CHAR_WIDTH)
                {
                    pGBK = 0;       // 计次归零

                    /*遍历整个汉字字模库,寻找匹配的汉字*/
                    /*如果找到最后一个汉字(定义为空字符串),则表示汉字未在字模库定义,停止寻找*/
                    for ( pIndex = 0; strcmp(Font_Data[pIndex].txt, "") != 0; pIndex++)
                    {
                        /*找到匹配的汉字*/
                        if (strcmp(Font_Data[pIndex].txt, SingleChinese) == 0)
                        {
                            break;                //跳出循环,此时pIndex的值为指定汉字的索引
                        }
                    }

                    /*将汉字字模库OLED_CF16x16的指定数据以16*16的图像格式显示*/
                    OLED_Set_Pos((u8)(px), y); // 汉字上半部分坐标(第x列,第y行)
                    for (j = 0; j < 16; j++)
                    {
                        OLED_Write_Byte(Is_Reverse == 0 ? Font_Data[pIndex].dat[j] : ~Font_Data[pIndex].dat[j], OLED_DATA);
                    }
                    OLED_Set_Pos((u8)(px), (u8)(y + 1));   // 汉字下半部分坐标(第x列,第y+1行)
                    for (j = 0; j < 16; j++)
                    {
                        OLED_Write_Byte(Is_Reverse == 0 ? Font_Data[pIndex].dat[16 + j] : ~Font_Data[pIndex].dat[16 + j], OLED_DATA);
                    }

                    // 自动换行
                    px += 16;
                    if ( (px) > 112)     
                    {
                        px = 0;
                        y = y + 2;
                        delay_oled_ms(500);
                        if (y > 7)
                        {
                            y = 0;
                        }
                    }
                }
            }
        }
    }

    void OLED_Printf(u8 x, u8 y, u8 Size, char *format, ...)
    {
        char String[100];                                                //定义字符数组
            va_list arg;                                                        //定义可变参数列表数据类型的变量arg
            va_start(arg, format);                                        //从format开始,接收参数列表到arg变量
            vsprintf(String, format, arg);                        //使用vsprintf打印格式化字符串和参数列表到字符数组中
            va_end(arg);                                                        //结束变量arg
            OLED_ShowString(x, y, String, Size , 0);//OLED显示字符数组(字符串)
    }
    2 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
    回复 支持 2 反对 0 送花

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-5-2 10:28 , Processed in 0.063030 second(s), 36 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表