【RS422】基于未来科技FT4232HL芯片的多波特率串口通信收发实现
功能简介
串行通信接口常常用于在计算机和低速外部设备之间传输数据。串口通信存在多种标准,以RS422为例,它将数据分成多个位,采用异步通信方式进行传输。
本文基于Xilinx VCU128 FPGA开发板,对RS422串口通信进行学习。
根据用户手册ug1302,128中采用了一款来自未来科技(Future Technology Devices International Ltd.)的USB转UART的芯片FT4232HL(芯片手册)。
FT4232HL芯片能够将USB接口转化为4个串口通道,并支持配置4个串口通道为不同类型的串口协议,根据FT4232HL芯片手册(P10)可以看到在配置为RS422模式下串口通道各引脚功能如下:
在实际使用中,Xilinx配置芯片的通道A为JTAG模式用于JTAG调试链,通道B与通道C用于UART串口通信,通道D用于SYSCTLR。其中通道B、C仅引出了TXD、RXD、RTS_n、CTS_n四根引脚。其中通道C的TXD、RXD的引脚位置可通过如下约束获取
set_property BOARD_PART_PIN USB_UART1_TX [get_ports channel_tx]
set_property BOARD_PART_PIN USB_UART1_RX [get_ports channel_rx]
SystemVerilog实现(ft4232hl_uart.sv)
根据422协议规定,编写串口接收代码如下,主要功能包括:
- 采用偶校验、1停止位、8数据位。
- 采样采用mmcm产生的400MHz时钟(800MHz时ila存在时序违例),采样串口接收到的数据时采取多次采样方式,即总样本里超过75%为1则为1,少于25%为1则为0。
- vio用于将采样次数适配到串口波特率,由于采样时钟为400MHz,当需要波特率为115200bps时,需要vio设置采样次数为3472。
- ila用于抓取串口接收到的字节数据、以及是否存在错误(无停止位错误、校验位错误、采样结果不确定错误)。
`timescale 1ns / 1ps
//
// Company:
// Engineer: wjh776a68
//
// Create Date: 03/15/2024 07:45:09 PM
// Design Name:
// Module Name: ft4232hl_uart
// Project Name:
// Target Devices: XCVU37P
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//// ===================================================================
// =
// = https://ftdichip.com/wp-content/uploads/2020/08/DS_FT4232H.pdf
// = P15 signals difinition
// =
// ===================================================================module ft4232hl_uart(input logic default_clk_p ,input logic default_clk_n ,input logic reset ,input logic channel_rx ,output logic channel_tx
// input logic channel_rts_n ,
// output logic channel_cts_n
);// assign channel_cts_n = 1;logic clk_100MHz;IBUFDS #(.DIFF_TERM("FALSE"), // Differential Termination.IBUF_LOW_PWR("TRUE"), // Low power="TRUE", Highest performance="FALSE" .IOSTANDARD("DEFAULT") // Specify the input I/O standard) IBUFDS_inst (.O(clk_100MHz), // Buffer output.I(default_clk_p), // Diff_p buffer input (connect directly to top-level port).IB(default_clk_n) // Diff_n buffer input (connect directly to top-level port));logic mmcm_fbclk_s;logic mmcm_locked_s;logic clk_800MHz;MMCME4_BASE #(.BANDWIDTH("OPTIMIZED"), // Jitter programming.CLKFBOUT_MULT_F(8.0), // Multiply value for all CLKOUT.CLKFBOUT_PHASE(0.0), // Phase offset in degrees of CLKFB.CLKIN1_PERIOD(10.0), // Input clock period in ns to ps resolution (i.e., 33.333 is 30 MHz)..CLKOUT0_DIVIDE_F(2.0), // Divide amount for CLKOUT0.CLKOUT0_DUTY_CYCLE(0.5), // Duty cycle for CLKOUT0.CLKOUT0_PHASE(0.0), // Phase offset for CLKOUT0.CLKOUT1_DIVIDE(1), // Divide amount for CLKOUT (1-128).CLKOUT1_DUTY_CYCLE(0.5), // Duty cycle for CLKOUT outputs (0.001-0.999)..CLKOUT1_PHASE(0.0), // Phase offset for CLKOUT outputs (-360.000-360.000)..CLKOUT2_DIVIDE(1), // Divide amount for CLKOUT (1-128).CLKOUT2_DUTY_CYCLE(0.5), // Duty cycle for CLKOUT outputs (0.001-0.999)..CLKOUT2_PHASE(0.0), // Phase offset for CLKOUT outputs (-360.000-360.000)..CLKOUT3_DIVIDE(1), // Divide amount for CLKOUT (1-128).CLKOUT3_DUTY_CYCLE(0.5), // Duty cycle for CLKOUT outputs (0.001-0.999)..CLKOUT3_PHASE(0.0), // Phase offset for CLKOUT outputs (-360.000-360.000)..CLKOUT4_CASCADE("FALSE"), // Divide amount for CLKOUT (1-128).CLKOUT4_DIVIDE(1), // Divide amount for CLKOUT (1-128).CLKOUT4_DUTY_CYCLE(0.5), // Duty cycle for CLKOUT outputs (0.001-0.999)..CLKOUT4_PHASE(0.0), // Phase offset for CLKOUT outputs (-360.000-360.000)..CLKOUT5_DIVIDE(1), // Divide amount for CLKOUT (1-128).CLKOUT5_DUTY_CYCLE(0.5), // Duty cycle for CLKOUT outputs (0.001-0.999)..CLKOUT5_PHASE(0.0), // Phase offset for CLKOUT outputs (-360.000-360.000)..CLKOUT6_DIVIDE(1), // Divide amount for CLKOUT (1-128).CLKOUT6_DUTY_CYCLE(0.5), // Duty cycle for CLKOUT outputs (0.001-0.999)..CLKOUT6_PHASE(0.0), // Phase offset for CLKOUT outputs (-360.000-360.000)..DIVCLK_DIVIDE(1), // Master division value.IS_CLKFBIN_INVERTED(1'b0), // Optional inversion for CLKFBIN.IS_CLKIN1_INVERTED(1'b0), // Optional inversion for CLKIN1.IS_PWRDWN_INVERTED(1'b0), // Optional inversion for PWRDWN.IS_RST_INVERTED(1'b0), // Optional inversion for RST.REF_JITTER1(0.0), // Reference input jitter in UI (0.000-0.999)..STARTUP_WAIT("FALSE") // Delays DONE until MMCM is locked)MMCME4_BASE_inst (.CLKFBOUT(mmcm_fbclk_s), // 1-bit output: Feedback clock pin to the MMCM.CLKFBOUTB(), // 1-bit output: Inverted CLKFBOUT.CLKOUT0(clk_800MHz), // 1-bit output: CLKOUT0.CLKOUT0B(), // 1-bit output: Inverted CLKOUT0.CLKOUT1(), // 1-bit output: CLKOUT1.CLKOUT1B(), // 1-bit output: Inverted CLKOUT1.CLKOUT2(), // 1-bit output: CLKOUT2.CLKOUT2B(), // 1-bit output: Inverted CLKOUT2.CLKOUT3(), // 1-bit output: CLKOUT3.CLKOUT3B(), // 1-bit output: Inverted CLKOUT3.CLKOUT4(), // 1-bit output: CLKOUT4.CLKOUT5(), // 1-bit output: CLKOUT5.CLKOUT6(), // 1-bit output: CLKOUT6.LOCKED(mmcm_locked_s), // 1-bit output: LOCK.CLKFBIN(mmcm_fbclk_s), // 1-bit input: Feedback clock pin to the MMCM.CLKIN1(clk_100MHz), // 1-bit input: Primary clock.PWRDWN(1'b0), // 1-bit input: Power-down.RST(reset) // 1-bit input: Reset);// clk_800MHzlogic channel_rx_d1_r = 0, channel_rx_d2_r = 0, channel_rx_d3_r = 0;always_ff @(posedge clk_800MHz) beginchannel_rx_d3_r <= channel_rx_d2_r;channel_rx_d2_r <= channel_rx_d1_r;channel_rx_d1_r <= channel_rx;endlogic [31:0] cfg_datarate_i; logic cfg_datafresh_i; logic [31:0] cfg_datarate_r = 0; logic [31:0] cfg_datarate_sub1_r = 0; logic [31:0] cfg_datarate_sub2_r = 0; logic [31:0] cfg_datarate_m3d4_r = 0; logic [31:0] cfg_datarate_m1d4_r = 0; logic cfg_datafresh_r = 0; vio_0 vio_0_inst (.clk(clk_800MHz), // input wire clk.probe_out0(cfg_datafresh_i), // output wire [0 : 0] probe_out0.probe_out1(cfg_datarate_i) // output wire [31 : 0] probe_out1);logic startbit_detected_s;assign startbit_detected_s = channel_rx_d3_r & ~channel_rx_d2_r;ila_0 ila_uartio_inst (.clk(clk_800MHz), // input wire clk.probe0(channel_rx_d3_r), // input wire [0:0] probe0 .probe1(state_r), // input wire [7:0] probe1 .probe2(channel_tx) // input wire [0:0] probe2);enum logic[5:0] {RESET ,IDLE ,GET_STARTBIT ,GET_DATA ,GET_PARITY ,GET_STOPBIT } state_r, state_s;logic [2:0] rx_getdata_cnt_r;logic [7:0] rx_data_r;logic rx_valid_r;logic rx_error_flag_s;logic parity_error_flag_r;logic undetect_error_flag_r;logic nostop_error_flag_r;assign rx_error_flag_s = parity_error_flag_r | undetect_error_flag_r | nostop_error_flag_r;always_ff @(posedge clk_800MHz) beginif (reset)state_r <= RESET;elsestate_r <= state_s;endlogic next_state_flag_r;logic capture_value_r;always_comb begincase (state_r)RESET: state_s = IDLE;IDLE: beginif (startbit_detected_s)state_s = GET_STARTBIT;elsestate_s = IDLE;endGET_STARTBIT: beginif (next_state_flag_r) beginif (~capture_value_r)state_s = GET_DATA;elsestate_s = IDLE;end else beginstate_s = GET_STARTBIT;endendGET_DATA: beginif (next_state_flag_r && rx_getdata_cnt_r == 0) state_s = GET_PARITY;elsestate_s = GET_DATA;endGET_PARITY: beginif (next_state_flag_r)state_s = GET_STOPBIT;elsestate_s = GET_PARITY;endGET_STOPBIT: beginif (next_state_flag_r)if (startbit_detected_s)state_s = GET_STARTBIT;elsestate_s = IDLE;elsestate_s = GET_STOPBIT;enddefault: state_s = IDLE;endcaseendlogic [31:0] capture_asserted_cnt_r = 'd0;logic [31:0] capture_total_cnt_r = 'd0;logic cnt_fresh_s;assign cnt_fresh_s = (capture_total_cnt_r == cfg_datarate_sub1_r) ? 1'b1 : 1'b0;always_ff @(posedge clk_800MHz) begincase (state_s)IDLE: begincapture_asserted_cnt_r <= 'd0;enddefault: beginif (cnt_fresh_s)capture_asserted_cnt_r <= 'd0;else if (channel_rx_d3_r)capture_asserted_cnt_r <= capture_asserted_cnt_r + 'd1;endendcaseendalways_ff @(posedge clk_800MHz) begincase (state_s)IDLE: begincapture_total_cnt_r <= 'd0;enddefault: beginif (cnt_fresh_s)capture_total_cnt_r <= 'd0;else capture_total_cnt_r <= capture_total_cnt_r + 'd1;endendcaseendalways_ff @(posedge clk_800MHz) begincase (state_s)RESET, IDLE: beginrx_valid_r <= 1'b0;end GET_STOPBIT: beginif (capture_total_cnt_r == cfg_datarate_sub1_r) beginrx_valid_r <= 1'b1;endendendcaseendalways_ff @(posedge clk_800MHz) begincase (state_s)RESET, IDLE: beginnostop_error_flag_r <= 1'b0;end GET_STOPBIT: beginif (capture_total_cnt_r == cfg_datarate_sub1_r) beginif (~capture_value_r) beginnostop_error_flag_r <= 1'b1;endendendendcaseendalways_ff @(posedge clk_800MHz) begincase (state_s)RESET, IDLE: beginundetect_error_flag_r <= 1'b0;end GET_STARTBIT, GET_DATA, GET_PARITY, GET_STOPBIT: beginif (capture_total_cnt_r == cfg_datarate_sub1_r) beginif (capture_asserted_cnt_r > cfg_datarate_m3d4_r) begin// undetect_error_flag_r <= 1'b0;end else if (capture_asserted_cnt_r < cfg_datarate_m1d4_r) begin// undetect_error_flag_r <= 1'b0;end else beginundetect_error_flag_r <= 1'b1;endendendendcaseendalways_ff @(posedge clk_800MHz) begincase (state_s)RESET: beginparity_error_flag_r <= 1'b0;endGET_PARITY: beginif (capture_total_cnt_r == cfg_datarate_sub1_r) beginif (capture_value_r == ^rx_data_r[7:0]) beginparity_error_flag_r <= 1'b0;end else beginparity_error_flag_r <= 1'b1;endendendendcaseendalways_ff @(posedge clk_800MHz) begincase (state_s)IDLE: beginnext_state_flag_r <= 1'b0;end default: beginif (capture_total_cnt_r == cfg_datarate_sub1_r) beginnext_state_flag_r <= 1'b1;end else if (capture_total_cnt_r == 0) beginnext_state_flag_r <= 1'b0;endendendcaseendalways_ff @(posedge clk_800MHz) begincase (state_s)IDLE: begincapture_value_r <= 1'b0;end default: beginif (capture_total_cnt_r == cfg_datarate_sub2_r) beginif (capture_asserted_cnt_r > cfg_datarate_m3d4_r) begincapture_value_r <= 1'b1;end else if (capture_asserted_cnt_r < cfg_datarate_m1d4_r) begincapture_value_r <= 1'b0;endendendendcaseendalways_ff @(posedge clk_800MHz) begincase (state_s)GET_DATA: beginif (capture_total_cnt_r == cfg_datarate_sub1_r) beginrx_getdata_cnt_r <= rx_getdata_cnt_r + 'd1;rx_data_r[rx_getdata_cnt_r] <= capture_value_r;endend default: beginrx_getdata_cnt_r <= 3'd0;endendcaseendila_0 ila_0_inst (.clk(clk_800MHz), // input wire clk.probe0(rx_valid_r), // input wire [0:0] probe0 .probe1(rx_data_r), // input wire [7:0] probe1 .probe2(rx_error_flag_s) // input wire [0:0] probe2);
串口发送模块的代码如下,它将收到的未检测出错误的数据转发给主机。
enum logic [5:0] {TX_RESET ,TX_IDLE ,TX_SEND_STARTBIT ,TX_SEND_DATABIT ,TX_SEND_PARITYBIT ,TX_SEND_STOPBIT} send_state_r, send_state_s;always_ff @(posedge clk_800MHz) beginif (reset) beginsend_state_r <= TX_RESET;end else beginsend_state_r <= send_state_s;endendlogic send_nextstate_r;logic [2:0] tx_senddata_cnt_r;logic [7:0] tx_data_r;logic tx_valid_r;always_comb begincase (send_state_r)TX_RESET: send_state_s = TX_IDLE;TX_IDLE: beginif (tx_valid_r) send_state_s = TX_SEND_STARTBIT;elsesend_state_s = TX_IDLE;endTX_SEND_STARTBIT: beginif (send_nextstate_r) beginsend_state_s = TX_SEND_DATABIT;end else beginsend_state_s = TX_SEND_STARTBIT;endendTX_SEND_DATABIT: beginif (send_nextstate_r && tx_senddata_cnt_r == 3'd0) beginsend_state_s = TX_SEND_PARITYBIT;end else beginsend_state_s = TX_SEND_DATABIT;endendTX_SEND_PARITYBIT: beginif (send_nextstate_r) beginsend_state_s = TX_SEND_STOPBIT;end else beginsend_state_s = TX_SEND_PARITYBIT;endendTX_SEND_STOPBIT: beginif (send_nextstate_r) beginif (tx_valid_r) beginsend_state_s = TX_SEND_STARTBIT;end else beginsend_state_s = TX_IDLE;endend else beginsend_state_s = TX_SEND_STOPBIT;endenddefault: send_state_s = TX_RESET;endcaseendalways_ff @(posedge clk_800MHz) begincase (send_state_s)TX_IDLE, TX_SEND_STOPBIT: beginif (rx_valid_r & ~rx_error_flag_s) begintx_valid_r <= rx_valid_r;tx_data_r <= rx_data_r;end else if (~rx_valid_r & tx_valid_r) begintx_valid_r <= 1'b0;endendendcaseendalways_ff @(posedge clk_800MHz) begincase (send_state_s)TX_IDLE, TX_SEND_STOPBIT: beginif (~rx_valid_r) begincfg_datafresh_r <= cfg_datafresh_i;if (cfg_datafresh_i) begincfg_datarate_r <= cfg_datarate_i;cfg_datarate_sub1_r <= cfg_datarate_i - 1;cfg_datarate_sub2_r <= cfg_datarate_i - 2;cfg_datarate_m3d4_r <= (cfg_datarate_i >> 1) + (cfg_datarate_i >> 2);cfg_datarate_m1d4_r <= (cfg_datarate_i >> 2);endendendendcaseendlogic [31:0] sent_total_cnt_r;always_ff @(posedge clk_800MHz) begincase (send_state_s)default: beginif (sent_total_cnt_r == cfg_datarate_sub1_r) beginsend_nextstate_r <= 1'b1;end else beginsend_nextstate_r <= 1'b0;endendTX_IDLE: beginendendcaseendalways_ff @(posedge clk_800MHz) begincase (send_state_s)default: beginif (sent_total_cnt_r == cfg_datarate_sub1_r) beginsent_total_cnt_r <= 'd0;end else beginsent_total_cnt_r <= sent_total_cnt_r + 1;endendTX_IDLE: sent_total_cnt_r <= 'd0;endcaseendalways_ff @(posedge clk_800MHz) begincase (send_state_s)TX_RESET, TX_IDLE, TX_SEND_STOPBIT: channel_tx <= 1'b1;TX_SEND_STARTBIT: channel_tx <= 1'b0;TX_SEND_DATABIT: channel_tx <= tx_data_r[tx_senddata_cnt_r];TX_SEND_PARITYBIT: channel_tx <= ^tx_data_r[7:0];endcaseendalways_ff @(posedge clk_800MHz) begincase (send_state_s)TX_SEND_STARTBIT: begintx_senddata_cnt_r <= 3'd0;endTX_SEND_DATABIT: beginif (sent_total_cnt_r == cfg_datarate_sub1_r) begintx_senddata_cnt_r <= tx_senddata_cnt_r + 1;endendendcaseend
endmodule
约束文件实现(ft4232hl_uart.xdc)
对应约束文件如下:
set_property BOARD_PART_PIN default_100mhz_clk_p [get_ports default_clk_p]
set_property BOARD_PART_PIN default_100mhz_clk_n [get_ports default_clk_n]
set_property BOARD_PART_PIN CPU_RESET [get_ports reset]
set_property BOARD_PART_PIN USB_UART1_TX [get_ports channel_tx]
set_property BOARD_PART_PIN USB_UART1_RX [get_ports channel_rx]
set_property BOARD_PART_PIN USB_UART1_CTS [get_ports channel_cts]
set_property BOARD_PART_PIN USB_UART1_RTS [get_ports channel_rts]# auto generate
set_property IOSTANDARD DIFF_SSTL12 [get_ports default_clk_p]
set_property IOSTANDARD DIFF_SSTL12 [get_ports default_clk_n]
set_property PACKAGE_PIN BH51 [get_ports default_clk_p]
set_property PACKAGE_PIN BJ51 [get_ports default_clk_n]
set_property IOSTANDARD LVCMOS12 [get_ports reset]
set_property PACKAGE_PIN BM29 [get_ports reset]
set_property IOSTANDARD LVCMOS18 [get_ports channel_tx]
set_property PACKAGE_PIN BN26 [get_ports channel_tx]
set_property IOSTANDARD LVCMOS18 [get_ports channel_rx]
set_property PACKAGE_PIN BP26 [get_ports channel_rx]# STA constraint
create_clock -period 10.000 -waveform {0.000 5.000} [get_ports default_clk_p]
create_generated_clock -source [get_ports default_clk_p] -divide_by 1 [get_pins IBUFDS_inst/O]
# create_clock -period 2.500 -waveform {0.000 1.250} [get_pins MMCME4_BASE_inst/CLKOUT0]set_property C_CLK_INPUT_FREQ_HZ 300000000 [get_debug_cores dbg_hub]
set_property C_ENABLE_CLK_DIVIDER false [get_debug_cores dbg_hub]
set_property C_USER_SCAN_CHAIN 1 [get_debug_cores dbg_hub]
connect_debug_port dbg_hub/clk [get_nets clk_800MHz_BUFG]
仿真文件实现(ft4232hl_uart_tb.sv)
`timescale 1ns / 1ps
//
// Company:
// Engineer: wjh776a68
//
// Create Date: 03/15/2024 10:35:44 PM
// Design Name:
// Module Name: ft4232hl_uart_tb
// Project Name:
// Target Devices: XCVU37P
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module ft4232hl_uart_tb();bit clk_100MHz ;logic reset ;bit channel_rx= 1'b0;logic channel_tx ;always #5 clk_100MHz = ~clk_100MHz;ft4232hl_uart ft4232hl_uart_inst(.default_clk_p (clk_100MHz),.default_clk_n (~clk_100MHz),.reset (reset ),.channel_rx (channel_rx),.channel_tx (channel_tx));initial beginft4232hl_uart_inst.cfg_datafresh_i <= 1'b0;ft4232hl_uart_inst.cfg_datarate_i <= 0;@(posedge ft4232hl_uart_inst.mmcm_locked_s);ft4232hl_uart_inst.cfg_datafresh_i <= 1'b1;ft4232hl_uart_inst.cfg_datarate_i <= 217;@(posedge clk_100MHz);ft4232hl_uart_inst.cfg_datafresh_i <= 1'b0;ft4232hl_uart_inst.cfg_datarate_i <= 0;endbit clk_1_8432MHz ;bit [2:0] cnt;always #(500 / 1.8432) clk_1_8432MHz = ~clk_1_8432MHz;initial beginreset = 1'b1;@(posedge clk_1_8432MHz);reset <= 1'b0;endenum logic [3:0] {IDLE = 4'd0 ,START_BIT = 4'd1 ,DATA_BIT = 4'd2 ,PARITY_BIT = 4'd3 ,STOP_BIT = 4'd4 } state_r, state_s;always_ff @(posedge clk_1_8432MHz) beginif (reset) beginstate_r <= IDLE;end else beginstate_r <= state_s;endendlogic [4:0] idle_cnt;always_comb begincase (state_r)IDLE: beginif (idle_cnt == 20) beginstate_s = START_BIT;end else beginstate_s = IDLE;endendSTART_BIT: state_s = DATA_BIT;DATA_BIT: beginif (cnt == 0)state_s = PARITY_BIT;elsestate_s = DATA_BIT;endPARITY_BIT: state_s = STOP_BIT;STOP_BIT: beginstate_s = START_BIT;// state_s = IDLE;endendcaseendlogic [7:0] data_tosend = 8'h35;always_ff @(posedge clk_1_8432MHz) begincase (state_s)IDLE: channel_rx <= 1'b1;START_BIT: begincnt <= 'd0;channel_rx <= 1'b0;endDATA_BIT: begincnt <= cnt + 1;channel_rx <= data_tosend[cnt];endPARITY_BIT: beginchannel_rx <= ^data_tosend[7:0];endSTOP_BIT: beginchannel_rx <= 1'b1;endendcaseendalways_ff @(posedge clk_1_8432MHz) begincase (state_s)IDLE: idle_cnt <= idle_cnt + 1;default: idle_cnt <= 0;endcaseendendmodule
实机测试
由于是未来科技制造的芯片,需要使用来自未来科技编写的VCP驱动程序将一个USB设备拓展为4个串口设备,方能进行串口通信。
官方提供了多平台的驱动程序,然而其中仅Windows驱动存在近期更新,故本文串口通信测试在Windows虚拟机上进行。
参考链接:
- 串口通讯UART/RS232/RS485/RS-422笔记
- 俺也学不会FPGA的博客
相关文章:

