0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

SWM32SRET6——LVGL移植

jf_pJlTbmA9 ? 來源:華芯微特32位MCU ? 作者:華芯微特32位MCU ? 2023-10-26 17:33 ? 次閱讀

硬件資源介紹

SWM320是一款基于ARM Cortex-M4的32位微控制器,片上包含精度為1%以內(nèi)的 20MHz/40MHz時鐘,可通過PLL倍頻到120MHz 時鐘,提供多種內(nèi)置FLASH/SRAM大小可供選擇,支持ISP(在系統(tǒng)編程)操作及IAP(在應(yīng)用編程)。

外設(shè)串行總線包括:1個CAN接口、內(nèi)部疊封8MB SDRAM、多個UART接口、SPI 通信接口(支持主/從選擇)及I2C接口(支持主/從選擇)。

此外還包括1個32位看門狗定時器,6組32位通用定時器,1組32位專用脈沖寬度測量定時器,12通道16位的PWM發(fā)生器,2個8通道12位、1MSPS的逐次逼近型ADC模塊,1個SDIO接口模塊,TFT-LCD液晶驅(qū)動模塊以及RTC實時時鐘、SRAMC、NORFLC接口控制模塊,同時提供欠壓檢測及低電壓復(fù)位功能。

LittlevGL移植

LittlevGL概述

LittlevGL是一個免費的開放源代碼圖形庫,它提供創(chuàng)建嵌入式GUI所需的一切,它具有易于使用的圖形元素,精美的視覺效果和低內(nèi)存占用。強大的構(gòu)建塊按鈕,圖表,列表,滑塊,圖像等,帶有動畫,抗鋸齒,不透明度,平滑滾動的高級圖形,各種輸入設(shè)備的觸摸板,鼠標,鍵盤,編碼器等,多顯示器支持,即同時使用更多的TFT和單色顯示器,支持UTF-8編碼的多語言,完全可定制的圖形元素。

獨立于任何微控制器或顯示器使用的硬件,可擴展以使用較少的內(nèi)存(80kB閃存,12 kB RAM),支持操作系統(tǒng),外部存儲器和GPU,但不是必需的,即使使用單幀緩沖區(qū)操作,也具有高級圖形效果。

C語言編寫,以實現(xiàn)最大的兼容性(與C++兼容),模擬器可在沒有嵌入式硬件的PC 上啟動嵌入式GUI設(shè)計,快速GUI設(shè)計的教程,示例,主題,在線和離線文檔,在 MIT 許可下免費和開源。

LittlevGL硬件要求

● 16、32或64位微控制器或處理器

● 建議時鐘頻率大于16MHz

● 閃存/ ROM:對于非常重要的組件,其大小大于64 kB(建議大于180 kB)

● 內(nèi)存:

● 靜態(tài)RAM使用量:大約8至16 kB,具體取決于所使用的功能和對象類型

● 堆棧:大于2kB(建議大于4kB)

● 動態(tài)數(shù)據(jù)(堆):大于4 KB(如果使用多個對象,則建議大于16 kB)。LV_MEM_SIZE 在lv_conf.h中設(shè)置

● 顯示緩沖區(qū):大于“水平分辨率”像素(建議大于10× “水平分辨率”)

● C99或更高版本的編譯器

● 基本的C(或C ++)知識:指針,結(jié)構(gòu),回調(diào)

LittlevGL移植

01、屏幕介紹

開發(fā)板板載的是一個RGB接口的屏幕JLT4301A,我們的板子使用的是RGB565接口。屏幕分辯率480*272,顯示方向為橫向。

觸摸采用的是 GT911的電容觸摸屏。

使用RGB屏,SDRAM是必須的,因為RGB屏需要使用顯存,例如480*272的RGB565 屏幕,一個像素占用2字節(jié)的顯存,總共需要480*272*2=261120 折合255KB的顯存,內(nèi)部RAM很顯然是不夠用的。那么RGB屏的驅(qū)動只需要使能背光、配置LCDC的外設(shè)以及顯存的地址就可以了。然后往屏幕填充內(nèi)容就是往對應(yīng)的顯存發(fā)送數(shù)據(jù)就可以了。不同 RGB 屏的配置參數(shù)可能不一樣,顯示方向也不一樣。

