當前位置:首頁 » 操作系統 » linuxuart

linuxuart

發布時間: 2022-10-22 13:22:22

❶ 如何實現在linux系統上直接控制串口RTS信號電

嵌入式開發板到手後一般都會開放串口,對串口的操作可以說是最基本的操作,那麼拿到開發板後怎樣操作串口呢?怎樣利用串口向外發送數據呢?

我做的是一個通過串口來發送一串字元,實現NBIot的傳輸,系統是linux系統下的,發送的數據需要是16進制的數據。以下是c語言開發串口的相關代碼記錄。
1.找到串口的設備號
在linux系統下,所有的設備都是文件,所以要先找到串口這個設備文件,之後就可以對這個串口進行操作。
#define UART_DEV "/dev/ttyAMA2"
2.打開串口並初始化串口

串口的打開只需要一個open函數就可以打開,下面有一個初始化的函數,先將串口打開,如果打開成功,會返回一個設備描述符。

❷ linux 內核 uart driver 只有fifo滿才向用戶buf傳遞數據嗎

對於串口驅動的移植准備自己分析一下源代碼的,但是發現自己好多地方都只知道一 些皮毛,不明白其中的道理,所以我上網搜的時候發現有好多人寫了很多很好的文章了,下面我轉載的這篇就非常不錯,一個困惱我好久的問題是驅動代碼中只是注 冊了platform驅動,而platform設備注冊在哪裡?這個問題困惱我好久,源代碼中一直沒找到,下面文章就解決了這個問題。當然文章中詳細了講 述了很多細節的知識。
原文地址 http://chxxxyg.blog.163.com/blog/static/150281193201082044140894/

