2019年10月21日 星期一

Arduino 控制 HD44780 點陣文字LCD熒幕模組

早期使用 七段顯示器 及 八乘八點陣顯示器
都使用基本的訊號操作,顯示比較少及基本的訊息
但要顯示比較多內容及訊息時,七段顯示器 及 八乘八點陣顯示器 便比較不足
若果有一個可以一次過顯示一大段文字顯示器相信會更方便顯示訊息……


見下文
HD44780 16x2點陣文字LCD熒幕 正面

見下文
HD44780 16x2點陣文字LCD熒幕 背面

見下文
1排16針引腳座

見下文
將引腳安裝到 LCD熒幕

見下文
見下文
見下文
見下文
將引腳焊接到 LCD熒幕
(焊接效果仍然不熟練)

引腳功能

HD44780 共有 16支引腳 (部分只有14支引腳)
編號引腳方向用途
1VSS熒幕接地
2VDD熒幕電源 接受 5V
3Vo熒幕對比度 電壓越低,對比度越明顯
4RS輸入暫存器選擇 (Register Select)
低電壓指示暫存器 (Instruction Register (IR))
高電壓資料暫存器 (Data Register (DR))
5RW輸入讀寫 (Read / Write)
低電壓寫入狀態 (Write Status)
高電壓讀取狀態 (Read Status)
6E輸入啟動 (Enable) ,由 低電壓 調整成 高電壓
寫入資料 或 讀取資料 後再調整回 低電壓 以完成資料操作
7D0輸入輸出第0位元資料,設定資料寫入資料低電壓 為 0 ,高電壓 為 1 (4位元模式 為 無效)
8D1輸入輸出第1位元資料,設定資料寫入資料低電壓 為 0 ,高電壓 為 1 (4位元模式 為 無效)
9D2輸入輸出第2位元資料,設定資料寫入資料低電壓 為 0 ,高電壓 為 1 (4位元模式 為 無效)
10D3輸入輸出第3位元資料,設定資料寫入資料低電壓 為 0 ,高電壓 為 1 (4位元模式 為 無效)
11D4輸入輸出第4位元資料,設定資料寫入資料低電壓 為 0 ,高電壓 為 1
12D5輸入輸出第5位元資料,設定資料寫入資料低電壓 為 0 ,高電壓 為 1
13D6輸入輸出第6位元資料,設定資料寫入資料低電壓 為 0 ,高電壓 為 1
14D7輸入輸出第7位元資料,設定資料寫入資料低電壓 為 0 ,高電壓 為 1
15ALED背光電源,接受 5V (14支引腳 LCD熒幕 沒有)
16KLED背光接地 (14支引腳 LCD熒幕 沒有)

暫存器訊號

8位元模式 (8-Bit Mode)
HD44780 基本使用 D0 至 D7 共8支引腳 控制暫存器
引腳初始化啟動8位元模式暫存器 週期
Time延遲2毫秒延遲2毫秒延遲2毫秒延遲2毫秒
RS高/低
RW高/低
E
D7低/高
D6低/高
D5低/高
D4低/高
D3低/高
D2低/高
D1低/高
D0低/高

訊號波紋時序圖
RSRWEND7D6D5D4D3D2D1D0

4位元模式 (4-Bit Mode)
考慮接駁引腳數量,HD44780 提供 4位元模式 只需要使用 D4 至 D7 4支引腳 便可以控制暫存器,但訊號會有些微不同
引腳初始化啟動4位元模式暫存器 週期
前4位元後4位元
Time延遲2毫秒延遲2毫秒延遲2毫秒延遲2毫秒延遲2毫秒延遲2毫秒
RS高/低高/低
RW高/低高/低
E
D7低/高低/高
D6低/高低/高
D5低/高低/高
D4低/高低/高

訊號波紋時序圖
RSRWEND7D6D5D4

指示暫存器