開發(fā)板使用的是電容觸摸屏,使用I2C進行通信,利用I2C初始化觸摸IC GT911后,我們就可以通過I2C讀出觸摸的絕對位置,跟屏幕是一一對應(yīng)的。

02、移植流程

LittlevGL 的移植過程也非常簡單,總結(jié)了以下幾個步驟:

1. 添加庫文件到工程

2. 配置屏幕大小以及顏色深度等跟顯示相關(guān)的參數(shù)

3. 分配一個顯示緩沖區(qū)并實現(xiàn)屏幕填充的接口

4. 實現(xiàn)輸入設(shè)備接口,讀取觸摸屏坐標

5. 實現(xiàn)文件系統(tǒng)接口,實現(xiàn)文件的讀取寫入

6. 提供一個滴答時鐘的接口 lv_tick_inc();

7. 完成庫的初始化以及接口的初始化 lv_init();lv_port_disp_init();lv_port_indev_init(); lv_port_fs_init;

8. 定期調(diào)用任務(wù)處理函數(shù),可設(shè)置為 5-10ms lv_task_handler();

03、源碼下載

LittlevGL 的源碼可以在GitHub 進行下載,https://github.com/littlevgl/lvgl,可以 clone 到本地也可以直接下載壓縮包。除了下載源碼以外,還可以下載example和drivers。example里面包含了各種應(yīng)用展示和控件使用示例,drivers 里面包含了一些液晶屏驅(qū)動接口示例。

wKgZomUD6liAFTLLAABOmq358Xg923.png

共下載3個文件夾

wKgZomUD6lmAANgwAAFYjvJZHoQ605.png

打開源碼文件,里面包含了接口示例文件和配置示例文件,其中src文件夾下面又進行了分類,具體請查看源碼。

wKgaomUD6luAc4iQAAYKOwgoVAE744.png

04、添加庫文件到工程

第一步,復(fù)制庫文件

復(fù)制lvgl文件夾到工程文件夾APP下面。

將lvgllv_conf_template.h文件復(fù)制一份并改名為lv_conf.h。這個文件是lvgl的配置文件,后面再介紹如何修改。

將lv_examples文件夾復(fù)制到工程文件夾下面,這里面包含了各種應(yīng)用和基礎(chǔ)示例,我們后面需要使用。

第二步,添加庫文件到工程

打開MDK工程,添加源碼,在lvglsrc文件夾下面有如下文件,我們在MDK里面添加全部文件即可。

wKgaomUD6lyABpqBAABSUGtFUe0911.png

然后在MDK里面再新建一個lvgl_porting文件夾和一個lvgl_demo文件夾,前者用于添加接口文件,后者用于我們后面添加示例文件,將 lvglportinglv_port_disp_template.c和lvglportinglv_port_indev_template.c,lvglportinglv_port_fs_template.c各復(fù)制一份,分別改名為lv_port_disp,c和lv_port_indev.c,lv_port_fs.c添加到MDK的lv_porting文件夾下面,后面再針對開發(fā)板的硬件進行對應(yīng)的修改。

wKgZomUD6l2AL2VoAAA67fEZWp4686.png
wKgZomUD6l6AaAK7AAA0gga4q3U156.png

05、移植文件的適配

lvgl的源碼中包含頭文件有完整路徑和簡單路徑兩種方式,在MDK里面我們直接使用簡單的頭文件包含形式。

/*********************

 *      INCLUDES

 *********************/

#ifdef LV_CONF_INCLUDE_SIMPLE

#include "lv_conf.h"

#else

#include "../../../lv_conf.h"

#endif

我們使用簡單的頭文件包含,在MDK的宏定義里面添加LV_CONF_INCLUDE_SIMPLE 定義,如果后面還有l(wèi)vgl的頭文件路徑是MDK不能識別的,讀者根據(jù)實際情況修改為編譯器能識別的格式,后面不再對此修改做介紹。

wKgaomUD6mCAYZjoAAAci-mT35Y955.png