(1)串口移植
S3C2440共有3個串口,在SMDK2440平台上串口0和串口1都作為普通串口使用,串口2工作在紅外收發模式。TQ2440開發板將它們都作為普通串口,目前所需要的只有串口0,作為控制終端,所以此處不作修改。
在文件 linux/arch/arm/plat-s3c24xx/devs.c中定義了三個串口的硬體資源。
static struct resource s3c2410_uart0_resource[] = {
………………………………
};
static struct resource s3c2410_uart1_resource[] = {
………………………………
};
static struct resource s3c2410_uart2_resource[] = {
………………………………
};
在文件linux/arch/arm/plat-samsung/dev-uart.c中定義了每個串口對應的平台設備。
static struct platform_device s3c24xx_uart_device0 = {
.id = 0,
};
static struct platform_device s3c24xx_uart_device1 = {
.id = 1,
};
static struct platform_device s3c24xx_uart_device2 = {
.id = 2,
};
在文件linux/arch/arm/mach-s3c2440/mach-smdk2440.c中有串口一些寄存器的初始化配置。
static struct s3c2410_uartcfg smdk2440_uartcfgs[] __initdata = {
[0] = {
…………………………
},
[1] = {
…………………………
},
/* IR port */
[2] = {
…………………………
}
};
在文件linux/arch/arm/mach-s3c2440/mach-smdk2440.c中將調用函數
s3c24xx_init_uarts()最終將上面的硬體資源,初始化配置,平台設備整合到一起。
在文件 linux/arch/arm/plat-s3c/init.c中有
static int __init s3c_arch_init(void)
{
………………………………
ret = platform_add_devices(s3c24xx_uart_devs, nr_uarts);
return ret;
}
這個函數將串口所對應的平台設備添加到了內核。
(2)串口設備驅動原理淺析
我認為任何設備在linux中的實現就「兩條線」。一是設備模型的建立,二是讀寫數據流。串口驅動也是這樣。
串口設備模型建立:
串口設備驅動的核心結構體在文件linux/drivers/serial/samsuing.c中如下
static struct uart_driver s3c24xx_uart_drv = {
.owner = THIS_MODULE,
.dev_name = "s3c2410_serial",
.nr = CONFIG_SERIAL_SAMSUNG_UARTS,
.cons = S3C24XX_SERIAL_CONSOLE,
.driver_name = S3C24XX_SERIAL_NAME,
.major = S3C24XX_SERIAL_MAJOR,
.minor = S3C24XX_SERIAL_MINOR,
};
串口驅動的注冊
static int __init s3c24xx_serial_modinit(void)
{
………………………………
ret = uart_register_driver(&s3c24xx_uart_drv);
………………………………
}
串口驅動其實是一個典型的tty驅動
int uart_register_driver(struct uart_driver *drv)
{
………………………………
//每一個埠對應一個state
drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);
………………………………
normal = alloc_tty_driver(drv->nr); //分配該串口驅動對應的tty_driver
………………………………
drv->tty_driver = normal; //讓drv->tty_driver欄位指向這個tty_driver
………………………………
normal->driver_name = drv->driver_name;
normal->name = drv->dev_name;
normal->major = drv->major;
normal->minor_start = drv->minor;
………………………………
//設置該tty驅動對應的操作函數集tty_operations (linux/drivers/char/core.c)
tty_set_operations(normal, &uart_ops);
………………………………
retval = tty_register_driver(normal); //將tty驅動注冊到內核
………………………………
}
其實tty驅動的本質是一個字元設備,在文件 linux/drivers/char/tty_io.c中
int tty_register_driver(struct tty_driver *driver)
{
………………………………
cdev_init(&driver->cdev, &tty_fops);
driver->cdev.owner = driver->owner;
error = cdev_add(&driver->cdev, dev, driver->num);
………………………………
}
它所關聯的操作函數集tty_fops在文件linux/drivers/char/tty_io.c中實現
static const struct file_operations tty_fops = {
.llseek = no_llseek,
.read = tty_read,
.write = tty_write,
………………………………
.open = tty_open,
………………………………
};
到此串口的驅動作為tty_driver被注冊到了內核。前面提到串口的每一個埠都是作為平台設備被添加到內核的。那麼這些平台設備就對應著有它們的平台設備驅動。在文件linux/drivers/serial/s3c2440.c中有:
static struct platform_driver s3c2440_serial_driver = {
.probe = s3c2440_serial_probe,
.remove = __devexit_p(s3c24xx_serial_remove),
.driver = {
.name = "s3c2440-uart",
.owner = THIS_MODULE,
},
};
當其驅動與設備匹配時就會調用他的探測函數
static int s3c2440_serial_probe(struct platform_device *dev)
{
return s3c24xx_serial_probe(dev, &s3c2440_uart_inf);
}
每一個埠都有一個描述它的結構體s3c24xx_uart_port 在 文件linux/drivers/serial/samsuing.c
static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = {
[0] = {
.port = {
.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock),
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX0, //該埠的中斷號
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops, //該埠的操作函數集
.flags = UPF_BOOT_AUTOCONF,
.line = 0, //埠編號
}
},
………………………………

上面探測函數的具體工作是函數s3c24xx_serial_probe()來完成的
int s3c24xx_serial_probe(struct platform_device *dev,
struct s3c24xx_uart_info *info)
{
………………………………
//根據平台設備提供的硬體資源等信息初始化埠描述結構體中的一些欄位
ret = s3c24xx_serial_init_port(ourport, info, dev);
//前面注冊了串口驅動,這里便要注冊串口設備
uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
………………………………
}
int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
{
………………………………
//前面說串口驅動是tty_driver,這里可以看到串口設備其實是tty_dev
tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev);
………………………………
}
串口數據流分析:
在串口設備模型建立中提到了三個操作函數集,uart_ops ,tty_fops,s3c24xx_serial_ops數據的流動便是這些操作函數間的調用,這些調用關系如下:

在對一個設備進行其他操作之前必須先打開它,linux/drivers/char/tty_io.c
static const struct file_operations tty_fops = {
………………………………
.open = tty_open,
………………………………
};
static int tty_open(struct inode *inode, struct file *filp)
{
………………………………
dev_t device = inode->i_rdev;
………………………………
driver = get_tty_driver(device, &index); //根據埠設備號獲取它的索引號
………………………………
if (tty) {
………………………………
} else
tty = tty_init_dev(driver, index, 0); //創建一個tty_struct 並初始化
………………………………
}
struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,int first_ok)
{
………………………………
tty = alloc_tty_struct(); //分配一個tty_struct結構
//一些欄位的初始化,
initialize_tty_struct(tty, driver, idx);
//完成的主要工作是driver->ttys[idx] = tty;
retval = tty_driver_install_tty(driver, tty);
………………………………
/*
下面函數主要做的就是調用線路規程的打開函數ld->ops->open(tty)。
在這個打開函數中分配了一個重要的數據緩存
tty->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
*/
retval = tty_ldisc_setup(tty, tty->link);
}
void initialize_tty_struct(struct tty_struct *tty,struct tty_driver *driver, int idx)
{
………………………………
//獲取線路規程操作函數集tty_ldisc_N_TTY,並做這樣的工作tty->ldisc = ld;
tty_ldisc_init(tty);
………………………………
/*
下面函數的主要工作是INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc);
初始化一個延時tty->buf.work 並關聯一個處理函數flush_to_ldisc(),這個函數將在
數據讀取的時候用到。
*/
tty_buffer_init(tty);
………………………………
tty->driver = driver;
tty->ops = driver->ops; //這里的ops就是struct tty_operations uart_ops
tty->index = idx; //idx就是該tty_struct對應埠的索引號
tty_line_name(driver, idx, tty->name);
}
埠設備打開之後就可以進行讀寫操作了,這里只討論數據的讀取,在文件 linux/drivers/char/tty_io.c中,
static const struct file_operations tty_fops = {
………………………………
.read = tty_read,
………………………………
};
static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
………………………………
ld = tty_ldisc_ref_wait(tty); //獲取線路規程結構體
if (ld->ops->read) //調用線路規程操作函數集中的n_tty_read()函數
i = (ld->ops->read)(tty, file, buf, count);
else
………………………………
}
在linux/drivers/char/N_tty.c中:
struct tty_ldisc_ops tty_ldisc_N_TTY = {
………………………………
.open = n_tty_open,
………………………………
.read = n_tty_read,
………………………………
};
static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
unsigned char __user *buf, size_t nr)
{
………………………………
while (nr) {
………………………………
if (tty->icanon && !L_EXTPROC(tty)) {
//如果設置了tty->icanon 就從緩存tty->read_buf[]中逐個數據讀取,並判斷讀出的每一個數//據的正確性或是其他數據類型等。
eol = test_and_clear_bit(tty->read_tail,tty->read_flags);
c = tty->read_buf[tty->read_tail];
………………………………
} else {
………………………………
//如果沒有設置tty->icanon就從緩存tty->read_buf[]中批量讀取數據,之所以要進行兩次讀
//取是因為緩存tty->read_buf[]是個環形緩存
uncopied = _from_read_buf(tty, &b, &nr);
uncopied += _from_read_buf(tty, &b, &nr);
………………………………
}
}
………………………………
}
用戶空間是從緩存tty->read_buf[]中讀取數據讀的,那麼緩存tty->read_buf[]中的數據有是從那裡來的呢?分析如下:
回到文件 linux/drivers/serial/samsuing.c中,串口數據接收中斷處理函數實現如下:
這是串口最原始的數據流入的地方
static irqreturn_t s3c24xx_serial_rx_chars(int irq, void *dev_id)
{
………………………………
while (max_count-- > 0) {
………………………………
ch = rd_regb(port, S3C2410_URXH); //從數據接收緩存中讀取一個數據
………………………………
flag = TTY_NORMAL; //普通數據,還可能是其他數據類型在此不做討論
………………………………
/*
下面函數做的最主要工作是這樣
struct tty_buffer *tb = tty->buf.tail;
tb->flag_buf_ptr[tb->used] = flag;
tb->char_buf_ptr[tb->used++] = ch;
將讀取的數據和該數據對應標志插入 tty->buf。
*/
uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN, ch, flag);
}
tty_flip_buffer_push(tty); //將讀取到的max_count個數據向上層傳遞。
out:
return IRQ_HANDLED;
}
void tty_flip_buffer_push(struct tty_struct *tty)
{
………………………………
if (tty->low_latency)
flush_to_ldisc(&tty->buf.work.work);
else
schele_delayed_work(&tty->buf.work, 1);
//這里這個延時work在上面串口設備打開中提到過,該work的處理函數也是flush_to_ldisc。
}
static void flush_to_ldisc(struct work_struct *work)
{
………………………………
while ((head = tty->buf.head) != NULL) {
………………………………
char_buf = head->char_buf_ptr + head->read;
flag_buf = head->flag_buf_ptr + head->read;
………………………………
//剛才在串口接收中斷處理函數中,將接收到的數據和數據標志存到tty->buf中,現在將
//這些數據和標志用char_buf 和flag_buf指向進一步向上傳遞。
disc->ops->receive_buf(tty, char_buf,flag_buf, count);
spin_lock_irqsave(&tty->buf.lock, flags);
}
}
上面調用的函數disc->ops->receive_buf在文件linux/drivers/char/N_tty.c中實現
struct tty_ldisc_ops tty_ldisc_N_TTY = {
………………………………
.receive_buf = n_tty_receive_buf,
………………………………
};
static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
{
………………………………
//現在可以看到緩沖區tty->read_buf 中數據的由來了。
if (tty->real_raw) {
//如果設置了tty->real_raw將上面講到的些傳入數據批量拷貝到tty->read_head中。
//對環形緩存區的數據拷貝需要進行兩次,第一次拷貝從當前位置考到緩存的末尾,如果還//有沒考完的數據而且緩存區開始出處還有剩餘空間,就把沒考完的數據考到開始的剩餘空
//間中。
spin_lock_irqsave(&tty->read_lock, cpuflags);
i = min(N_TTY_BUF_SIZE - tty->read_cnt,N_TTY_BUF_SIZE - tty->read_head);
i = min(count, i);
memcpy(tty->read_buf + tty->read_head, cp, i);
tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
tty->read_cnt += i;
cp += i;
count -= i;
i = min(N_TTY_BUF_SIZE - tty->read_cnt,
N_TTY_BUF_SIZE - tty->read_head);
i = min(count, i);
memcpy(tty->read_buf + tty->read_head, cp, i);
tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
tty->read_cnt += i;
spin_unlock_irqrestore(&tty->read_lock, cpuflags);
} else {
for (i = count, p = cp, f = fp; i; i--, p++) {
//如果沒有設置tty->real_raw,就根據傳入數據標志分類獲取數據。
………………………………
}
………………………………
}
………………………………
}
到此,數據讀取的整個過程就結束了。可以看出數據讀取可以分為兩個階段,一個階段是上層函數從環形緩存區tty->read_buf 讀取數據,第二階段是底層函數將接收的數據考到環形緩存區tty->read_buf 中。

