STC32G12K128 成长道路
本帖最后由 t176 于 2023-4-27 08:46 编辑Lesson 1
开篇:
LINK1D 仿真:
1.首先,仿真线路的连接;
屠龙刀:
2.目标芯片与STC LINK1D硬件仿真器通过或SWD接口连接(P3.0,P3.1),以建立仿真通讯链路;
3.在keil进行参数配置,以及ISP设置仿真芯片
详细方法,请参考STC32G.PDF5.11章节和5.12章节.(****必看,根据手册内容进行配置)
Page135-151.
PDF下载:
请注意:如果在ISP中设置为仿真芯片,没设置端口和SWD,将仿真失败
4.编写并编译代码,生成HEX文件
5.通过STC_ISP,将生成的可烧录指令文件下载到STC LINK1D硬件仿真器中的处理器内存区域,作为仿真器内部的程序;
6.启动keil调试功能,在仿真器和目标芯片之间建立仿真操作链路;
7. LINK1D仿真操作过程中,通过LINK1D与PC之间的通讯,将LINK1D内部的程序烧录进目标芯片中.
8.keil调试工具可以实时地显示芯片内部状态信息.比如查看某一个变量的值,或是切换到代码窗口查看此时程序的执行位置;实现目标芯片的单步调试、断点调试、变量跟踪等功能,方便用户对复杂程序进行调试。
本帖最后由 t176 于 2023-4-21 16:07 编辑
Lesson 2
5分钟理解进制存储机制,IO口:(相关理论知识,可通过百度查询,这里只做仿真效果下的学习)
IO口是单片机用来控制外部设备的一组通用输入/输出接口,
IO口 可以配置为4种模式:
准双向口:传统8051端口模式,弱上拉.灌电流可达20mA,拉电流为270~150μA(存在制造误差)
推挽输出:强上拉输出,可达20mA,要加限流电阻
高阻输入:电流既不能流入也不能流出
开漏输出:内部上拉电阻断开开漏模式既可读外部状态也可对外输出(高电平或低电平)。如要正确读外部状态或需要对外输出高电平,需外加上拉电阻,否则读不到外部状态,也对外输不出高电平。
准双向模式:准双向IO口是一种介于输入和输出之间的模式,它可以在不改变端口的输入/输出状态的情况下,切换IO口的方向。这种模式常用于I/O总线和共享总线设备的控制。
开漏/推挽模式:开漏模式和推挽模式是输出模式的两种变体。在开漏模式下,输出端口只能输出低电平或不输出电平;而在推挽模式下,输出端口可以输出高电平或低电平。这两种模式常用于将多个输出口连接到同一总线上,从而实现集中控制。
目前学习我们先用准双向IO口进行配置学习,后期应用案列中会逐步介绍其他模式
4种模式的定义可以参考PDF 11章 Page 293 或者直接使用ISP 生成配置代码
通过编程控制IO口的高低电平状态,就可以实现对外部设备的控制。
32GIO口的引脚图:
根据封装工艺的需求,芯片在生成时,有多种封装规格 下面是LQFP的封装样式,
当然还有其他样式,在ISP 中可以查阅观察.
通过引脚的观察 我们看到 有一组P开头的引脚0-7,这就是IO口.
通常IO 口 一组为八个. 0-7 列如 P0.1-P0.7
他们在内存中形态以十六进制存储(00-FF).单个IO口则是二进制存储(0-1)
8个二进制位 组成二个十六进制的存储单元
如果还是理解不太明白.没关系,接下来使用一个仿真程序带你窥视内存.
下面是一份简单的代码,你不需要对他进行理解.我们这里只用作于仿真,强化学习进制和IO 的知识点.
#include <STC32G.H>
void main()
{
EAXFR = 1; // 使能访问 XFR
CKCON = 0x00; // 设置外部数据总线速度为最快
WTST = 0x00;// 设置程序代码等待参数,
// 赋值为 0 可将 CPU 执行程序的速度设置为最快
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
while (1)
{
P25=~P25;//翻转电平
}
}
我们先对这段代码进行仿真:
在单片机中,常用的进制有二进制、十进制和十六进制。
当你顺利进入仿真 你看到的keil 界面是这样的
我们可以看到
1 是命令执行执行窗口
2 是监视区域
我们为了实时观察变量 建议打开变量监视 按照步骤执行第3步 和第四部
点开 监视表1 我们就能看到 有三个字段
NAME VALUETYPE
NAME: 表达式
VALUE:值
TYPE:类型
在这里我们可以根据编辑特有的表达式 进行内容观察
图中我们可以看到使用表达式 可以直接进行计算,好了,基础的仿真 就讲到这里.我们接下来 IO口(数值)在内存是存储状态
我们打开内存窗口
我们在内存地址中输入&P2
为什么要加&,&是取地址,
我们可以看到内存中的存储单元都是 以16进制展示的(00-FF).这个FF 就是存储了 8个二进制位既P2(IO口组合)
那么我们如何理解IO口是二进制状态呢,接下来看这张图
当点击完成后我们就可以看到一个IO口的 具体二进制存储情况
7-0 Bits 存储了 P2_IO口组的 IO状态 .
打勾的表示1如果没勾 就会变成0;
现在你可以尝试下 点击这些勾选 对比 前面16进制的 变化.
通过点击,你会发现前面的16进制数值也跟着相应的变化,同时可以观察 内存区域或者变量监视表会跟着变化
那么我们就明白了,一个IO口存储一个二进制(0-1) 一个十六进制(0-F)存储着 4个IO口的二进制状态.FF所以可以存储8个IO口.到这里我相信你对进制的内存存储已经有一个 新的认识.
接下来,请点击勾选观察单片机的LED亮灭状态
点了没变化啊,咋回事?
别着急 因为代码IO口配置没有初始化 你没执行
我们可以选择快捷键F11 进行执行单步调试,在代码执行完20行,那么所以的IO 口初始化代码都已经初始化完毕.现在你再点击试试.
你会发现 你点击一个IO口,开发板上的LED就会产生相应的亮灭变化.
根据上面的试验,我们学习了 进制的存储状态,和IO口的概念.以及仿真的基本操作.
相信你对进制存储以及转换有了更直观的认识.
并且发现仿真器 对仿真芯片拥有实时的控制权和监视能力.那么在后面的开发中,相当于给程序员一只眼睛,在接下来的学习中.会开始写代码,这个过程中,使用仿真去调试会事半功倍.
现在问题来了...............
问题1:
硬件仿真模式下,LINK1D 是不是对32G有绝对控制权?
从理想状态上来说,是可以的.但是考虑到仿真环境中可能存在的各种干扰因素
(自然因素干扰)
例如噪声、时钟波形失真等因素,这些都可能会影响LINK1D对目标单片机的控制能力。
(人为因素干扰)
如果开发者在仿真过程中,对寄存器进行错误的修改,导致仿真链路的破坏.
LINK1D将不能完全地控制和解决这些问题.
问题2:
为什么IO口变成0LED就会点亮?变成1为什么又熄灭.
这就引出我们下一课学习,如何点亮一个LED灯,原理是什么,如何编写相应的代码?
本帖最后由 t176 于 2023-4-22 10:31 编辑
Lesson 3
编写第一个程序,点亮LED(以及寄存器的认识)
屠龙刀在出厂的时候默认P2端口焊接了电阻和绿光LED灯
图中
1为VCC
2为贴片发光二极管
3限流电阻
电路分析:
电流经过VCC(1)----->发光二极管(2)----->限流电阻---->IO口
当IO口状态为0时,IO口处于低电平状态 整个电流流通,LED点亮
当IO口状态为1时,IO口处于高电平状态.根据电气特性,LED熄灭
限流电阻的作用:
图中使用5.1K 的限流电阻,限制电路中电流大小,从而保护led,可以延长led的寿命.
明白了LED的亮灭,可以根据条件 编写相应代码 ,点亮LED
编写代码:
#include <STC32G.H>
sbit LED = P2 ^ 5; // 位定义,将LED 变量 定义为P2口的第5个引脚
void main()
{
EAXFR = 1; // 使能访问 XFR
CKCON = 0x00; // 设置外部数据总线速度为最快
WTST = 0x00;// 设置程序代码等待参数,
// 赋值为 0 可将 CPU 执行程序的速度设置为最快
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
LED = 0; // LED控制引脚为低电平
while (1)
{
}
}
代码拆解:
sbit是什么
sbit是 Keil C编译器中的一种语法.用于访问单个位(bit)。在使用sbit语法时,需要指定需要访问的位所在的寄存器和位的位置.
P2又是什么? 在STC32G.H头文件中
sfr P2 = 0xa0;
原来P2是个寄存器.
P2^5 是什么.表示访问寄存器的第5位.
LED=0; 将是将引脚赋予低电平.
拓展内容:
那么现在是不是 对寄存器也有了一个初步的认识.简言之,P2 其实就是在STC32G.H绑定了莫个寄存器.弄明白这个问题,你可以自己定义自定义IO口将其绑定在特定的寄存器上,从而使编程更加灵活.
点亮一组LED
在上面的教程中,我相信你已经学会了 如何点亮一个led,那么如何点亮一组LED呢?
还记得之前学的吗 ,一个内存单元(二个十六进制) 组成 8个IO口(二进制位),只要简单的转换下就好了
我们进入仿真来学习
我们随便取消掉几个勾选,也就是说给这几个端口赋予低电平.期望点亮这些IO口
得到了一个十六进制 CE ,我们将它转换成二进制试试
最简单的方法当然是使用 WINDOWS 自带的 计算器了
然后我们去代码实现下.
#include <STC32G.H>
void main()
{
EAXFR = 1; // 使能访问 XFR
CKCON = 0x00; // 设置外部数据总线速度为最快
WTST = 0x00;// 设置程序代码等待参数,
// 赋值为 0 可将 CPU 执行程序的速度设置为最快
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
P2 =0XCE;//将16进制数组赋值给P2寄存器,直接操控8个LED灯
while (1)//这是一个空循环,阻断程序继续执行,如果不加while 根据单片机的特性,main函数 在执行完毕后
{
}
}
通过本章的学习 我相信你已经学会 如何点亮一个IO 和点亮一组IO,并且对寄存器 有了一定的了解.那么问题来了
问题1:
我想让LED 实现闪烁的效果,那应该如何去做?
这将引出下面一章Delay 函数的使用...
本帖最后由 t176 于 2023-4-23 11:27 编辑
Lesson 4
Delay函数的使用,第一次使用寄存器
上一章中,我们提出一个问题,如果使用Delay 函数 进行LED的闪烁
首先我们整理下思路:
LED 的闪烁他的步骤应该是怎么样的?
LED灯亮---->LED灭----->LED灯亮---->LED灭
是不是这样一个执行过程,但是如果没有时间间隔,单片机的亮灭速度非常快,我们的肉眼是无法捕捉到.
那么有什么办法可以延迟LED的亮灭操作呢?
什么是延迟.
延迟顾名思义就是让计算机等下再执行下一条命令.
那么计算机如何让他等待呢?
我们可以嵌套一些循环代码,让单片机执行这些没有意义的代码,因为这些代码的执行需要时间,我们只要让他执行足够多的无用代码就能达到我们程序延时的 预期.
那么我们应该如何确定需要执行多少 无效代码呢.
STC_ISP 已经帮你做好了 你只要选下参数点下按钮就可以生成代码 .是不是很贴心.
只要简单的设置下参数,他就能生成C语言或者汇编代码.
看到注意事项没,WTST需要初始化00H(这将是我们接触的第一个寄存器)
00H:H 表示16进制 00H 也就是十六进制的0X00
那么WTST是什么呢,他是一个寄存器定义:
先看头文件:
sfr WTST = 0xe9;
当我们遇到不知道,不清楚的寄存器定义,务必先查手册,官方的手册最核心的内容之一就是寄存器的解释和使用方法.
为了方便编程,我已经将相关的头文件寄存器 翻译成中文 发布在STC 官网上,你也可以直接拿来替代 官方默认的头文件STC32G.H
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=1288
#include <STC32G.H>
void Delay500ms() //@11.0592MHz
{
unsigned long i;
_nop_();
_nop_();
i = 1382398UL;
while (i) i--;
}
void main()
{
EAXFR = 1; // 使能访问 XFR
CKCON = 0x00; // 设置外部数据总线速度为最快
WTST = 0x00;// 设置程序代码等待参数,// 赋值为 0 可将 CPU 执行程序的速度设置为最快
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
while (1)//这是一个空循环,阻断程序继续执行,如果不加while 根据单片机的特性,main函数 在执行完毕后
{
Delay500ms();
P25=~P25;
}
}
代码中
P25=~P25;
~是取反的运算符,
如果说P25 是高电平 那么就让他变成低电平.反之低电平变成高电平.
那么通过这章,我们已经学会了,如何控制一个IO口的高低电平,达到LED闪烁的目的.
这只是一个最简单的LED闪烁,程序.单片机能做的远远不止如此,比如我们需要实现一个花式点灯.那么应该如何去做呢?
下集我们将编写这个程序.
本帖最后由 t176 于 2023-4-24 08:45 编辑
Lesson 5
实现一个花式流水灯
#include <STC32G.H>
#define LIGHT_COUNT 8 // LED 数量
void Delay500ms() //@11.0592MHz
{
unsigned long i;
_nop_();
_nop_();
i = 1382398UL;
while (i)
i--;
}
void main()
{
unsigned char pattern = {
0x01, // 0000 0001 b
0x02, // 0000 0010 b
0x04, // 0000 0100 b
0x08, // 0000 1000 b
0x10, // 0001 0000 b
0x20, // 0010 0000 b
0x40, // 0100 0000 b
0x80// 1000 0000 b
}; // LED 点亮模式
EAXFR = 1; // 使能访问 XFR
CKCON = 0x00; // 设置外部数据总线速度为最快
WTST = 0x00;// 设置程序代码等待参数,// 赋值为 0 可将 CPU 执行程序的速度设置为最快
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
while (1)
{
int i;
// 反向点亮每个 LED
for (i = LIGHT_COUNT - 1; i >= 0; i--)
{
P2 = ~pattern; // 控制 LED 灯亮灭
Delay500ms();
}
// 轮流两个 LED 交替点亮
for (i = 0; i < LIGHT_COUNT - 1; i++)
{
P2 = ~(pattern | pattern); // 控制 LED 灯亮灭
Delay500ms();
}
// 轮流两个 LED 交替点亮(2)
for (i = 7; i >= 0; i--)
{
P2 = ~(pattern | pattern); // 控制 LED 灯亮灭
Delay500ms();
}
// 依次点亮每个 LED
for (i = 0; i < LIGHT_COUNT; i++)
{
P2 = ~pattern; // 控制 LED 灯亮灭
Delay500ms();
}
}
}
在这个代码中分别实现了 LED 流水灯,和LED拖尾灯,当然如果你想让LED效果更炫酷可以,再进一步优化,这里只做简单学习.
代码中我们第一次接触到了|这个按位运算,
P2 = ~(pattern | pattern);
代码中 | 的 作用 将这两个数进行合并,
~我们之前已经学过了,这里将合并计算后的结果,进行取反.
在intrins.h 头文件 也有封装好的函数来实现我们所需的功能,但是前期我们少用,甚至不用.
尽量使用位运算符,使用娴熟后.可以让代码变得很精简干练.
好了这章就先到这里,留意下数组的写法,下一章数码管学习,我们会使用类似的写法
一定要理解掌握相关的知识点,这一章其实没多少知识点,重点是要善于思考,尝试自己去写一个炫酷的花式点灯效果.
下一章,我们将接触数码管.
本帖最后由 t176 于 2023-5-2 20:13 编辑
Lesson 6
数码管的原理
昨天刚好收到官方邮寄的STC试验箱9.6.这就刚好排上用场了.本来打算数码管部分使用,89开发板制作教程.试验箱来的很及时啊
拿到硬件第一件事,就是先看原理图.如果没有原理图的就追板.
拓展知识:
追板的手法是强光打底,勾出线路,然后抄板.蚀刻,钻孔,清洗....在这里不做多的介绍 因为STC 已经提供了完整的原理图,和PCB 图 .对于我们学习已经完全足够了.
原理图:
让我们跟着,官方的原理图开始学习把.
图1
图2
图3
数码管:(基础知识)
数码管是一种用来显示数字和某些特殊符号的电子器件,通常由七个或更多个发光二极管组成。每个发光二极管被排列在一个固定的位置上,以便按照要求显示数字和字符。
段的概念:每个数码管通常有七个以及七个以上发光二极管,用于显示数字 0 到 9 和一些字母。这些发光二极管组成一个显示单元被称为“段”
位的概念:为了显示多个数字或字母,需要使用多个数码管。在多个数码管中,每个数码管被称为“位”.列如实验箱中9.6 所用的元件就是2个4位的数码管,当然比较常见的 有1/2/3/4位数码管
共阳极和共阴极:
数码管的共阴和共阳是指数码管的引脚连接方式。
在共阴数码管中,所有段的阴极(负极)都连接在一起,而每个段的阳极(正极)都分别连接到不同的引脚上。
共阴极接法,所有的数码管共享一个阴极,而每个发光二极管的阳极通过转换器单独控制。因此,为了点亮某个数字或符号,必须将相应的阳极接到高电平,而将公共阴极连接到低电平。
在共阳数码管中,所有段的阳极都连接在一起,而每个段的阴极都分别连接到不同的引脚上。
在共阳极接法,所有的数码管共享一个阳极,而每个发光二极管的阴极通过转换器单独控制。因此,为了点亮某个数字或符号,必须将相应的阴极接到低电平,而将公共阳极连接到高电平。
在试验箱9.6中,数码管使用的 共阳BS,当然还有一种是共阴AS.(本人非常有幸,在试验箱中同时体验了一波AS,和BS ){:4_192:}.这是是一个心塞的故事....
仔细观察 图1/2/3中的 原理图
我们看到数码管的引脚连接,引脚相连在P6组上,并且看到位选连接在网络标识COM0-COM7 连接到了P7组
点亮数码管
学习完数码管的基础知识后.先将数码管当成普通发光二极管去使用. 那么我们如何点亮某位数码管中的一个LED(段):
在这个数码管中,我们需要点亮改段中F通道,那么应该怎么做呢?
我们回过来参考图1中的原理图
我们发现,他接在单片机的P65 IO口上.现在知道 一组数码管的F通道了,那么如何让他点亮第一位数码管的 F通道呢?,
那么你必须彻底弄清楚位选的概念.
在原理图中,我们看到有K1-K4的4个引脚,没错!那就是 位选.相应的引脚参考图3(IO口则以SS850 为媒介实现以小推大,将VCC电源放行到数码管位选端口
)
下面是 代码实现点亮 第一位数码管的F通道.
#include <STC32G.H>
void main()
{
P6M0 = 0x00;
P6M1 = 0x00;
P7M0 = 0x00;
P7M1 = 0x00;
P7 = 0x7F; //01111111 B
P6 = 0xDF;//11011111 B
while (1)
{
}
}实验现象:
请尝试思考下代码中 P7 和P6 的取值原理,如果弄明白,那么恭喜你,数码管你已经学会了一大半了.如果没弄明白,没关系,我们下一章 静态显示和动态扫描中,会详细讲解,段码 ,位码.
static/image/hrline/1.gif
课外话:
根据有关部门,相关人士透露我手上这张板子是测试用的错版,在自己动手 修复完板子错版问题:数码管AS---->BS,经过测试.PCB中,R41--->U12的F通道还出现了断板情况.,后来通过飞线解决.不知道有没有其他暗病.走一步算一步{:dizzy:}.整个系列下来,内心还是挺烦躁的.
本楼层我们随时可以下沉或删除,不影响楼主编辑创作
做为楼主发帖:
1,可以反复修改自己的各层分贴;
2,先发个N层/20层/60层,自己后面再完善修改其中的各楼层内容
3,一层也可以发表多章节
这样就可以先开放了
还有我们可以帮楼主删除部分他人跟贴/或下沉某个跟贴,帮楼主将后来楼主发表某个跟帖的,置顶到2楼
本楼层我们随时可以下沉或删除,不影响楼主编辑创作
本帖最后由 t176 于 2023-5-5 11:30 编辑
Lesson 7
数码管实践(静态和动态扫描)
段码讲解:
通过上一课的学习,我们已经能点亮指定数码管中的一个发光二极管通道
我们接下来通过仿真的方式学习下,段码和位码的原理
首先在ISP 中将试验箱设置成仿真
因为代码很简短,我们直接F8 单步调试到while 中,进行空循环
我们再观察试验箱的 现象,已经成功点亮数码管 的F通道
我们在仿真中,查看下内存的段码 数据
我们可以看到 P6 的数据是DF 我们将它转换成二进制 ,再和数码管的排序进行比对
眼尖的小伙伴们 应该发现规律
1 1 0 1 1 1 1 1 二进制
dpG F E D C BA 对应段码
小知识点:
dp:就是小数点,有的数码管样式是: 也是dp位.
因为试验箱中使用的共阳数码管,也就是说, IO口为0情况下,通道才能点亮.
是不是 很简单,明白了 这个道理,那么我们应该如何点亮 一个数字5呢?
我们通过刚才的学习,将它转成二进制
1 0 0 1 0 0 1 0 二进制
dpG F E D C BA 对应段码
10010010 B = 92 H
现在去内存中将DF,修改成92 试试.
我们看下试验箱的 现象:
是不是很简单.........段码讲完了.....别说你没弄明白 {:smile:}
位码讲解:
段码我们已经学习完了,现在说说位码,刚才的实验现象可以看到,5显示在 第一位数码管上 如果我们需要让他显示在第二位数码管应该怎么做呢?
从之前的原理图中我们了解过,位控制位COM0-7
使用P7IO口 进行控制,那么我们去看下内存中的P7数据
我们将7F HEX转换成二进制 01111111,是不是很熟悉. 那么如果显然他 点亮第二位 是不是只要改成 10111 1111 再将10111 1111 B 转换成HEX 是 BF
我们也去内存中将 P7的数据改成 BF HEX
我们再观察下实验现象:
是不是已经达到我们的预期效果.理解了 段码后,位码是不是感觉好简单....
根据刚才学的知识 你可以根据数码管制造很多奇奇怪怪的 字符 ,甚至,可以通过 流程控制 写一个 花样流水灯.
实际数码管应用中,我们比较常见的 还是数字和简单的英文.下面我给整理出来了,这样你就不需要自己一个个的去制造段码了.
试验箱中使用的共阳:
unsigned char code leddata[]={
0xC0,//"0"
0xF9,//"1"
0xA4,//"2"
0xB0,//"3"
0x99,//"4"
0x92,//"5"
0x82,//"6"
0xF8,//"7"
0x80,//"8"
0x90,//"9"
0x88,//"A"
0x83,//"B"
0xC6,//"C"
0xA1,//"D"
0x86,//"E"
0x8E,//"F"
0x89,//"H"
0xC7,//"L"
0xC8,//"n"
0xC1,//"u"
0x8C,//"P"
0xA3,//"o"
0xBF,//"-"
0xFF,//熄灭
0x92//自定义
};
当然,市面还有共阴,这里为了以后你们方便我也提供下:
unsigned char code leddata[]={
0x3F,//"0"
0x06,//"1"
0x5B,//"2"
0x4F,//"3"
0x66,//"4"
0x6D,//"5"
0x7D,//"6"
0x07,//"7"
0x7F,//"8"
0x6F,//"9"
0x77,//"A"
0x7C,//"B"
0x39,//"C"
0x5E,//"D"
0x79,//"E"
0x71,//"F"
0x76,//"H"
0x38,//"L"
0x37,//"n"
0x3E,//"u"
0x73,//"P"
0x5C,//"o"
0x40,//"-"
0x00,//熄灭
0x6D//自定义
};
接下来是 位码表:
unsigned char code WEI_data[] = {
0x7f, // 0111 1111 b 0
0xbf, // 1011 1111 b 1
0xdf, // 1101 1111 b 2
0xef, // 1110 1111 b 3
0xf7, // 1111 0111 b 4
0xfb, // 1111 1011 b 5
0xfd, // 1111 1101 b 6
0xfe, // 1111 1110 b 7
} ;
静态扫描:
好了段码表和位码表 都提供了.现在,可以写一个小程序巩固下:
#include <STC32G.H>
unsigned char code WEI_data[] = {
0x7f, // 0111 1111 b 0
0xbf, // 1011 1111 b 1
0xdf, // 1101 1111 b 2
0xef, // 1110 1111 b 3
0xf7, // 1111 0111 b 4
0xfb, // 1111 1011 b 5
0xfd, // 1111 1101 b 6
0xfe, // 1111 1110 b 7
};
unsigned char code leddata[] = {
0xC0, //"0"
0xF9, //"1"
0xA4, //"2"
0xB0, //"3"
0x99, //"4"
0x92, //"5"
0x82, //"6"
0xF8, //"7"
0x80, //"8"
0x90, //"9"
0x88, //"A"
0x83, //"B"
0xC6, //"C"
0xA1, //"D"
0x86, //"E"
0x8E, //"F"
0x89, //"H"
0xC7, //"L"
0xC8, //"n"
0xC1, //"u"
0x8C, //"P"
0xA3, //"o"
0xBF, //"-"
0xFF, // 熄灭
0x92// 自定义
};
void Delay500ms() //@11.0592MHz
{
unsigned long i;
_nop_();
_nop_();
i = 1382398UL;
while (i)
i--;
}
void main()
{
int DUAN = 0, WEI = 0, i = 0;
WTST =0X00;
P6M0 = 0x00;
P6M1 = 0x00;
P7M0 = 0x00;
P7M1 = 0x00;
while (1)
{
for (i = 0; i < 8; i++)
{
P7 = WEI_data;
P6 = leddata;
Delay500ms();
}
}
}
试验箱现象:
attach://9396.mp4
通过上面的实验,我们发现只能显示一位数码管或者几位相同的数字数码管,那么有什么办法同时显示多位并且不同的数值呢呢?,这就引出 我们下面这一部分的内容:
动态扫描:
动态扫描是一种常见的多路复用显示方法,基本原理是将要显示的数字分别输出到每个数码管上,由于人眼的视觉暂留效应,数码管快速切换时会产生“看起来同时显示”的效果。
当系统的刷新率高于人眼视觉的响应速度,人眼就无法察觉到数码管的闪烁,而是错觉它们在同时显示。
在动态扫描中,每次只有一个数码管被选通,其他数码管都处于关闭状态。
所以当数码管每次切换的速度足够快,就能达到动态扫描的目的
其原理 也非常的简单.我们传入一个值只要将每一位上的数据存到一个数组中,然后用极短的时间去切换显示每一位数码管.下面是实现代码
#include <STC32G.H>
unsigned char code WEI_data[] = {
0x7f, // 0111 1111 b 0
0xbf, // 1011 1111 b 1
0xdf, // 1101 1111 b 2
0xef, // 1110 1111 b 3
0xf7, // 1111 0111 b 4
0xfb, // 1111 1011 b 5
0xfd, // 1111 1101 b 6
0xfe, // 1111 1110 b 7
};
unsigned char code leddata[] = {
0xC0, //"0"
0xF9, //"1"
0xA4, //"2"
0xB0, //"3"
0x99, //"4"
0x92, //"5"
0x82, //"6"
0xF8, //"7"
0x80, //"8"
0x90, //"9"
0x88, //"A"
0x83, //"B"
0xC6, //"C"
0xA1, //"D"
0x86, //"E"
0x8E, //"F"
0x89, //"H"
0xC7, //"L"
0xC8, //"n"
0xC1, //"u"
0x8C, //"P"
0xA3, //"o"
0xBF, //"-"
0xFF, // 熄灭
0x92// 自定义
};
/*
*----------------------------------------------------------------------------------------------
* 函数名称:void Delay2ms()
* 函数功能:延迟2ms
* 入口参数:@
* 函数返回:@
* 当前版本: Ver1.0
* 修改时间:2023/05/05 10:45:07
* 作者:t176#qq.com
* 创建时间:2023/05/05 10:45:07
-----------------------------------------------------------------------------------------------
*/
void Delay2ms() //@11.0592MHz
{
unsigned long i;
_nop_();
i = 5528UL;
while (i)
i--;
}
/*
*----------------------------------------------------------------------------------------------
* 函数名称:void Display( long val)
* 函数功能:拆分一个长整型,数码管每一位显示相关数据
* 入口参数:@
* 函数返回:@
* 当前版本: Ver1.0
* 修改时间:2023/05/05 10:43:11
* 作者:t176#qq.com
* 创建时间:2023/05/05 10:43:11
-----------------------------------------------------------------------------------------------
*/
void Display(long val)
{
int val_arr; // 定义一个大小为8的整型数组
int i, j = 0;
while (val != 0)
{
val_arr = val % 10; // 取num的最后一位,存入数组
val /= 10; // 缩小10倍
j++; // 移动数组下标
}
for (i = 0; i < j; i++)
{
P6 = 0XFF; // 清除鬼影
P7 = WEI_data; // 位选择(j-i-1)反转显示
P6 = leddata]; // 段选择
Delay2ms();
}
}
void main()
{
WTST = 0X00; // 速度最快
P6M0 = 0x00;
P6M1 = 0x00;
P7M0 = 0x00;
P7M1 = 0x00;
while (1)
{
Display(1254680);
}
}
试验箱现象:
attach://9454.mp4
Lesson 8
独立键盘和矩阵键盘 Lesson 9
点阵屏的使用