修改lv_conf文件,在我們之前復(fù)制過來的配置示例文件默認是被注釋掉了。我們需要打開他。只需要將開頭的#if 0修改為#if 1即可,如果后續(xù)的文件中再出現(xiàn)這種開關(guān),讀者自行打開即可。

/**

/*

 * COPY THIS FILE AS `lv_conf.h` NEXT TO the `lvgl` FOLDER

 */

#if 1 /*Set it to "1" to enable content*/

#ifndef LV_CONF_H

#define LV_CONF_H

/* clang-format off */

#include

配置屏幕的大小,我們的液晶屏是480*272

/* Maximal horizontal and vertical resolution to support by the library.*/

#define LV_HOR_RES_MAX          (480)

#define LV_VER_RES_MAX          (272)

配置顏色位數(shù),我們使用RGB565模式,16位色

/* Color depth:

 * - 1:  1 byte per pixel

 * - 8:  RGB233

 * - 16: RGB565

 * - 32: ARGB8888

 */

#define LV_COLOR_DEPTH     16



/* Swap the 2 bytes of RGB565 color.

 * Useful if the display has a 8 bit interface (e.g. SPI)*/

#define LV_COLOR_16_SWAP   0

LVGL內(nèi)存配置,這里區(qū)別與繪圖緩沖區(qū),這里配置的是lvgl的控件等使用的內(nèi)存,需大于2KB,這里可以使用默認的32K配置,也可以將內(nèi)存定義100K,從而分配更多的內(nèi)存。

/* 1: use custom malloc/free, 0: use the built-in `lv_mem_alloc` and `lv_mem_free` */

#define LV_MEM_CUSTOM      0

#if LV_MEM_CUSTOM == 0

/* Size of the memory used by `lv_mem_alloc` in bytes (>= 2kB)*/

#  define LV_MEM_SIZE    (100 * 1024U)

GPU配置,這里關(guān)閉,我們使用LCD中斷進行buffer的填充

/* 1: Enable GPU interface*/

#define LV_USE_GPU              0

LOG接口配置,這里暫未使用,讀者在使用是可以將其配置為串口等

/*1: Enable the log module*/

#define LV_USE_LOG      0

#if LV_USE_LOG

/* How important log should be added:

 * LV_LOG_LEVEL_TRACE       A lot of logs to give detailed information

 * LV_LOG_LEVEL_INFO        Log important events

 * LV_LOG_LEVEL_WARN        Log if something unwanted happened but didn't cause a problem

 * LV_LOG_LEVEL_ERROR       Only critical issue, when the system may fail

 * LV_LOG_LEVEL_NONE        Do not log anything

 */

#  define LV_LOG_LEVEL    LV_LOG_LEVEL_WARN

/* 1: Print the log with 'printf';

 * 0: user need to register a callback with `lv_log_register_print_cb`*/

#  define LV_LOG_PRINTF   1

#endif  /*LV_USE_LOG*/

06、配置植接口

LittlevGL繪制的過程需要有一個緩沖區(qū)disp_buf,lvgl內(nèi)部將位圖繪制到這個緩沖區(qū),緩沖區(qū)滿了以后調(diào)用flush_cb接口函數(shù)進行屏幕的填充,我們將這部分緩沖區(qū)的內(nèi)容通過LCD中斷搬運到液晶屏,當填充完成后,調(diào)用lv_disp_flush_ready函數(shù)通知庫繪制已經(jīng)完成,可以開始其他繪制過程。

LittlevGL已經(jīng)提供了一個示例文件,我們上面提到的復(fù)制文件也是使用他提供的文件,只需要我們修改幾個接口函數(shù)即可。

定義lvgl繪制的緩沖區(qū),這里需定義在外部SDRAM定義兩個全屏的緩沖區(qū)。

static lv_disp_buf_t disp_buf;

#ifdef SWM_USING_SRAM

static lv_color_t lcdbuf_1[LV_HOR_RES_MAX * LV_VER_RES_MAX] __attribute__((at(SRAMM_BASE)))           = {0x00000000};

static lv_color_t lcdbuf_2[LV_HOR_RES_MAX * LV_VER_RES_MAX] __attribute__((at(SRAMM_BASE + 0x3FC00))) = {0x00000000};