❸ linux啟動後怎麼打開uart

一般都在UBOOT里修改,也可以在內核中進行修改。 初始化LCD後可以和QT或者其它圖形工具做一個開機進度條。

❹ linux 怎麼禁用uart驅動

驅動軟體你可以去官網下載安裝,如果覺得麻煩,你可以嘗試使用第三方驅動管理軟體,像驅動人生就可以。

❺ linux下uart的文件節點是怎樣創建的


(1)試驗目的:掌握通過文件系統操作UART設備的方法.

(2)在linux中,所有設備都是以文件的形式被打開並進行讀/寫操作的,本試驗中使用POSIX兼容的文件操作介面函數對底層設備進行操作.其中,POSIX是Portable Operating System Interface for UNIX的首字母縮寫,是一套IEEE和ISO標准.

❻ linux如何查看哪個串口是真實串口,哪個串口

1.使用ls -l ttyS*命令顯示如下
crw-rw----. 1 root dialout 4, 64 5月 17 02:24 /dev/ttyS0
crw-rw----. 1 root dialout 4, 65 5月 17 02:24 /dev/ttyS1
crw-rw----. 1 root dialout 4, 66 5月 17 02:24 /dev/ttyS2
crw-rw----. 1 root dialout 4, 67 5月 17 02:24 /dev/ttyS3
但你不知到哪個是真實的串口,雖然一般都是ttyS0,但也不敢妄然確定。
2.使用cat /proc/tty/driver/serial
serinfo:1.0 driver revision:
0: uart:16550A port:000003F8 irq:4 tx:0 rx:0
1: uart:unknown port:000002F8 irq:3
2: uart:unknown port:000003E8 irq:4
3: uart:unknown port:000002E8 irq:3
我們發現串口0的uart值時16550A,tx值為0,rx值也為0,因此我們斷定本機只有一個串口,是串口0,即ttyS0
3.也可以用dmesg | grep ttyS*,但這個不是很好用,當然你可以自己使用正則法則取找到。
注意:還應查看是否有USB轉串口,這個就很簡單了:ls ttyUSB*,全部搞定。

