差别
这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
book_excise_pwm [2021/08/17 17:22] zili |
book_excise_pwm [2021/08/17 17:40] (当前版本) zili |
||
---|---|---|---|
行 30: | 行 30: | ||
</WRAP> | </WRAP> | ||
整个程序的架构如图8 2所示,主要由两个模块PWM_Controller和PWM_basic1~PWM_basic8组成:\\ | 整个程序的架构如图8 2所示,主要由两个模块PWM_Controller和PWM_basic1~PWM_basic8组成:\\ | ||
- | 1.PWM_controller实现对8个LED灯亮度的控制,即决定每个LED灯的亮度应该是多少;\\ | + | 1. PWM_controller实现对8个LED灯亮度的控制,即决定每个LED灯的亮度应该是多少;\\ |
- | 2.PWM_basic1~PWM_basic8每一个模块用于控制一个LED灯亮度的实现,也就是使得LED灯的亮度满足PWM_controller提出的要求;\\ | + | 2. PWM_basic1~PWM_basic8每一个模块用于控制一个LED灯亮度的实现,也就是使得LED灯的亮度满足PWM_controller提出的要求;\\ |
- | 3.Counter是一个从0到PERIOD_WIDTH的一个计数器,PERIOD_WIDTH是脉宽调制信号的周期。\\ | + | 3. Counter是一个从0到PERIOD_WIDTH的一个计数器,PERIOD_WIDTH是脉宽调制信号的周期。 \\ |
+ | | ||
\\ | \\ | ||
行 39: | 行 40: | ||
PWM_Basic的输入输出接口如下: | PWM_Basic的输入输出接口如下: | ||
+ | <code verilog> | ||
input clk, reset; //时钟和复位信号。 | input clk, reset; //时钟和复位信号。 | ||
行 58: | 行 59: | ||
end | end | ||
+ | </code> | ||
+ | |||
+ | 在注释1处,当计数器clk_tick为0时点亮LED灯,Pwm_out为低时点亮LED灯。在注释2处,当计数器clk_tick等于pulse_width,也就是脉冲宽度达到所需要的脉冲宽度时,熄灭LED灯。如此,就完成对脉宽调制。 | ||
\\ | \\ | ||
- | \\ | ||
- | ### 仿真结果 | ||
+ | #### 3.3 PWM_controller模块(PWM_controller.v) | ||
+ | PWM_controller的主要功能如下:\\ | ||
+ | 1)控制每个LED的初始亮度,也就是初始脉宽;\\ | ||
+ | 2)更新每个LED的亮度,让每个LED灯逐渐变亮或变暗。\\ | ||
+ | <code verilog> | ||
+ | always @(posedge clk or negedge reset ) begin : PWM_controller | ||
+ | integer loop; | ||
+ | if( !reset ) begin | ||
+ | state_counter <= 7'd0; | ||
+ | add <= 8'b1111_1111; | ||
+ | //add的每一位用来控制一个LED是变亮还是变暗,初始时都要求变亮。 | ||
+ | trigger_pointer[0] <= 16'd0; | ||
+ | trigger_pointer[1] <= `RESET_PHASE; | ||
+ | trigger_pointer[2] <= 2*`RESET_PHASE; | ||
+ | trigger_pointer[3] <= 3*`RESET_PHASE; | ||
+ | trigger_pointer[4] <= 4*`RESET_PHASE; | ||
+ | trigger_pointer[5] <= 5*`RESET_PHASE; | ||
+ | trigger_pointer[6] <= 6*`RESET_PHASE; | ||
+ | trigger_pointer[7] <= 7*`RESET_PHASE; | ||
+ | // reg[15:0] trigger_pointer[7:0]; | ||
+ | //trigger_pointer是一个二维数组,用于控制LED灯的脉宽,上列8行对每个LED灯进行了初始化,从上面可以看出,LED7的初始值最大,也就是初始时最亮。RESET_PHASE是宏定义。 | ||
+ | end | ||
+ | else begin | ||
+ | if( clk_tick == 16'd0 ) begin | ||
+ | if( state_counter == `STAT_TRANSFER_NUM ) begin | ||
+ | //clk_tick和State_counter共同决定了亮度变化的间隔,为STAT_TRANSFER_NUM*PERIOD_WIDTH个时钟周期。如果设STAT_TRANSFER_NUM为20,PERIOD_WIDTH为25000,时钟为50MHz,则亮度约10ms变化依次。 | ||
+ | state_counter <= 7'd0; | ||
+ | for( loop = 0; loop < 8; loop = loop + 1 ) begin | ||
+ | //对每个LED灯,更新其亮度,也就是脉宽。 | ||
+ | if( add[loop] == 1 ) begin | ||
+ | if( trigger_pointer[loop] >= `PERIOD_WIDTH - `STEP ) | ||
+ | add[loop] <= 0; | ||
+ | trigger_pointer[loop] <= trigger_pointer[loop] + `STEP; | ||
+ | end | ||
+ | //如果是add为1,则要求变亮,即使脉宽加上一个步长STEP;但如果亮度为最亮,则将add置为0,使其开始变暗。 | ||
+ | else begin | ||
+ | if( trigger_pointer[loop] <= 2*`STEP ) | ||
+ | add[loop] <= 1; | ||
+ | |||
+ | trigger_pointer[loop] <= trigger_pointer[loop] - `STEP; | ||
+ | end | ||
+ | //如果add不为1,也就是0,则要求变暗,即使脉宽减去一个步长STEP;但如果亮度为最暗,则将add置为1,使其开始变亮。 | ||
+ | end | ||
+ | end | ||
+ | else | ||
+ | state_counter <= state_counter + 7'd1; | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | </code> | ||
+ | |||
+ | 上述涉及的宏包括脉宽增加步长STEP、脉宽调制的周期PERIOD_WIDTH、亮度变化控制STAT_TRANSFER_NUM,这些宏可以设置成不同的值以观察控制效果。 | ||
\\ | \\ | ||
\\ | \\ | ||
- | ### 演示程序文件说明 | + | ### 4. 程序仿真 |
+ | Ledtest.v是仿真模块,用于产生需要的时钟和复位信号,同时实例化PWM模块。 | ||
+ | {{ :图_8_3.png |图 8 3 PWM程序仿真结果}} | ||
+ | <WRAP centeralign> | ||
+ | 图 8 3 PWM程序仿真结果 | ||
+ | </WRAP> | ||
+ | 图 8 3为仿真的结果,由于仿真时间不能太长,因此三个宏的设置如下: | ||
+ | <code verilog> | ||
+ | `define STEP 16'd1 | ||
+ | `define PERIOD_WIDTH 16'd10 | ||
+ | `define RESET_PHASE 16'd1 | ||
+ | `define STAT_TRANSFER_NUM 7'd2 | ||
+ | </code> | ||
+ | 上面三个宏都设的很小,便于仿真。从图中可以看出,每个LED灯的脉宽调制信号的脉宽都不一样的;同时由于STAT_TRANSFER_NUM为 2,每个脉宽调制信号是每三个周期变一次,也就是每三个周期亮度变化一次。 | ||
+ | \\ | ||
+ | \\ | ||
+ | ### 5. 演示程序文件说明 | ||
+ | |文件名|功能| | ||
+ | |PWM.v|顶层模块,并包含PWM_Controller模块| | ||
+ | |Counter.v|Counter定时器模块| | ||
+ | |PWM_Basic.v|PWM_Basic模块| | ||
+ | |Pwmtest.mpf|ModelSim仿真工程| | ||
+ | |Ledtest.v|仿真顶层模块| | ||
+ | |PWM.qpf|Quartus II项目文件| | ||
\\ | \\ | ||
\\ | \\ | ||
- | ### 演示程序使用 | + | ### 6. 演示程序使用 |
+ | 演示设备:核心板。 | ||
+ | 演示方法:把程序下载到开发系统中后,可以观察到核心板上8个LED灯不断地变亮或变暗,reset为复位键。 | ||
+ | ### 7. 实验中注意的问题 | ||
+ | 由于核心板上的LED灯数量有限,而且观察距离近,亮灭的变化不是很明显。在本实验中采用的是线性脉宽调制,即脉冲宽度的变化是个常数。事实上,LED的亮度和脉冲宽度不是线性的关系,是一个指数曲线,因此要使得LED的亮度线性地变化,脉冲宽度的变化就不应该是线性的,这就是伽玛校正。有兴趣的同学可以自己尝试对脉冲宽度进行非线性调制使得LED亮度按线性进行变化。 | ||