#endif

#ifdef SWM_USING_SDRAM

static uint32_t lcdbuf_1[LV_HOR_RES_MAX * LV_VER_RES_MAX / 2] __attribute__((at(SDRAMM_BASE)))           = {0x00000000};

static uint32_t lcdbuf_2[LV_HOR_RES_MAX * LV_VER_RES_MAX / 2] __attribute__((at(SDRAMM_BASE + 0x3FC00))) = {0x00000000};

#endif

    lv_disp_buf_init( disp_buf, lcdbuf_1, lcdbuf_2, LV_HOR_RES_MAX * LV_VER_RES_MAX); /*Initialize the display buffer*/

定義一個lv_disp_drv_t的變量并初始化。

 lv_disp_drv_t disp_drv;      /*Descriptor of a display driver*/

    lv_disp_drv_init( disp_drv); /*Basic initialization*/

設(shè)置緩沖區(qū)。

/*Set a display buffer*/

    disp_drv.buffer =  disp_buf;

設(shè)置屏幕填充接口,這里的 disp_fluash 是一個函數(shù),在示例中已經(jīng)定義,我們直接對其修改就行了。

/*Used to copy the buffer's content to the display*/

    disp_drv.flush_cb = disp_flush;

注冊驅(qū)動程序。

 /*Finally register the driver*/

    lv_disp_drv_register( disp_drv);

修改disp_flush函數(shù)以適應(yīng)我們自己的硬件和屏幕。

static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)

{

    LCD->SRCADDR = (uint32_t)disp_drv->buffer->buf_act;

    LCD_Start(LCD);



    /* IMPORTANT!!!

     * Inform the graphics library that you are ready with the flushing*/

    lv_disp_flush_ready(disp_drv);

}

07、配置輸入設(shè)備接口

lvgl支持鍵盤、鼠標、按鍵、觸摸屏作為輸入設(shè)備,我們這里僅僅使用觸摸屏進行輸入。

在lv_port_indev_template.c中,注冊一個觸摸屏設(shè)備需要以下步驟,我們只需要對觸摸屏讀取的回調(diào)函數(shù)進行修改即可。

/*Register a touchpad input device*/

    lv_indev_drv_init( indev_drv);

    indev_drv.type = LV_INDEV_TYPE_POINTER;

    indev_drv.read_cb = touchpad_read;

    indev_touchpad = lv_indev_drv_register( indev_drv);

打開觸摸屏讀取的回調(diào)函數(shù)touchpad_read函數(shù)

* Will be called by the library to read the touchpad */

static bool touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)

{

    static lv_coord_t last_x = 0;

    static lv_coord_t last_y = 0;

    /*Save the pressed coordinates and the state*/

    if (touchpad_is_pressed())

    {

        touchpad_get_xy( last_x,  last_y);

        data->state = LV_INDEV_STATE_PR;

    }

    else

    {

        data->state = LV_INDEV_STATE_REL;

    }

    /*Set the last pressed coordinates*/

    data->point.x = last_x;

    data->point.y = last_y;

    /*Return `false` because we are not buffering and no more data to read*/

    return false;

}

從touchpad_read函數(shù)可以看出,用戶只需要完成兩個接口函數(shù)即可。這兩個函數(shù)的實現(xiàn)如下:

/*Return true is the touchpad is pressed*/

static bool touchpad_is_pressed(void)

{

    /*Your code comes here*/

    if(tp_dev.sta   0x80)

    {

        return true;

    }

    return false;

}

/*Get the x and y coordinates if the touchpad is pressed*/

static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y)

{

    /*Your code comes here*/

    (*x) = tp_dev.x[0];

    (*y) = tp_dev.y[0];

}

08、配置文件系統(tǒng)接口

文件系統(tǒng)使用FATFS,對接前需要完成文件系統(tǒng)的掛載。

文件系統(tǒng)注冊。

void lv_port_fs_init(void)