❼ Linux怎麼把串口設置

簡單的運行 dmesg 命令
$ dmesg | grep tty
輸出:
[ 37.531286] serial8250: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[ 37.531841] 00:0b: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[ 37.532138] 0000:04:00.3: ttyS1 at I/O 0x1020 (irq = 18) is a 16550A

setserial 命令
setserial 是一個程序用於設定並/或報告某個串口關聯的配置信息。該信息包括串口用到的I/O 埠和中斷號,以及Break鍵是否應被解釋為Secure Attention Key 等等。 僅僅是輸出如下的命令:
$ setserial -g /dev/ttyS[0123]
輸出:
/dev/ttyS0, UART: 16550A, Port: 0x03f8, IRQ: 4
/dev/ttyS1, UART: 16550A, Port: 0x1020, IRQ: 18
/dev/ttyS2, UART: unknown, Port: 0x03e8, IRQ: 4
/dev/ttyS3, UART: unknown, Port: 0x02e8, IRQ: 3

帶-g選項的setserial幫助找到你的Linux板子上的物理串口。
Linux 串口控制台程序
一旦串口被確定了,你就能使用許多的工具來配置Linux板子:
minicom- 用於控制modem和連接到mp 設備的最好的串口通信程序。
wvidial or other GUI dial up networking program - 一個內建智能PPP 撥號器。
getty / agetty - agetty 打開一個 tty 埠, 提示登錄名稱並調用 /bin/login 命令。
grub / lilo configuration - 配置串口為系統控制台。

❽ linux內核中怎麼通過uart輸出

1.通用串列數據匯流排,用於非同步傳輸,就是電腦串口之類的 2.硬體層一樣,驅動層架構不同,因為操作系統給的介面不同 3.除了必須的模塊載入卸載函數外,還有read函數,write函數,ioctl函數,最重要的就是這幾個,以方便你以文件方式調用文件讀寫API

❾ arm linux問題:我板子的uart1串口是調試串口,我看大多都是uart0是調試口,我怎麼改linux的源碼

你用的是什麼板子啊?

這個要改uboot的。

比如,如果用的是s3c2410,改一下include/configs/smdk2410.h

將第63行,#defineCONFIG_SERIAL11 /*weuseSERIAL1onSMDK2410*/

的CONFIG_SERIAL2,就行了。

可以看一下cpu/arm920t/s3c24x0/serial.c就能理解了。

#ifdefCONFIG_SERIAL1

#defineUART_NR S3C24X0_UART0

#elifdefined(CONFIG_SERIAL2)

#ifdefined(CONFIG_TRAB)

#error"TRABsupportsonlyCONFIG_SERIAL1"

#endif

#defineUART_NR S3C24X0_UART1

#elifdefined(CONFIG_SERIAL3)

#ifdefined(CONFIG_TRAB)