指示暫存器 (Instruction Register) 指示 HD44780 的設定資料
RSRW第n位元 (* 不限制)用途
D7D6D5D4D3D2D1D0
0000000001清除熒幕所有內容 (Clear)
000000001*游標回到原始位置 (Home)
00000001DT項目模式 (Entry Mode)
寫入資料後
當 D 為 0 時 向左移動;為 1 時 向右移動 (預設 1)
當 T 為 0 時 移動游標;為 1 時 偏移熒幕 (預設 0)
0000001SCB顯示模式 (Display Mode)
當 S 為 0 時 隱藏熒幕;為 1 時 顯示熒幕 (預設 0)
當 C 為 0 時 隱藏游標;為 1 時 顯示游標 (預設 0)
當 B 為 0 時 停止閃爍;為 1 時 啟動閃爍 (預設 0)
000001TD**游標與熒幕模式 (Cursor and Screen Setting)
當 T 為 0 時 只 移動游標;為 1 時 移動游標 及 偏移熒幕
當 D 為 0 時 向左移動(及偏移);為 1 時 向右移動(及偏移)
00001BRD**功能設定 (Function Set)
當 B 為 0 時 4位元模式;為 1 時 8位元模式 (沒有預設值)
當 R 為 0 時 1行顯示;為 1 時 2行顯示 (預設 0)
當 D 為 0 時 5x10點陣圖;為 1 時 5x8點陣圖 (預設 0)
0001AAA000設定自訂點陣圖 (CGRAM Setting)
可保存 8個
001AAAAAAA設定游標位置 (DDRAM Setting)
01BAAAAAAA傳回游標位置 (DDRAM Getting)
當 B 為 0 時表示 閒置狀態;為 1 時表示 繁忙狀態
A 為傳回 DDRAM 地址的資料
10DDDDDDDD寫入資料 (CGRAM)
11DDDDDDDD讀取資料 (CGRAM)
D 為傳回 游標 (DDRAM 地址) 的 CGRAM 資料
執行後,游標位置 會受 項目模式 的設定而改變

不使用微控制器

HD44780 可以直接使用基本電子零件控制

見下文
在下的線路接駁方法
(由於不使用微控制器只能使用 寫入狀態RW引腳 可以直接連接到接地線)

見下文
剪裁一些短曲接駁鐵線
(分別是 麵包板 4格長度 及 5格長度,考慮安裝進 麵包板 深度的長度)

見下文
安裝鐵線在麵包板

見下文
在下使用 4環電阻器,顏色為:第一環啡色、第二環黑色、第三環黃色、第四環金色
電阻值為 100KΩ 正負差為 5%
可以參考 http://resistor.cherryjourney.pt/

見下文
安裝電阻器在麵包板
(電阻器避免電壓不穩定,保持 E引腳 運作時穩定)

見下文
簡單的 滑桿開關 Slide Switch
(滑桿開關 的 引腳1 及 引腳3 接駁 正極 或 負極 ,但沒有方向限制
假如 引腳1 是 負極 , 引腳3 是 正極 ,當 滑桿 在 正極 方向,可通過 引腳2 獲得 電壓
反之,當滑桿在 負極 方向只會獲得 0V 電壓)

見下文
見下文
安裝滑桿開關在麵包板

見下文
在下使用電阻值為 10KΩ 的 電位器 (Potentiometer) (或稱為 可變電阻器 (Variable Resistor))
(電位器 的 引腳1 及 引腳3 接駁 正極 或 負極 ,同樣沒有方向限制,與 滑桿開關 類似
假如 引腳1 是 負極 , 引腳3 是 正極 ,當 控制器 越向 正極 轉動,可通過 引腳2 獲得越接近最高 電壓
反之,當 控制器 越向 負極 轉動 ,越獲得接近 0V 電壓)

見下文
安裝電位器在麵包板

見下文
見下文
安裝 HD44780 在麵包板

見下文
見下文
見下文
接駁跳線,並連接上下兩行正負極引腳
(在下的麵包板 第30欄 及 第31欄 不相連,需要再接駁跳線連接)

見下文
VSS 接駁到接地、VDD 接駁到電源
因為在下只顯資料,只使用 寫入模式 (Write Mode) ,所以 RW 接駁到接地即可

見下文
D0 至 D7 分別接駁到與 8個滑桿按鈕的信號引腳
D0 為最右 (最低位值),D7 為最左 (最高位值),以二進制排列,比較方便使用

見下文
連接 A引腳 及 K引腳

見下文
K引腳 接駁到接地

見下文
A引腳 接駁到 左為正極,右為負極 的 可變電阻器

見下文
連接 V0引腳

見下文
A引腳 接駁到 左為負極,右為正極 的 可變電阻器

