找回密码
 立即注册
楼主: 浦江***

新手学用STC32G12K128, 实践与思考(都是干货,盖楼砖瓦,实用基础)

[复制链接]
  • TA的每日心情
    开心
    1 小时前
  • 签到天数: 148 天

    [LV.7]常住居民III

    5

    主题

    97

    回帖

    672

    积分

    高级会员

    积分
    672
     楼主| 发表于 2023-10-30 10:44:26 | 显示全部楼层
    关于LCD1602显示屏的两个文件:



    /******************************************************************************
    * 文件: 头文件 LCD1602.H
    * 说明: 关于LCD1602的驱动函数: 用于STC32G12K128 自制实验板
    * 编程: 浦晓明(浦江一水) 2023.10
    * 特点: 经典实用/简明扼要/便于移植
    * 接口: 数据口-P0 指令-P4.5 读写-P2.7 使能-P2.6
    ***************************************************************************** */

    #include "STC32G.h"

    #ifndef __LCD1602_H_
    #define __LCD1602_H_

    /*****************************************
      LCD1602PIN口定义 (数据口和控制位说明)
    ******************************************/
    #define LCD_DATAP     P0     //P0数据口(8位)

    sbit LCD_RS =P4^5;            //指令端 0:命令 1:数据
    sbit LCD_RW=P2^7;           //读写端 0;写入 1:读出(直接接地--只写方式)
    sbit LCD_E   =P2^6;            //使能端 0:失能 1:使能

    /*****************************************
      函数声明
    ******************************************/
    /*在11.0592MHz时钟下的延时1ms毫秒函数*/
    void LCD_Delay1ms(unsigned int ms);  //误差 0us
    /*LCD1602初始化子程序*/               
    void LCD_Init(void);
    /*LCD1602 清屏函数 */
    void LCD_CLS(void);                                                  
    /*LCD1602写入8位命令子函数*/
    void LCD_COM(unsigned char com);
    /*LCD1602写入8位数据子函数*/       
    void LCD_DAT(unsigned char dat);
    /*LCD1602指定坐标写字符串函数 X:行(0/1) Y:列(0-15) */       
    void LCD_STR(unsigned char X,unsigned char Y,unsigned char * str);
    void LCD_SetXY(unsigned char,unsigned char);  //定位
    void LCD_Cursor(unsigned char mode); //控制光标
    void LCD_Blink(unsigned char mode);    //控制闪烁       

    #endif




    /******************************************************************************
    * 文件: LCD1602.C
    * 说明: 关于LCD1602驱动函数的实现: 用于STC32G12K128 自制实验板
    * 编程: 浦晓明(浦江一水) 2023.10
    * 特点: 经典实用/简明扼要/便于移植
    * 接口: 数据口-P0 指令-P4.5 读写-P2.7 使能-P2.6
    ***************************************************************************** */

    #include "LCD1602.H"

    /*******************************************************************************
    * 函 数 名         : LCD1602_Delay1ms
    * 函数功能         : 延时函数,延时1ms
    * 输    入         : 无
    * 输    出         : 无
    * 说    名         : 该函数是在11.0592MHZ晶振下,12分频单片机的延时。//误差 0us
    *******************************************************************************/
    void Delay1ms()         //@11.0592MHz
    { unsigned char i, j;
      i = 15; j = 90;
      do { while (--j); } while (--i);
    }

    void LCD_Delay1ms(unsigned int ms)   
    { for (; ms>0; ms--)Delay1ms(); }

    /*******************************************************************************
    * 函 数 名         : LCD1602_COM(unsigned char com)
    * 函数功能         : 向LCD写入一个字节的命令
    * 输    入         : com
    * 输    出         : 无
    *******************************************************************************/
    void LCD_COM(unsigned char com)   //八位/四位数据口写入共用
    {
      LCD_E = 0; Delay1ms();  
      LCD_RW= 0; Delay1ms();    //选择写入
      LCD_RS= 0; Delay1ms();    //选择发送命令
      LCD_E = 0; Delay1ms();    //使能
      LCD_DATAP= com; LCD_Delay1ms(2); //先发送命令字节高四位
      LCD_E = 1; Delay1ms();    //写入时序(脉冲)
      LCD_E = 0; Delay1ms();  
    }
    /*******************************************************************************
    * 函 数 名         : LCD1602_DAT(unsigned char dat);
    * 函数功能         : 向LCD写入一个字节的数据
    * 输    入         : dat
    * 输    出         : 无
    *******************************************************************************/      
    void LCD_DAT(unsigned char dat)    //写入数据
    {
      LCD_E = 0; Delay1ms();  
      LCD_RW= 0; Delay1ms();  //选择写入
      LCD_RS= 1; Delay1ms();  //选择输入数据
      LCD_E = 0; Delay1ms();  //清零使能
      LCD_DATAP= dat; LCD_Delay1ms(2); //先发送数据字节高四位
      LCD_E = 1; Delay1ms();  //写入时序(脉冲)
      LCD_E = 0; Delay1ms();
    }
    /*******************************************************************************
    * 函 数 名       : LCD1602_Init(void)
    * 函数功能       : 初始化LCD屏
    * 输    入       : 无
    * 输    出       : 无
    *******************************************************************************/      
    void LCD_Init(void)   //LCD初始化子程序
    {
      LCD_COM(0x38);   //开显示
      LCD_COM(0x38);   //开显示
      LCD_COM(0x0C);   //开显示不显示光标
      LCD_COM(0x06);   //写一个指针加1
      LCD_COM(0x01);   //清屏
      LCD_COM(0x80);   //设置数据指针起点
    }
    /*******************************************************************************
    * 函 数 名       : LCD1602_CLS(void)
    * 函数功能       : 清屏
    *******************************************************************************/      
    void LCD_CLS(void)
    {
      LCD_COM(0x01);   //清屏
      LCD_COM(0x80);   //设置数据指针起点
    }
    /*LCD1602写入字符串函数*/
    //指定坐标函数 ( X:行[0-1] Y:列[0-15] )
    void LCD_STR(unsigned char X,unsigned char Y,unsigned char * str)

    { unsigned char i = 0;
      LCD_COM(0x80+X*0x40+Y);
      while(str[i]!= 0x0)LCD_DAT(str[i++]);
    }
    //设定坐标函数 ( X:行[0-1] Y:列[0-15] )
    void LCD_SetXY(unsigned char X,unsigned char Y)
    {
      if(X==0)LCD_COM(Y+0x80);
      if(X==1)LCD_COM(Y+0xC0);
    }
    //LCD定位显示光标函数 mode=0:光标关闭 mode=1:光标显示
    void LCD_Cursor(unsigned char mode)       
    {
      if(mode==0)LCD_COM(0x0C);  
      if(mode==1)LCD_COM(0x0E);  
    }
    //LCD定位显示光标函数 mode=0:关闭闪动 mode=1:开启闪动
    void LCD_Blink(unsigned char mode)       
    {
      if(mode==0)LCD_COM(0x0C);  
      if(mode==1)LCD_COM(0x0D);
    }   
    //*** END ****************************************************************************


    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    1 小时前
  • 签到天数: 148 天

    [LV.7]常住居民III

    5

    主题

    97

    回帖

    672

    积分

    高级会员

    积分
    672
     楼主| 发表于 2023-11-1 13:17:59 | 显示全部楼层

    上面使用STC32G做实验键盘、LCD1602显示驱动以及串口通信的同时, 已经将LCD1602做成了一个简单的“智能串口屏”了, 由此也引发一个思考。。。

    关于LCD1602的驱动转接板的思考:


    众所周知, LCD1602显示屏是一种经典而简单的显示设备, 几乎所有C51单片机学习开发板,都将它作为基本的外设配置, 或者加上对LCD1602的接口.
    然而,驱动LCD1602需要8位数据 口,3位控制口, 共11位IO口,占用IO口比较多, 就算是采用四线制数据口方式, 也要占用7位IO口.
    那么能不能占用较少的比如2位IO口来驱动呢? 答案是有的。

    市面有一种被称之为“LCD1602_IIC驱动转接板”, 就是通过Vcc,GND,SCL,SDA一共四线, 实际是2根数据线,2根电源线.
    如图所示.....

    话说LCD1602_IIC转接板.jpg


    我原以为这个方案是可以用最少的接口、更方便地驱动LCD1602了, 于是就买了一套来学习实验了。
    如图所示....
    IIC_LCD1602转接板.jpg


    但是, 实验结果却令我大失所望.....

    原来这个方案是通过一片PCF8574串转并的芯片, 用IIC数据通讯的方式, 模拟LCD1602的控制时序,来达到对LCD1602的8位数据口和3位控制口的控制驱动的.  
    从硬件经济成本方面来说,LCD1602 ,RMB > 3.5元, 转接板 > RMB 5元,(还不算运费...),并不便宜....
    从编程软件上来说,  要驱动LCD6102的话, 就要编程用IIC的通讯方式语句,来模拟实现原来的8位数据口和3位控制口的控制时序, 完全是隔山打牛, 编程复杂,语句逻辑变得很古怪, 语言效率非常低下, 移植麻烦....

    而如果使用STC单片机(小封装的芯片)来做这个"转接板"的话, 无论是从硬件成本还是从软件编程来说, 都是大大胜出的了...
    在STC单片机小电路板方面, 只要连接LCD1602的原来接口,按原来的LCD1602驱动接口时序编程,
    再增加一个简单的串口通讯协议, 将串口指令(自定义)转换为LCD1602显示指令, 就能实现对LCD1602的全面控制。
    这是充分利用了STC单片机外围元件少而功能强大的特点, 实现最少的接口、最低的成本、最简便的语句来驱动LCD1602显示屏。转接板同样可以做的很小,经济成本更低.
    从理论上讲, 对于常用的128*64,320*240等小面积单色或彩色显示屏, 都可以做成“智能串口屏”。这一点应该引起开发“IIC转接板”的开发者和经销商的注意了。

    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    1 小时前
  • 签到天数: 148 天

    [LV.7]常住居民III

    5

    主题

    97

    回帖

    672

    积分

    高级会员

    积分
    672
     楼主| 发表于 2023-11-3 21:07:23 | 显示全部楼层

    学用STC32G12K128的实践和思考在继续进行中……

    实验IIC单色OLED显示屏

    人们总是希望用最少的IO、最简单的接口来控制最基本的输出设备、控制使用显示屏。我当然也是这样想的。

    市面上有一种四针接口的单色显示屏,除了电源线以外,只用两根IO口即可驱动,一共是四根线。那就是淘宝上看到的,0.96寸的IIC接口的OLED显示屏。如图。。。
    0.96寸4针接口OLED屏.jpg
    这种显示屏,屏幕显示面积很小,实际应用到项目中去的可能性较小,但是分辨率128*64比较常用,倒是用做单片机学习,实验显示屏编程是比较经济实惠的,价格便宜,仅RMB 7.4元,就淘了一块来做实验。
    在自制的实验板中,原先LCD1602接口,最末尾四个引脚是:D6,D7,A+,K-,这块显示屏引脚是GND、VCC,SCL、SDA 。 倒过来插入, 正好,无需做任何改动,即可实验。
    为此,编写了一段简单的程序,点亮了显示屏。实现了STC32G12K128对OLED单色128*64显示屏的控制输出。如图所示……
    STC32G-实验IIC单色显示屏0.jpg

    在这个实践过程中,学习编程两线IIC协议的通讯,实现了部分简单的显示功能:6*8点阵西文字符串显示、8*16点阵西文字符串显示、16点阵中西文混合显示。

    源代码稍后整理贴出…… 供有兴趣的同学们参考……

    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    1 小时前
  • 签到天数: 148 天

    [LV.7]常住居民III

    5

    主题

    97

    回帖

    672

    积分

    高级会员

    积分
    672
     楼主| 发表于 2023-11-3 21:50:58 | 显示全部楼层
    主程序


    //========================================================================
    // 实验STC32G驱动OLED单色显示屏(128*64)。。。
    // MCU:  STC32G12K128 4KEY 实验板
    // 特点: 中西文混合显示,增强源码可读性...
    // 编程: 浦晓明(浦江一水) 2023-10 ...
    //=====================================================


    #include <STC32G.H>
    #include <stdio.h>
    #include <string.h>
    #include "OLED_IIC.h"


    //延时函数...//@11.0592MHz
    void Delayms(unsigned int xms)
    { unsigned long i;
      while(xms--)
      { _nop_(); _nop_();
        i = 2763UL;
        while (i) i--;
      }
    }
    //主程序入口
    void main()
    {
        EAXFR = 1;     //这里使能XFR
        CKCON = 0x00;  //设置外部数据总线时钟速度最快
        WTST  = 0x00;  //这里是CPU等待每条指令的时间
           
         P2M1 = 0x00;
         P2M0 = 0x00;


         OLED_Init();          //显示屏初始化
         OLED_ON();          //开显示
         OLED_CLS();         //清屏
         OLED_A8(6,0,"-* TestOLED_IIC *-",18);
         OLED_A8(0,1,"--------------------",20);
         OLED_P16(20,2,"STC-单片机");     //中西文混合编写,增强源码可读性...
         OLED_A8(30,4, "2023-10-17",10);
         OLED_A8(30,5,"----------",10);
         OLED_A16(12,6,"PuXiaoMingOK!",13);
      
        while(1)
        { //LED指示程序正在运行中...
           P20=0;P21=0;P22=0;P23=0;
           Delayms(100);
           P20=1;P21=1;P22=1;P23=1;
          Delayms(900);
        }
    }


    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    1 小时前
  • 签到天数: 148 天

    [LV.7]常住居民III

    5

    主题

    97

    回帖

    672

    积分

    高级会员

    积分
    672
     楼主| 发表于 2023-11-3 21:57:03 | 显示全部楼层
    OLED显示屏驱动头文件

    //=====================================================
    // 文件: OLED_IIC.H
    // 功能: OLED_IIC 4针接口单色显示屏 驱动程序
    // MCU:  STC32G12K128 4KEY 实验板
    // 接口: P0.7 -- SCL 时钟   P0.6 -- SDA 数据
    // 整理: 浦晓明(浦江一水) 2023-10 ...
    //=====================================================
    #ifndef _OLED_IIC_H
    #define _OLED_IIC_H

    #include "STC32G.H"                //基于: STC32G系列

    //根据实验电路板实际情况定义端口...
    //同时 在这里通过宏定义体现IIC协议的相关端口电平状态变化   */
    #define IIC_SDA_H         P06=1     //数据端高电平
    #define IIC_SDA_L          P06=0     //数据端低电平
    #define IIC_SCL_H          P07=1     //时钟端高电平
    #define IIC_SCL_L           P07=0     //时钟端低电平
    #define IIC_SDA_READ        P06       //读数据端电平

    void OLED_Init(void);             //OLED初始化
    void OLED_ON(void);             //开显示
    void OLED_OFF(void);            //关显示

    void OLED_CLS(void);            //清除屏幕
    void OLED_SetXY(unsigned char X,unsigned char Y);                                                       //定位坐标 X:水平列(0..127) Y:垂直行(0..7)
    void OLED_A8( unsigned char X,unsigned char Y,unsigned char *str,unsigned char len);  //显示6*8点阵ASCII字符串
    void OLED_A16(unsigned char X,unsigned char Y,unsigned char *str,unsigned char len); //显示8*16点阵ASCII字符串
    void OLED_P16(unsigned char X,unsigned char Y,unsigned char *str);                             //中西文混合显示16点阵汉字和8*16点阵ASC字符串

    #endif


    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    1 小时前
  • 签到天数: 148 天

    [LV.7]常住居民III

    5

    主题

    97

    回帖

    672

    积分

    高级会员

    积分
    672
     楼主| 发表于 2023-11-3 22:02:27 | 显示全部楼层
    本帖最后由 浦江一水 于 2023-11-3 22:04 编辑

    OLED驱动函数的具体实现....

    //=====================================================
    // 文件:  OLED_IIC.C  4针接口单色显示屏 驱动程序
    // MCU:  STC32G12K128 4KEY 实验板
    // 接口: P0.7 -- SCK 时钟   P0.6 -- SDA 数据
    // 编程整理: 浦晓明(浦江一水) 2023-10 ...
    //=====================================================
    #include <STC32G.H>
    #include <stdio.h>
    #include <string.h>
    #include "OLED_IIC.H"
    #include "OLED_Font.H"        //字库:包括ASCII字符和汉字

    //延时函数...//@11.0592MHz
    void Delay_ms(unsigned int xms)
    { unsigned long i;
      while(xms--)
      { _nop_(); _nop_();
        i = 2763UL;
        while (i) i--;
      }
    }
    //==关于IIC内部基础函数=========
    // IIC 初始化,把2条端口电平拉高(为总线释放状态)
    void IIC_Init(void)  
    {
        P0M1 = 0x00;  P0M0 = 0x00;
        IIC_SDA_H;  IIC_SCL_H; _nop_();_nop_();_nop_();_nop_();
    }
    //开始信号函数 //开始条件: 时钟端高电平时,数据端下降沿跳变.
    void IIC_Start(void)
    {
        IIC_SDA_H;  _nop_();_nop_();_nop_();_nop_();_nop_();
        IIC_SCL_H;  _nop_();_nop_();_nop_();_nop_();_nop_();
        IIC_SDA_L;  _nop_();_nop_();_nop_();_nop_();_nop_();
        IIC_SCL_L;  //开始后时钟端保持低电平....
    }
    //结束信号函数
    //结束条件: 时钟端高电平时,数据端上升沿跳变.
    void IIC_Stop(void)
    {
        IIC_SCL_L;
        IIC_SDA_L; _nop_();_nop_();_nop_();_nop_();
        IIC_SCL_H;
        IIC_SDA_H; _nop_();_nop_();_nop_();_nop_();_nop_();
    }
    //应答信号函数
    //数据端为低电平时,发一个时钟脉冲...
    void IIC_Ack(void)
    {
        IIC_SCL_L;
        IIC_SDA_L; _nop_();_nop_();
        IIC_SCL_H; _nop_();_nop_();_nop_();_nop_();_nop_();
        IIC_SCL_L;
    }
    //非应答信号函数
    //数据端为高电平时,发一个时钟脉冲...
    void IIC_NAck(void)
    {
      IIC_SCL_L;
      IIC_SDA_H;  _nop_();_nop_();
      IIC_SCL_H;  _nop_();_nop_();_nop_();_nop_();_nop_();
      IIC_SCL_L;
    }
    // 等待从机应答信号函数:
    unsigned char IIC_Wait_Ack(void)
    { unsigned char ACK = 0;
      IIC_SDA_H;  _nop_();
      IIC_SCL_H;  _nop_();
      if(IIC_SDA_READ)ACK = 1;
      else            ACK = 0;
      IIC_SCL_L;  _nop_();_nop_();
      return ACK;
    }
    // 发送一个字节数据函数
    void IIC_SendByte(unsigned char dat)
    { unsigned char i;
      for(i = 0;i < 8;i++)
      { if(dat & 0x80)IIC_SDA_H;
        else          IIC_SDA_L;
        dat<<=1;      _nop_();_nop_();
        IIC_SCL_H;    _nop_();_nop_();
        IIC_SCL_L;    _nop_();_nop_();
      }
    }
    //读取一个字节数据函数
    unsigned char IIC_ReaByte(void)
    { unsigned char i,receive = 0;
      for(i=0;i<8;i++)
      { IIC_SCL_L;   _nop_();_nop_();
        IIC_SCL_H;
        receive<<=1;
        if(IIC_SDA_READ)receive++;
        _nop_();
      } _nop_();_nop_();_nop_();
      IIC_SCL_L;
      return receive;
    }
    // 向OLED发送指令函数
    void IIC_SendCMD(unsigned char IIC_Command)
    {
      IIC_Start();                //开始信号
      IIC_SendByte(0x78); //发送设备地址
      IIC_Wait_Ack();         //等待应答,这里应答可以不用处理,一般会给一个应答信号
      IIC_SendByte(0x00); //设置D/C为0,为指令模式
      IIC_Wait_Ack();         //等待应答
      IIC_SendByte(IIC_Command); //发送指令
      IIC_Wait_Ack();         //等待应答
      IIC_Stop();                //结束信号
    }
    // 向OLED发送数据函数
    void IIC_SendDAT(unsigned char IIC_Data)
    {
      IIC_Start();                //开始信号
      IIC_SendByte(0x78); //发送设备地址
      IIC_Wait_Ack();         //等待应答,这里应答可以不用处理,一般会给一个应答信号
      IIC_SendByte(0x40); //设置D/C为1,为数据模式
      IIC_Wait_Ack();         //等待应答
      IIC_SendByte(IIC_Data);//发送数据
      IIC_Wait_Ack();         //等待应答
      IIC_Stop();                //结束信号
    }
    //==外部函数==屏幕初始化====

    void OLED_Init(void)
    {
      IIC_Init();                   //IIC协议初始化
      IIC_Stop();                //IIC协议初始化
      Delay_ms(200);        //上电后延迟,等待复位。
      IIC_SendCMD(0xAE);//.关闭显示
      IIC_SendCMD(0xD5);//.设置时钟分频因子,震荡频率
      IIC_SendCMD(0x80);//.低4位设置分频因子,高4位设置震荡频率
      IIC_SendCMD(0xA8);//.设置驱动路数
      IIC_SendCMD(0x3F);//.默认0x3F(1/64)
      IIC_SendCMD(0xD3);//.设置显示偏移
      IIC_SendCMD(0x00);//.默认为0
      IIC_SendCMD(0x00);//.设置显示位置-列低地址
      IIC_SendCMD(0x10);//.设置显示位置-列高地址
      IIC_SendCMD(0x40);//.设置显示开始行[5:0],行数
      IIC_SendCMD(0x8D);//.电荷泵设置
      IIC_SendCMD(0x14);//.bit2:开启/关闭
      IIC_SendCMD(0x20);//设置内存寻址模式
      IIC_SendCMD(0x02);//设置成为页面寻址模式
      IIC_SendCMD(0xA1);//.段重定义设置,bit0:0,0->1;1:0->127;这里是设置成1,是将127映射到SEG0
      IIC_SendCMD(0xC8);//.设置COM扫描方向,bit3:0:普通模式;1:重定义模式(COM[N-1]->COM0,N:驱动路数);
      IIC_SendCMD(0xDA);//.设置COM引脚的硬件配置
      IIC_SendCMD(0x12);//.A[5:4],这里只配置了第5位,启动了COM的左右映射,顺序COM引脚配置
      IIC_SendCMD(0x81);//.设置对比度
      IIC_SendCMD(0xEF);//.这里设置成EF,默认是7F,数据越大对比度越大
      IIC_SendCMD(0xD9);//.设置预充电周期
      IIC_SendCMD(0xF1);//.第一阶段为1个时钟周期,第二阶段为15个时间周期
      IIC_SendCMD(0xDB);//.设置VCOMH电压倍率
      IIC_SendCMD(0x30);//.[6:4]000:0.65*vcc;001:0.77*vcc;011:0.83*vcc;
      IIC_SendCMD(0xA4);//恢复到RAM内容显示
      IIC_SendCMD(0xA6);//.设置显示方式;bit0:1反向显示;0正常显示;
      IIC_SendCMD(0xAF);//.开启显示
      //OLED_CLS();
    }
    //==外部函数==清屏函数 ========================
    void OLED_CLS(void)
    { unsigned char i,j;
      for(i = 0;i < 8;i++)            //由于SSD1306分了8页(行):0-7
      { IIC_SendCMD(0xB0+i);  //按页分配总共8页:0xB0-0xB7
        IIC_SendCMD(0x00);     //设置低4位地址,这里重新配置会被置为0000
        IIC_SendCMD(0x10);     //设置高4位地址,这里重新配置会被置为0000
        for(j = 0;j < 128;j++)    //每一行的长度是128点
        { IIC_SendDAT(0x00); }//每次都写0x00
      }
    }
    //OLED开显示函数
    void OLED_ON(void)
    {
      IIC_SendCMD(0x8D);  //电荷泵设置指令
      IIC_SendCMD(0x14);  //打开电荷泵
      IIC_SendCMD(0xAF);  //打开显示
    }
    //OLED关显示函数
    void OLED_OFF(void)
    {
      IIC_SendCMD(0x8D);  //电荷泵设置指令
      IIC_SendCMD(0x10);  //关闭电荷泵
      IIC_SendCMD(0xAE);  //关闭显示
    }
    // 设置行列光标坐标函数: X:0..127 Y:0..7
    void OLED_SetXY(unsigned char X,unsigned char Y)
    {
      IIC_SendCMD(0xB0+Y);                    //确定页面开始
      IIC_SendCMD((X&0xF0)>>4|0x10);  //设置高4位的列
      IIC_SendCMD((X&0x0F));                  //设置低4位的列
    }
    //显示6*8点阵ASCII字符串
    //入口参数: X,Y坐标,str字符串,len长度
    void OLED_A8( unsigned char X,unsigned char Y,unsigned char *str,unsigned char len)
    {  unsigned int l,i=0;
       unsigned char ch;
       for(l=0;l<len;l++)
       { ch=str[l]-0x20;
         OLED_SetXY(X+l*6,Y);
         for(i=0;i<6;i++)IIC_SendDAT(ASC8[ch]);
       }
    }
    // ******  OLED_IIC.C END******************************************************************
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    1 小时前
  • 签到天数: 148 天

    [LV.7]常住居民III

    5

    主题

    97

    回帖

    672

    积分

    高级会员

    积分
    672
     楼主| 发表于 2023-11-3 22:14:37 | 显示全部楼层
    本帖最后由 浦江一水 于 2023-11-15 19:37 编辑

    字库文件  (简略表达)

    #ifndef _OLED_FONT_H
    #define _OLED_FONT_H

    /*****6*8点阵ASCII字符点阵模 ************************************/
    unsigned char code ASC8[][6] =
    {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // sp
        0x00, 0x00, 0x00, 0x2f, 0x00, 0x00,   // !
        0x00, 0x00, 0x07, 0x00, 0x07, 0x00,  // "
        0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14,    // #
        0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12,   // $
        0x00, 0x62, 0x64, 0x08, 0x13, 0x23,  // %
        0x00, 0x36, 0x49, 0x55, 0x22, 0x50,  // &

        .........

        0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C,// y
        0x00, 0x44, 0x64, 0x54, 0x4C, 0x44,// z
        0x14, 0x14, 0x14, 0x14, 0x14, 0x14,// horiz lines
    };

    /************ 8*16点阵ASCII字符点阵模 ************************************/
    unsigned char code ASC16[][16]=      
    {
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,   // - -
            0x00,0x00,0x38,0xFC,0xFC,0x38,0x00,0x00,0x00,0x00,0x00,0x0D,0x0D,0x00,0x00,0x00,  // -!-
            0x00,0x0E,0x1E,0x00,0x00,0x1E,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // -"-
            0x20,0xF8,0xF8,0x20,0xF8,0xF8,0x20,0x00,0x02,0x0F,0x0F,0x02,0x0F,0x0F,0x02,0x00,    // -#-
            0x38,0x7C,0x44,0x47,0x47,0xCC,0x98,0x00,0x03,0x06,0x04,0x1C,0x1C,0x07,0x03,0x00, // -$-
            0x30,0x30,0x00,0x80,0xC0,0x60,0x30,0x00,0x0C,0x06,0x03,0x01,0x00,0x0C,0x0C,0x00, // -%-
            0x80,0xD8,0x7C,0xE4,0xBC,0xD8,0x40,0x00,0x07,0x0F,0x08,0x08,0x07,0x0F,0x08,0x00, // -&-

           .........

            0x00,0x00,0x00,0xBC,0xBC,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x00,0x00,0x00, // -|-
            0x00,0x04,0x04,0xBC,0xF8,0x40,0x40,0x00,0x00,0x08,0x08,0x0F,0x07,0x00,0x00,0x00, // -}-
            0x08,0x0C,0x04,0x0C,0x08,0x0C,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // -~-
            0x80,0xC0,0x60,0x30,0x60,0xC0,0x80,0x00,0x07,0x07,0x04,0x04,0x04,0x07,0x07,0x00, // --
    };

    /* **************** 自定义中文小字库,16*16点阵  *********************************************/
    #define  TotalHZ16  3                                                 //说明一下汉字总数(根据需要扩展...)
    unsigned char code HZ16M[][2]={ "单","片","机",};   //汉字索引列表(根据需要扩展...)

    //具体点阵模数组... ( 取模方式: 纵向8点下高位 )        //数组顺序与汉字索引列表排列一致
    unsigned char code HZ16[][32]={
    /* 单0 */{
    0x00,0x00,0xF8,0x28,0x29,0x2E,0x2A,0xF8,0x28,0x2C,0x2B,0x2A,0xF8,0x00,0x00,0x00,
    0x08,0x08,0x0B,0x09,0x09,0x09,0x09,0xFF,0x09,0x09,0x09,0x09,0x0B,0x08,0x08,0x00,},
    /* 片1 */{
    0x00,0x00,0x00,0xFE,0x10,0x10,0x10,0x10,0x10,0x1F,0x10,0x10,0x10,0x18,0x10,0x00,
    0x80,0x40,0x30,0x0F,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0xFF,0x00,0x00,0x00,0x00,},
    /* 机2 */{
    0x08,0x08,0xC8,0xFF,0x48,0x88,0x08,0x00,0xFE,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,
    0x04,0x03,0x00,0xFF,0x00,0x41,0x30,0x0C,0x03,0x00,0x00,0x00,0x3F,0x40,0x78,0x00,},
    };

    //****** 字库文件 END ************************************************************************





    02-TestOLED096.rar

    28.73 KB, 下载次数: 23

    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    1 小时前
  • 签到天数: 148 天

    [LV.7]常住居民III

    5

    主题

    97

    回帖

    672

    积分

    高级会员

    积分
    672
     楼主| 发表于 2023-11-6 11:46:38 | 显示全部楼层
    实践与思考: 为什么在驱动OLED_IIC单色显示屏时, 没用 STC32G12K128 的硬件IIC接口功能?

    有两个原因:

    1, 在自制的实验电路板上, 已经设有LCD1602的IO接口, 在驱动0.96寸OLED_IIC单色显示屏时, 是利用了现有的接口:  P0.7 -- SCK 时钟, P0.6 -- SDA 数据. 在这两个端口上没有硬件IIC功能,只好用普通IO口来模拟IIC口;

    2, 思想懒惰,急功近利: 没有静心去研究STC3212K128有关IIC的13个寄存器各个位的定义和功能。 而是个人固执地认为:只要理解了IIC通讯协议的时序规则,用普通IO口模拟IIC通讯,也能完成对IIC接口外设的通讯控制。只要这个CPU的IO口具有输入输出切换功能、编程时注意一下延时等待,就没有必要再去研究弄懂此CPU的硬件IIC寄存器定义了。并且,用普通IO口模拟IIC通讯的方法,适用于各种CPU的应用需要,源码的可移植性非常强,几乎是可以“以不变应万变”了。当然,这样的思想是片面的,学习态度是不认真的,是要接受批评的。待以后有空余时间时再慢慢细细阅读STC32G手册有关章节, 再深入学习和理解了……


    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    550

    主题

    9331

    回帖

    1万

    积分

    管理员

    积分
    13936
    发表于 2023-11-6 13:31:58 | 显示全部楼层
    截图202311061331541950.jpg
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    1 小时前
  • 签到天数: 148 天

    [LV.7]常住居民III

    5

    主题

    97

    回帖

    672

    积分

    高级会员

    积分
    672
     楼主| 发表于 2023-11-6 15:05:02 | 显示全部楼层
    非常感谢"神农鼎"管理员的指点,有您的关照和指点,学习STC32G则更有信心和底气了。
    也很感叹STC的不断努力和进取,已经注意到了,STC-ISP(V6.92D)软件又更新到V6.92E版本了,速度很快。
    新增的“功能脚切换”标签页,很好,很实用。真是想的很周到,让人很方便地查询到哪些引脚具有哪些可能的功能切换,并且立即给出参考代码。
    STC-ISP这款天天不离手的软件功能越来越强大了。也期待着“范例程序”页中,能出现STC32G系列的相关例程(猜想有这个计划可能吧?)。
    回复 支持 反对 送花

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2024-5-6 10:11 , Processed in 0.091044 second(s), 65 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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