##error"TRABsupportsonlyCONFIG_SERIAL1"

#endif

#defineUART_NR S3C24X0_UART2

#else

#error"Bad:youdidn'tconfigureserial..."

#endif

❿ linux vivado怎麼都識別不了uart

首先第一步,需要把想要觀測的信號標記出來,即mark_debug,有兩種mark_debug的方法,我用verilog寫了一個簡單的流水燈程序,只有幾行代碼,如下:
mole main(
input clk,
input rst,
output reg [7:0] led
);

(*mark_debug = "true"*)reg [23:0] counter;

always @(posedge clk) begin
if(rst) begin
counter <= 0;
led <= 8'b00000001;
end
else counter <= counter + 1;
if (counter == 24'hffffff)
led <= {led[6:0],led[7]};
end

endmole
例如,要觀察counter信號的波形,那麼在第7行定義reg型信號counter時,前面加上(*mark_debug=「true」*),這樣就把counter信號標記了出來。如果用vhdl語言實現的話,這句話用該這樣寫:
signal counter : std_logic_vector (23 downto 0);
attribute mark_debug: string;
attribute mark_debug of counter : signal is "true";
另外添加xdc約束文件,內容如下:
set_property PACKAGE_PIN Y9 [get_ports clk]
set_property PACKAGE_PIN T18 [get_ports rst]

set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property IOSTANDARD LVCMOS18 [get_ports rst]

set_property PACKAGE_PIN T22 [get_ports {led[0]}]
set_property PACKAGE_PIN T21 [get_ports {led[1]}]
set_property PACKAGE_PIN U22 [get_ports {led[2]}]
set_property PACKAGE_PIN U21 [get_ports {led[3]}]
set_property PACKAGE_PIN V22 [get_ports {led[4]}]
set_property PACKAGE_PIN W22 [get_ports {led[5]}]
set_property PACKAGE_PIN U19 [get_ports {led[6]}]
set_property PACKAGE_PIN U14 [get_ports {led[7]}]

set_property IOSTANDARD LVCMOS33 [get_ports {led[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[7]}]
之後run synthesis綜合,之後open synthesized design,在左上角選擇debug layout,在debug窗口中netlist看到counter信號前面有一個綠色的小蜘蛛,表示counter信號被標記出來了。
這其實是一種比較繁瑣的方法,更為方便的方法是,直接綜合工程,在之後打開綜合設計,在netlist中直接選中想要查看的信號,右鍵選擇mark debug,即可將信號標記出來。
但是採用第一種方式的好處是,如果工程比較復雜的話,一些信號可能會被綜合優化掉,加上模塊層層實例化,在netlist中可能找不到要觀測的信號,這時在代碼裡面mark_debug,依舊可以將該信號引出來。

接著第二步就是插入調試內核了,在Vivado界面下方,找到Unassigned Debug Nets,右鍵選擇 set up debug,在接下來的對話框中列出了counter信號的lk domain是CLK_IBUG_BUFG,其trig和data項都打了對勾,表示counter信號既作為觸發信號也作為數據信號。

熱點內容
如何下載奧特曼高級化3安卓版 發布:2025-05-14 07:47:31 瀏覽:345
qml文件修改後編譯未生效 發布:2025-05-14 07:31:00 瀏覽:331
內到內演算法 發布:2025-05-14 07:29:11 瀏覽:34
文件夾名字不顯示 發布:2025-05-14 07:27:47 瀏覽:775
oracle的資料庫驅動jar 發布:2025-05-14 07:23:20 瀏覽:556
我的世界電腦版伺服器手機版能進嗎 發布:2025-05-14 07:22:01 瀏覽:679
達內培訓php多少錢 發布:2025-05-14 07:19:10 瀏覽:27
python位元組轉字元串 發布:2025-05-14 07:06:35 瀏覽:422
subplotpython 發布:2025-05-14 06:53:51 瀏覽:662
豎屏大屏導航工廠密碼一般是多少 發布:2025-05-14 06:49:29 瀏覽:807