見下文
見下文
連接 RS引腳

見下文
見下文
連接 E引腳

見下文
連接所有跳線的狀態

見下文
5V USB 差電池

見下文
USB Type A 電線,另一端只有正負極

見下文
接駁到 麵包板 正負極電線

見下文
避免正負極短路,使用電線膠布包裹

見下文
接通電源

見下文
見下文
見下文
調整 HD44780 的 LED背光光度

見下文
展示 調整 HD44780 的 LED背光光暗效果

見下文
見下文
調整 HD44780 的 對比度

見下文
展示 調整 HD44780 的 對比度效果

見下文
RS引腳 設定為 低電壓 (設定模式)

見下文
D0, D1, D2, D6, D7引腳 設定為 低電壓
D3, D4, D5引腳 設定為 高電壓
(二進制 00111000)

見下文
E引腳 設定為 高電壓,然後設定為 低電壓
設定 HD44780 使用 8-Bit模式2行顯示5乘8點陣

見下文
D4, D5, D6, D7引腳 設定為 低電壓
D0, D1, D2, D3引腳 設定為 高電壓
(二進制 00001111)

見下文
E引腳 設定為 高電壓,然後設定為 低電壓
設定 HD44780 啟用熒幕顯示游標啟用游標閃爍

見下文
RS引腳 設定為 高電壓 (資料模式)

見下文
D1, D2, D3, D4, D5, D7引腳 設定為 低電壓
D0, D6引腳 設定為 高電壓
(二進制 01000001)

見下文
HD44780 顯示 字母 A

使用微控制器

最簡單就是使用 Arduino 之類的微控制器

見下文
見下文
在下將 HD44780 接駁到 Arduino 的方法

寫入狀態 (Write Status)

寫入狀態 需要將所有 資料引腳 設定為 OUTPUT
編寫 Arduino 程式
const byte RS_PIN = 12;
const byte RW_PIN = 11;
const byte EN_PIN = 10;
const byte DA_LENGTH = 8;
const byte DA_PINS[DA_LENGTH] = {9, 8, 7, 6, 5, 4, 3, 2};
 
void setup() {
    pinMode(RS_PIN, OUTPUT);
    pinMode(RW_PIN, OUTPUT);
    pinMode(EN_PIN, OUTPUT);
    // 使用 8位元模式
    setIR(0x20 | 0x10 | 0x02 | 0x01);
    // 使用 2行 及 5x10陣點
    setIR(0x20 | 0x10 | 0x08);
    // 顯示熒幕、顯示游標、游標閃爍
    setIR(0x08 | 0x04 | 0x02 | 0x01);
}
 
void loop() {
    // 清除熒幕資料
    setIR(0x01);
    delay(1000);
    setDR('A');
    delay(1000);
    setDR('B');
    delay(1000);
    setDR('C');
    delay(1000);
}
 
void setPin(byte pin, byte value) {
    digitalWrite(pin, value);
    delay(2);
}
 
void writeData(byte mode, byte data) {
    setPin(RS_PIN, mode);
    setPin(RW_PIN, LOW);
    setPin(EN_PIN, HIGH);
    for (byte i = 0; i < DA_LENGTH; i++) {
        pinMode(DA_PINS[i], OUTPUT);
        setPin(DA_PINS[i], (((data & (1 << i)) > 0) ? HIGH : LOW));
    }
    setPin(EN_PIN, LOW);
}
 
void setIR(byte data) {
    writeData(LOW, data);
}
 
void setDR(byte data) {
    writeData(HIGH, data);
}
此 Arduino 程式可以在 HD44780 顯示 ABC

// 在 setIR(0x01); 後加入程式碼
// 改變寫入資料後游標位置
setIR(0x04 | 0x02 | 0x01);
// 設定游標位置
setIR(0x80 | 0x08);

見下文
展示 D = 1, T = 0 時,寫入資料後,游標向右移動 (預設)

見下文
展示 D = 0, T = 0 時,寫入資料後,游標向左移動

見下文
展示 D = 1, T = 1 時,寫入資料後,熒幕向左偏移

見下文
展示 D = 0, T = 1 時,寫入資料後,熒幕向右偏移

資料暫存器 (Data Register)

