本帖最后由 UT发布 于 2025-4-8 13:55 编辑
软件版本: TD_ 5.6.4 _Release_ 97693
操作系统: WIN11 64bit
硬件平台:适用安路 (Anlogic)FPGA
1概述 小小呼吸灯在很多设备上我们可以看到,我们可以在 FPGA的控制主板上也可以加入呼吸灯,指示我们的 FPGA 主板正在运行。一般呼吸灯的亮灭周期是 2S ,呼吸灯的亮度可以通过 PWM 来调节。本文实现一个实用的小程序,读者完全可以自己编写代码,并且通过仿真测试代码的正确性,然后下载到开发板看实际运行效果。
在完成本实验前,请确保已经完成前面的实验,包括已经掌握以下能力:
1.1呼吸灯简介 呼吸灯,就是指灯光设备的亮度随着时间由暗到亮逐渐增强,再由亮到暗逐渐衰减。呼吸灯最早是被苹果公司开发出来的,一经面世,立刻吸引众多科技公司效仿并广泛应用于各类电子产品上 。本 章课程 将通过 PWM 的方式 实现呼吸灯效果 。
脉冲宽度调制 (PWM),是英文 “Pulse Width Modulation” 的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域。
PWM的频率 f 是指 1 秒钟内信号从高电平到低电平再回到高电平的次数 ( 一个周期 ) ,单位为 Hz ;
PWM的周期是指频率的倒数, T = 1/f ,如果频率为 50Hz ,即一个周期是 20ms ,那么 1s 中有 1s/20ms=50 次 PWM 周期;
占空比是指高电平在一个周期之内所占的时间比率。若信号的周期为 T,每周期高电平时间为 t1, 低电平时间为 t2,T=t1+t2, 则占空比 D=t1/T
呼吸灯采用 PWM 的方式,在固定的频率下,通过调整占空比的方式来控制 LED 灯亮度的变化。一般人眼睛对于 80Hz 以上刷新频率则完全没有闪烁感。频率太小的话, LED 灯看起来就会闪烁,当频率大于 50Hz 的时候,人眼就会产生视觉暂留效果,基本就看不到闪烁了,就是一个常亮的 LED 灯。如果高电平点亮 LED 灯,低电平熄灭 LED 灯,占空比为 100% , LED 灯最亮,占空比为 0% , LED 灯最暗。所以,在频率一定下,可以用不同占空比改变 LED 灯的亮度。
1.2 硬件电路分析 2 PWM呼吸灯程序设计
2. 1系统框图 本次实验目的为 1个 LED 实现呼吸灯的效果, LED 变换间隔时间需要基于系统时钟来计数,实现间隔时间的计时,除此之外,添加系统复位使程序恢复至默认状态,输出结果由 1 个 LED 灯显示。命名模块名为 pwm_light ,此模块需要两个输入的端口,分别为系统时钟和系统复位,输出为 1 位的 LED 端口。
呼吸灯是由两个部分组成,一个是由亮到暗的过程,一个是由暗到亮的过程,再由简介可知我们是在固定的频率下通过调整高电平的占空比来调控 LED 灯的亮度。第一个过程由亮到暗的过程为 t=2s,如果高电平点亮 LED 灯,低电平熄灭 LED 灯,不同的占空比显示不同的亮度,占空比就要在 2s 之间逐渐由 100% 减小至 0% ,如果我们把 2s 划分成 100 份,那么每一个占空比就要保持 t1=2s/100=20ms 。由于占空比 100% 减小到 0% 一共变化了 100 次,占空比 = 高电平周期 / 整个周期 t1 ,所以需要将一个占空比周期 t1 划分成 100 份,从而达到高电平周期每减小一个周期 t2 ,占空比就减少 1% , t2=20ms/100=200us 。
200 us定时器,作为本系统的基本定时器,产生时间基准。
20ms定时器,通过 20 0 us定时器,计数 10 0 次完成 20ms定时计数
2s定时器,通过 20ms 定时器,计数 100 次完成 2S 定时计数
PWM每间隔 2ms 更新一次,共计更新 100 次即 2S 后切换 PWM 的占空比调整方向。因此 PWM 占空比的调整是和 2ms 定时计数器和 2S 定时计数器相关。系统框图如下 :
2. 2程序源码
module pwm_light#
(
parameter REF_CLK = 32'd25000000
)
(
input I_sysclk,
input I_rstn,
output O_pwm
);
localparam T20US_SET = REF_CLK/5000 - 1; //set 200us,可根据实际晶振频率进行修改
localparam T20MS_SET = 100 - 1; //set 20ms
localparam PWM_SET = 100 - 1; //Set PWM duty cycle adjustment times
reg [23:0] t20us_cnt;
reg [9 :0] t20ms_cnt;
reg [9 :0] pwm_cnt;
reg PWM_S;
//记录计数状态
wire t20us_done;
wire t20ms_done;
//是否计满200us
assign t20us_done = (t20us_cnt == T20US_SET);
//是否计满20ms
assign t20ms_done = t20us_done & (t20ms_cnt == T20MS_SET) ;
//1us base timer
always @(posedge I_sysclk or negedge I_rstn)begin //系统时钟的上升沿以及复位的下降沿触发
if(I_rstn == 1'b0) //复位清零
t20us_cnt <= 0;
else if(t20us_cnt < T20US_SET) //t20us_cnt目标值T20US_SET
t20us_cnt <= t20us_cnt + 1'b1; //本轮计数未完成则+1
else
t20us_cnt <= 24'd0; //若达目标值则清零,进行新一轮计数
end
//1ms pwm compare timer,based on 1us base timer
always @(posedge I_sysclk or negedge I_rstn)begin
if(I_rstn == 1'b0)
t20ms_cnt <= 0;
else if(t20us_done) //前一级(200us)的一轮计数完成则+1
t20ms_cnt <= (t20ms_cnt < T20MS_SET) ? (t20ms_cnt + 1'b1) : 10'd0;
else //否则保持
t20ms_cnt <= t20ms_cnt;
end
//PWM counter for generating duty cycle parameters as well as PWM adjustment count
always @(posedge I_sysclk or negedge I_rstn)begin
if(I_rstn == 1'b0)
pwm_cnt <= 0;
else if(t20ms_done)
pwm_cnt <= (pwm_cnt < PWM_SET) ? (pwm_cnt + 1'b1) : 10'd0; //前一级(20ms)的一轮计数完成则+1
else
pwm_cnt <= pwm_cnt; //否则保持
end
//switch breathing state
always @(posedge I_sysclk or negedge I_rstn)begin
if(I_rstn == 1'b0)
PWM_S <= 0;
else if(t20ms_done && (pwm_cnt == PWM_SET)) //pwm_cnt == PWM_SET时(即计满2s),PWM_S状态进行翻转
PWM_S <= ~PWM_S;
else
PWM_S <= PWM_S;
end
//PWM wave generating
assign O_pwm = PWM_S ? (pwm_cnt >= t20ms_cnt) : (pwm_cnt < t20ms_cnt);
//在一轮计数中,t20ms_cnt逐渐增大
//若PWM_S==1,O_pwm输出为1的频率越来越小,表现为LED灯逐渐变暗
//若PWM_S==0,O_pwm输出为1的频率越来越大,表现为LED灯逐渐变亮
endmodule 复制代码
3 FPGA工程 fpga工程的创建过程不再重复,如有不清楚的请看前面实验 。
米联客的代码管理规范 ,在对应的 FPGA 工程路径下创建 uisrc 路径,并且创建以下文件夹
04_pin:放 fpga 的 pin 脚约束文件或者时序约束文件
05_boot:放编译好的 bit 或者 bin 文件 ( 一般为空 )
4 Modelsim仿真 4. 1准备工作 Modelsim仿真的创建过程不再重复,如有不清楚的请看前面实验
仿真测试文件源码如下,对于 led这种低速仿真,仿真精度可以设置为 1ns ,另外仿真阶段可以把间隔时间设置小一些,这样仿真速度就快了:
module tb_pwm_light();
reg I_sysclk,I_rstn;
wire O_pwm;
pwm_light#
(
.REF_CLK(25000)//可缩小间隔时间,提高仿真速度
)
pwm_light_inst
(
.I_sysclk(I_sysclk),
.I_rstn(I_rstn),
.O_pwm(O_pwm)
);
initial begin
I_sysclk <= 1'b0;
I_rstn <= 1'b0;
#100;
I_rstn <= 1'b1;
end
always #20 I_sysclk=~I_sysclk;
endmodule 复制代码
4.2 启动 modelsim仿真 设置运行 10ms。从仿真结果可以看到 PWM占空比的调整
5 下载演示
下载程序前,先确保 FPGA工程已经编译。
5. 1硬件连接 (该教程为通用型教程,教程中仅展示一款示例开发板的连接方式,具体连接方式以所购买的开发板型号以及结合配套代码管脚约束为准。)
请确保下载器和开发板已经正确连接,并且开发板已经上电 (注意 JTAG 端子不支持热插拔,而 USB 接口支持,所以在不通电的情况下接通好 JTAG 后,再插入 USB 到电脑,之后再上电,以免造成 JTAG IO 损坏 )
5. 2运行结果 (该教程为通用型教程,教程中仅展示一款示例开发板的上板现象,具体现象以所购买的开发板型号以及配套代码上板现象为准。)