【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虚拟机上进行。

在这里插入图片描述

参考链接:

  1. 串口通讯UART/RS232/RS485/RS-422笔记
  2. 俺也学不会FPGA的博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/749565.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

家具工厂5G智能制造数字孪生可视化平台,推进家具行业数字化转型

家具制造5G智能制造工厂数字孪生可视化平台&#xff0c;推进家具行业数字化转型。随着科技的飞速发展&#xff0c;家具制造业正迎来一场前所未有的数字化转型。在这场家具制造业转型中&#xff0c;5G智能制造工厂数字孪生可视化平台发挥着至关重要的作用。 5G智能制造工厂数字孪…

MySQL语法分类 DQL(3)排序查询

为了更好的学习这里给出基本表数据用于查询操作 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),…

华为数通方向HCIP-DataCom H12-821题库(多选题:161-180)

第161题 以下关于IPv6优势的描述,正确的是哪些项? A、底层自身携带安全特性 B、加入了对自动配置地址的支持,能够无状态自动配置地址 C、路由表相比IPv4会更大,寻址更加精确 D、头部格式灵活,具有多个扩展头 【参考答案】ABD 【答案解析】 第162题 在OSPF视图下使用Filt…

降维算法之t-SNE (t-Distributed Stochastic Neighbor Embedding)

注意&#xff1a;本文引用自专业人工智能社区Venus AI 更多AI知识请参考原站 &#xff08;[www.aideeplearning.cn]&#xff09; t-SNE是一种用于探索高维数据结构的非线性降维技术。它特别适用于高维数据的可视化&#xff0c;因为它能够在低维空间中保留原始高维数据的局部结…

[WUSTCTF2020]朴实无华

查看robots.txt 找到/fAke_flagggg.php 显然这是个假的flag&#xff0c;但是我们在header处发现了fl4g.php 近来发现中文全部变成了乱码 插件转成utf8后正常显示 <?php header(Content-type:text/html;charsetutf-8); error_reporting(0); highlight_file(__file__);//leve…

Linux 系统调用函数fork、vfork、clone详解

文章目录 1 fork1.1 基本介绍1.2 fork实例1.2.1多个fork返回值1.2.2 C语言 fork与输出1.2.3 fork &#x1f4a3; 2 vfork2.1 基本介绍2.2 验证vfork共享内存 3 clone3.1 基本介绍3.2 clone使用 1 fork 1.1 基本介绍 #include <sys/types.h> #include <unistd.h>p…

PS学习-抠图-蒙版-冰块酒杯等透明物体

选中图&#xff0c;ctrlA 全选 ctrlC复制 创建一个蒙版图层 选中蒙版Alt 点击进入 ctrlv 复制 ctrli 反转 原图层 ctrldelete填充为白色 添加一个背景&#xff0c;这个方法通用 首选创建一个 拖到最底部 给它填充颜色 这个可能是我图片的原因。视频是这样做的

五子棋小游戏(sut实验报告)

实验目的 实现人与人或人与电脑进行五子棋对弈 实验内容 启动游戏&#xff0c;显示游戏参数设置界面&#xff0c;用户输入参数后进入游戏界面&#xff0c;显示棋盘及双方博弈过程&#xff0c;游戏过程中可选择退出游戏。判定一方获胜后结束本局游戏&#xff0c;可选择继续下…

Fiddler抓不到包

fiddler该设置的设置好之后&#xff0c;为啥就是抓不到包 以下都是以谷歌浏览器为例子 方法一&#xff1a; 将fidder证书导入到浏览器&#xff0c;设置搜索证书-->安全-->管理证书 这里可以看到将证书导入之后样子&#xff0c;名字为&#xff1a;DO_NOT_TRUST_Fiddler…

Linux操作系统裸机开发-环境搭建

一、配置SSH服务 1、下载安装ssh服务输入以下命令 sudo apt-get install nfs-kernel-server portmap2、建立一个供SSH服务使用的文件夹如以下命令 mkdir linux 3、完成前两步之后需要将其文件路径放到/etc/exports文件里输入以下命令&#xff1a; sudo vi /etc/esports 4.打…

