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

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

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

    [LV.7]常住居民III

    5

    主题

    96

    回帖

    646

    积分

    高级会员

    积分
    646
     楼主| 发表于 2023-11-12 20:59:36 | 显示全部楼层

    关于STC32G12K128实验板驱动TM1638数码管模块的实验



    坛子里有布丁橘长的“视频教程-STC32位8051-屠龙刀-第0-100期合集”, 深受大家的欢迎喜爱,让人得益菲浅。
    对多种模块给出了实验教程。附件文档中给出了各种模块的清单XLS。
    其中有一款TM1638的模块,令我产生兴趣。
    截图202311122004397414.jpg

    但是好像没有看到布丁橘长有关这款模块的实验介绍。
    顺着布丁橘长的连接指引,淘购了一块来做实验。。。。


    仅用三个IO口,就能实现对8个按键、8个LED发光管、8位LED数码管的操作控制,如此节省IO资源, 在单片机应用项目中是有非常现实意义的。
    百度文档中有人谈到了对这模块的应用感受, 说是“又爱又恨”, 爱的是功能多、效率高,恨的是芯片数据手册的描述太简单而模糊,弄得人看不懂,导致实验很不顺利。
    比如芯片数据手册中这样描述:
    截图202311122018493470.jpg

    你能看得出,如果要在第三位显示一个“0”, 地址是哪个吗?
    没有参考代码,只好自己摸索实验了。。。
    于是我实验板与TM1638模块连接起来。如图所示:
    截图202311122024467788.jpg

    经过一番曲曲折折的调试摸索实验,终于弄懂或猜出了数据手册描述的意思。实现了对TM1638模块的控制使用。
    实验结果如图:
    截图202311122029105341.jpg

    在这个实验中实现:
    1. 在8位数码管上定位显示整数或小数及字符串显示;
    2. 按S1键增加显示亮度; 按S2键减小显示亮度;
    3. 显示键值, 图中"C80"的"80"就是键值的16进制显示, 对应键:S1=01,S2=02,S3=04,S4=08, S5=10,S6=20,S7=40,S8=80;
    4. 设一个无符号字节变量(0...255)变化,  按S3键使这变量加一 ,按S4键使这变量减一, 显示此变量值(如图中以16进制显示"3F")
        同时上面8个LED发光管对应变量的8位显示变化: 从左到右, 低位到高位。如图中显示变量为“3F”, 2进制即00111111,那么发光管显示○○○○○○●●  (○为1,●为0   

    回复 支持 反对 送花

    使用道具 举报

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

    [LV.7]常住居民III

    5

    主题

    96

    回帖

    646

    积分

    高级会员

    积分
    646
     楼主| 发表于 2023-11-15 20:05:35 | 显示全部楼层
    阶段性的学习实验小结



    自从用洞洞板做了STC32G12K128(DIP40)实验板以来,做了一些实验,阶段性的小结罗列一下:
    1,STC单片机 IO端口电平控制--“跑马灯” 程序练习,主要目的是学习掌握工程文件框架的基本建设;
    2,实验对LCD1602字符型显示屏的控制显示输出,对四键八值的输入练习;
    3,实验IIC单色OLED(128*64)点阵显示屏的控制,实现中西文混合显示;
    4,实验 STC32G12K128 对彩色显示屏(128*160)控制显示,实现中西文混合显示, 实验12位ADC转换
    5,实验 驱动TM1638数码管模块,实现用三个IO端口,控制8个键输入,8个LED发光管亮灭控制,8位数码管数字和字符串显示。


    在学习实验过程中,购买了 STC USB Link1D仿真器、一箭双雕转串口、USB转串口等等工具。
    截图202311151947358167.jpg

    由于没有充分了解和掌握STC USB Link1D仿真器和一箭双雕转串口工具对STC32G12K128仿真的有关知识。所以在整个实验过程中,仅仅依靠USB转串口的工具,反复下载调试。
    没有发挥STC USB Link1D仿真器和一箭双雕转串口工具的优势作用,给研究算法调试编程,带来了很大的困难。降低了学习实验的效率。


    最近经反复观看论坛前辈们的视频教程和技术帖子,初步感悟了使用STC USB Link1D仿真器的基本知识,准备下一阶段学习实验中,让这些调试工具发挥应有的作用。


    由于申请的STC32G12K128实验箱,已经收到。在此向STC国芯表示由衷感谢。
    下一阶段的学习实验,自己也已淘购配置了单色彩色显示屏, 学习实验将在实验箱中开展,将学习更多的STC单片机编程知识。
    自制的洞洞实验板,也是立下了汗马功劳,已完成了它的历史使命,也是自己学习过程的一个见证。
    在国芯论坛留下一笔,也许会有坛友记得它曾经的存在。












    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    难过
    2024-3-28 15:57
  • 签到天数: 2 天

    [LV.1]初来乍到

    0

    主题

    1

    回帖

    32

    积分

    新手上路

    积分
    32
    发表于 2024-3-23 18:04:58 | 显示全部楼层
    照搬程序但字符串显示不正确是为什么呜呜
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    1 小时前
  • 签到天数: 55 天

    [LV.5]常住居民I

    2

    主题

    517

    回帖

    655

    积分

    高级会员

    积分
    655
    发表于 2024-3-24 00:03:00 来自手机 | 显示全部楼层
    各种各样的屏真多
    回复 支持 反对 送花

    使用道具 举报

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

    [LV.5]常住居民I

    2

    主题

    106

    回帖

    464

    积分

    中级会员

    积分
    464
    发表于 2024-3-24 06:20:26 来自手机 | 显示全部楼层
    不知道为啥非要251…
    回复 支持 反对 送花

    使用道具 举报

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

    [LV.7]常住居民III

    5

    主题

    96

    回帖

    646

    积分

    高级会员

    积分
    646
     楼主| 发表于 2024-3-24 08:56:03 | 显示全部楼层
    楼上朋友,我的理解是:
    由于:微处理器位数不同, 指令集不同,编译器不同。
    因此:
    STC8H8K64U       使用C51 。   
    STC32G12K128   使用C251。
    不能兼容。
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    6 天前
  • 签到天数: 42 天

    [LV.5]常住居民I

    14

    主题

    53

    回帖

    386

    积分

    中级会员

    积分
    386
    发表于 2024-3-26 09:25:52 | 显示全部楼层
    这帖子不给加精一下?收藏学习中,谢谢楼主无私共享,关键还注释这么详细
    回复 支持 反对 送花

    使用道具 举报

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

    [LV.7]常住居民III

    5

    主题

    96

    回帖

    646

    积分

    高级会员

    积分
    646
     楼主| 发表于 2024-3-27 15:21:47 | 显示全部楼层
    QW123 发表于 2024-3-26 09:25
    这帖子不给加精一下?收藏学习中,谢谢楼主无私共享,关键还注释这么详细 ...

    感谢您的浏览阅读和谬赞,我们共同学习STC单片机的应用。
    回复 支持 反对 送花

    使用道具 举报

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

    [LV.2]偶尔看看I

    0

    主题

    13

    回帖

    104

    积分

    注册会员

    积分
    104
    发表于 2024-4-20 15:26:05 | 显示全部楼层
    浦江一水 发表于 2023-11-12 20:59
    关于STC32G12K128实验板驱动TM1638数码管模块的实验

    源码可以分享吗?
    用在STC8G中,LED和数码管正常,S1-S8不可靠,有误动作不敢用
    回复 支持 反对 送花

    使用道具 举报

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

    [LV.7]常住居民III

    5

    主题

    96

    回帖

    646

    积分

    高级会员

    积分
    646
     楼主| 发表于 2024-4-21 09:38:09 | 显示全部楼层
    本帖最后由 浦江一水 于 2024-4-21 09:39 编辑
    cadplus 发表于 2024-4-20 15:26
    源码可以分享吗?
    用在STC8G中,LED和数码管正常,S1-S8不可靠,有误动作不敢用 ...


    感谢楼上朋友对本帖的浏览和阅读。
    关于TM1638模块的本实验, 虽然不是在STC8G中实验的, 但是相信原理应该是相同的,都是纯IO口的读写操作。
    源码是自己写的, 连同工程文件, 仅供参考。本自制洞洞实验板,本来也有四个按键,注意与TM1638模块上按键的区别……



    04-TestTM1638.rar (34.02 KB, 下载次数: 1)



    主程序体现了本实验的动作内容,可看注释……

    //========================================================
    // TM1638_8键8LED8数码管模块 实验程序
    // 驱动:TM1638
    // 基于: STC32G12K128芯片实验板编程 主频选择: 22.118400MHz
    // 整理:编程: 浦晓明(浦江一水) 2023-11...
    //========================================================
    #include "STC32G.H"
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "KEY4_IO.H"
    #include "TM1638.H"

    //4LED
    sbit LED0  = P2^0;  //运行指示
    sbit LED1  = P2^1;  //运行指示
    sbit LED2  = P2^2;  //运行指示
    sbit LED3  = P2^3;  //运行指示

    unsigned char k,TMk;
    char S[20];
    //非精确延时...
    void Delay_ms(unsigned int count)
    { unsigned int i,j;
      for(i=0;i<count;i++)      
      for(j=0;j<50000;j++);            
    }
    //主程序入口
    void main(void)
    { unsigned int wait=0;
      unsigned char Light=0,ch=0x3F,disp=0;
      float pi=3.14159;
      //IO端口初始化
      WTST  = 0; //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
      EAXFR = 1; //扩展寄存器(XFR)访问使能
      CKCON = 0; //提高访问XRAM速度
      //IO端口初始化//全部为双向口
      P0M1 = 0x00;   P0M0 = 0x04;   //设置为准双向口: P0.2推挽输出控制背光
      P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
      P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
      P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
      P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
      P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口

      LED1=0;LED2=0;LED3=0;
      LED1=1;LED2=1;LED3=1;
      TM1638_Init();
      TM1638_All_LED(0xFF);         //8LED灯全亮
      TM1638_All_LED(0x00);         //8LED灯全灭
      TM1638_A_LED(0,1);            //指定位LED亮
      TM1638_A_LED(0,0);            //指定位LED灭
      TM1638_A_LED(1,1);            //指定位LED亮
      TM1638_A_LED(1,0);            //指定位LED灭
      TM1638_Write_DATA( 0,0x06);   //测试单个数码位显示
      TM1638_Write_DATA( 2,0x5B);
      TM1638_Write_DATA( 4,0x4F);
      TM1638_Write_DATA( 6,0x66);
      TM1638_Write_DATA( 8,0x6D);
      TM1638_Write_DATA(10,0x7D);
      TM1638_Write_DATA(12,0x07);
      TM1638_Write_DATA(14,0x7F);
      GETCH();                                      //按任意键继续...
      TM1638_DispSTR(0,"ABCDEFGH"); //显示字符串...
      GETCH();                                     //按任意键继续...
      TM1638_DispSTR(0,"CPU-32G.H");//显示字符串...
      GETCH();                                    //按任意键继续...
      sprintf(S,"P=%07.5f",pi);             //组织字符串...
      TM1638_DispSTR(0,S);                //显示字符串...
      sprintf(S,"H-%02X C00",(unsigned int)ch); //组织字符串...

      TM1638_DispSTR(0,S);                //显示字符串...

      TM1638_All_LED(ch);                  //全显
      while(1)
      { if(wait==0)LED2=0;                 //指示程序正在运行中...  
        if(wait==100)LED2=1;
        wait=wait<10000?wait+1:0;      //循环计数...
        k=0; k=RDKEY();                      //读取实验板按键输入...
        if(k!=0)
        { switch(k)
          { case 0x10: Light=Light<8?Light+1:8;  TM1638_SetLight(Light);Delay_ms(2000); break;   //控制亮度+
            case 0x20: Light=Light>0?Light-1:0;    TM1638_SetLight(Light);Delay_ms(2000); break;   //控制亮度-
            case 0x30: ch=ch<255?ch+1:0; disp=1; TM1638_All_LED(ch);     break;                         //根据递增ch数值显示...
            case 0x40: ch=ch>0?ch-1:255;  disp=1; TM1638_All_LED(ch);     break;                         //根据递减ch数值显示...

          }        
        }        Delay_ms(20);
        if(disp){ sprintf(S,"H-%02X",(unsigned int)ch); TM1638_DispSTR(0,S); disp=0; }
        if(wait%2500==0)
        { TMk=0; TMk=TM1638_Read_key();          //读取TM1638模块8按键输入...
          if(TMk>0)
          { sprintf(S,"C%02X",(unsigned int)TMk);  TM1638_DispSTR(5,S);
            switch(TMk)
            { case 0x01: Light=Light<8?Light+1:8;  TM1638_SetLight(Light);Delay_ms(20000);  break;
              case 0x02: Light=Light>0?Light-1:0;   TM1638_SetLight(Light);Delay_ms(20000);  break;
              case 0x04: ch=ch<255?ch+1:0; disp=1; TM1638_All_LED(ch);     break;
              case 0x08: ch=ch>0?ch-1:255;  disp=1; TM1638_All_LED(ch);     break;
            } Delay_ms(50000);
          }  
        }
        Delay_ms(100);
      }
    }



    //****************************************************************************
    // TM1638 8键8数码管8LED模块.头文件
    //****************************************************************************

    #ifndef  _TM1638_H_
    #define  _TM1638_H_

    #include  "STC32G.H"

    //TM1638模块在实验板上的引脚定义
    sbit  STB=P4^5;  //片选
    sbit  CLK=P2^7;  //时钟
    sbit  DIO=P2^6;  //数据

    void TM1638_Init(void);                                                          //TM1638初始化函数
    void TM1638_Write_DATA(unsigned char add,unsigned char DATA);//指定地址写入数据 地址:0..15
    void TM1638_A_LED(unsigned char num,unsigned char flag);     //单独某个LED亮灭函数,num序号 flag=0熄灭,1:点亮
    void TM1638_All_LED(unsigned char LEDs);                             //8个LED函数同时控制 位=1;点亮 =0熄灭...
    void TM1638_SetLight(unsigned char light);                              //设置亮度0:灭 1..8:亮度增强...
    void TM1638_DispSTR(unsigned char x,char * str);                   //显示字符串
    unsigned char TM1638_Read_key(void);                                  //读键函数

    #endif


    //****************************************************************************
    // TM1638.C  8键8数码管8LED模块 函数实现
    //****************************************************************************
    #include  "STC32G.H"
    #include  <stdio.h>
    #include  <string.h>
    #include  "TM1638.H"

    //命令字
    #define  DATA_CMD  0x40
    #define  DISP_CMD  0x80
    #define  ADDR_CMD  0xC0

    //共阴数码管显示字符表 (共33字符)
    unsigned char code Asc[]={ '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F',
                               '.','_','-','=','G','P','q','c','H','h','L','J','U','u','o','n',' ', };
    //共阴数码管显示段码表 (对应33字符的段码)
    unsigned char code Tab[]={ 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
                               0x80,0x08,0x40,0x48,0x3D,0x73,0x67,0x58,0x76,0x74,0x68,0x0E,0x3E,0x1C,0x5C,0x54,0x00,};

    //****************************************************************************
    // 仅供本模块调用的内部函数
    //****************************************************************************
    // 写一个字节函数
    void TM1638_Write(unsigned char DATA)      //写数据函数
    { unsigned char i;
      for(i=0;i<8;i++)
      { CLK=0;
        if(DATA & 0x01)DIO=1;
        else           DIO=0;
        DATA>>=1;
        CLK=1;
      }
    }
    // 写一个命令字节
    void Write_CMD(unsigned char cmd)    //发送命令字
    {
      STB=0;             //片选低(产生一个从1到0的跳变.)  
      TM1638_Write(cmd);
      STB=1;             //片选高
    }


    // 读取一个字节
    unsigned char TM1638_Read(void)          //读数据函数
    { unsigned char i;
      unsigned char temp=0;
      DIO=1;      //设置为输入
      for(i=0;i<8;i++)
      { CLK=0;
        temp>>=1;  
        CLK=1;    //数据正在时钟上升沿后读取...
        if(DIO)temp|=0x80;
      }
      return temp;
    }

    //****************************************************************************
    // 外部可调用函数
    //****************************************************************************
    // TM1638初始化函数
    void TM1638_Init(void)
    { unsigned char i;
      Write_CMD(0x88);       //亮度 (0x88-0x8F)8级亮度可调
      Write_CMD(0x40);       //采用地址自动加1
      STB=0;                      //片选中
      TM1638_Write(0xC0);  //设置起始地址
      for(i=0;i<16;i++)       //传送16个字节的数据0
        TM1638_Write(0x00);
      STB=1;
    }
    // 读取键值函数 返回0:无按键 按键1..8键值0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,
    unsigned char TM1638_Read_key(void)
    { unsigned char c[4],i,key_value=0;
      STB=0;
      TM1638_Write(0x42);                          //读键扫数据 命令
      for(i=0;i<4;i++)c=TM1638_Read();  //一次读4个字节
      STB=1;                                              //4个字节数据合成一个字节
      for(i=0;i<4;i++)key_value|=c<<i;
      return key_value;                                //返回键值
    }
    //指定地址写入数据 地址:0..15
    void TM1638_Write_DATA(unsigned char add,unsigned char DATA)   
    {
      STB=0;  //片选中
      //Write_CMD(0x44);
      TM1638_Write(0xC0|add);   //地址
      TM1638_Write(DATA);
      STB=1;  //不选中
    }
    //单独控制一个LED函数,num为需要控制的led序号,flag为0时熄灭,不为0时点亮
    void TM1638_A_LED(unsigned char num,unsigned char flag)  
    {
      if(flag)TM1638_Write_DATA((unsigned char)(2*num+1),1);
      else    TM1638_Write_DATA((unsigned char)(2*num+1),0);
    }
    //控制全部LED函数,LEDs表示各个位LED状态
    void TM1638_All_LED(unsigned char LEDs)
    { unsigned char i;
      for(i=0;i<8;i++)
      { if(LEDs&(1<<i))TM1638_Write_DATA((unsigned char)(2*i+1),1);
        else           TM1638_Write_DATA((unsigned char)(2*i+1),0);
      }
    }
    //设置亮度 0:灭 1..8:亮度增强.   
    void TM1638_SetLight(unsigned char light)
    {
      switch(light)
      { case 0: Write_CMD(0x80);break; //灭
        case 1: Write_CMD(0x88);break; //低亮
        case 2: Write_CMD(0x89);break;
        case 3: Write_CMD(0x8A);break;
        case 4: Write_CMD(0x8B);break;
        case 5: Write_CMD(0x8C);break;
        case 6: Write_CMD(0x8D);break;
        case 7: Write_CMD(0x8E);break;
        case 8: Write_CMD(0x8F);break; //高亮
      }
    }
    // (TM1638八位数码管)显示字符串函数
    // 入口参数: x定位(0..7), str:需要显示的字符串(字符仅限于)
    void TM1638_DispSTR(unsigned char x, char * str)
    { unsigned char ch,y,i;
      if(x>=8)return;              //超界..返回..
      for(;x<8;x++)               //从指定位置0到7
      { y=0;
        for(i=0;i<33;i++)        //根据字符查找对应段码
        { if(*str==Asc)         //      if(SS==Asc[ii])
          { ch=Tab;              //取段码
            y=1; break;
          } else ch=0x00;         //若无对应段码则用0空替代.
        }
        if(y==1)
        { if(*(str+1)=='.')       //如果遇小数点处理...
          { ch |= 0x80;           //段码最高位置1...(加小数点)  
            str++;
          }
          TM1638_Write_DATA((unsigned char)(2*x),ch);//定位写入显示
        }
        str++;
        if(*str=='\0')break;      //字符串结束
      }
    }
    //**** END *********************************************************************************




    回复 支持 反对 送花

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2024-4-29 16:24 , Processed in 0.078771 second(s), 65 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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