国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

MATLAB :【11】一文帶你讀懂serialport串口收發(fā)原理與實現(xiàn)

這篇具有很好參考價值的文章主要介紹了MATLAB :【11】一文帶你讀懂serialport串口收發(fā)原理與實現(xiàn)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

碎碎念:

這周的主要工作還是集中于FOC中,因為羨慕稚暉君做出的漂亮Qt面板,因此在利用MATLAB復刻過程中,學習了一下serialport的使用。FOC的GUI部分就在加班加點寫作中啦,同時最近打算開一個新坑,大家可以期待一下哈哈哈。

歡迎大佬們點贊+收藏+關注~ o(* ̄▽ ̄*)ブ

目錄

1 串口接收

2 串口發(fā)送


考慮到互聯(lián)網中對MATLAB中最新的serialport的使用案例有些混亂,并且很多都是基于已經被淘汰的serial庫,嚴重缺乏易用性,因此在本文中給出簡單的串口收發(fā)模板,特別是串口回調函數的使用案例。

1 串口接收

串口接收是指,開發(fā)板將數據發(fā)送給電腦,電腦讀取數據并進行數據分析處理的過程。

想弄清楚怎么接收串口的數據,那你首先就需要知道串口的數據是怎么發(fā)送出來的。

試想這樣的應用場景,我的開發(fā)板上安裝了一個溫度傳感器,溫度傳感器采集的數據長度是3字節(jié)(24比特);我需要將開發(fā)板采集到的溫度信息實時顯示在屏幕上,我需要怎么做?

這其中需要注意的有下面幾點:

  1. 溫度傳感器是3字節(jié)的,如何確定接收到的某一個字節(jié)位于三個字節(jié)中的哪個位置?
  2. 實時顯示要求我需要對每次發(fā)送過來的數據做出響應,這種響應需要怎么做?

針對問題1:

其實這也是初學者常遇到的問題,有時候串口發(fā)送的數據就像一個堵不住的水管,完全不知道要怎么處理。

由于串口協(xié)議的限定,導致其每次發(fā)送的只能是一個字節(jié),對于多字節(jié)的數據【ABC】來說,就只能通過三個字節(jié)【A】、【B】、【C】來發(fā)送,如下圖所示(最左端為最先接收到的字節(jié)):

MATLAB :【11】一文帶你讀懂serialport串口收發(fā)原理與實現(xiàn)

這就顯然會遇到問題,在任意一個時刻,我沒辦法確定接收到的數據到底處于【ABC】的哪一個位置;更致命的是,由于物理介質的影響,甚至可能會造成數據的丟失,這就更給數據的接受造成了影響。

如何解決這一問題呢?人們開始想到了“打包”的方式,也可以理解為我們常說的“幀”的概念。只要在每組數據的開頭加一些標志,表示出這是數據的最開始位置不就好了,即為下圖所示(最左端為最先接收到的字節(jié)):

MATLAB :【11】一文帶你讀懂serialport串口收發(fā)原理與實現(xiàn)

假設我們設置的這個標志為【FF、FF】,當上位機檢測到連續(xù)的兩個【FF】時,就表示之后的三個字節(jié)分別為【A】、【B】、【C】。

這其實就解決了這個問題1,實現(xiàn)了對一幀中每一個字節(jié)的位置確定。

針對問題2:

解決問題1后,我們當然可以利用順序執(zhí)行的方式,來實現(xiàn)對串口數據的一次讀取以及數據處理。但是如何實現(xiàn)當每一次檢測到特定信號,就調用一次數據處理函數呢?

這就要先理解一下MATLAB中serialportlist的使用邏輯了,整體來說serialportlist是對serial的升級版本(在幫助頁面也有提到),其通過構建SerialObject對象的方式,來實現(xiàn)串口參數的設置以及讀寫。

具體細節(jié)可以參考MATLAB文檔serialport,太全面的參數設置過于冗余,不在本文討論范圍內。這里主要介紹兩個比較重要的概念緩沖區(qū)以及回調函數。

緩沖區(qū):