线性回归 quickstart

构建一元一次方程 100个&#xff08;X, y &#xff09;&#xff0c;大概是’y3x4’ import numpy as npnp.random.seed(42) # to make this code example reproducible m 100 # number of instances X 2 * np.random.rand(m, 1) # column vector y 4 3 * X np.random…

最详细数据仓库项目实现:从0到1的电商数仓建设(数仓部分)

1、数仓 数据仓库是一个为数据分析而设计的企业级数据管理系统&#xff0c;它是一个系统&#xff0c;不是一个框架。可以独立运行的&#xff0c;不需要你参与&#xff0c;只要运行起来就可以自己运行。 数据仓库不是为了存储&#xff08;但是能存&#xff09;&#xff0c;而是…

创业板指399006行情数据API接口

# 测试&#xff1a;返回不超过10条数据&#xff08;2年历史&#xff09; https://tsanghi.com/api/fin/index/CHN/daily?tokendemo&ticker399006&order2Python示例 import requestsurl f"https://tsanghi.com/api/fin/index/CHN/daily?tokendemo&ticker399…

EtherCAT 开源主站 IGH 在 linux 开发板的移植和伺服通信测试

手边有一套正点原子linux开发板imax6ul&#xff0c;一直在吃灰&#xff0c;周末业余时间无聊&#xff0c;把EtherCAT的开源IGH主站移植到开发板上玩玩儿&#xff0c;搞点事情做。顺便学习研究下EtherCAT总线协议及其对伺服驱动器的运动控制过程。实验很有意思&#xff0c;这里总…

【JDBC编程】 Java程序操作数据库

目录 一、数据库编程的必备条件 二、什么是JDBC&#xff1f; 三、JDBC的使用 1. 准备工作 2. 建立数据库连接 2.1 加载驱动程序 2.2 数据库连接池技术 3. 正式操作 四、JDBC的局限性与MyBatis的优势 一、数据库编程的必备条件 编程语言&#xff0c;如Java&#xff0…

创业新手看过来!四招助你开启成功之旅

如果你每个月的薪资仅有几千块&#xff0c;还背负着债务的重担&#xff0c;家中的老少都期盼着你为他们撑起一片天&#xff0c;那么&#xff0c;你每日都可能为了如何打破这一困境而焦虑不安。不过&#xff0c;请稍安勿躁&#xff0c;今天我将为你提供四个建议&#xff0c;或许…

Transformer学习笔记(二)

一、文本嵌入层Embedding 1、作用&#xff1a; 无论是源文本嵌入还是目标文本嵌入&#xff0c;都是为了将文本中词汇的数字表示转变为向量表示&#xff0c;希望在这样的高维空间捕捉词汇间的关系。 二、位置编码器Positional Encoding 1、作用&#xff1a; 因为在Transformer…

解锁区块链游戏数据解决方案

作者&#xff1a;stellafootprint.network 随着区块链技术的日新月异&#xff0c;游戏行业正迎来一场革命&#xff0c;催生了区块链游戏的崛起。这一变革不仅为用户带来了全新的互动体验&#xff0c;也开辟了全新的盈利渠道。然而&#xff0c;在这一新兴领域&#xff0c;数据的…

html--花瓣

代码 <!DOCTYPE html> <html lang"en" ><head> <meta charset"UTF-8"> <title>Petals</title><link rel"stylesheet" href"css/style.css"></head><body><div class"…

Jpg图片变gif怎么操作?1分钟教你在线生成

jpg是一种常见的图像文件格式&#xff0c;它使用有损压缩算法来减小文件大小。这意味着JPG图像可以在保持较高质量的同时减小文件大小&#xff0c;但会导致一些细节的损失。JPG图像适用于存储照片和其他需要高质量图像的场景。而GIF是一种支持动画的图像文件格式。与JPG不同&am…