既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)
- 共阴极:8个二极管的参考地GND都接到一起,二极管的另一端单独接出(a-g、dp),通过对不同二极管的电源控制,即可实现对应二极管的亮灭,此类数码管被称为共阴极数码管。将a-g或dp的端口给与高电平,即可点亮对应的二极管;反之、给与低电平,即可熄灭对应的二极管;
- 共阳极:8个二极管的电源都接到一起,二极管的另一端单独接出(a-g、dp),通过对不同二极管的电源控制,即可实现对应二极管的亮灭,此类数码管被称为共阳极数码管;将a-g或dp的端口给与低电平,即可点亮对应的二极管;反之、给与高电平,即可熄灭对应的二极管;。
根据上述我们可以总结:共阴极数码管使用高电平控制点亮;而共阳极数码管使用低电平控制点亮。
2、数码管的显示方式
对于共阳极数码管来说:
假设我们使用一个7位(先不管小数点)的二进制数num来分别表示二极管a~g,即num的最高位num[6]=“a的值”,num[5]=“b的值”······num[0]=“g的值”。那么只要控制num的值,我们就可以实现点亮数码管的对应二极管。比如,num=7’b000_0110,那么就是对应的b(从右数第2位)、c(从右数第3位)被点亮,具体到数码管就是显示了一个类似“1”的效果,如下:
图2:共阴极数码管显示数字“1”
其他数字的演示就不做了,根据这个原理可以整理出0~9这10个数字的编码方式(适用共阳极,共阴极只要将编码取反即可):
图3:共阳极数码管编码表
这里涉及到两个概念:
- 段选:单个数码管的二极管控制信号(a~g),控制段选可以实现数码管显示不同的数字
- 位选:单个数码管的“电源开关”信号,只有在位选有效的情况下(有电情况下),控制数码管的段选才有意义
也就是说通过控制位选可以控制数码管是否上电工作,通过控制段选可以控制数码管显示具体的内容。
在通常的设计中,只用一个数码管显然是不太方便的,一般都需要4个、6个或者多个(这个看自身,我们这里用6个举例)。假设我们需要用6个数码管来显示数字,那么岂不是需要控制8个*6=48个信号,也就是需要48个IO口来进行控制?虽然我们知道FPGA的IO资源比较丰富,但是也架不住这么造不是?
所以一般在FPGA开发板中,基本都是将6个数码管的8个二极管的控制信号(段选)连接到了一起来统一控制,而将数码管的位选信号分开控制。
3、静态显示
我们可以通过位选信号去控制数码管点亮,而在同一时刻,位选选通的数码管上显示的字形是一样的,因为我们将 6 个数码管相对应的段选连在了一起,数码管的显示自然就相同了,数码管的这种显示方式即为静态显示。
接下来我以某Cyclone IVE的开发板为例,编写静态显示的驱动代码进行验证。该开发板有6个共阳极数码管(低电平控制亮),数码管位选控制信号(低电平有效)。
3.1、端口
驱动模块输入输出端口如下:
图4:数码管静态显示模块框图
各信号含义如下:
- 输入端:
- sys_clk:系统时钟,我的开发板是50M,周期20ns
- sys_rst_n:低电平有效的异步复位信号
- num[3:0]:需要显示的数字,共10个数字,所以需要4bit的位宽
- 输出端
- dis_seg[6:0]:数码管7位段选,从高到底分别控制二极管a~g,低电平有效
- dis_sel[5:0]:数码管位宽,共6个数码管所以共需要6bit,低电平有效
- dp:小数点二极管控制信号,低电平有效
3.2、Verilog代码
驱动代码很好写,我们只需要使用两个always块和1个assign语句即可完成。
第1个 always块来对位选信号赋值,这里复位熄灭所有数码管;复位完成后给所有数码管供电(选中所有数码管)
//控制数码管位选信号(低电平有效),选中所有的数码管
always @ (posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
dis_sel <= 6’b111111; //复位熄灭所有数码管
else
dis_sel <= 6’b000000; //复位完成后给所有数码管供电
end
第2个 always块来段选信号赋值,根据输入的数据(要显示的数)来对段选信号赋取对应的码值。
//根据数码管显示的数值,控制段选信号(低电平有效)
always @ (posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
dis_seg <= 7’b111_1111; //复位时熄灭数码管(这一条用处不大,因为复位时数码管也不供电)
else begin
case (num)
4’h0 : dis_seg <= 7’b000_0001; //显示数字“0”,则数码管的段选编码为7’b000_0001
4’h1 : dis_seg <= 7’b100_1111;
4’h2 : dis_seg <= 7’b001_0010;
4’h3 : dis_seg <= 7’b000_0110;
4’h4 : dis_seg <= 7’b100_1100;
4’h5 : dis_seg <= 7’b010_0100;
4’h6 : dis_seg <= 7’b010_0000;
4’h7 : dis_seg <= 7’b000_1111;
4’h8 : dis_seg <= 7’b000_0000;
4’h9 : dis_seg <= 7’b000_0100; //显示数字“9”,则数码管的段选编码为7’b000_0100
default : dis_seg <= 7’b111_1111; //其他数字(16进制的数字相对10进制无效)则熄灭数码管
endcase
end
end
小数点显示我们暂时不用,直接将其赋值1,使其失效。
assign dis_dp = 1’b1; //小数点,我们暂时不同,使其无效即可
完整代码如下:
//6位8段式数码管静态显示驱动
//端口定义
module dis_sta_dri (
input sys_clk , //时钟信号
input sys_rst_n , //复位信号(低有效)
input [3:0] num, //数码管显示的十进制数
output reg [5:0] dis_sel, //数码管位选
output reg [6:0] dis_seg, //数码管段选
output dis_dp //数码管小数点
);
assign dis_dp = 1'b1; //小数点,我们暂时不同,使其无效即可
//控制数码管位选信号(低电平有效),选中所有的数码管
always @ (posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
dis_sel <= 6'b111111; //复位熄灭所有数码管
else
dis_sel <= 6'b000000; //复位完成后给所有数码管供电
end
//根据数码管显示的数值,控制段选信号(低电平有效)
always @ (posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
dis_seg <= 7'b111_1111; //复位时熄灭数码管(这一条用处不大,因为复位时数码管也不供电)
else begin
case (num)
4'h0 : dis_seg <= 7'b000_0001; //显示数字“0”,则数码管的段选编码为7'b000_0001
4'h1 : dis_seg <= 7'b100_1111;
4'h2 : dis_seg <= 7'b001_0010;
4'h3 : dis_seg <= 7'b000_0110;
4'h4 : dis_seg <= 7'b100_1100;
4'h5 : dis_seg <= 7'b010_0100;
4'h6 : dis_seg <= 7'b010_0000;
4'h7 : dis_seg <= 7'b000_1111;
4'h8 : dis_seg <= 7'b000_0000;
4'h9 : dis_seg <= 7'b000_0100; //显示数字“9”,则数码管的段选编码为7'b000_0100
default : dis_seg <= 7'b111_1111; //其他数字(16进制的数字相对10进制无效)则熄灭数码管
endcase
end
end
endmodule
那么现在静态显示的驱动写好了,我们还需要写个数据生成模块,也就是我们要想办法写入数据到这个驱动来进行显示。
这个模块只有两个always块,第1个 always块做一个1s的计时器,该计时器循环计时1s。该模块可以顺序生成0-9这10个数,每隔1s,数据累加1。
//1s计时模块,该模块循环计数到1s
always @ (posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
cnt_1s <= 0; //复位计数器为0
else if(cnt_1s == (50_000_000 - 1)) //计数器计数到了1s,每个时钟周期20ns,则从0开始需要计数(1_000_000_000/20 - 1)
cnt_1s <= 0; //计数器清零重新开始计数
else
cnt_1s <= cnt_1s + 1; //没有计数到1s则每个周期计数1次
end
第2个 always块每隔1s生成1个数据,数据范围0-9循环。
//数据生成模块,从0开始累加(每1s累加一次),到9结束。然后循环
always @ (posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
data <= 0; //复位时熄灭数码管(这一条用处不大,因为复位时数码管也不供电)
else if(cnt_1s == (50_000_000 - 1))begin //每次计数到1s
if(data == 9) //数据生成到了9则重新开始从0生成
data <= 0;
else //数据没有生成到9则累加1
data <= data + 1;
end
end
有了驱动模块和数据生成模块,我们再写一个顶层模块,顶层模块调用这两个模块并完成连接,实现模块化设计。顶层模块的代码如下:
//6位8段式数码管静态顶层文件
//例化静态显示驱动模块和数据生成模块,将数据生成模块生成的数字,通过静态驱动,用数码管显示出来
**收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。**
![img](https://img-blog.csdnimg.cn/img_convert/f85977f51d6af7a994277ac3be4601bb.png)
![img](https://img-blog.csdnimg.cn/img_convert/e0709e2883b2b6b6cd196ef682430713.png)
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**
**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人**
**都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
3330222)]
[外链图片转存中...(img-5b9BtPoN-1715873330222)]
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**
**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人**
**都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**