在serialport中,緩沖區(qū)是自動存在于SerialObject對象中,但是有時使用時(如本文)不需要針對性設置緩沖區(qū)的大小??梢岳斫鉃橐粋€長度固定的FIFO隊列,當檢測到特定信號的時候,將串口傳入的每一個字節(jié)的數據,按順序保存在里面,當長度滿了之后,就不再繼續(xù)在里面添加新的數據了。

可能會使用到的函數為

flush(SerialObj)

可以用來清空緩沖區(qū),常常用在串口對象初始化的時候。

回調函數:

這個是解決問題2的關鍵,回調函數可以理解為一個開關被觸發(fā)后需要進行的操作(或者簡單理解為單片機的中斷處理函數);我們可以通過SerialObject的對象設置,來設置檢測到什么信號(這個信號是作為一幀的結尾的時候,執(zhí)行回調函數。

舉個方案A作為例子,我們可以設置檢測到【FF FF】信號的時候,執(zhí)行三個字節(jié)的數據讀取。(盡管不這樣用,后面會說為什么)

MATLAB :【11】一文帶你讀懂serialport串口收發(fā)原理與實現(xiàn)

如上圖所示,當我們按照上面方案A的方式,設置回調函數的觸發(fā)條件,有什么問題呢?每當檢測到【FF FF】的時候,就會觸發(fā)回調函數。

看似沒問題,但是此時一幀的組合已經從【FF FF A B C】變成了【A B C FF FF】,因為我們提到回調函數敏感的是一幀的結尾。檢測到【FF FF】時,下一個字節(jié)顯然就是【A】。這其實是不規(guī)范的,我們不能理所當然地認為每一幀都是傳輸正確的。

舉個例子:

【 A B C FF FF】【 A B C FF FF】【 A B C FF FF】【 A B C FF FF】【 A B C FF FF】

中間紅色的ABC表示因為數據線接觸不良導致的傳輸錯誤,如果具有固定幀頭的話,或許幀頭也會出現(xiàn)錯誤,從而直接跳過這一幀錯誤的信號【 A B C FF FF】。

因此必須通過固定的幀頭來確定此時傳輸的是否是完整的數據。

這就需要我們進一步對一幀的結構,進行修改了,讓其完整地包含“幀頭”與“幀尾”。在MATLAB中給出了configureTerminator的方法,可以編輯SerialObject需要檢測到的幀尾信號。詳細解釋可以看configureTerminator官方文檔,其中有這樣的介紹:

configureTerminator(t,terminator) defines the terminator for both read and write communications with the remote host specified by the TCP/IP client t. Allowed terminator values are "LF" (default), "CR", "CR/LF", and integer values from 0 to 255. The syntax sets the Terminator property of t.

這里提到,我們可以設置需要檢測幀尾信號為“LF”、“CR”、“CR/LF”或一個0-255的整數(剛好對應了8位無符號數,也就是一字節(jié))。

按照上面的說明,我們可以對之前的幀進行下圖的修改,加上幀尾(最左端為最先接收到的字節(jié)):

MATLAB :【11】一文帶你讀懂serialport串口收發(fā)原理與實現(xiàn)

這樣,我們就可以利用檢測幀尾(橙色部分),來實現(xiàn)對回調函數的調用啦。但是新的疑問又誕生了:我理解0-255的數字怎么發(fā)送,但是這畢竟是單字節(jié)的,會不會造成數據讀取混亂?上文提到的“LF”、“CR”、“CR/LF”這三個又是什么?(這也是困擾了我一段時間的問題)

“LF”、“CR”、“CR/LF”概念解釋:

引用自:CR,LF詳解_Berwyn丶的博客-CSDN博客_cr的16進制

從起源上來說,在計算機還沒有出現(xiàn)之前,有一種叫做電傳打字機(Teletype Model 33,Linux/Unix下的tty概念也來自于此)的玩意,每秒鐘可以打10個字符。但是它有一個問題,就是打完一行換行的時候,要用去0.2秒正好可以打兩個字符。要是在這0.2秒里面,又有新的字符傳過來,那么這個字符將丟失。

于是,研制人員想了個辦法解決這個問題,就是在每行后面加兩個表示結束的字符。一個叫做“回車”,告訴打字機把打印頭定位在左邊界;另一個叫做“換行”,告訴打字機把紙向下移一行。這就是“換行”和“回車”的來歷,從它們的英語名字上也可以看出一二。

后來,計算機發(fā)明了,這兩個概念也就被般到了計算機上。那時,存儲器很貴,一些科學家認為在每行結尾加兩個字符太浪費了,加一個就可以。于是,就出現(xiàn)了分歧。在不同的系統(tǒng)中,就出現(xiàn)了下面的狀況:

系統(tǒng) 符號 名稱 十六進制(ASCII)
Linux ’\n’ LF 0x0A
Mac ’\r’ CR 0x0D
Windows ’\r\n’ CR/LF 【0x0D?0x0A】
注:這里并不是說在Windows系統(tǒng)中只能使用CR/LF作為幀尾,表格里說的是對應系統(tǒng)本文編輯器中的默認換行符。

是不是感覺豁然開朗?那我們就可以理所當然的將之前的圖改為下面的樣子(最左端為最先接收到的字節(jié)):

MATLAB :【11】一文帶你讀懂serialport串口收發(fā)原理與實現(xiàn)

讀到這里,我想讀者朋友們已經逐漸理解了最開始所說的:想弄清楚怎么接收串口的數據,那你首先就需要知道串口的數據是怎么發(fā)送出來的?;叵胍幌挛覀兊乃悸?,因為要實現(xiàn)多字節(jié)讀取,所以需要給一個固定的幀頭用來確定每個字節(jié)的位置;為了提供一個可以激活回調函數的信號,并且不影響幀頭的存在,我們需要添加一個幀尾。結合configureTerminator中的設置信號,我們發(fā)現(xiàn)可以使用“LF”、“CR”、“CR/LF”或者0-255的數字作為幀尾讓回調函數激活,通過查閱原來前面的三個“LF”、“CR”、“CR/LF”說的是換行符的ASCII碼,我們可以使用開發(fā)板讓他們發(fā)出對應的十六進制數據來表示。

至此,我們知道了數據從開發(fā)板上發(fā)送出來時的結構。對比四種幀尾,只有“CR/LF”是兩個字節(jié)的,對于溫度這種未知的數據信號來說,是最穩(wěn)妥的,可以更好的避免出現(xiàn)雷同情況,導致讀取錯誤。

舉個例子:

當我們發(fā)送的數據是:【FF FF A B C 幀尾】。

當幀尾是1字節(jié)很有可能出現(xiàn)【C】與【幀尾】相同的情況,如果【幀尾】是兩字節(jié),【B C】與之雷同的情況則會概率減小很多。

因此我們選擇在開發(fā)板中按照下圖的方式來發(fā)送數據給上位機(最左端為最先接收到的字節(jié)),這需要先在開發(fā)板中定義好,本文默認讀者已經完成了這部分,如果有需要的話,讀者也可以留言給我,我會單獨出一篇文章進行講解:

MATLAB :【11】一文帶你讀懂serialport串口收發(fā)原理與實現(xiàn)

那么現(xiàn)在就可以開始激動人心(bushi)的MATLAB編程環(huán)節(jié)啦,基于MATLAB文檔serialport,下面給出一個簡單的模板:

Port_List = serialportlist("available");
SerialObj = serialport("COM7",115200);
configureTerminator(SerialObj,"CR/LF");
flush(SerialObj);
SerialObj.UserData = struct("Data",[]);
configureCallback(SerialObj,"terminator",@readSerialData);

% 回調函數
function readSerialData(src, ~)
    data = read(src,7,"uint8");
    src.UserData.Data = data;
    ShowTemp(src);
end

% 溫度數據處理與展示
function ShowTemp(src)
    if(src.UserData.Data(1:2) == [0xFF 0xFF])
        Temperature = src.UserData.Data(3)*256*256 + src.UserData.Data(4)*256 + src.UserData.Data(5);
        disp(Temperature);
    end
end

下面對代碼進行一下講解:

Port_List = serialportlist("available");

展示出當前系統(tǒng)中可用的串口列表,與電腦設備管理器中的端口是對應的。


SerialObj = serialport("COM7",115200);

利用serialport函數來構造一個串口對象SerialObj,設定對應的端口是COM7端口,波特率是115200。


configureTerminator(SerialObj,"CR/LF");

設置需要檢測到的幀尾是"CR/LF"。


flush(SerialObj);

清空串口對象的接收緩沖區(qū)。


SerialObj.UserData = struct("Data",[]);

通過查看SerialObj對象的屬性,可以看到其中存在一個屬性叫做UserData,可以用來存儲數據,這里我們將其定義為一個結構體,里面自行定義只有一個叫做Data的數據。


configureCallback(SerialObj,"terminator",@readSerialData);

指定回調函數,也就是第三個屬性提到的readSerialData函數,表示檢測到幀尾后需要進行的操作?!皌erminator”參數的意思是檢測結束符,讀者只需要修改最后一個參數readSerialData即可。


function readSerialData(src, ~)

定義回調函數,src表示自定傳入的對象,因此不需要進行修改。


? ? data = read(src,7,"uint8");

read函數表示從串口對象中讀取7字節(jié)的數據,因為是從檢測到結束符后面開始的也就是【FF FF A B C 0D 0A】這7個字節(jié)的內容?!皍int8”表示讀取的是8位無符號數。值得注意的是,這部分還有其他的函數可以使用,例如用來讀取一行字符的readline函數,同樣在MATLAB文檔serialport有明確介紹。

這里其實就可以進一步理解CR/LF之所以是換行符的原因了,從一個換行符讀取到另一個換行符之間,不就是讀取一行(readline)的含義嗎?


? ? src.UserData.Data = data;

將讀取到的數據data存儲到對象屬性UserData里面的結構體下的Data中,實現(xiàn)數據的存儲。數據的存儲方式是一個長度為7的數組,可以直接利用索引1-7進行調用。

????ShowTemp(src);

調用數據處理的函數,用來預處理和顯示接收到的數據。


end


function ShowTemp(src)

定義數據處理函數


? ? if(src.UserData.Data(1:2) == [0xFF 0xFF])

使用if語句,判斷數據頭是否是【FF FF】,確定是否有傳輸錯誤。


? ? ? ? Temperature = src.UserData.Data(3)*256*256 + src.UserData.Data(4)*256 + src.UserData.Data(5);

之后的三個字節(jié)是【A B C】,每個是8比特,因此要乘以它們的權值進行計算,獲得原始的數據。


? ? ? ? disp(Temperature);

展示當前的數據到控制臺。


? ? end
end

2 串口發(fā)送

串口發(fā)送是指,電腦將需要發(fā)送的數據(一般是指令或者參數設置信息)整合好,發(fā)送給開發(fā)板的過程。

相信有了前面串口接收的基礎,這對大家來說就非常簡單了,在這里,我們還是假設一個應用場景來進行講解,由于很對讀者會使用到GUI進行串口發(fā)送的測試,這里我們就以GUI中的文本輸入框的數據格式為例。

在GUI中,我需要將一個十六進制字符串“FF 01 02 03 04”發(fā)送給開發(fā)板,我需要怎么做?GUI如下圖所示,是“文本區(qū)域”類型的模塊:

MATLAB :【11】一文帶你讀懂serialport串口收發(fā)原理與實現(xiàn)

這里需要注意下面的問題:

  1. 如何從GUI中獲取數據(僅限于GUI使用時,如果是腳本文件,則需要按照字符串來進行處理)。
  2. GUI中獲取到的數據,實際上是cell類型,而不是單純的字符串類型(僅限于GUI使用時,如果是腳本文件,則需要按照字符串來進行處理)。
  3. 如何將數據進行分割并發(fā)送。

這里由于三個問題相當明確且容易解決,因此我直接給出串口發(fā)送函數write的使用案例:

Port_List = serialportlist("available");
SerialObj = serialport("COM7",115200);
send_data = get(app.TextAreaTabSend, "value");
HEX       = hex2dec(strsplit(cell2mat(send_data), " "));
write(app.SerialObject,HEX,"uint8");

下面對代碼進行一下講解:

Port_List = serialportlist("available");

展示出當前系統(tǒng)中可用的串口列表,與電腦設備管理器中的端口是對應的。


SerialObj = serialport("COM7",115200);

利用serialport函數來構造一個串口對象SerialObj,設定對應的端口是COM7端口,波特率是115200。


send_data = get(app.TextAreaTabSend, "value");

從GUI中獲取當前TextArea中的值信息,返回的時cell類型的數據。


HEX ? ? ? = hex2dec(strsplit(cell2mat(send_data), " "));

從內層到外層,依次完成cell2mat()將cell類型轉為mat類型;strsplit()將mat類型按照空格進行分割;hex2dec()將字符串視為hex類型的數據轉為十進制進行傳輸。

如果是單純的字符串操作,則換為下面的函數即可:

HEX ? ? ? = hex2dec(strsplit(send_str, " "));

將字符串先進行分割,然后轉為十進制的數組。

注意,這兩種寫法我都是默認,發(fā)送的信息必須每個字節(jié)之間使用空格進行分割處理,因為使用的時write函數,并且是uint8類型。


write(SerialObj ,HEX,"uint8");

將數據HEX發(fā)送給SerialObj對象,實現(xiàn)發(fā)送。這里使用的是write函數,其實還有另一個函數writeline,讀者可以參考MATLAB文檔serialport進行查閱。

至此,就完成了全部的數據收發(fā)任務啦,當需要關閉串口時,只需要使用下面的函數,刪除創(chuàng)建的對象即可。

delete(SerialObj);                        %通過刪除對象來斷開串口

最后再提及一下,為什么我都是使用的write以及read的uint8類型呢?一方面我們的應用環(huán)境還是數字的傳輸為主,字符串的傳輸這里并沒有怎么涉及到。另一方面,逐個字節(jié)的收發(fā),在我看來是更方便理解其中串口協(xié)議原理的,并且ASCII本身就是8位無符號數。


首次嘗試這樣的寫作方式,希望本篇文章能夠給讀者一些幫助,同時由于本人水平有限,如果有一些問題的話,請務必留言指出,我一定虛心接受!

這就是本期的全部內容啦,如果你喜歡我的文章,不要忘了點贊+收藏+關注,分享給身邊的朋友哇~文章來源地址http://www.zghlxwxcb.cn/news/detail-417068.html

到了這里,關于MATLAB :【11】一文帶你讀懂serialport串口收發(fā)原理與實現(xiàn)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯(lián)網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 抖音小店無貨源處罰全解,一文帶你讀懂官方規(guī)則,合理規(guī)避風險

    抖音小店無貨源處罰全解,一文帶你讀懂官方規(guī)則,合理規(guī)避風險

    大家好,我是電商年年 根據官方解釋, “無貨源店鋪” ,指店鋪經營者沒有現(xiàn)貨,在網上找產品找貨源,在未取得貨源方授權的情況下,把貨源信息“搬運”到自己的店鋪中,等有消費者下單,店鋪經營者再去 貨源方店鋪下 單,由貨源方向消費者派單發(fā)貨。 ? 那官方對于

    2024年02月03日
    瀏覽(23)
  • 一口氣帶你讀懂跨境電商出海模式

    作為一名跨境電商賣家,掌握正確的“出海模式”至關重要。今天,就讓我們一起揭開跨境電商的神秘面紗,探索它的各種出海模式,為你的電商之旅提供指引。 1???國際站模式 ?起步門檻:10W及以內 ?利潤:高 ?客單價:較高(以?B2B?大單為主) ?運營難度:中低,

    2024年02月21日
    瀏覽(27)
  • 工時管理為何對項目如此重要?8Manage 帶你讀懂!

    工時管理為何對項目如此重要?8Manage 帶你讀懂!

    “時間就是金錢”,相信作為管理者都已經聽膩了這話,但在項目管理中確實是真理。你要知道項目工時是會直接影響到項目費用成本的,不論項目工作是按小時還是按固定費用計費和付款,在一段工時內完成的工作越多,說明效率就越高,而費用成本也就越低。而且員工工

    2024年02月16日
    瀏覽(26)
  • Linux - 一篇帶你讀懂 Curl Proxy 代理模式

    Linux - 一篇帶你讀懂 Curl Proxy 代理模式

    curl 是一個很有名的處理網絡請求的 類Unix 工具。出于某種原因,我們進行網絡請求,需要設置代理。本文講全面介紹如何為 curl 設置代理 設置代理參數 基本用法 設置 HTTP 代理 下面兩種設置代理的方式是可以的 由于代理地址的默認協(xié)議為? HTTP, 所以可以省略,按照下面的

    2024年02月05日
    瀏覽(29)
  • 1.4W字!讓我?guī)阕x懂springmvc的世界!

    1.4W字!讓我?guī)阕x懂springmvc的世界!

    目錄 一.前提了解 1.tomcat和servlet的關系? 2.springmvc想要實現(xiàn)web開發(fā)必須滿足的條件是什么? 二.什么是SpringMVC 三.基于SpringMVC創(chuàng)建web項目 ①創(chuàng)建項目并選擇依賴 ?②設置熱部署(部分代碼改動不需要手動重新run即可生效) 四.理解前后端分離的開發(fā)過程 五.SpringMVC實現(xiàn)web開發(fā)

    2024年02月06日
    瀏覽(31)
  • 圖論:一文教你讀懂常見的圖遍歷算法

    圖論:一文教你讀懂常見的圖遍歷算法

    深度優(yōu)先搜索(DFS): 從一個起始節(jié)點開始,訪問該節(jié)點并將其標記為已訪問。 遞歸地訪問所有與當前節(jié)點直接相連且未被訪問過的節(jié)點。 重復上述步驟,直到所有節(jié)點都被訪問過或沒有未訪問的節(jié)點。 廣度優(yōu)先搜索(BFS): 從一個起始節(jié)點開始,將其放入隊列中,并標

    2024年04月25日
    瀏覽(19)
  • 3D智能相機:帶你讀懂3D機器視覺如何實時掃描構建物體的3D模型

    3D智能相機:帶你讀懂3D機器視覺如何實時掃描構建物體的3D模型

    作者:御劍飛行? 3D智能相機是一種能夠捕捉三維空間中物體形狀和位置信息的相機。它可以在一個瞬間同時捕捉到物體的深度和顏色信息,并用這些數據創(chuàng)建一個三維模型。 3D智能相機工作方式示意圖,圖源@御劍飛行 3D智能相機能夠捕獲物體的更詳細信息,包括其尺寸、形

    2024年04月09日
    瀏覽(22)
  • 一文帶你如何用SpringBoot+RabbitMQ方式來收發(fā)消息

    一文帶你如何用SpringBoot+RabbitMQ方式來收發(fā)消息

    預告了本篇的內容:利用RabbitTemplate和注解進行收發(fā)消息,還有一個我臨時加上的內容:消息的序列化轉換。 本篇會和SpringBoot做整合,采用自動配置的方式進行開發(fā),我們只需要聲明RabbitMQ地址就可以了,關于各種創(chuàng)建連接關閉連接的事都由Spring幫我們了~ 交給Spring幫我們管

    2024年02月09日
    瀏覽(24)
  • Matlab上位機——串口收發(fā)、接收轉為圖像實時顯示、圖像放大縮小等功能

    Matlab上位機——串口收發(fā)、接收轉為圖像實時顯示、圖像放大縮小等功能

    原例程代碼可以進行串口接收發(fā)送,加載與存儲數據 本人在例程代碼的基礎上添加了共三個功能 1.加載文件數據,三通道同時顯示波形 2.放大縮小 3.均值濾波 4.將接收到的數據以固定位數轉換為實時波形 布局 加載文件數據后(excel的csv格式) 濾波效果 實時波形采集當時忘了

    2024年02月02日
    瀏覽(24)
  • 數學建模 | 一文讀懂:支持向量機(matlab源碼)

    ===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 =====================================================

    2024年02月01日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包