字符產生器 (Character Generator)
字符產生器 是使用 點陣圖 (Dot Matrix) 方式將 字符 顯示在 LCD熒幕 上
HD44780 區分 5x8點陣圖 及 5x10點陣圖 ,部分字符由於以 5x10點陣圖 設計, 5x8點陣圖的 HD44780 會不能完全顯示
跳過字符產生器表單

D4D3D2D1D0
5x8點陣圖範圍
5x8點陣圖游標
5x10點陣圖會使用額外2行
5x10點陣圖游標


字符產生器唯讀記憶體 (Character Generator Readonly Memory (CGROM))
字符產生器唯讀記憶體 保存著一堆預製的資料在暫存器中
CGROM 共保存 256個 8位元 字符點陣圖
基本上,都會保存著 數字、英文字母、常用拉丁符號
不同地區其他字符會有些微不同,日版 會保存 五十音,歐美版 會保存 希臘文
CGROM 的資料不能覆蓋
(在下的 A00版本 HD44780 為日版)

字符產生器隨記存取記憶體 (Character Generator Random Access Memory (CGRAM))
字符產生器隨記存取記憶體 可以自訂點陣圖
CGROM 中 0 至 7 共 8個 CGRAM ,其中 0 至 7 與 8 至 15 是相同
當截斷電源後 CGRAM 的資料便會遺失
跳過字符產生器唯讀記憶體表單

A00 版本
前4位元後4位元
0000000100100011010001010110011110001001101010111100110111101111
0000CG
RAM
0
CG
RAM
1
CG
RAM
2
CG
RAM
3
CG
RAM
4
CG
RAM
5
CG
RAM
6
CG
RAM
7
CG
RAM
0
CG
RAM
1
CG
RAM
2
CG
RAM
3
CG
RAM
4
CG
RAM
5
CG
RAM
6
CG
RAM
7
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111


// 改寫 loop 的內容
byte i = ' ';
for (; i < ' ' + 16; i++) {
    setDR(i);
}
setIR(0x80 | 0x40);
for (; i < ' ' + 32; i++) {
    setDR(i);
}
將 CGROM 寫入到 DDRAM
不同 HD44780熒幕顯示範圍不同,需要適當地修改資料

見下文
CGROM 第 32 至 63 字符實際效果

見下文
CGROM 第 64 至 95 字符實際效果

見下文
CGROM 第 96 至 127 字符實際效果

見下文
CGROM 第 160 至 191 字符實際效果

見下文
CGROM 第 192 至 223 字符實際效果

見下文
CGROM 第 224 至 255 字符實際效果

// 加入 setup 的內容
// 將資料寫入至 CGRAM 第0位置
setIR(0x40 | 0x00);
// 設定自訂點陣圖
setDR(0x08 | 0x04 | 0x02);
setDR(0x10 | 0x08 | 0x02 | 0x01);
setDR(0x10 | 0x01);
setDR(0x10 | 0x01);
setDR(0x10 | 0x01);
setDR(0x10 | 0x01);
setDR(0x10 | 0x01);
setDR(0x10 | 0x01);
setIR(0x01);

// 將資料寫入至 CGRAM (留意:只有 8個儲存位置)
// 然後在熒幕顯示

// 改寫 loop 的內容
// 使用 CGRAM 第0位置 資料
setDR(0x00);
執行自訂點陣圖的指示後,便執行資料將點陣圖資料儲存到 CGRAM 中

見下文
CGRAM 自訂字符參考效果
自訂字符一共使用 8組5位元資料 製作 (5x10點陣圖 為 10組5位元資料)

第 32 至 125 與 American Standard Code for Information Interchange (ASCII) 相同
第 160 至 223 與 Shift Japanese Industrial Standards (Shift JIS) 相同
(第 92 字符是 反斜號 (Backslash) ,但由於在下使用的 LCD熒幕 是使用 日本字符,所以會顯示 ¥ (日元符號))

顯示資料隨機存取記憶體 (Display Data Random Access Memory (DDRAM))
顯示資料隨機存取記憶體 是讓資料顯示在 HD44780 上的資料的記憶體
即使不同尺寸或不同展示數量的 HD44780 都會提供 80個 DDROM 空間
同樣截斷電源後 DDRAM 的資料便會遺失