{

    /*----------------------------------------------------

     * Initialize your storage device and File System

     * -------------------------------------------------*/

    fs_init();



    /*---------------------------------------------------

     * Register the file system interface  in LittlevGL

     *--------------------------------------------------*/

    /* Add a simple drive to open images */

    lv_fs_drv_t fs_drv;

    lv_fs_drv_init( fs_drv);

    /*Set up fields...*/

    fs_drv.file_size     = sizeof(file_t);

    fs_drv.letter        = 'P';

    fs_drv.open_cb       = fs_open;

    fs_drv.close_cb      = fs_close;

    fs_drv.read_cb       = fs_read;

    fs_drv.write_cb      = fs_write;

    fs_drv.seek_cb       = fs_seek;

    fs_drv.tell_cb       = fs_tell;

    fs_drv.free_space_cb = fs_free;

    fs_drv.size_cb       = fs_size;

    fs_drv.remove_cb     = fs_remove;

    fs_drv.rename_cb     = fs_rename;

    fs_drv.trunc_cb      = fs_trunc;

    fs_drv.rddir_size   = sizeof(dir_t);

    fs_drv.dir_close_cb = fs_dir_close;

    fs_drv.dir_open_cb  = fs_dir_open;

    fs_drv.dir_read_cb  = fs_dir_read;

    lv_fs_drv_register( fs_drv);

}

09、配置LittlevGL的嘀嗒心跳時鐘接口

LittlevGL的使用需要需要周期性的時鐘支持,用戶需要定期調(diào)用 lv_tick_inc(uint32_t tick_period)函數(shù),我們這里利用滴答定時器的1KHz去調(diào)用這個函數(shù)。在滴答定時器的中斷服務(wù)函數(shù)中添加lvgl時基函數(shù)。

uint8_t tick_indev = 0;

void SysTick_Handler_cb(void)

{

    lv_tick_inc(1);

    tick_indev++;

    if (tick_indev > 100)

    {

        tick_indev = 0;

        GT911_Scan();

    }

}

10、初始化

包含lvgl的初始化以及顯示和觸摸,文件系統(tǒng)接口的初始化。

 lv_init();

lv_port_disp_init();

    lv_port_indev_init();

    lv_port_fs_init();

我們需要在主循環(huán)中周期性調(diào)用LittelvGL的任務(wù)處理函數(shù)。

while (1 == 1)

    {

        lv_task_handler();

    }

然后就可以進行應(yīng)用的開發(fā)了。

來源:華芯微特32位MCU

免責(zé)聲明:本文為轉(zhuǎn)載文章,轉(zhuǎn)載此文目的在于傳遞更多信息,版權(quán)歸原作者所有。本文所用視頻、圖片、文字如涉及作品版權(quán)問題,請聯(lián)系小編進行處理

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 微控制器
    +關(guān)注

    關(guān)注

    48

    文章

    7454

    瀏覽量

    150854
  • LVGL
    +關(guān)注

    關(guān)注

    1

    文章

    79

    瀏覽量

    2887
