資料介紹
描述
介紹
該項目是為 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次下載 | 免費
評論
查看更多