8x1 LCD熒幕
最簡單的 HD44780
但即使只有 8格顯示範圍,但仍然有 80個 DDRAM
因此當游標不在範圍時,熒幕便不能顯示游標及資料
跳過 8x1 LCD熒幕
偏移顯示欄顯示欄以外
沒有0
0x00
1
0x01
2
0x02
3
0x03
4
0x04
5
0x05
6
0x06
7
0x07
...77
0x4D
78
0x4E
79
0x4F
1
0x01
2
0x02
3
0x03
4
0x04
5
0x05
6
0x06
7
0x07
8
0x08
...78
0x4E
79
0x4F
0
0x00
79
0x4F
0
0x00
1
0x01
2
0x02
3
0x03
4
0x04
5
0x05
6
0x06
...76
0x4C
77
0x4D
78
0x4E


8x2 LCD熒幕
使用 2行 的 HD44780, DDRAM 將 第 0 至 39 格 為 第一部分,第 40 至 79 格 為 第二部分
第一部分 的 地址 為 0x00 至 0x27 ,第二部分 的 地址 為 0x40 至 0x67
當兩行都要顯示資料時,要留意 DDRAM 的地址
同樣如果游標不在範圍時,熒幕便不能顯示游標及資料
跳過 8x2 LCD熒幕
偏移行數顯示欄顯示欄以外
沒有00
0x00
1
0x01
2
0x02
3
0x03
4
0x04
5
0x05
6
0x06
7
0x07
...37
0x25
38
0x26
39
0x27
140
0x40
41
0x41
42
0x42
43
0x43
44
0x44
45
0x45
46
0x46
47
0x47
...77
0x65
78
0x66
79
0x67
01
0x01
2
0x02
3
0x03
4
0x04
5
0x05
6
0x06
7
0x07
8
0x08
...38
0x26
39
0x27
0
0x00
141
0x41
42
0x42
43
0x43
44
0x44
45
0x45
46
0x46
47
0x47
48
0x48
...78
0x66
79
0x67
40
0x40
039
0x27
0
0x00
1
0x01
2
0x02
3
0x03
4
0x04
5
0x05
6
0x06
...36
0x24
37
0x25
38
0x26
179
0x4F
40
0x40
41
0x41
42
0x42
43
0x43
44
0x44
45
0x45
46
0x46
...76
0x64
77
0x65
78
0x66


16x4 LCD熒幕
使用 4行 的 HD44780 與 2行 的 LCD熒幕 相似,但 DDRAM 地址並不是順序
第1行 為 第 0 至 19 個 DDRAM ,第2行 為 第 40 至 59 個 DDRAM
第3行 為 第 20 至 39 個 DDRAM ,第4行 為 第 60 至 79 個 DDRAM
需要順序顯示資料時,要留意行數次序
同樣如果游標不在範圍時,熒幕便不能顯示游標及資料
跳過 16x4 LCD熒幕
偏移行數顯示欄顯示欄以外
沒有00
0x00
1
0x01
2
0x02
3
0x03
...13
0x0D
14
0x0E
15
0x0F
16
0x10
17
0x11
18
0x12
19
0x13
140
0x40
41
0x41
42
0x42
43
0x43
...53
0x4D
54
0x4E
55
0x4F
56
0x50
57
0x51
58
0x52
59
0x53
220
0x14
21
0x15
22
0x16
23
0x17
...33
0x21
34
0x22
35
0x23
36
0x24
37
0x25
38
0x26
39
0x27
360
0x54
61
0x55
62
0x56
63
0x57
...73
0x61
74
0x62
75
0x63
76
0x64
77
0x65
78
0x66
79
0x67
01
0x01
2
0x02
3
0x03
4
0x04
...14
0x0E
15
0x0F
16
0x10
17
0x11
18
0x12
19
0x13
0
0x00
141
0x41
42
0x42
43
0x43
44
0x44
...54
0x4E
55
0x4F
56
0x50
57
0x51
58
0x52
59
0x53
40
0x40
221
0x15
22
0x16
23
0x17
24
0x18
...34
0x22
35
0x23
36
0x24
37
0x25
38
0x26
39
0x27
20
0x14
361
0x55
62
0x56
63
0x57
64
0x58
...74
0x62
75
0x63
76
0x64
77
0x65
78
0x66
79
0x67
60
0x54
019
0x13
0
0x00
1
0x01
2
0x02
...12
0x0C
13
0x0D
14
0x0E
15
0x0F
16
0x10
17
0x11
18
0x12
159
0x53
40
0x40
41
0x41
42
0x42
...52
0x4C
53
0x4D
54
0x4E
55
0x4F
56
0x50
57
0x51
58
0x52
239
0x27
20
0x14
21
0x15
22
0x16
...32
0x20
33
0x21
34
0x22
35
0x23
36
0x24
37
0x25
38
0x26
379
0x67
60
0x54
61
0x55
62
0x56
...72
0x60
73
0x61
74
0x62
75
0x63
76
0x64
77
0x65
78
0x66


