LED与KEY的使用在前面的帖子中已经使用过了,这里就不再赘述了。 直接从蜂鸣器开始吧。 这里使用蜂鸣器,并不是让它响或不响,而是发出不同的声调。这里就要用到了晶振时钟了。 这一部分还是属于数电与语法的学习与对外设的操作的认知,还是基础性质的内容。
先看一下电路中蜂鸣器的实现,如下,就是使用一个管脚进行控制。BEEP 的频率决定了声音的音调。而频率的控制就要用到50M 的信号进行分频了。
这里除了使用50M的信号与复位管脚,还要用到的就是蜂鸣器的控制管脚与选择音调的按键管脚了。先看具体的程序:
- module A4_Beep
- (
- //输入端口
- CLK_50M,RST_N,KEY,
- //输出端口
- BEEP
- );
- //---------------------------------------------------------------------------
- //-- 外部端口声明
- //---------------------------------------------------------------------------
- input CLK_50M; //时钟的端口,开发板用的50MHz晶振
- input RST_N; //复位的端口,低电平复位
- input [ 7:0] KEY; //按键端口
- output BEEP; //蜂鸣器端口
- //---------------------------------------------------------------------------
- //-- 内部端口声明
- //---------------------------------------------------------------------------
- reg [15:0] time_cnt; //用来控制蜂鸣器发声频率的定时计数器
- reg [15:0] time_cnt_n; //time_cnt的下一个状态
- reg [15:0] freq; //各种音调的分频值
- reg beep_reg; //用来控制蜂鸣器发声的寄存器
- reg beep_reg_n; //beep_reg的下一个状态
- //---------------------------------------------------------------------------
- //-- 逻辑功能实现
- //---------------------------------------------------------------------------
- //时序电路,用来给time_cnt寄存器赋值
- always @ (posedge CLK_50M or negedge RST_N)
- begin
- if(!RST_N) //判断复位
- time_cnt <= 16'b0; //初始化time_cnt值
- else
- time_cnt <= time_cnt_n; //用来给time_cnt赋值
- end
- //组合电路,判断频率,让定时器累加
- always @ (*)
- begin
- if(time_cnt == freq) //判断分频值
- time_cnt_n = 16'b0; //定时器清零操作
- else
- time_cnt_n = time_cnt + 1'b1; //定时器累加操作
- end
- //时序电路,用来给beep_reg寄存器赋值
- always @ (posedge CLK_50M or negedge RST_N)
- begin
- if(!RST_N) //判断复位
- beep_reg <= 1'b0; //初始化beep_reg值
- else
- beep_reg <= beep_reg_n; //用来给beep_reg赋值
- end
- //组合电路,判断频率,使蜂鸣器发声
- always @ (*)
- begin
- if(time_cnt == freq) //判断分频值
- beep_reg_n = ~beep_reg; //改变蜂鸣器的状态
- else
- beep_reg_n = beep_reg; //蜂鸣器的状态保持不变
- end
- //组合电路,按键选择分频值来实现蜂鸣器发出不同声音
- //中音do的频率为523.3hz,freq = 50 * 10^6 / (523 * 2) = 47774
- always @ (*)
- begin
- case(KEY)
- 8'b00000001: freq = 16'd47774; //中音1的频率值523.3Hz
- 8'b00000010: freq = 16'd42568; //中音2的频率值587.3Hz
- 8'b00000100: freq = 16'd37919; //中音3的频率值659.3Hz
- 8'b00001000: freq = 16'd35791; //中音4的频率值698.5Hz
- 8'b00010000: freq = 16'd31888; //中音5的频率值784Hz
- 8'b00100000: freq = 16'd28409; //中音6的频率值880Hz
- 8'b01000000: freq = 16'd25309; //中音7的频率值987.8Hz
- 8'b10000000: freq = 16'd23889; //高音1的频率值1046.5Hz
- default : freq = 16'd0;
- endcase
- end
- assign BEEP = beep_reg; //最后,将寄存器的值赋值给端口BEEP
- endmodule
复制代码
外部输入端口KEY有8个管脚组成。内部端口大都用来记数,区分不同频率的。
从两个时序电路中可以看到:
第一个时序电路,在CLK_50M的上升沿与RST_N的下降沿都是初始化部分。
第二个时序电路,对记数的清零与蜂鸣器输出的赋值。
第一个组合电路,判断按键所选择的频率值是不是已经到了,否则定时器继续累加。
第二个组合电路,同样也是判断分频频率,然后驱动蜂鸣器。
代码了解后,就要下载的板子上运行,查看结果了,在此之前,先进行管脚分配。如下图:
2
|
|
|
|