收藏 人收藏

    評論

    相關(guān)推薦

    SWM32SRET6單片機的ADC功能介紹與串口應(yīng)用

    SWM32SRET6單片機內(nèi)置2個12位SAR型ADC,最多支持8通道,1MSPS 轉(zhuǎn)換速率。支持軟件觸發(fā)、定時器觸發(fā)。該單片機的ADC模塊結(jié)構(gòu)框圖如下,
    發(fā)表于 07-29 08:48 ?1657次閱讀
    <b class='flag-5'>SWM32SRET6</b>單片機的ADC功能介紹與串口應(yīng)用

    #單片機 移植nes模擬器到SWM32SRET6

    單片機
    liuzhuocai
    發(fā)布于 :2022年02月15日 00:39:12

    如何對SWM32SRET6芯片進行測試呢

    SWM32SRET6芯片有哪些特點呢?如何對SWM32SRET6芯片進行測試呢?
    發(fā)表于 12-21 06:27

    lvgl移植的相關(guān)資料下載

    lvgl移植下載鏈接[lvglgithub官方](lvgl/lvgl: Powerful and easy-to-use embedded GUI library with many
    發(fā)表于 01-11 06:45

    N32G457快速移植LVGL圖形庫的方法

    1、N32G457快速移植LVGL圖形庫  由于 lvgl 軟件包過大,超過壓縮后整個工程超過 20M,所以沒有上傳,需要自行 pkgs —update 一下,下載 lvgl 軟件包,
    發(fā)表于 11-04 15:52

    MDK536+SWM34S平臺移植LVGL8.3.3定義數(shù)組使用ALIGN()對齊時編譯報錯?

    使用MDK536 SWM34S單片機 ENV下添加LVGL軟件包8.3.3后,編譯工程報錯。提示出錯在定義數(shù)組時使用ALIGN字節(jié)對齊,在lv_rt_thread_port.c中和一些樣例代碼文件
    發(fā)表于 05-17 11:00

    分享一款適合做GUI的國產(chǎn)MUC

    所以就想著找一個便宜點的方案。無意中看到了華芯微特的一個芯片SWM32SRET6,芯片特點如下
    的頭像 發(fā)表于 04-25 14:34 ?2779次閱讀
    分享一款適合做GUI的國產(chǎn)MUC

    LVGL系列(二)之二 LVGL常見問題解答 整理自官方文檔

    為什么要學(xué)習(xí)LVGLLVGL系列(二)之二 LVGL常見問題解答 整理自官方文檔二、LVGL系列(二)LVGL仿真環(huán)境的搭建(WIN下) 2.1如何在仿真環(huán)境下運行自己的代碼三、LVG
    發(fā)表于 11-24 13:36 ?12次下載
    <b class='flag-5'>LVGL</b>系列(二)之二 <b class='flag-5'>LVGL</b>常見問題解答 整理自官方文檔

    STM32F4芯片移植_LVGL7.11_UCOS移植代碼工程

    STM32F4芯片移植_LVGL7.11_UCOS移植代碼工程
    發(fā)表于 12-09 17:45 ?24次下載

    W806單片機移植LVGL庫例程源碼下載

    W806單片機移植LVGL庫例程源碼下載。
    發(fā)表于 05-11 15:11 ?15次下載

    華芯微特SWM341系列微控制器主要性能 SWM34SRT6-50顯示驅(qū)動應(yīng)用

    本文介紹了華芯微特SWM341系列主要性能,和其系列之一的SWM34SRET6-50驅(qū)動4.3寸800*480 TFTLCD顯示的例程應(yīng)用。
    的頭像 發(fā)表于 06-13 11:49 ?7235次閱讀

    【開鴻智谷NiobeU4開發(fā)板免費試用體驗】移植LVGL

    ,使用的控制器是ST7735,SPI接口,16位。前兩篇已經(jīng)進行了屏幕的顯示測試,具備了移植GUI的條件,本篇我們移植LVGL。 參考 https://lvgl.io/ 準備代碼 cd
    的頭像 發(fā)表于 10-14 15:23 ?1107次閱讀
    【開鴻智谷NiobeU4開發(fā)板免費試用體驗】<b class='flag-5'>移植</b><b class='flag-5'>LVGL</b>

    AN042基于GD32F450I的LVGL移植

    AN042 基于GD32F450I的LVGL移植
    發(fā)表于 02-27 18:28 ?4次下載
    AN042基于GD32F450I的<b class='flag-5'>LVGL</b><b class='flag-5'>移植</b>

    Hi3861移植LVGL教程

    給 Hi3861 適配了硬件 spi ,master 模式下最高 spi 速率可以達到 40M,用來驅(qū)動 oled 屏幕。適配過程遇到了一個芯片bug,困擾了很久,clk 管腳驅(qū)動能力差,需要外接一個上拉電阻才能正常運行。適配完成移植 lvgl 8,分享適配的過程。
    的頭像 發(fā)表于 05-18 09:23 ?2115次閱讀
    Hi3861<b class='flag-5'>移植</b><b class='flag-5'>LVGL</b>教程

    SWM341系列之SWM34SRET6介紹

    SWM341系列之SWM34SRET6介紹
    的頭像 發(fā)表于 10-27 10:19 ?2043次閱讀
    <b class='flag-5'>SWM</b>341系列之<b class='flag-5'>SWM34SRET6</b>介紹