setIR(0x10 | 0x08 | 0x04);
移動游標 或 偏移熒幕

見下文
展示 T = 0, D = 0 時,游標向左移動

見下文
展示 T = 0, D = 1 時,游標向右移動

見下文
展示 T = 1, D = 0 時,游標向左移動 及 熒幕向左偏移

見下文
展示 T = 1, D = 1 時,游標向右移動 及 熒幕向右偏移

讀取狀態 (Read Status)

讀取狀態 需要將所有 資料引腳 設定為 INPUT
必須使用 微控制器 才能讀取資料

見下文
展示 游標位置 (DDRAM) 的 地址 及 游標位置 的 顯示資料 (CGRAM)

見下文
在下在 Tinkercad 製作了一個模擬不使微控制器的狀態控制 HD44780
https://www.tinkercad.com/embed/fDoBmZB5Of6
有興趣可以測試
而在下發現 Tinkercad 的不能完全模擬真實的 Arduino, HD44780 或 其他晶片 功能,若要測試還是需要有實物才能正常測試

額外資料

在下為了測試,購買 20x4 HD44780

見下文
20x4 HD44780 的正面

見下文
20x4 HD44780 的背面

見下文
見下文
經過多次焊接工作,在下大致掌握到更好的焊接方法
終於可以焊接到這些漂亮的小山丘

見下文
使用效果
第一行顯示大寫 A 至 Z ,第二行顯示小寫 a 至 z
但會發現文字串斷開,第一行內容移至第三行,第二行內容移至第四行
操作上 20x4 HD44780 都是只有兩行,只是視覺果下有四行
視覺上第三行,實際是第一行之後;視覺上第四行,實際是第二行之後

見下文
如果要順序顯示,需要計算每行需要顯示內容的字元數量,選擇行數,才能正確顯示內容順序
在下的例子顯示
Row 1 Position 0x00
Row 2 Position 0x40
Row 3 Position 0x14
Row 4 Position 0x54
實際上內容是
Row 1 Position 0x00 Row 3 Position 0x14 Row 2 Position 0x40 Row 4 Position 0x54
可以使用 空格 移動游標 到另一行,或使用 指示暫存器指 移動游標 到另一行

總結

在下翻查不同網頁及函式庫,都沒有處理 讀取狀態,因此在下再次細閱 HD44780 的官方說明文件,終於發現錯誤
在下原本是參考最多人建議使用的 LiquidCrystal 函式庫,原始碼顯示
  1. 寫入狀態:調整 各D引腳 為 高電壓 或 低電壓
  2. 調整 E引腳 為 高電壓
  3. 調整 E引腳 為 低電壓
但 HD44780 的官方說明文件顯示 Timing Characteristics 應該是
  1. 調整 E引腳 為 高電壓
    • 寫入狀態:調整 各D引腳 為 高電壓 或 低電壓
    • 讀取狀態:接收 各D引腳 的 高電壓 或 低電壓
  2. 調整 E引腳 為 低電壓
通常 RW引腳 很少需要調整,一般都是使用 寫入狀態 便足夠,即是 低電壓
只需要將 RW引腳 接駁到 接地線 便可以使用 寫入狀態

在下將程式編寫成 類別 (Class) 方便控制 HD44780 ,亦有 簡單範例 及 說明
案已經上載到 https://bitbucket.org/hkgoldenmra/hd44780module
https://create.arduino.cc/editor/hkgoldenmra/3c07d034-177e-47c0-91b9-ef46c3683697/preview
有興趣可以透過 git
git clone "https://bitbucket.org/hkgoldenmra/hd44780module.git" --depth=1
下載、使用甚至改良

沒有留言 :

張貼留言