资料介绍
描述
介绍
该项目是为 MiniZed 电机控制构建挑战而创建的,最终应用程序是在Adam Taylor的Mini But Mighty项目上构建的。该项目是一个 VHDL 参考设计,用于在可编程逻辑中创建多路复用 7 段显示硬件驱动程序,并展示了如何在没有大量按钮/开关和 LED 的小型电路板(例如 MiniZed)上使用和测试 HDL 硬件模块。该示例介绍了将创建的 VHDL 硬件模块实现到 Mini But Mighty 项目中,以在 7 段显示器上显示实际的 PWM 占空比。
硬件
为了这个项目的需要,我为 5641AS 四位 7 段 LED 显示器创建了一个手工制作的 PCB。段线通过300欧姆电阻连接到表头,每个显示器的共阴极由2N7000 N-MOS晶体管驱动,其栅极通过10k欧姆电阻连接到表头并通过220k欧姆电阻接地。一个 13 针接头(8 段、4 个公共阴极、1 个 GND)通过 Arduino 连接器连接到 MiniZed。
附板子原理图和LED显示屏内部接线图。但是,您可以使用其他具有类似硬件的显示器和电路板。
创建 VHDL 7 段 LCD 显示驱动程序
我从框图开始。输入数据是一个 16 位数字,其中每 4 位是一个显示器的编号,因此最低有效 4 位是从右开始第一个显示器的数字,连续的 4 位是下一个显示器,最多 4 个最高有效位是从左数第 4 个显示屏上的数字。因此 16 位二进制数 0b0011001000010000 将显示在显示器 3210 上。第二个 4 位输入用于显示小数精度,其中最低有效位是从左数第一个显示器上的点,最高有效位是从左数第四个显示器。所以 4 位二进制数 0b0001 只会在左起第一个显示器上显示点。其他输入是时钟和复位,该模块设计用于默认 50 MHz 时钟,并提供约 800Hz(每个数字 200 Hz)的显示刷新率的结果。
选择器.vhd
该模块分频并控制多路复用器,2 位输出地址 00 用于第一个显示,11 用于最后一个显示。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity selector is
Port
(
clk, reset: in std_logic;
sel: out std_logic_vector(1 downto 0)
);
end selector;
architecture Behavioral of selector is
signal state, next_state: unsigned(17 downto 0);
begin
--register
process(clk, reset)
begin
if reset='1' then
state <= (others=>'0');
elsif (clk'event and clk='1') then
state <= next_state;
end if;
end process;
--next state logic
next_state <= state + 1;
--output clk/2^16 for 50MHz around 800 Hz out
sel <= std_logic_vector(state(17 downto 16));
end Behavioral;
mux_4_to_1.vhd
该模块在当前控制的 LED 显示屏上设置点段。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity mux_4_to_1 is
Port
(
input : in std_logic_vector (3 downto 0);
sw : in std_logic_vector (1 downto 0);
output : out std_logic
);
end mux_4_to_1;
architecture Behavioral of mux_4_to_1 is
begin
with sw select
output <=
input(0) when "00",
input(1) when "01",
input(2) when "10",
input(3) when "11",
'0' when others;
end Behavioral;
mux_16_to_1.vhd
该模块为当前控制的 LED 显示屏设置 16 位输入的 4 位输出。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity mux_16_to_4 is
Port
(
input : in std_logic_vector (15 downto 0);
sw : in std_logic_vector (1 downto 0);
output : out std_logic_vector (3 downto 0)
);
end mux_16_to_4;
architecture Behavioral of mux_16_to_4 is
begin
with sw select
output(3 downto 0) <=
input(3 downto 0) when "00",
input(7 downto 4) when "01",
input(11 downto 8) when "10",
input(15 downto 12) when "11",
"0000" when others;
end Behavioral;
hex4b_to_lcd.vhd
将 4 位输入数据转换为当前控制的 LED 显示屏的输出。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity hex4b_to_lcd is
Port
(
input: in std_logic_vector(3 downto 0);
dot: in std_logic;
output: out std_logic_vector(7 downto 0)
);
end hex4b_to_lcd;
architecture Behavioral of hex4b_to_lcd is
begin
with input select
output(6 downto 0) <=
"0111111" when "0000",
"0000110" when "0001",
"1011011" when "0010",
"1001111" when "0011",
"1100110" when "0100",
"1101101" when "0101",
"1111101" when "0110",
"0000111" when "0111",
"1111111" when "1000",
"1101111" when "1001",
"1110111" when "1010", --a
"1111100" when "1011", --b
"0111001" when "1100", --c
"1011110" when "1101", --d
"1111001" when "1110", --e
"1110001" when others; --f
output(7) <= dot;
end Behavioral;
seg_mux_4.vhd
模块切换当前使用的 LED 显示。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity seg_mux_4 is
Port
(
input: in std_logic_vector (1 downto 0);
enable: in std_logic;
output: out std_logic_vector (3 downto 0)
);
end seg_mux_4;
architecture Behavioral of seg_mux_4 is
begin
output <= "0000" when (enable = '0') else
"0001" when (input = "00") else
"0010" when (input = "01") else
"0100" when (input = "10") else
"1000" when (input = "11") else
"0000";
end Behavioral;
主.vhd
这是将上述所有模块组合成 7 段显示驱动程序的顶层模块。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity main is
Port
(
clk: in std_logic;
dat_in: in std_logic_vector(15 downto 0);
dp: in std_logic_vector(3 downto 0);
reset : in std_logic;
lcd_out: out std_logic_vector (7 downto 0);
seg_out: out std_logic_vector (3 downto 0)
);
end main;
architecture Behavioral of main is
signal num_sel: std_logic_vector (1 downto 0);
signal num_out: std_logic_vector (3 downto 0);
signal dp_out: std_logic;
begin
u1: entity work.selector
port map(clk=>clk, reset=>reset, sel=>num_sel);
u2: entity work.mux_16_to_4
port map(input=>dat_in, sw=>num_sel, output=>num_out);
u3: entity work.seg_mux_4
port map(input=>num_sel, enable=>'1', output=>seg_out);
u4: entity work.mux_4_to_1
port map(input=>dp, sw=>num_sel, output=>dp_out);
u5: entity work.hex4b_to_lcd
port map(input=>num_out, dot=>dp_out, output=>lcd_out);
end Behavioral;
包含所有模块的 VHDL 代码文件以供使用和分析。
VHDL 模块在 Mini But Mighty 项目中的实现
所以模块是使用 VHDL 创建的,但是如何在 MiniZed 板上测试它呢?较大的 FPGA 板通常有 8 或 16 个输入开关和 LED,用于测试在可编程逻辑中实现的硬件模块的输入和输出。好的,我们在 MiniZed 板上没有足够的 LED 和开关,但我们有更多的东西,Zynq 7000 SoC,它有一个 ARM Cortex - A9 处理器系统 (PS) 和 Xilinx Artix 可编程逻辑 (PL)。我们可以使用和组合这些资源,在芯片内部创建一个灵活的测试环境,并拥有我们需要的尽可能多的输入和输出。这将通过将创建的 VHDL 模块实施到 Mini But Mighty 项目中来呈现。
起点将是Mini But Mighty项目。
Vivado 硬件构建
第一步是将我们创建的源添加到项目中。为此,我们使用选项卡源和“加号”按钮。
在下一步中,我们选择“添加或创建设计源”。
然后单击“添加文件”按钮。
我们选择我们的 VHDL 文件并单击“确定”。
现在在添加源窗口中我们可以看到我们的 VHDL 文件。确保选中“将源代码复制到项目中”,然后接受添加的源代码并转到下一步。
源窗口应该是这样的。
现在在块空间的空白处单击鼠标右键并选择“添加模块”。
在新窗口中选择“main.vhd”并单击“确定”。
现在在块设计中我们看到创建的 VHDL 模块。
这个模块是简单的 RTL 块,我们需要一些 I/O 来使用它。我们将使用 axi_gpio IP,但首先我们需要配置处理系统。为此,双击 Zynq 块并选择 PS-PL 配置选项卡。
单击“Axi Non Secure Enablement”,然后单击“GP Master AXI Interface”并选择“M AXI GP0 interface”并确认更改。
添加 AXI GPIO IP 是通过单击块设计中的“加号”按钮,在搜索窗口中键入“gpio”并选择“AXI GPIO”来完成的。
我们还需要两个“切片”块,因此重复最后一步两次,在搜索框中键入“切片”。
现在我们有了所有的元素,我们需要配置其中的一些。首先是 AXI GPIO,在 IP 设置配置选项卡中手动设置 20 位宽度。
为 20 位输入宽度和 15 到 0 输出配置第一个切片,为 20 位输入宽度和 19 到 16 输出配置第二个切片。
所有块都已配置,因此应建立它们之间的连接。为此,首先单击“运行连接自动化”。
并选择“All automation”(FCLK0 默认配置为 50MHz,它是我们的 RTL 块所需的输入频率)。
默认情况下,Vivado 会将 VHDL 模块复位连接到 peripheral_aresten,我们需要更正这一点并将复位连接到 peripheral_reset。
现在我们将切片块连接到 axi_gpio_0 并将切片输出连接到相应的 RTL 模块输入。
最后一步是使 RTL 模块输出到外部并保存块设计。最终的块设计如下。
在实施、合成和比特流生成之前,必须修改约束条件。显示器的公共部分连接到 Arduino IO0 到 IO7,每个显示器的公共阴极连接到 IO8 到 IO11。因此,我们必须在 io.xdc 文件中添加以下行。
set_property PACKAGE_PIN R8 [get_ports {lcd_out_0[7]}]; # "R8.ARDUINO_IO0"
set_property PACKAGE_PIN P8 [get_ports {lcd_out_0[6]}]; # "P8.ARDUINO_IO1"
set_property PACKAGE_PIN P9 [get_ports {lcd_out_0[5]}]; # "P9.ARDUINO_IO2"
set_property PACKAGE_PIN R7 [get_ports {lcd_out_0[4]}]; # "R7.ARDUINO_IO3"
set_property PACKAGE_PIN N7 [get_ports {lcd_out_0[3]}]; # "N7.ARDUINO_IO4"
set_property PACKAGE_PIN R10 [get_ports {lcd_out_0[2]}]; # "R10.ARDUINO_IO5"
set_property PACKAGE_PIN P10 [get_ports {lcd_out_0[1]}]; # "P10.ARDUINO_IO6"
set_property PACKAGE_PIN N8 [get_ports {lcd_out_0[0]}]; # "N8.ARDUINO_IO7"
set_property PACKAGE_PIN M9 [get_ports {seg_out_0[0]}]; # "M9.ARDUINO_IO8"
set_property PACKAGE_PIN N9 [get_ports {seg_out_0[1]}]; # "N9.ARDUINO_IO9"
set_property PACKAGE_PIN M10 [get_ports {seg_out_0[2]}]; # "M10.ARDUINO_IO10"
set_property PACKAGE_PIN M11 [get_ports {seg_out_0[3]}]; # "M11.ARDUINO_IO11"
set_property IOSTANDARD LVCMOS33 [get_ports -of_objects [get_iobanks 34]];
一旦创建了包装器和约束,我们就可以实施设计了。选择 Generate BitStream Option 并在设计编译时等待几分钟。
实施设计
一旦比特流可用,下一步就是导出 XSA 以在 Vitis 中使用。在文件下选择导出-> 导出硬件。
导出硬件
在出现的对话框中选择包含比特流选项
导出 XSA
我们现在准备好打开 Vitis 并更新软件应用程序
Vitis 软件构建
使用“工具”选项卡启动 Vitis 并选择 Mini But Mighty Workspace。现在我们必须更新硬件平台。在 design_1_wrapper 上单击鼠标右键并选择 Update Hardware Specification。
在新打开的窗口中,选择更新的 XSA 文件并确认。
点击build按钮,等待编译结束,然后打开platform.spr文件查看配置,axi_gpio_0应该在Hardware Specification Address Map for processor list中。
现在我们将修改 helloworld.c 应用程序以在我们的显示器上显示实际的 PWM。首先,我们需要为 AXI GPIO 添加额外的库:
#include "xparameters.h"
#include "xgpio.h"
and
定义:
#define GPIO_EXAMPLE_DEVICE_ID XPAR_GPIO_0_DEVICE_ID
#define GPIO_CHANNEL 1
和 GPIO 驱动程序实例:
XGpio GpioPL; /* The Instance of the GPIO Driver */
我们的 7 段 LED 显示和硬件驱动模块默认调整为十六进制数。因此,我们需要创建一个函数,以便在我们的软件应用程序中轻松使用十进制数:
uint8_t set_7seg_dec(uint16_t dec_num, uint8_t dp)
{
uint32_t seg7_out;
seg7_out = 0; // set 0 output
seg7_out = dp<<16; // set decimal point
seg7_out |= (seg7_out & LED_MASK) | (dec_num % 10)*0x01;
seg7_out |= (seg7_out & LED_MASK) | (dec_num / 10)%10*0x10;
seg7_out |= (seg7_out & LED_MASK) | (dec_num / 100)%10*0x100;
seg7_out |= (seg7_out & LED_MASK) | (dec_num / 1000)%10*0x1000;
XGpio_DiscreteWrite(&GpioPL, GPIO_CHANNEL, seg7_out);
return 0;
}
dec_num - 是 16 位无符号整数,
dp - 是 8 位 usigned int 数字,其中 4 个最低有效位用于小数点,例如 decimal 2 = 0b00000010 将在第二个显示形式右侧显示点。
LED_MASK 是 0x0000FFFF 十六进制数,用于屏蔽 32 位 seg7_out 变量的小数点部分。
最后要做的是修改用于设置输出 PWM 占空比的函数。我们通过将 set_7seg_function 添加到 set_pwm 函数并使用“cycle”变量来实现。变量乘以十是因为我们在第二个显示器上设置了小数点:
void set_pwm(u32 cycle) {
u32 MatchValue;
set_7seg_dec(cycle*10, 2);
MatchValue = (TimerSetup->Interval * cycle) / 100;
XTtcPs_SetMatchValue(&ttcTimer, 0, MatchValue);
}
下面是修改后的 helloworld.c 的完整代码,该文件也可以在 github 存储库中找到。
#include
#include "platform.h"
#include "xparameters.h"
#include "xil_printf.h"
#include "xgpiops.h"
#include "sleep.h"
#include "xil_exception.h"
#include "xttcps.h"
#include "xscugic.h"
#include "xgpio.h"
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define GPIO_EXAMPLE_DEVICE_ID XPAR_GPIO_0_DEVICE_ID
/*
* The following constant is used to determine which channel of the GPIO is
* used for the LED if there are 2 channels supported.
*/
#define GPIO_CHANNEL 1
/*
* The following constant is used to wait after an LED is turned on to make
* sure that it is visible to the human eye. This constant might need to be
* tuned for faster or slower processor speeds.
*/
#define LOOP_DELAY 1000000
#define LED_MASK 0x0FFFF
#define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_SCUGIC_0_DEVICE_ID
#define TICK_TIMER_FREQ_HZ 100
#define TTC_TICK_DEVICE_ID XPAR_XTTCPS_0_DEVICE_ID
#define TTC_TICK_INTR_ID XPAR_XTTCPS_0_INTR
static void TickHandler(void *CallBackRef);
int SetupTicker(XTtcPs *TtcPsInst, u16 DeviceID, u16 TtcTickIntrID,
XScuGic *InterruptController);
static int SetupInterruptSystem(u16 IntcDeviceID, XScuGic *IntcInstancePtr);
int SetupTimer(u16 DeviceID, XTtcPs *TtcPsInst);
void set_pwm(u32 cycle);
void display_menu();
typedef struct {
u32 OutputHz; /* Output frequency */
XInterval Interval; /* Interval value */
u8 Prescaler; /* Prescaler value */
u16 Options; /* Option settings */
} TmrCntrSetup;
/*
* The following are declared globally so they are zeroed and so they are
* easily accessible from a debugger
*/
XGpio GpioPL; /* The Instance of the GPIO Driver */
XGpioPs Gpio;
XGpioPs_Config *ConfigPtr;
XTtcPs_Config *TtcConfig;
XTtcPs ttcTimer;
TmrCntrSetup *TimerSetup;
XScuGic InterruptController; /* Interrupt controller instance */
XTtcPs TtcPsInst;
u32 MatchValue;
static TmrCntrSetup SettingsTable = { TICK_TIMER_FREQ_HZ, 0, 0, 0 };
uint8_t set_7seg_dec(uint16_t dec_num, uint8_t dp)
{
uint32_t seg7_out;
seg7_out = 0; // set 0 output
seg7_out = dp<<16; // set decimal point
seg7_out |= (seg7_out & LED_MASK) | (dec_num % 10)*0x01;
seg7_out |= (seg7_out & LED_MASK) | (dec_num / 10)%10*0x10;
seg7_out |= (seg7_out & LED_MASK) | (dec_num / 100)%10*0x100;
seg7_out |= (seg7_out & LED_MASK) | (dec_num / 1000)%10*0x1000;
XGpio_DiscreteWrite(&GpioPL, GPIO_CHANNEL, seg7_out);
return 0;
}
int main() {
u8 DutyCycle;
char key_input;
int Status;
volatile int Delay;
uint32_t byte, l_byte;
uint32_t lcd_dec=0;
init_platform();
TmrCntrSetup SettingsTable = { TICK_TIMER_FREQ_HZ, 0, 0, 0 };
ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr);
XGpioPs_SetDirectionPin(&Gpio, 54, 1);
XGpioPs_SetOutputEnablePin(&Gpio, 54, 1);
XGpioPs_WritePin(&Gpio, 54, 0x1);
printf("www.adiuvoengineering.com\n\r");
printf("DC Motor Control Example\n\r");
SetupInterruptSystem(INTC_DEVICE_ID, &InterruptController);
SetupTicker(&ttcTimer, TTC_TICK_DEVICE_ID, TTC_TICK_INTR_ID,
&InterruptController);
byte = 0x20000;
/* Initialize the GPIO driver */
Status = XGpio_Initialize(&GpioPL, GPIO_EXAMPLE_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("Gpio Initialization Failed\r\n");
return XST_FAILURE;
}
print("Write byte.\n\r");
/* Set the direction for all signals as output */
XGpio_SetDataDirection(&GpioPL, GPIO_CHANNEL, 0x00);
/* Write inital data */
XGpio_DiscreteWrite(&GpioPL, GPIO_CHANNEL, byte);
// while (1) {
//
// if (lcd_dec == 1000) lcd_dec = 0;
//// byte = 0x20000;
// lcd_dec ++;
// set_7seg_dec(lcd_dec, 0x02);
//// byte |= (byte & 0x0ffff) | (lcd_dec % 10)*0x01;
//// byte |= (byte & 0x0ffff) | (lcd_dec / 10)%10*0x10;
//// byte |= (byte & 0x0ffff) | (lcd_dec / 100)%10*0x100;
//// byte |= (byte & 0x0ffff) | (lcd_dec / 1000)%10*0x1000;
////
////
//// XGpio_DiscreteWrite(&GpioPL, GPIO_CHANNEL, byte);
//
//
//// byte = inbyte(); // get byte from stdin (uart1)
////
//// if(l_byte != byte)
//// {
//// /* Set counter as output value of port */
//// XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, byte);
//// /*Send byte to stdout*/
//// xil_printf("0x%02x\r\n", byte);
//// /*Save last value*/
//// l_byte = byte;
//// }
//
//// /* Wait a small amount of time so the LED is visible */
//// for (Delay = 0; Delay < LED_DELAY; Delay++);
////
//// /* Clear the LED bit */
//// XGpio_DiscreteClear(&Gpio, LED_CHANNEL, LED);
//
// /* Wait a small amount of time */
// for (Delay = 0; Delay < LOOP_DELAY; Delay++);
// }
while (1) {
display_menu();
read(1, (char*) &key_input, 1);
printf("Echo %c\n\r", key_input);
switch (key_input) {
// case 0: // forward
//
// set_pwm(0);
// usleep(1000000);
//
// set_pwm(DutyCycle);
// break;
// case 1: //reverse
//
// //set_pwm(0);
// //usleep(1000000);
// //XGpioPs_WritePin(&Gpio, 54, 0x1);
// //set_pwm(DutyCycle);
// break;
case '1': //stop
set_pwm(0);
break;
case '2': //25%
printf("25%\n\r");
DutyCycle = 25;
set_pwm(DutyCycle);
break;
case '3': //33%
DutyCycle = 33;
set_pwm(DutyCycle);
break;
case '4': //50%
DutyCycle = 50;
set_pwm(DutyCycle);
break;
case '5': //66%
DutyCycle = 66;
set_pwm(DutyCycle);
break;
case '6': //75%
DutyCycle = 75;
set_pwm(DutyCycle);
break;
case '7': //100%
DutyCycle = 100;
set_pwm(DutyCycle);
break;
}
}
cleanup_platform();
return 0;
}
void display_menu() {
//Clear the screen
printf("\033[2J");
//Display the main menu
printf("*******************************************\n");
printf("**** www.adiuvoengineering.com ****\n");
printf("**** Motor Control Example ****\n");
printf("*******************************************\n");
printf("\n");
printf(" MM10 Motor Control \n");
printf("------------------------------------------\n");
printf("\n");
printf("Select a Speed:\n");
printf(" (1) - Stop\n");
printf(" (2) - 25%\n");
printf(" (3) - 33%\n");
printf(" (4) - 50%\n");
printf(" (5) - 66%\n");
printf(" (6) - 75%\n");
printf(" (7) - 100%\n");
printf("\n");
}
void set_pwm(u32 cycle) {
u32 MatchValue;
set_7seg_dec(cycle*10, 2);
MatchValue = (TimerSetup->Interval * cycle) / 100;
XTtcPs_SetMatchValue(&ttcTimer, 0, MatchValue);
}
int SetupTicker(XTtcPs *TtcPsInst, u16 DeviceID, u16 TtcTickIntrID,
XScuGic *InterruptController) {
int Status;
TmrCntrSetup *TimerSetup;
XTtcPs *TtcPsTick;
TimerSetup = &SettingsTable;
TimerSetup->Options |= (XTTCPS_OPTION_INTERVAL_MODE |
XTTCPS_OPTION_MATCH_MODE | XTTCPS_OPTION_WAVE_POLARITY);
Status = SetupTimer(DeviceID, TtcPsInst);
if (Status != XST_SUCCESS) {
return Status;
}
TtcPsTick = TtcPsInst;
Status = XScuGic_Connect(InterruptController, TtcTickIntrID,
(Xil_InterruptHandler) TickHandler, (void *) TtcPsTick);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
XScuGic_Enable(InterruptController, TtcTickIntrID);
XTtcPs_EnableInterrupts(TtcPsTick, XTTCPS_IXR_INTERVAL_MASK);
XTtcPs_Start(TtcPsTick);
return Status;
}
static int SetupInterruptSystem(u16 IntcDeviceID, XScuGic *IntcInstancePtr) {
int Status;
XScuGic_Config *IntcConfig;
IntcConfig = XScuGic_LookupConfig(IntcDeviceID);
if (NULL == IntcConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,
IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
(Xil_ExceptionHandler) XScuGic_InterruptHandler, IntcInstancePtr);
Xil_ExceptionEnable();
return XST_SUCCESS;
}
int SetupTimer(u16 DeviceID, XTtcPs *TtcPsInst) {
int Status;
XTtcPs_Config *Config;
XTtcPs *Timer;
TmrCntrSetup *TimerSetup;
TimerSetup = &SettingsTable;
Timer = TtcPsInst;
Config = XTtcPs_LookupConfig(DeviceID);
if (NULL == Config) {
return XST_FAILURE;
}
Status = XTtcPs_CfgInitialize(Timer, Config, Config->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
XTtcPs_SetOptions(Timer, TimerSetup->Options);
XTtcPs_CalcIntervalFromFreq(Timer, TimerSetup->OutputHz,
&(TimerSetup->Interval), &(TimerSetup->Prescaler));
XTtcPs_SetInterval(Timer, TimerSetup->Interval);
XTtcPs_SetPrescaler(Timer, TimerSetup->Prescaler);
return XST_SUCCESS;
}
static void TickHandler(void *CallBackRef) {
u32 StatusEvent;
/*
* Read the interrupt status, then write it back to clear the interrupt.
*/
StatusEvent = XTtcPs_GetInterruptStatus((XTtcPs * )CallBackRef);
XTtcPs_ClearInterruptStatus((XTtcPs * )CallBackRef, StatusEvent);
//printf("timer\n\r");
/*update the flag if interrupt has been occurred*/
//UpdateFlag = TRUE;
}
之后我们必须保存文件并构建项目。
然后,如果没有错误,请单击“运行”按钮并尝试在终端中键入数字以更改 Pmod HB3 输出上的脉冲宽度。实际占空比将显示在 7 段 LED 显示屏上。
包起来
该项目通过四路 7 段 LED 显示示例和 Mini But Mighty 项目的更新展示了我们如何使用 AXI GPIO IP 将我们自己的 VHDL 或其他 HDL 模块用于 Vivado 和 Vitis。可编程逻辑和处理系统的结合是强大的,唯一的限制是想象力。您可以对另一个 HDL 模块使用相同的方法。
- 带7段显示模块MAX7219的秒表
- 7段LED时钟开源分享
- 使用3x7段LED显示器的反应计时器 0次下载
- 使用WS2812b可单独寻址LED制成的7段显示器
- 一位7段LED显示屏开源分享
- 4511 7位七段显示模块
- 离散4位LED7段显示开源分享
- Arduino与Proteus仿真实例-7段数码管(7线)驱动仿真
- 如何在VHDL设计中使用库模块 13次下载
- 7段数码管显示的Proteus仿真电路图和程序免费下载 56次下载
- VHDL硬件描述语言入门教程资料免费下载 43次下载
- 硬件描述语言VHDL 12次下载
- LED点阵显示模块驱动设计 832次下载
- 使用MAX6954驱动7段LED显示器
- 7段数码管译码器设计与实现
- 七段LED显示器的工作原理与驱动方法 979次阅读
- LED数码管显示原理详解 5418次阅读
- 如何使用7段码数码管? 1633次阅读
- 使用MAX6955 LED显示驱动器和PIC微控制器滚动消息 814次阅读
- 如何使用MAX7219和DS1307制作7段数字时钟 3124次阅读
- 基于7段LED的水位指示器电路图 3345次阅读
- 使用7段LED的比赛计分显示电路图介绍 3661次阅读
- 基于钻井深度显示器和带有Arduino支持的7段显示器设计 2480次阅读
- 微雪电子8段数码管简介 1789次阅读
- 基于一种模块化的LED显示屏设计 1848次阅读
- 七段LED数码管显示原理 4w次阅读
- Avnet MiniZed单核Zynq 7Z007S入门开发方案 5161次阅读
- 7段数码管显示的VHDL设计(两款设计方案) 2.1w次阅读
- 开关控制数码管的VHDL程序的设计与实现 5186次阅读
- LED显示系统DMA控制器的设计 3137次阅读
下载排行
本周
- 1山景DSP芯片AP8248A2数据手册
- 1.06 MB | 532次下载 | 免费
- 2RK3399完整板原理图(支持平板,盒子VR)
- 3.28 MB | 339次下载 | 免费
- 3TC358743XBG评估板参考手册
- 1.36 MB | 330次下载 | 免费
- 4DFM软件使用教程
- 0.84 MB | 295次下载 | 免费
- 5元宇宙深度解析—未来的未来-风口还是泡沫
- 6.40 MB | 227次下载 | 免费
- 6迪文DGUS开发指南
- 31.67 MB | 194次下载 | 免费
- 7元宇宙底层硬件系列报告
- 13.42 MB | 182次下载 | 免费
- 8FP5207XR-G1中文应用手册
- 1.09 MB | 178次下载 | 免费
本月
- 1OrCAD10.5下载OrCAD10.5中文版软件
- 0.00 MB | 234315次下载 | 免费
- 2555集成电路应用800例(新编版)
- 0.00 MB | 33566次下载 | 免费
- 3接口电路图大全
- 未知 | 30323次下载 | 免费
- 4开关电源设计实例指南
- 未知 | 21549次下载 | 免费
- 5电气工程师手册免费下载(新编第二版pdf电子书)
- 0.00 MB | 15349次下载 | 免费
- 6数字电路基础pdf(下载)
- 未知 | 13750次下载 | 免费
- 7电子制作实例集锦 下载
- 未知 | 8113次下载 | 免费
- 8《LED驱动电路设计》 温德尔著
- 0.00 MB | 6656次下载 | 免费
总榜
- 1matlab软件下载入口
- 未知 | 935054次下载 | 免费
- 2protel99se软件下载(可英文版转中文版)
- 78.1 MB | 537798次下载 | 免费
- 3MATLAB 7.1 下载 (含软件介绍)
- 未知 | 420027次下载 | 免费
- 4OrCAD10.5下载OrCAD10.5中文版软件
- 0.00 MB | 234315次下载 | 免费
- 5Altium DXP2002下载入口
- 未知 | 233046次下载 | 免费
- 6电路仿真软件multisim 10.0免费下载
- 340992 | 191187次下载 | 免费
- 7十天学会AVR单片机与C语言视频教程 下载
- 158M | 183279次下载 | 免费
- 8proe5.0野火版下载(中文版免费下载)
- 未知 | 138040次下载 | 免费
评论
查看更多