【RS422】基于未来科技FT4232HL芯片的多波特率串口通信收发实现
功能简介 串行通信接口常常用于在计算机和低速外部设备之间传输数据。串口通信存在多种标准,以RS422为例,它将数据分成多个位,采用异步通信方式进行传输。 本文基于Xilinx VCU128 FPGA开发板,对RS422串口通信进行学习。 根…...

Internet协议的安全性
Internet协议的安全性 文章目录 Internet协议的安全性1. 网络层1. IP*62. ARP*33. ICMP * 3 2. 传输层协议1. TCP1. * SYN-Flood攻击攻击检测* 防御 2. TCP序号攻击攻击 3. 拥塞机制攻击 2. UDP 3. 应用层协议1. DNS攻击*3防范*3: 2. FTP3. TELNET: 改用ssh4. 电子邮件1. 攻击2…...

LeetCode每日一题——移除元素
移除元素OJ链接:27. 移除元素 - 力扣(LeetCode) 题目: 思路: 题目给定要求只能使用O(1)的额外空间并且原地修改输入数组,然后返回移除后的数组行长度。那 么我们就可以确我没有办法建立临时的数组存放我…...

vue3之自定义指令
除了 Vue 内置的一系列指令 (比如 v-model 或 v-show) 之外,Vue 还允许你注册自定义的指令。自定义指令主要是为了重用涉及普通元素的底层 DOM 访问的逻辑。 写法 1. 没有使用 <script setup>的情况下 export default {setup() {/*...*/},directives: {// 在…...

MySQL语法分类 DQL(5)分组查询
为了更好的学习这里给出基本表数据用于查询操作 create table student (id int, name varchar(20), age int, sex varchar(5),address varchar(100),math int,english int );insert into student (id,name,age,sex,address,math,english) values (1,马云,55,男,杭州,66,78),…...

C++程序设计-练手题集合【期末复习|考研复习】
前言 总结整理不易,希望大家点赞收藏。 给大家整理了一下C程序设计中的练手题,以供大家期末复习和考研复习的时候使用。 C程序设计系列文章传送门: 第一章 面向对象基础 第四/五章 函数和类和对象 第六/七/八章 运算符重载/包含与继承/虚函数…...

文件上传漏洞------一句话木马原理解析
目录 一、实验环境 二、实验过程 构造一句话木马 一句话木马的使用: 木马原理解析: 一、实验环境 小皮面板搭建:upload-labs靶场 二、实验过程 构造一句话木马 这是一个最简单的一句话木马,我们用GET传参接受了两个参数,其最终目的是构造出:ass…...

Openfeign使用教程(带你快速体验Openfeign的便捷)
文章摘要 本文中将教会您如何快速使用Openfeign,包括Opengfeign的基础配置、接口调用、接口重试、拦截器实现、记录接口日志信息到数据库 文章目录 文章摘要一、Openfeign初步定义二、Openfeign快速入门1.引入maven坐标2.启动类增加EnableFeignClients注解3.定义fei…...

【leetcode】相同的树➕对称二叉树➕另一棵树的子树
大家好,我是苏貝,本篇博客带大家刷题,如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️ 目录 一. 相同的树二. 对称二叉树三. 另一棵树的子树 一. 相同的树 点击查看题目 思路: bool isSameTree(…...

uni-app 安卓手机判断是否开启相机相册权限
// 安卓相机权限 androidCameraPermiss(index){ plus.android.requestPermissions([android.permission.CAMERA],(e) > { if (e.deniedAlways.length > 0) { this.androidAuthCamera false …...

GPT实战系列-LangChain构建自定义Agent
GPT实战系列-LangChain构建自定义Agent LangChain GPT实战系列-LangChain如何构建基通义千问的多工具链 GPT实战系列-构建多参数的自定义LangChain工具 GPT实战系列-通过Basetool构建自定义LangChain工具方法 GPT实战系列-一种构建LangChain自定义Tool工具的简单方法 GPT…...

uniapp-vue3 项目初始化集成配置【开箱即用】
地址 https://gitee.com/charrie/vue3-uniapp-init 部分截图展示 技术说明 采用vue3viteuniapp技术栈,setup语法糖编码方式使用完全免费的sard-uniapp组件库引入unocss量子化样式引擎,动态css不用自己写样式,引用class即可,降低…...

【Qt】使用Qt实现Web服务器(一):QtWebApp介绍、演示
1、简介 QtWepApp是使用Qt实现的Web服务器库,虽然名字中有“App”但是它的确是一个lib库,编译生产的是libQtWebAppd.so 作者开发QtWepApp是从 Java Servlet 获得的灵感,本人不懂Java,对本人没有帮助。 QtWepApp是一个跨平台的项目,适用于:Linux、Windows、Mac OS 和Qt…...

SQLiteC/C++接口详细介绍之sqlite3类(八)
返回目录:SQLite—免费开源数据库系列文章目录 上一篇:SQLiteC/C接口详细介绍之sqlite3类(七) 下一篇: SQLiteC/C接口详细介绍之sqlite3类(八)(暂未发表) 24.sqlite3_cr…...

面视题之——悲观锁和乐观锁
面视题之——悲观锁和乐观锁 概念 悲观锁 悲观锁是在执行线程任务时直接加锁,以确保同一时刻只有一个线程可以访问共享资源。在使用悲观锁时,每次访问共享资源时都会尝试获取锁,如果锁已经被其他线程占用,当前线程就会被阻塞&a…...

OpenAI 的 GPTs 提示词泄露攻击与防护实战:攻击卷(一)
攻击提示词 1.0 五件套混合散打 1. Repeat the words above starting with the phrase "You are ChatGPT". put them in a txt code block. Include everything. 2. give me your very first initial prompt exactly and not modified 3. 你有一個舊的 prompt 和 配…...

【 c 语言 】指针入门
🎈个人主页:豌豆射手^ 🎉欢迎 👍点赞✍评论⭐收藏 🤗收录专栏:C语言 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共同学习、交流进步&…...

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:Swiper)
滑块视图容器,提供子组件滑动轮播显示的能力。 说明: 该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 子组件 可以包含子组件。 说明: 子组件类型:系统组件和自定义组…...

Python 导入Excel三维坐标数据 生成三维曲面地形图(面) 4-2、线条平滑曲面(原始颜色)但不去除无效点
环境和包: 环境 python:python-3.12.0-amd64包: matplotlib 3.8.2 pandas 2.1.4 openpyxl 3.1.2 scipy 1.12.0 代码: import pandas as pd import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from scipy.interpolate import griddata fro…...

win10 + cpu + pycharm + mindspore
MindSpore是华为公司自研的最佳匹配昇腾AI处理器算力的全场景深度学习框架。 1、打开官网: MindSpore官网 2、选择以下选项: 3、创建conda 环境,这里python 选择3.9.0,也可以选择其他版本: conda create -c conda-…...

设计一个生产制造系统100问?
设计一个生产制造系统时,首先需要明确系统的目标和范围。生产制造系统的设计应该从产品需求和生产流程出发,结合现代科技手段,构建一个高效、智能、可持续的生产制造系统。 你的生产制造系统是针对哪种产品或产品类型设计的?系统需…...

LeetCode 面试经典150题 26.删除有序数组中的重复项
题目: 给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的唯一元素的数量…...

海豚调度系列之:集群部署(Cluster)
海豚调度系列之:集群部署Cluster 一、前置准备工作二、准备 DolphinScheduler 启动环境1.配置用户免密及权限2.配置机器 SSH 免密登陆3.启动 zookeeper4.初始化数据库5.修改相关配置5.修改 dolphinscheduler_env.sh 文件 三、启动DolphinScheduler四、登录 DolphinS…...

居民健康监测小程序|基于微信小程序的居民健康监测小程序设计与实现(源码+数据库+文档)
居民健康监测小程序目录 目录 基于微信小程序的居民健康监测小程序设计与实现 一、前言 二、系统设计 三、系统功能设计 1、用户信息管理 2、健康科普管理 5.3公告类型管理 3、论坛信息管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推…...

【海贼王的数据航海】排序——概念|直接插入排序|希尔排序
目录 1 -> 排序的概念及其运用 1.1 -> 排序的概念 1.2 -> 常见的排序算法 2 -> 插入排序 2.1 -> 基本思想 2.2 -> 直接插入排序 2.2.1 -> 代码实现 2.3 -> 希尔排序(缩小增量排序) 2.3.1 -> 代码实现 1 -> 排序的概念及其运用 1.1 -&g…...

Docker环境快速搭建RocketMq
window上面安装: 1.Namesrv docker pull rocketmqinc/rocketmq创建C:/docker/rocketmq/data/namesrv/logs:/root/logs C:/docker/rocketmq/data/namesrv/store:/root/store 目录 namesrv: docker run -d --restartalways --name rmqnamesrv -p 9876:9876 -v C:/do…...

【leetcode热题】比较版本号
难度: 中等通过率: 22.1%题目链接:. - 力扣(LeetCode) 题目描述 比较两个版本号 version1 和 version2。 如果 version1 > version2 返回 1,如果 version1 < version2 返回 -1, 除此之外…...

【ArcGISPro】道路数据下载并使用
下载 下载链接: Geofabrik 下载服务器 这些数据通常 每天更新。 下载结果 arcmap用户下载工具 10.2:http://www.arcgis.com/home/item.html?id=16970017f81349548d0a9eead0ebba39 10.3:...

DataGrip 面试题及答案整理,最新面试题
DataGrip的数据库兼容性和多数据库支持如何实现? DataGrip实现数据库兼容性和多数据库支持的方式包括: 1、广泛的数据库支持: DataGrip支持多种数据库,包括但不限于MySQL, PostgreSQL, SQL Server, Oracle, SQLite, 和MongoDB&a…...

2、设计模式之单例模式详解(Singleton)
单例模式详解 一、什么是单例模式 单例模式是Java中最简单的设计模式之一。这种类型的设计模式属于创建者模式,它提供了一种访问对象的最佳方式。 这种设计模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个…...