找回密码
 立即注册
查看: 2821|回复: 33

STC32G12K128 成长道路

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

    [LV.7]常住居民III

    11

    主题

    69

    回帖

    2874

    积分

    金牌会员

    单片机编程魔法师

    积分
    2874
    发表于 2023-4-24 08:42:40 | 显示全部楼层 |阅读模式
    本帖最后由 t176 于 2023-4-27 08:46 编辑

    Lesson 1

    开篇:
    LINK1D 仿真:




    1.首先,仿真线路的连接;
    屠龙刀:
    屠龙刀接线.png
    2.目标芯片与STC LINK1D硬件仿真器通过或SWD接口连接(P3.0,P3.1),以建立仿真通讯链路;
    链路1.jpg


    3.在keil进行参数配置,以及ISP设置仿真芯片
    详细方法,请参考STC32G.PDF  5.11章节和5.12章节.(****必看,根据手册内容进行配置)
    Page135-151.

    查阅手册.png


    PDF下载:
    PDF下载.png

    请注意:如果在ISP中设置为仿真芯片,没设置端口和SWD,将仿真失败
    设置仿真芯片.png
    4.编写并编译代码,生成HEX文件
    测试代码.png
    5.通过STC_ISP,将生成的可烧录指令文件下载到STC LINK1D硬件仿真器中的处理器内存区域,作为仿真器内部的程序;
    烧录完成.png

    6.启动keil调试功能,在仿真器和目标芯片之间建立仿真操作链路;


    启动仿真功能.png
    7. LINK1D仿真操作过程中,通过LINK1D与PC之间的通讯,将LINK1D内部的程序烧录进目标芯片中.
    下载.png

    8.keil调试工具可以实时地显示芯片内部状态信息.比如查看某一个变量的值,或是切换到代码窗口查看此时程序的执行位置;实现目标芯片的单步调试、断点调试、变量跟踪等功能,方便用户对复杂程序进行调试。


    打开窗口.png

    内部信息.png
















    喜欢研究如何让电子产品变得更加智能和有趣.
    回复 送花

    使用道具 举报

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

    [LV.7]常住居民III

    11

    主题

    69

    回帖

    2874

    积分

    金牌会员

    单片机编程魔法师

    积分
    2874
     楼主| 发表于 2023-4-24 08:42:41 | 显示全部楼层
    本帖最后由 t176 于 2023-4-21 16:07 编辑

    Lesson 2

    5分钟理解进制存储机制,IO口:(相关理论知识,可通过百度查询,这里只做仿真效果下的学习)

    IO口是单片机用来控制外部设备的一组通用输入/输出接口,
    IO口 可以配置为4种模式:

    准双向口:传统8051端口模式,弱上拉.灌电流可达20mA,拉电流为270150μA(存在制造误差)

    推挽输出:强上拉输出,可达20mA,要加限流电阻


    高阻输入:电流既不能流入也不能流出


    开漏输出:内部上拉电阻断开开漏模式既可读外部状态也可对外输出(高电平或低电平)。如要正确读外部状态或需要对外输出高电平,需外加上拉电阻,否则读不到外部状态,也对外输不出高电平。

    准双向模式:准双向IO口是一种介于输入和输出之间的模式,它可以在不改变端口的输入/输出状态的情况下,切换IO口的方向。这种模式常用于I/O总线和共享总线设备的控制。


    开漏/推挽模式:开漏模式和推挽模式是输出模式的两种变体。在开漏模式下,输出端口只能输出低电平或不输出电平;而在推挽模式下,输出端口可以输出高电平或低电平。这两种模式常用于将多个输出口连接到同一总线上,从而实现集中控制。


    目前学习我们先用准双向IO口进行配置学习,后期应用案列中会逐步介绍其他模式
    4种模式的定义可以参考PDF 11章 Page 293 或者直接使用ISP 生成配置代码

    IO配置.png


    通过编程控制IO口的高低电平状态,就可以实现对外部设备的控制。
    32G  IO口的引脚图:
    根据封装工艺的需求,芯片在生成时,有多种封装规格 下面是LQFP的封装样式,


    引脚图.png

    当然还有其他样式,在ISP 中可以查阅观察.
    引脚封装.png

    通过引脚的观察 我们看到 有一组P开头的引脚0-7,这就是IO口.
    通常IO 口 一组为八个. 0-7 列如 P0.1-P0.7
    他们在内存中形态以十六进制存储(00-FF).单个IO口则是二进制存储(0-1)
    8个二进制位 组成二个十六进制的存储单元


    如果还是理解不太明白.没关系,接下来使用一个仿真程序带你窥视内存.







    下面是一份简单的代码,你不需要对他进行理解.我们这里只用作于仿真,强化学习进制和IO 的知识点.

    1. #include <STC32G.H>
    2. void main()
    3. {
    4.     EAXFR = 1;    // 使能访问 XFR
    5.     CKCON = 0x00; // 设置外部数据总线速度为最快
    6.     WTST = 0x00;  // 设置程序代码等待参数,
    7.     // 赋值为 0 可将 CPU 执行程序的速度设置为最快
    8.     P0M0 = 0x00;
    9.     P0M1 = 0x00;
    10.     P1M0 = 0x00;
    11.     P1M1 = 0x00;
    12.     P2M0 = 0x00;
    13.     P2M1 = 0x00;
    14.     P3M0 = 0x00;
    15.     P3M1 = 0x00;
    16.     P4M0 = 0x00;
    17.     P4M1 = 0x00;
    18.     P5M0 = 0x00;
    19.     P5M1 = 0x00;
    20.     while (1)
    21.     {
    22.        P25=~P25;//翻转电平
    23.     }
    24.    
    25. }
    复制代码


    我们先对这段代码进行仿真:


    在单片机中,常用的进制有二进制、十进制和十六进制。

    当你顺利进入仿真 你看到的keil 界面是这样的
    默认界面.png


    我们可以看到
    1 是命令执行执行窗口
    2 是监视区域



    我们为了实时观察变量 建议打开变量监视 按照步骤执行第3步 和第四部
    变量监视.png


    点开 监视表1 我们就能看到 有三个字段
    NAME VALUE  TYPE
    NAME: 表达式
    VALUE:值
    TYPE:类型

    在这里我们可以根据编辑特有的表达式 进行内容观察
    表达式计算.png


    图中我们可以看到  使用表达式 可以直接进行计算,好了,基础的仿真 就讲到这里.我们接下来 IO口(数值)在内存是存储状态

    我们打开内存窗口

    内存.png

    我们在内存地址中输入&P2
    为什么要加&,&是取地址,
    我们可以看到内存中的存储单元都是 以16进制展示的(00-FF).这个FF 就是存储了 8个二进制位  既P2(IO口组合)
    那么我们如何理解IO口是二进制状态呢,接下来看这张图
    IO口.png

    当点击完成后我们就可以看到一个IO口的 具体二进制存储  情况
    IO口监视器.png

    7-0 Bits 存储了 P2_IO口组的 IO状态 .
    打勾的表示1  如果没勾 就会变成0;
    现在你可以尝试下 点击这些勾选 对比 前面16进制的 变化.
    IO口操作.png


    通过点击,你会发现  前面的16进制数值也跟着相应的变化,同时可以观察 内存区域或者变量监视表会跟着变化
    那么我们就明白了,一个IO口存储一个二进制(0-1) 一个十六进制(0-F)存储着 4个IO口的二进制状态.FF所以可以存储8个IO口.到这里我相信你对进制的内存存储已经有一个 新的认识.

    接下来,请点击勾选观察单片机的LED亮灭状态
    点了没变化啊,咋回事?

    别着急 因为代码IO口配置没有  初始化 你没执行


    单步调试.png

    我们可以选择快捷键F11 进行执行单步调试,在代码执行完20行,那么所以的IO 口初始化代码都已经初始化完毕.现在你再点击试试.

    你会发现 你点击一个IO口,开发板上的LED就会产生相应的亮灭变化.

    亮灭变化.png
    板子亮灭情况.jpg


    根据上面的试验,我们学习了 进制的存储状态,和IO口的概念.以及仿真的基本操作.
    相信你对进制存储以及转换有了更直观的认识.


    并且发现仿真器 对仿真芯片拥有实时的控制权和监视能力.那么在后面的开发中,相当于给程序员一只眼睛,在接下来的学习中.会开始写代码,这个过程中,使用仿真去调试会事半功倍.

    现在问题来了...............

    问题1:
    硬件仿真模式下,LINK1D 是不是对32G有绝对控制权?


    从理想状态上来说,是可以的.但是考虑到仿真环境中可能存在的各种干扰因素

    (自然因素干扰)
    例如噪声、时钟波形失真等因素,这些都可能会影响LINK1D对目标单片机的控制能力。
    (人为因素干扰)
    如果开发者在仿真过程中,对寄存器进行错误的修改,导致仿真链路的破坏.

    LINK1D将不能完全地控制和解决这些问题.


    问题2:
    为什么IO口变成0  LED就会点亮?变成1为什么又熄灭.

    这就引出我们下一课学习,如何点亮一个LED灯,原理是什么,如何编写相应的代码?







    喜欢研究如何让电子产品变得更加智能和有趣.
    回复 支持 1 反对 0 送花

    使用道具 举报

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

    [LV.7]常住居民III

    11

    主题

    69

    回帖

    2874

    积分

    金牌会员

    单片机编程魔法师

    积分
    2874
     楼主| 发表于 2023-4-24 08:42:42 | 显示全部楼层
    本帖最后由 t176 于 2023-4-22 10:31 编辑

    Lesson 3
    编写第一个程序,点亮LED(以及寄存器的认识)
    屠龙刀在出厂的时候默认P2端口焊接了电阻和绿光LED灯
    LED电路.png

    图中
    1为VCC
    2为贴片发光二极管   
    3限流电阻


    电路分析:
    电流经过VCC(1)----->发光二极管(2)----->限流电阻---->IO口
    当IO口状态为0时,IO口处于低电平状态 整个电流流通,LED点亮
    当IO口状态为1时,IO口处于高电平状态.根据电气特性,LED熄灭
    限流电阻的作用:
    图中使用5.1K 的限流电阻,限制电路中电流大小,从而保护led,可以延长led的寿命.


    明白了LED的亮灭,可以根据条件 编写相应代码 ,点亮LED


    编写代码:

    1. #include <STC32G.H>
    2. sbit LED = P2 ^ 5; // 位定义,将LED 变量 定义为P2口的第5个引脚
    3. void main()
    4. {
    5.     EAXFR = 1;    // 使能访问 XFR
    6.     CKCON = 0x00; // 设置外部数据总线速度为最快
    7.     WTST = 0x00;  // 设置程序代码等待参数,
    8.     // 赋值为 0 可将 CPU 执行程序的速度设置为最快
    9.     P0M0 = 0x00;
    10.     P0M1 = 0x00;
    11.     P1M0 = 0x00;
    12.     P1M1 = 0x00;
    13.     P2M0 = 0x00;
    14.     P2M1 = 0x00;
    15.     P3M0 = 0x00;
    16.     P3M1 = 0x00;
    17.     P4M0 = 0x00;
    18.     P4M1 = 0x00;
    19.     P5M0 = 0x00;
    20.     P5M1 = 0x00;
    21.     LED = 0; // LED控制引脚为低电平
    22.     while (1)
    23.     {
    24.     }
    25. }
    复制代码

    代码拆解:
    sbit  是什么
    sbit  是 Keil C编译器中的一种语法.用于访问单个位(bit)。在使用sbit语法时,需要指定需要访问的位所在的寄存器和位的位置.


    P2又是什么? 在STC32G.H头文件中
    sfr P2 = 0xa0;
    原来P2是个寄存器.
    P2^5 是什么.表示访问寄存器的第5位.

    LED=0; 将是将引脚赋予低电平.

    拓展内容:

    那么现在是不是 对寄存器也有了一个初步的认识.简言之,P2 其实就是在STC32G.H绑定了莫个寄存器.弄明白这个问题,你可以自己定义自定义IO口将其绑定在特定的寄存器上,从而使编程更加灵活.
    寄存器.png


    点亮一组LED
    在上面的教程中,我相信你已经学会了 如何点亮一个led,那么如何点亮一组LED呢?
    还记得之前学的吗 ,一个内存单元(二个十六进制) 组成 8个IO口(二进制位),只要简单的转换下就好了
    我们进入仿真来学习

    IO组.png

    我们随便取消掉几个勾选,也就是说给这几个端口赋予低电平.期望点亮这些IO口
    得到了一个十六进制 CE ,我们将它转换成二进制试试
    最简单的方法当然是使用 WINDOWS 自带的 计算器了
    计算器1.png


    然后我们去代码实现下.

    1. #include <STC32G.H>
    2. void main()
    3. {
    4.     EAXFR = 1;    // 使能访问 XFR
    5.     CKCON = 0x00; // 设置外部数据总线速度为最快
    6.     WTST = 0x00;  // 设置程序代码等待参数,
    7.     // 赋值为 0 可将 CPU 执行程序的速度设置为最快
    8.     P0M0 = 0x00;
    9.     P0M1 = 0x00;
    10.     P1M0 = 0x00;
    11.     P1M1 = 0x00;
    12.     P2M0 = 0x00;
    13.     P2M1 = 0x00;
    14.     P3M0 = 0x00;
    15.     P3M1 = 0x00;
    16.     P4M0 = 0x00;
    17.     P4M1 = 0x00;
    18.     P5M0 = 0x00;
    19.     P5M1 = 0x00;
    20.     P2 =0XCE;//将16进制数组赋值给P2寄存器,直接操控8个LED灯
    21.     while (1)//这是一个空循环,阻断程序继续执行,如果不加while 根据单片机的特性,main函数 在执行完毕后
    22.     {
    23.     }
    24. }
    复制代码

    XX1.jpg

    通过本章的学习 我相信你已经学会 如何点亮一个IO 和点亮一组IO,并且对寄存器 有了一定的了解.那么问题来了

    问题1:
    我想让LED 实现闪烁的效果,那应该如何去做?

    这将引出下面一章  Delay 函数的使用...





    喜欢研究如何让电子产品变得更加智能和有趣.
    回复 支持 1 反对 0 送花

    使用道具 举报

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

    [LV.7]常住居民III

    11

    主题

    69

    回帖

    2874

    积分

    金牌会员

    单片机编程魔法师

    积分
    2874
     楼主| 发表于 2023-4-24 08:42:43 | 显示全部楼层
    本帖最后由 t176 于 2023-4-23 11:27 编辑

    Lesson 4


    Delay函数的使用,第一次使用寄存器
    上一章中,我们提出一个问题,如果使用Delay 函数 进行LED的闪烁

    首先我们整理下思路:
    LED 的闪烁他的步骤应该是怎么样的?
    LED灯亮---->LED灭----->LED灯亮---->LED灭
    是不是这样一个执行过程,但是如果没有时间间隔,单片机的亮灭速度非常快,我们的肉眼是无法捕捉到.
    那么有什么办法可以延迟LED的亮灭操作呢?
    什么是延迟.
    延迟顾名思义就是让计算机等下再执行下一条命令.
    那么计算机如何让他等待呢?
    我们可以嵌套一些循环代码,让单片机执行这些没有意义的代码,因为这些代码的执行需要时间,我们只要让他执行足够多的无用代码就能达到我们程序延时的 预期.
    那么我们应该如何确定需要执行多少 无效代码呢.
    STC_ISP 已经帮你做好了 你只要选下参数点下按钮就可以生成代码 .是不是很贴心.

    软件延时.png


    只要简单的设置下参数,他就能生成C语言或者汇编代码.
    注意.png

    看到注意事项没,WTST需要初始化00H(这将是我们接触的第一个寄存器)
    00H:H 表示16进制 00H 也就是十六进制的0X00
    那么WTST是什么呢,他是一个寄存器定义:
    先看头文件:
    sfr WTST = 0xe9;
    当我们遇到不知道,不清楚的寄存器定义,务必先查手册,官方的手册最核心的内容之一就是寄存器的解释和使用方法.
    为了方便编程,我已经将相关的头文件寄存器 翻译成中文 发布在STC 官网上,你也可以直接拿来替代 官方默认的头文件STC32G.H

    https://www.stcaimcu.com/forum.php?mod=viewthread&tid=1288

    WTST.png

    1. #include <STC32G.H>
    2. void Delay500ms()                //@11.0592MHz
    3. {
    4.         unsigned long i;
    5.         _nop_();
    6.         _nop_();
    7.         i = 1382398UL;
    8.         while (i) i--;
    9. }
    10. void main()
    11. {
    12.     EAXFR = 1;    // 使能访问 XFR
    13.     CKCON = 0x00; // 设置外部数据总线速度为最快
    14.     WTST = 0x00;  // 设置程序代码等待参数,// 赋值为 0 可将 CPU 执行程序的速度设置为最快
    15.     P0M0 = 0x00;
    16.     P0M1 = 0x00;
    17.     P1M0 = 0x00;
    18.     P1M1 = 0x00;
    19.     P2M0 = 0x00;
    20.     P2M1 = 0x00;
    21.     P3M0 = 0x00;
    22.     P3M1 = 0x00;
    23.     P4M0 = 0x00;
    24.     P4M1 = 0x00;
    25.     P5M0 = 0x00;
    26.     P5M1 = 0x00;
    27.     while (1)//这是一个空循环,阻断程序继续执行,如果不加while 根据单片机的特性,main函数 在执行完毕后
    28.     {
    29.                 Delay500ms();
    30.                 P25=~P25;
    31.     }
    32. }
    复制代码

    代码中
    P25=~P25;
    ~是取反的运算符,
    如果说P25 是高电平 那么就让他变成低电平.反之低电平变成高电平.




    那么通过这章,我们已经学会了,如何控制一个IO口的高低电平,达到LED闪烁的目的.
    这只是一个最简单的LED闪烁,程序.单片机能做的远远不止如此,比如我们需要实现一个花式点灯.那么应该如何去做呢?
    下集我们将编写这个程序.






    喜欢研究如何让电子产品变得更加智能和有趣.
    回复 支持 1 反对 0 送花

    使用道具 举报

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

    [LV.7]常住居民III

    11

    主题

    69

    回帖

    2874

    积分

    金牌会员

    单片机编程魔法师

    积分
    2874
     楼主| 发表于 2023-4-24 08:42:44 | 显示全部楼层
    本帖最后由 t176 于 2023-4-24 08:45 编辑

    Lesson 5


    实现一个花式流水灯


    1. #include <STC32G.H>
    2. #define LIGHT_COUNT 8 // LED 数量
    3. void Delay500ms() //@11.0592MHz
    4. {
    5.   unsigned long i;
    6.   _nop_();
    7.   _nop_();
    8.   i = 1382398UL;
    9.   while (i)
    10.     i--;
    11. }
    12. void main()
    13. {
    14.   unsigned char pattern[LIGHT_COUNT] = {
    15.       0x01, // 0000 0001 b
    16.       0x02, // 0000 0010 b
    17.       0x04, // 0000 0100 b
    18.       0x08, // 0000 1000 b
    19.       0x10, // 0001 0000 b
    20.       0x20, // 0010 0000 b
    21.       0x40, // 0100 0000 b
    22.       0x80  // 1000 0000 b
    23.   };            // LED 点亮模式
    24.   EAXFR = 1;    // 使能访问 XFR
    25.   CKCON = 0x00; // 设置外部数据总线速度为最快
    26.   WTST = 0x00;  // 设置程序代码等待参数,// 赋值为 0 可将 CPU 执行程序的速度设置为最快
    27.   P0M0 = 0x00;
    28.   P0M1 = 0x00;
    29.   P1M0 = 0x00;
    30.   P1M1 = 0x00;
    31.   P2M0 = 0x00;
    32.   P2M1 = 0x00;
    33.   P3M0 = 0x00;
    34.   P3M1 = 0x00;
    35.   P4M0 = 0x00;
    36.   P4M1 = 0x00;
    37.   P5M0 = 0x00;
    38.   P5M1 = 0x00;
    39.   while (1)
    40.   {
    41.     int i;
    42.     // 反向点亮每个 LED
    43.     for (i = LIGHT_COUNT - 1; i >= 0; i--)
    44.     {
    45.       P2 = ~pattern[i]; // 控制 LED 灯亮灭
    46.       Delay500ms();
    47.     }
    48.     // 轮流两个 LED 交替点亮
    49.     for (i = 0; i < LIGHT_COUNT - 1; i++)
    50.     {
    51.       P2 = ~(pattern[i] | pattern[i + 1]); // 控制 LED 灯亮灭
    52.       Delay500ms();
    53.     }
    54.     // 轮流两个 LED 交替点亮(2)
    55.     for (i = 7; i >= 0; i--)
    56.     {
    57.       P2 = ~(pattern[i] | pattern[i - 1]); // 控制 LED 灯亮灭
    58.       Delay500ms();
    59.     }
    60.     // 依次点亮每个 LED
    61.     for (i = 0; i < LIGHT_COUNT; i++)
    62.     {
    63.       P2 = ~pattern[i]; // 控制 LED 灯亮灭
    64.       Delay500ms();
    65.     }
    66.   }
    67. }
    复制代码


    在这个代码中分别实现了 LED 流水灯,和LED拖尾灯,当然如果你想让LED效果更炫酷可以,再进一步优化,这里只做简单学习.

    代码中我们第一次接触到了|  这个按位运算,
    P2 = ~(pattern | pattern[i - 1]);

    代码中 | 的 作用    将这两个数进行合并,

    ~我们之前已经学过了,  这里将合并计算后的结果,进行取反.

    在intrins.h 头文件 也有封装好的函数来实现我们所需的功能,但是前期我们少用,甚至不用.
    尽量使用位运算符,使用娴熟后.可以让代码变得很精简干练.

    好了这章就先到这里,留意下数组的写法,下一章数码管学习,我们会使用类似的写法

    一定要理解掌握相关的知识点,这一章其实没多少知识点,重点是要善于思考,尝试自己去写一个炫酷的花式点灯效果.




    下一章,我们将接触数码管.



    喜欢研究如何让电子产品变得更加智能和有趣.
    回复 支持 1 反对 0 送花

    使用道具 举报

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

    [LV.7]常住居民III

    11

    主题

    69

    回帖

    2874

    积分

    金牌会员

    单片机编程魔法师

    积分
    2874
     楼主| 发表于 2023-4-24 11:10:34 | 显示全部楼层
    本帖最后由 t176 于 2023-5-2 20:13 编辑

    Lesson 6


    数码管的原理

    昨天刚好收到官方邮寄的STC试验箱9.6.这就刚好排上用场了.本来打算数码管部分使用,89开发板制作教程.试验箱来的很及时啊

    拿到硬件第一件事,就是先看原理图.如果没有原理图的就追板.
    拓展知识:
    追板的手法是强光打底,勾出线路,然后抄板.蚀刻,钻孔,清洗....在这里不做多的介绍 因为STC 已经提供了完整的原理图,和PCB 图 .对于我们学习已经完全足够了.


    试验箱.jpg


    原理图:
    PCB.jpg 原理图.jpg

    让我们跟着,官方的原理图开始学习把.




    图1

    数码管接线图.jpg
    图2

    IC引脚.jpg
    图3

    COMSS8550.jpg


    数码管:(基础知识)
    数码管是一种用来显示数字和某些特殊符号的电子器件,通常由七个或更多个发光二极管组成。每个发光二极管被排列在一个固定的位置上,以便按照要求显示数字和字符。


    段的概念:每个数码管通常有七个以及七个以上发光二极管,用于显示数字 0 到 9 和一些字母。这些发光二极管组成一个显示单元被称为“段”

    数码管.png

    位的概念:为了显示多个数字或字母,需要使用多个数码管。在多个数码管中,每个数码管被称为“位”.列如实验箱中9.6 所用的元件就是2个4位的数码管,当然比较常见的 有1/2/3/4  位数码管


    多位数码管.png







    共阳极和共阴极:

    数码管的共阴和共阳是指数码管的引脚连接方式。
    在共阴数码管中,所有段的阴极(负极)都连接在一起,而每个段的阳极(正极)都分别连接到不同的引脚上。
    共阴极接法,所有的数码管共享一个阴极,而每个发光二极管的阳极通过转换器单独控制。因此,为了点亮某个数字或符号,必须将相应的阳极接到高电平,而将公共阴极连接到低电平。




    在共阳数码管中,所有段的阳极都连接在一起,而每个段的阴极都分别连接到不同的引脚上。

    在共阳极接法,所有的数码管共享一个阳极,而每个发光二极管的阴极通过转换器单独控制。因此,为了点亮某个数字或符号,必须将相应的阴极接到低电平,而将公共阳极连接到高电平。

    在试验箱9.6中,数码管使用的 共阳BS,当然还有一种是共阴AS.(本人非常有幸,在试验箱中同时体验了一波AS,和BS ).这是是一个心塞的故事....



    仔细观察 图1/2/3中的 原理图
    我们看到数码管的引脚连接,引脚相连在P6组上,并且看到位选连接在网络标识COM0-COM7 连接到了P7组


    点亮数码管
    学习完数码管的基础知识后.先将数码管当成普通发光二极管去使用. 那么我们如何点亮某位数码管中的一个LED(段):

    点亮数码管.png

    在这个数码管中,我们需要点亮改段中F通道,那么应该怎么做呢?

    我们回过来参考图1中的原理图

    段原理.png

    我们发现,他接在单片机的P65 IO口上.现在知道 一组数码管的F通道了,那么如何让他点亮第一位  数码管的 F通道呢?,
    那么你必须彻底弄清楚位选的概念.
    在原理图中,我们看到有K1-K4的  4个引脚,没错!那就是 位选.相应的引脚参考图3(IO口则以SS850 为媒介实现以小推大,将VCC电源放行到数码管位选端口
    )

    位原理图.png

    下面是 代码实现点亮 第一位数码管的F通道.

    1. #include <STC32G.H>
    2. void main()
    3. {
    4.     P6M0 = 0x00;
    5.     P6M1 = 0x00;
    6.     P7M0 = 0x00;
    7.     P7M1 = 0x00;
    8.     P7 = 0x7F; //01111111 B
    9.     P6 = 0xDF;//11011111 B
    10.     while (1)
    11.     {
    12.         
    13.    
    14.     }
    15. }
    复制代码
    实验现象:

    实验现象.jpg

    请尝试思考下代码中 P7 和P6 的取值原理,如果弄明白,那么恭喜你,数码管你已经学会了一大半了.如果没弄明白,没关系,我们下一章 静态显示和动态扫描中,会详细讲解,段码 ,位码.



    课外话:
    根据有关部门,相关人士透露我手上这张板子是测试用的错版,在自己动手 修复完板子错版问题:数码管AS---->BS,经过测试.PCB中,R41--->U12的F通道还出现了断板情况.,后来通过飞线解决.不知道有没有其他暗病.走一步算一步.整个系列下来,内心还是挺烦躁的.

    错板.jpg


    F通道断板.jpg
    飞线.jpg

    修复完.jpg






    喜欢研究如何让电子产品变得更加智能和有趣.
    回复 支持 1 反对 0 送花

    使用道具 举报

    该用户从未签到

    551

    主题

    9428

    回帖

    1万

    积分

    管理员

    积分
    14003
    发表于 2023-4-26 16:55:48 | 显示全部楼层

    本楼层我们随时可以下沉或删除,不影响楼主编辑创作


    做为楼主发帖:
    1,可以反复修改自己的各层分贴;
    2,先发个N层/20层/60层,自己后面再完善修改其中的各楼层内容
    3,一层也可以发表多章节
    这样就可以先开放了
    还有我们可以帮楼主删除部分他人跟贴/或下沉某个跟贴,帮楼主将后来楼主发表某个跟帖的,置顶到2楼


    本楼层我们随时可以下沉或删除,不影响楼主编辑创作

    回复 支持 反对 送花

    使用道具 举报

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

    [LV.7]常住居民III

    11

    主题

    69

    回帖

    2874

    积分

    金牌会员

    单片机编程魔法师

    积分
    2874
     楼主| 发表于 2023-4-27 08:54:29 | 显示全部楼层
    本帖最后由 t176 于 2023-5-5 11:30 编辑

    Lesson 7
    数码管实践(静态和动态扫描)

    段码讲解:
    通过上一课的学习,我们已经能点亮指定数码管中的一个发光二极管通道
    我们接下来通过仿真的方式学习下,段码和位码的原理


    首先在ISP 中将试验箱设置成仿真
    1.png

    因为代码很简短,我们直接F8 单步调试到while 中,进行空循环
    2.png


    我们再观察试验箱的 现象,已经成功点亮数码管 的F通道
    3.jpg

    我们在仿真中,查看下内存的段码 数据
    4.png


    我们可以看到 P6 的数据是DF 我们将它转换成二进制 ,再和数码管的排序进行比对
    5.png 6.png


    眼尖的小伙伴们 应该发现规律

    1   1    0   1        1   1   1   1    二进制
    dp  G   F   E        D   C   B  A   对应段码

    小知识点:
    dp:就是小数点,有的数码管样式是: 也是dp位.

    因为试验箱中使用的共阳数码管,也就是说, IO口为0情况下,通道才能点亮.

    是不是 很简单,明白了 这个道理,那么我们应该如何点亮 一个数字5呢?
    7.png

    我们通过刚才的学习,将它转成二进制


    1   0    0   1        0   0   1   0    二进制
    dp  G   F   E        D   C   B  A   对应段码


    8.png

    10010010 B = 92 H

    现在去内存中将DF,修改成92 试试.
    9.png

    我们看下试验箱的 现象:
    10.jpg


    是不是很简单.........段码讲完了.....别说你没弄明白

    位码讲解:

    段码我们已经学习完了,现在说说位码,刚才的实验现象可以看到,5显示在 第一位数码管上 如果我们需要让他显示在第二位数码管应该怎么做呢?
    从之前的原理图中我们了解过,位控制位COM0-7
    使用P7IO口 进行控制,那么我们去看下内存中的P7数据
    11.png

    我们将7F HEX转换成二进制 01111111,是不是很熟悉. 那么如果显然他 点亮第二位 是不是只要改成 10111 1111 再将10111 1111 B 转换成HEX 是 BF
    我们也去内存中将 P7的数据改成 BF HEX
    12.png

    我们再观察下实验现象:
    13.jpg

    是不是已经达到我们的预期效果.理解了 段码后,位码  是不是感觉好简单....


    根据刚才学的知识 你可以根据数码管  制造  很多奇奇怪怪的 字符 ,甚至,可以通过 流程控制 写一个 花样流水灯.

    实际数码管应用中,我们比较常见的 还是数字和简单的英文.下面我给整理出来了,这样你就不需要自己一个个的去制造段码了.

    试验箱中使用的共阳:

    1. unsigned char code leddata[]={
    2.                 0xC0,  //"0"
    3.                 0xF9,  //"1"
    4.                 0xA4,  //"2"
    5.                 0xB0,  //"3"
    6.                 0x99,  //"4"
    7.                 0x92,  //"5"
    8.                 0x82,  //"6"
    9.                 0xF8,  //"7"
    10.                 0x80,  //"8"
    11.                 0x90,  //"9"
    12.                 0x88,  //"A"
    13.                 0x83,  //"B"
    14.                 0xC6,  //"C"
    15.                 0xA1,  //"D"
    16.                 0x86,  //"E"
    17.                 0x8E,  //"F"
    18.                 0x89,  //"H"
    19.                 0xC7,  //"L"
    20.                 0xC8,  //"n"
    21.                 0xC1,  //"u"
    22.                 0x8C,  //"P"
    23.                 0xA3,  //"o"
    24.                 0xBF,  //"-"
    25.                 0xFF,  //熄灭
    26.                 0x92  //自定义
    27.                          };
    复制代码
    当然,市面还有共阴,这里为了以后你们方便我也提供下:

    1. unsigned char code leddata[]={
    2.                 0x3F,  //"0"
    3.                 0x06,  //"1"
    4.                 0x5B,  //"2"
    5.                 0x4F,  //"3"
    6.                 0x66,  //"4"
    7.                 0x6D,  //"5"
    8.                 0x7D,  //"6"
    9.                 0x07,  //"7"
    10.                 0x7F,  //"8"
    11.                 0x6F,  //"9"
    12.                 0x77,  //"A"
    13.                 0x7C,  //"B"
    14.                 0x39,  //"C"
    15.                 0x5E,  //"D"
    16.                 0x79,  //"E"
    17.                 0x71,  //"F"
    18.                 0x76,  //"H"
    19.                 0x38,  //"L"
    20.                 0x37,  //"n"
    21.                 0x3E,  //"u"
    22.                 0x73,  //"P"
    23.                 0x5C,  //"o"
    24.                 0x40,  //"-"
    25.                 0x00,  //熄灭
    26.                 0x6D  //自定义
    27.                          };
    复制代码


    接下来是 位码表:

    1.     unsigned char code WEI_data[] = {
    2.         0x7f, // 0111 1111        b 0
    3.         0xbf, // 1011 1111        b 1
    4.         0xdf, // 1101 1111        b 2
    5.         0xef, // 1110 1111        b 3
    6.         0xf7, // 1111 0111        b 4
    7.         0xfb, // 1111 1011        b 5
    8.         0xfd, // 1111 1101        b 6
    9.         0xfe, // 1111 1110        b 7
    10.     } ;
    复制代码


    静态扫描:
    好了段码表和位码表 都提供了.现在,可以写一个小程序巩固下:
    1. #include <STC32G.H>
    2. unsigned char code WEI_data[] = {
    3.     0x7f, // 0111 1111        b 0
    4.     0xbf, // 1011 1111        b 1
    5.     0xdf, // 1101 1111        b 2
    6.     0xef, // 1110 1111        b 3
    7.     0xf7, // 1111 0111        b 4
    8.     0xfb, // 1111 1011        b 5
    9.     0xfd, // 1111 1101        b 6
    10.     0xfe, // 1111 1110        b 7
    11. };
    12. unsigned char code leddata[] = {
    13.     0xC0, //"0"
    14.     0xF9, //"1"
    15.     0xA4, //"2"
    16.     0xB0, //"3"
    17.     0x99, //"4"
    18.     0x92, //"5"
    19.     0x82, //"6"
    20.     0xF8, //"7"
    21.     0x80, //"8"
    22.     0x90, //"9"
    23.     0x88, //"A"
    24.     0x83, //"B"
    25.     0xC6, //"C"
    26.     0xA1, //"D"
    27.     0x86, //"E"
    28.     0x8E, //"F"
    29.     0x89, //"H"
    30.     0xC7, //"L"
    31.     0xC8, //"n"
    32.     0xC1, //"u"
    33.     0x8C, //"P"
    34.     0xA3, //"o"
    35.     0xBF, //"-"
    36.     0xFF, // 熄灭
    37.     0x92  // 自定义
    38. };
    39. void Delay500ms() //@11.0592MHz
    40. {
    41.     unsigned long i;
    42.     _nop_();
    43.     _nop_();
    44.     i = 1382398UL;
    45.     while (i)
    46.         i--;
    47. }
    48. void main()
    49. {
    50.     int DUAN = 0, WEI = 0, i = 0;
    51.     WTST =0X00;
    52.     P6M0 = 0x00;
    53.     P6M1 = 0x00;
    54.     P7M0 = 0x00;
    55.     P7M1 = 0x00;
    56.     while (1)
    57.     {
    58.         for (i = 0; i < 8; i++)
    59.         {
    60.             P7 = WEI_data[i];
    61.             P6 = leddata[i];
    62.             Delay500ms();
    63.         }
    64.     }
    65. }
    复制代码

    试验箱现象:








    通过上面的实验,我们发现只能显示一位数码管或者几位相同的数字数码管,那么有什么办法同时显示多位并且不同的数值呢呢?,这就引出 我们下面这一部分的内容:

    动态扫描:
    动态扫描是一种常见的多路复用显示方法,基本原理是将要显示的数字分别输出到每个数码管上,由于人眼的视觉暂留效应,数码管快速切换时会产生“看起来同时显示”的效果。
    当系统的刷新率高于人眼视觉的响应速度,人眼就无法察觉到数码管的闪烁,而是错觉它们在同时显示。

    在动态扫描中,每次只有一个数码管被选通,其他数码管都处于关闭状态。
    所以当数码管每次切换的速度足够快,就能达到动态扫描的目的

    其原理 也非常的简单.我们传入一个值只要将每一位上的数据存到一个数组中,然后用极短的时间去切换显示每一位数码管.下面是实现代码

    1. #include <STC32G.H>
    2. unsigned char code WEI_data[] = {
    3.     0x7f, // 0111 1111        b 0
    4.     0xbf, // 1011 1111        b 1
    5.     0xdf, // 1101 1111        b 2
    6.     0xef, // 1110 1111        b 3
    7.     0xf7, // 1111 0111        b 4
    8.     0xfb, // 1111 1011        b 5
    9.     0xfd, // 1111 1101        b 6
    10.     0xfe, // 1111 1110        b 7
    11. };
    12. unsigned char code leddata[] = {
    13.     0xC0, //"0"
    14.     0xF9, //"1"
    15.     0xA4, //"2"
    16.     0xB0, //"3"
    17.     0x99, //"4"
    18.     0x92, //"5"
    19.     0x82, //"6"
    20.     0xF8, //"7"
    21.     0x80, //"8"
    22.     0x90, //"9"
    23.     0x88, //"A"
    24.     0x83, //"B"
    25.     0xC6, //"C"
    26.     0xA1, //"D"
    27.     0x86, //"E"
    28.     0x8E, //"F"
    29.     0x89, //"H"
    30.     0xC7, //"L"
    31.     0xC8, //"n"
    32.     0xC1, //"u"
    33.     0x8C, //"P"
    34.     0xA3, //"o"
    35.     0xBF, //"-"
    36.     0xFF, // 熄灭
    37.     0x92  // 自定义
    38. };
    39. /*
    40. *----------------------------------------------------------------------------------------------
    41. * 函数名称:void Delay2ms()
    42. * 函数功能:延迟2ms
    43. * 入口参数:@
    44. * 函数返回:@
    45. * 当前版本: Ver1.0
    46. * 修改时间:2023/05/05 10:45:07
    47. * 作者:t176#qq.com
    48. * 创建时间:2023/05/05 10:45:07
    49. -----------------------------------------------------------------------------------------------
    50. */
    51. void Delay2ms() //@11.0592MHz
    52. {
    53.     unsigned long i;
    54.     _nop_();
    55.     i = 5528UL;
    56.     while (i)
    57.         i--;
    58. }
    59. /*
    60. *----------------------------------------------------------------------------------------------
    61. * 函数名称:void Display( long val)
    62. * 函数功能:拆分一个长整型,数码管每一位显示相关数据
    63. * 入口参数:@
    64. * 函数返回:@
    65. * 当前版本: Ver1.0
    66. * 修改时间:2023/05/05 10:43:11
    67. * 作者:t176#qq.com
    68. * 创建时间:2023/05/05 10:43:11
    69. -----------------------------------------------------------------------------------------------
    70. */
    71. void Display(long val)
    72. {
    73.     int val_arr[8]; // 定义一个大小为8的整型数组
    74.     int i, j = 0;
    75.     while (val != 0)
    76.     {
    77.         val_arr[j] = val % 10; // 取num的最后一位,存入数组
    78.         val /= 10;             // 缩小10倍
    79.         j++;                   // 移动数组下标
    80.     }
    81.     for (i = 0; i < j; i++)
    82.     {
    83.         P6 = 0XFF;                // 清除鬼影
    84.         P7 = WEI_data[j - i - 1]; // 位选择(j-i-1)反转显示
    85.         P6 = leddata[val_arr[i]]; // 段选择
    86.         Delay2ms();
    87.     }
    88. }
    89. void main()
    90. {
    91.     WTST = 0X00; // 速度最快
    92.     P6M0 = 0x00;
    93.     P6M1 = 0x00;
    94.     P7M0 = 0x00;
    95.     P7M1 = 0x00;
    96.     while (1)
    97.     {
    98.         Display(1254680);
    99.     }
    100. }
    复制代码


    试验箱现象:





    喜欢研究如何让电子产品变得更加智能和有趣.
    回复 支持 1 反对 0 送花

    使用道具 举报

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

    [LV.7]常住居民III

    11

    主题

    69

    回帖

    2874

    积分

    金牌会员

    单片机编程魔法师

    积分
    2874
     楼主| 发表于 2023-4-27 08:55:09 | 显示全部楼层
    Lesson 8
    独立键盘和矩阵键盘
    喜欢研究如何让电子产品变得更加智能和有趣.
    回复 支持 反对 送花

    使用道具 举报

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

    [LV.7]常住居民III

    11

    主题

    69

    回帖

    2874

    积分

    金牌会员

    单片机编程魔法师

    积分
    2874
     楼主| 发表于 2023-4-27 08:55:53 | 显示全部楼层
    Lesson 9
    点阵屏的使用
    喜欢研究如何让电子产品变得更加智能和有趣.
    回复 支持 反对 送花

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2024-5-14 14:55 , Processed in 0.098990 second(s), 71 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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