51单片机基本刷屏测试实验_51单片机开发基础8——实时时钟实验
8.1 實(shí)時(shí)時(shí)鐘簡介
?????? RTC(Real Time Clock),是實(shí)時(shí)時(shí)鐘的縮寫,實(shí)時(shí)時(shí)鐘是日常生活中應(yīng)用最為廣泛的功能。它為人們提供精確的實(shí)時(shí)時(shí)間,或者為電子系統(tǒng)提供精確的時(shí)間基準(zhǔn),目前實(shí)時(shí)時(shí)鐘芯片大多采用精度較高的晶體振蕩器作為時(shí)鐘源。有些時(shí)鐘芯片為了在主電源掉電時(shí),還可以工作,需要外加電池供電。
?????? 現(xiàn)在的高端處理器大都內(nèi)置了RTC模塊,但是由于51單片機(jī)速度較慢,主要用于低端的控制系統(tǒng)中,所以沒有內(nèi)置RTC模塊,需要采用時(shí)鐘芯片來完成這個(gè)功能,現(xiàn)在常用的時(shí)鐘芯片有很多,現(xiàn)在以DS1302為例說明時(shí)鐘芯片的使用方法。
8.2 DS1302簡介
8.2.1 DS1302概述
?????? DS1302是美國DALLAS公司推出的一種高性能、低功耗的實(shí)時(shí)時(shí)鐘芯片,附加31字節(jié)靜態(tài)RAM,采用SPI三線接口與CPU進(jìn)行同步通信,并可采用突發(fā)方式一次傳送多個(gè)字節(jié)的時(shí)鐘信號(hào)和RAM數(shù)據(jù)。實(shí)時(shí)時(shí)鐘可提供秒、分、時(shí)、日、星期、月和年,一個(gè)月小于31天時(shí)可以自動(dòng)調(diào)整,且具有閏年補(bǔ)償功能。工作電壓寬達(dá)2.5~5.5V。采用雙電源供電(主電源和備用電源),可設(shè)置備用電源充電方式,提供了對(duì)備用電源進(jìn)行涓細(xì)電流充電的能力。
8.2.2通信協(xié)議
?????? 在之前的章節(jié)中,除了USART那一部分,都是采用了并行通信作為數(shù)據(jù)傳輸?shù)姆绞?#xff0c;并行通信雖然速度很快,但是對(duì)硬件有著很高的要求,比如如果傳輸8位的數(shù)據(jù),就需要8根通信線,如果是16位的數(shù)據(jù)就需要16根通信線,并且隨著通信線長度不一樣,可能會(huì)存在數(shù)據(jù)錯(cuò)誤或者丟失的情況。串行通信雖然速度沒有并行通信那么高,但是一根數(shù)據(jù)線可以傳送任意字節(jié)的數(shù)據(jù),降低了設(shè)計(jì)中布線的難度。
?????? DS1302就是串行通信方式,芯片的引腳分布如下圖所示。
引腳編號(hào) | 英文縮寫 | 引腳功能 |
1 | VCC2 | 主電源 |
2 | X1 | 32.768KHz晶振 |
3 | X2 | 32.768KHz晶振 |
4 | GND | 數(shù)字地 |
5 | RST | 復(fù)位 |
6 | I/O | 數(shù)據(jù)輸入/輸出 |
7 | CLK | 時(shí)鐘輸入 |
8 | VCC1 | 備用電源(接電池) |
????串行通信中,用到了兩個(gè)端口,時(shí)鐘信號(hào)CLK和數(shù)據(jù)信號(hào)I/O,時(shí)鐘信號(hào)用于提供數(shù)據(jù)發(fā)送的脈沖,數(shù)據(jù)信號(hào)I/O用于將數(shù)據(jù)拆成0101的形式發(fā)送過去,DS1302的時(shí)序包括讀和寫兩種時(shí)序,時(shí)序圖如下圖所示。
(1)寫時(shí)序
(2)讀時(shí)序
8.2.3 RTC內(nèi)部寄存器
(1)秒寄存器
讀地址:0x81
寫地址:0x80
Bit ?7 | Bit ?6 | Bit ?5 | Bit ?4 | Bit ?3 | Bit ?2 | Bit ?1 | Bit ?0 | 數(shù)據(jù)范圍 |
CH | Second ?1 | Second ?2 | 0~59 | |||||
Bit 7:時(shí)鐘開關(guān)
?????? 0:關(guān)閉
?????? 1:開啟
Bit 6~Bit 4:秒數(shù)據(jù)十位
Bit 3~Bit 0:秒數(shù)據(jù)個(gè)位
(2)分鐘寄存器
讀地址:0x83
寫地址:0x82
Bit ?7 | Bit ?6 | Bit ?5 | Bit ?4 | Bit ?3 | Bit ?2 | Bit ?1 | Bit ?0 | 數(shù)據(jù)范圍 |
- | Minute ?1 | Minute ?2 | 0~59 | |||||
Bit 6~Bit 4:分鐘數(shù)據(jù)十位
Bit 3~Bit 0:分鐘數(shù)據(jù)個(gè)位
(3)小時(shí)寄存器
讀地址:0x85
寫地址:0x84
Bit ?7 | Bit ?6 | Bit ?5 | Bit ?4 | Bit ?3 | Bit ?2 | Bit ?1 | Bit ?0 | 數(shù)據(jù)范圍 |
12/24 | 0 | Hour ?1 | Hour ?2 | 1~12 0~23 | ||||
AM/PM | Hour ?1 | |||||||
Bit 7:小時(shí)制選擇
?????? 0:24小時(shí)制
?????? 1:12小時(shí)制
Bit 5~Bit 4:小時(shí)數(shù)據(jù)十位(24小時(shí)制)
????????????? 當(dāng)Bit 7設(shè)置為12小時(shí)制的時(shí)候Bit5代表上下午,Bit 4代表小時(shí)數(shù)據(jù)的十位
Bit 3~Bit 0:小時(shí)數(shù)據(jù)個(gè)位
(4)日期寄存器
讀地址:0x87
寫地址:0x86
Bit ?7 | Bit ?6 | Bit ?5 | Bit ?4 | Bit ?3 | Bit ?2 | Bit ?1 | Bit ?0 | 數(shù)據(jù)范圍 |
0 | 0 | Data ?1 | Data ?2 | 1~31 | ||||
Bit 5~Bit 4:日期數(shù)據(jù)十位
Bit 3~Bit 0:日期數(shù)據(jù)個(gè)位
(5)月份寄存器
讀地址:0x89
寫地址:0x88
Bit ?7 | Bit ?6 | Bit ?5 | Bit ?4 | Bit ?3 | Bit ?2 | Bit ?1 | Bit ?0 | 數(shù)據(jù)范圍 |
0 | 0 | 0 | Month ?1 | Month ?2 | 1~12 | |||
Bit 5~Bit 4:月份數(shù)據(jù)十位
Bit 3~Bit 0:月份數(shù)據(jù)個(gè)位
(6)星期寄存器
讀地址:0x8B
寫地址:0x8A
Bit ?7 | Bit ?6 | Bit ?5 | Bit ?4 | Bit ?3 | Bit ?2 | Bit ?1 | Bit ?0 | 數(shù)據(jù)范圍 |
0 | 0 | 0 | 0 | 0 | Day | 1~7 | ||
Bit 2~Bit 0:星期數(shù)據(jù)個(gè)位
(7)年份寄存器
讀地址:0x8D
寫地址:0x8C
Bit ?7 | Bit ?6 | Bit ?5 | Bit ?4 | Bit ?3 | Bit ?2 | Bit ?1 | Bit ?0 | 數(shù)據(jù)范圍 |
Year ?1 | Year ?2 | 0~99 | ||||||
Bit 7~Bit 4:年份數(shù)據(jù)十位
Bit 3~Bit 0:年份數(shù)據(jù)個(gè)位
(8)寫保護(hù)寄存器
讀地址:0x8F
寫地址:0x8E
Bit ?7 | Bit ?6 | Bit ?5 | Bit ?4 | Bit ?3 | Bit ?2 | Bit ?1 | Bit ?0 | 數(shù)據(jù)范圍 |
WP | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Bit 7:寫保護(hù)控制
?????? 0:關(guān)閉寫保護(hù)
?????? 1:開啟寫保護(hù)
8.2.4 原理圖
8.3 例程分析
(1)由于程度很長,只做幾個(gè)重點(diǎn)位置的講解。先來看顯示部分
在之前1602顯示的實(shí)驗(yàn)上增加了一個(gè)函數(shù)LCD_Show_String,這個(gè)函數(shù)用于在屏幕任意位置顯示字符串,C語言中的字符串其實(shí)是一個(gè)一維數(shù)組,這個(gè)一維數(shù)組中存放的是ASCII碼,假設(shè)定義一個(gè)字符串Hello World,那么實(shí)際在單片機(jī)里面存儲(chǔ)的數(shù)據(jù)如下表所示
00 ?H | 01 ?H | 02 ?H | 03 ?H | 04 ?H | 05 ?H | 06 ?H | 07 ?H | 08 ?H | 09 ?H | 0A ?H |
H | e | l | l | o | W | o | r | l | d |
換算到16進(jìn)制里面就是
00 ?H | 01 ?H | 02 ?H | 03 ?H | 04 ?H | 05 ?H | 06 ?H | 07 ?H | 08 ?H | 09 ?H | 0A ?H |
0x48 | 0x65 | 0x6C | 0x6C | 0x6F | 0x20 | 0x57 | 0x6F | 0x72 | 0x6C | 0x64 |
現(xiàn)在來分析這個(gè)子函數(shù)
第112行:使用switch語句來進(jìn)行坐標(biāo)轉(zhuǎn)換,因?yàn)長CD1602第1行第1個(gè)位置的地址是0x80,第2行第1個(gè)位置的地址則是0xC0,所以需要用分支語句來控制最后的地址
第115行,如果是第1行(第1行用0表示的),那么地址就是行地址加列地址,1602內(nèi)部規(guī)定了列地址從0~15,如果是第1行第2個(gè)位置,那么具體的地址就應(yīng)該是0x80+1=0x81,如果是第2行第5個(gè)位置就應(yīng)該是0xC0+4=0xC4
第124行:地址設(shè)置屬于輸入命令,所以應(yīng)該調(diào)用LCD命令寫入函數(shù),將之前的地址數(shù)據(jù)寫入LCD1602中
第125行:由于LCD1602設(shè)置了地址自動(dòng)加一,所以寫入連續(xù)的數(shù)據(jù)的時(shí)候不需要頻繁設(shè)置地址,這就可以采用循環(huán)的方式把字符串寫進(jìn)去,ASCII雖然有128個(gè)數(shù)據(jù),但是能夠顯示的數(shù)據(jù)并不多,仔細(xì)觀察ASCII碼表可以發(fā)現(xiàn),只有空格之后的數(shù)據(jù)是可以顯示的,之前的都是控制字符,而空格的ASCII碼值是0x20,程序中的\0的ASCII碼值是0x00,也就是說當(dāng)檢測到要寫入的數(shù)據(jù)是0x00的時(shí)候就說明字符串寫完了,此時(shí)結(jié)束循環(huán)即可
第127行:利用LCD數(shù)據(jù)寫入函數(shù)把指針指向的地址里面的數(shù)據(jù)寫入LCD1602
第128行:指針自增,為了讓指針指向的下一個(gè)字符的地址,因?yàn)閿?shù)組里面的數(shù)據(jù)在地址中都是連續(xù)存放的,如果第一個(gè)字符的地址是0x00,那么下一個(gè)字符的地址就一定是0x01
(2)然后我們來看DS1302的驅(qū)動(dòng)函數(shù),重點(diǎn)分析如何將一個(gè)字節(jié)拆分成0101的二進(jìn)制位發(fā)出去,并分析如何將0101的二進(jìn)制位變成一個(gè)完整的字節(jié)。
假設(shè)存在1個(gè)字節(jié)0x23,現(xiàn)在我想把這個(gè)字節(jié)從最低位到最高位一位一位的將數(shù)據(jù)傳送出去,應(yīng)該怎么辦呢?
?????? 首先23 H=0010 0011B,最低位是1,最高位是0,現(xiàn)在將0x23&0x01進(jìn)行運(yùn)算,結(jié)果當(dāng)然是0x01,這時(shí),我們就應(yīng)該將數(shù)據(jù)線變成1,然后0x23往右移動(dòng)一個(gè)二進(jìn)制位,得出的結(jié)果是11 H=0001 0001 B(這里有一個(gè)重點(diǎn),數(shù)據(jù)右移的時(shí)候,最高位是補(bǔ)0的,數(shù)據(jù)左移的時(shí)候,最低位補(bǔ)0)。
?????? 假設(shè)上面的數(shù)據(jù)右移了2次后,最初的23 H變成了08 H=0000 1000 B,現(xiàn)在繼續(xù)對(duì)0x08&0x01做運(yùn)算得出的結(jié)果是0,這時(shí),將數(shù)據(jù)線變?yōu)?,如此循環(huán)8次,就可以將1個(gè)字節(jié)分成串行數(shù)據(jù)一位一位的傳送出去了。
上圖所示的代碼就是串行數(shù)據(jù)的發(fā)送與接收,下面開始考慮接收,如何將串行數(shù)據(jù)拼接成并行數(shù)據(jù)呢?
?????? 假設(shè)串行數(shù)據(jù)先發(fā)送最低位,首先將一個(gè)數(shù)據(jù)00 H右移一個(gè)二進(jìn)制位,得出的數(shù)據(jù)當(dāng)然還是00 H,然后如果數(shù)據(jù)總線上的電平是1,那么此時(shí)就把00 H和80 H做或運(yùn)算,得出的結(jié)果就是80 H,然后下一個(gè)電平的時(shí)候80 H右移一個(gè)二進(jìn)制位,得出的結(jié)果是40 H,如果此時(shí)數(shù)據(jù)線的電平還是1,那就繼續(xù)和80 H做或運(yùn)算,得C0 H,最終通過8次運(yùn)算,就可以將1個(gè)字節(jié)全部接收完畢。
?????? 根據(jù)上面的分析和DS1302的時(shí)序圖,就可以寫出DS1302讀取數(shù)據(jù)的函數(shù),如下圖所示。
(3)下面我們來分析下如何將DS1302計(jì)算得出的數(shù)據(jù)顯示在屏幕上,主函數(shù)的程序如下圖所示。
????在while循環(huán)里面,由于數(shù)據(jù)不連續(xù),所以需要先寫顯示的地址,然后寫入數(shù)據(jù)以顯示年為例,由于年份后面2位(個(gè)位和十位)的坐標(biāo)是第1行的第4列和第5列,所以只需要將地址設(shè)置成第一行的第4列就行了,由于1602內(nèi)部地址從0開始,所以第1行的第4列地址應(yīng)該是0x80+3。
?????? 第229行和第230行里面,數(shù)據(jù)除以10取整數(shù)部分和除以10取余數(shù)部分都比較容易理解,那么為什么要加上0x30呢,這是因?yàn)锳SCII碼表里面,0~9的ASCII值是0x30~0x39,所以如果不加0x30,那么寫入的0~9實(shí)際是控制字符,剛才說過了ASCII碼表里面0x20之前的都是控制字符,直接寫入0x00~0x09是不顯示的,所以加上0x30之后,9就變成了0x39。
8.4 完整代碼
/********************************************************************************************************* 頭 文 件 引 用*********************************************************************************************************/#include //導(dǎo)入51單片機(jī)頭文件/********************************************************************************************************* 數(shù) 據(jù) 類 型 定 義*********************************************************************************************************/#define u8 unsigned char //定義無符號(hào)字符型數(shù)據(jù)(0~255)#define u16 unsigned int //定義無符號(hào)整型數(shù)據(jù)(0~65535)/********************************************************************************************************* 硬 件 端 口 定 義*********************************************************************************************************///LCD1602控制端口#define LCD_DB P0 //LCD數(shù)據(jù)口sbit LCD_RS = P2^0 ; //數(shù)據(jù)命令選擇sbit LCD_RW = P2^1 ; //讀寫控制sbit LCD_EN = P2^2 ; //使能控制//DS1302控制端口sbit DS_CLK = P2^6 ; //串行時(shí)鐘sbit DS_RST = P2^5 ; //復(fù)位sbit DS_IO = P2^7 ; //串行數(shù)據(jù)/********************************************************************************************************* 數(shù) 據(jù) 結(jié) 構(gòu) 定 義*********************************************************************************************************/typedef struct{ u8 Second; //秒 u8 Minute; //分 u8 Hour; //時(shí) u8 Date; //日 u8 Month; //月 u8 Year; //年}DS1302_Data;DS1302_Data Time;/********************************************************Name :delay_msFunction :毫秒延時(shí)函數(shù)Paramater : ms:延時(shí)的時(shí)間Return :None********************************************************/void delay_ms( u16 ms ){ u8 i ; while( --ms ) for( i=0; i<110; i++ ) ;}/********************************************************************************************************* LCD1602 顯 示 程 序*********************************************************************************************************//********************************************************Name :LCD_Write_CommandFunction :LCD寫入命令Paramater : Command:命令代碼Return :None********************************************************/void LCD_Write_Command( u8 Command ){ LCD_RS = 0 ; //命令模式 LCD_RW = 0 ; //寫模式 LCD_EN = 0 ; //使能復(fù)位 LCD_DB = Command ; //發(fā)送數(shù)據(jù)到P0總線 delay_ms( 5 ) ; LCD_EN = 1 ; //使能拉高 delay_ms( 1 ) ; LCD_EN = 0 ; //下降沿?cái)?shù)據(jù)寫入 delay_ms( 1 ) ;}/********************************************************Name :LCD_Write_DataFunction :LCD寫入數(shù)據(jù)Paramater : Data:數(shù)據(jù)Return :None********************************************************/void LCD_Write_Data( u8 Data ){ LCD_RS = 1 ; //數(shù)據(jù)模式 LCD_RW = 0 ; //寫模式 LCD_EN = 0 ; //使能復(fù)位 LCD_DB = Data ; //發(fā)送數(shù)據(jù)到P0總線 delay_ms( 5 ) ; LCD_EN = 1 ; //使能拉高 delay_ms( 1 ) ; LCD_EN = 0 ; //下降沿?cái)?shù)據(jù)寫入 delay_ms( 1 ) ;}/********************************************************Name :LCD_InitFunction :LCD初始化Paramater :NoneReturn :None********************************************************/void LCD_Init(){ LCD_Write_Command( 0x38 ) ; //8位總線寬度+顯示2行+每個(gè)字符占用5×10的點(diǎn)陣 LCD_Write_Command( 0x0C ) ; //開啟顯示+關(guān)閉光標(biāo)+關(guān)閉光標(biāo)顯示 LCD_Write_Command( 0x06 ) ; //光標(biāo)右移+寫入數(shù)據(jù)后顯示屏不移動(dòng) LCD_Write_Command( 0x01 ) ; //清屏}/********************************************************Name :LCD_Show_StringFunction :LCD顯示字符串Paramater :NoneReturn :None********************************************************/void LCD_Show_String( u8 x, u8 y, u8 *str ){ u8 Address ; //計(jì)算坐標(biāo) switch( y ) { case 0: Address=0x80+x ; //第一行數(shù)據(jù)地址 break; case 1: Address=0xC0+x ; //第二行數(shù)據(jù)地址 break; default: break; } //寫入數(shù)據(jù) LCD_Write_Command( Address ) ; //設(shè)置寫入地址 while( *str!='\0' ) { LCD_Write_Data( *str ) ; //寫入數(shù)據(jù) str ++ ; //指針地址累加 }}/********************************************************************************************************* DS1302 時(shí) 鐘 程 序*********************************************************************************************************//********************************************************Name :DS1302_Write_ByteFunction :DS1302寫入字節(jié)Paramater : Byte:寫入的字節(jié)Return :None********************************************************/void DS1302_Write_Byte( u8 Byte ){ u8 i ; for( i=0; i<8; i++ ) { if( ( Byte&0x01 )==0x01 ) //判斷最低位是1 DS_IO = 1 ; //數(shù)據(jù)線拉高發(fā)送1 else DS_IO = 0 ; //數(shù)據(jù)線拉低發(fā)送0 Byte >>= 1 ; //數(shù)據(jù)右移一個(gè)位 DS_CLK = 0 ; //時(shí)鐘線復(fù)位 DS_CLK = 1 ; //時(shí)鐘線拉高產(chǎn)生上升沿 }}/********************************************************Name :DS1302_Read_ByteFunction :DS1302讀取字節(jié)Paramater :NoneReturn :讀取的字節(jié)********************************************************/u8 DS1302_Read_Byte(){ u8 i, Byte ; DS_CLK = 1 ; //時(shí)鐘線拉高 Byte = 0 ; for( i=0; i<8; i++ ) { Byte >>= 1 ; //數(shù)據(jù)右移一個(gè)位 DS_CLK = 0 ; //時(shí)鐘線拉低產(chǎn)生下降沿 if( DS_IO==1 ) //判斷數(shù)據(jù)線上的值為1 Byte |= 0x80 ; //字節(jié)寫入1 DS_CLK = 1 ; //時(shí)鐘線拉高 } return Byte ;}/********************************************************Name :DS1302_Read_TimeFunction :DS1302讀取時(shí)間Paramater :NoneReturn :None********************************************************/void DS1302_Read_Time(){ u8 i, Byte ; u8 Read_Address[] = { 0x81, 0x83, 0x85, 0x87, 0x89, 0x8D } ; //寄存器地址 for( i=0; i<6; i++ ) { DS_RST = 0 ; //復(fù)位 DS_CLK = 0 ; //時(shí)鐘線復(fù)位 DS_RST = 1 ; //停止復(fù)位 DS1302_Write_Byte( Read_Address[ i ] ) ; //發(fā)送地址 Byte = DS1302_Read_Byte() ; //讀取數(shù)據(jù) switch( i ) { case 0: Time.Second = ( ( Byte&0xF0 )>>4 )*10+( Byte&0x0F ) ; //計(jì)算秒 break ; case 1: Time.Minute = ( ( Byte&0xF0 )>>4 )*10+( Byte&0x0F ) ; //計(jì)算分 break ; case 2: Time.Hour = ( ( Byte&0xF0 )>>4 )*10+( Byte&0x0F ) ; //計(jì)算時(shí) break ; case 3: Time.Date = ( ( Byte&0xF0 )>>4 )*10+( Byte&0x0F ) ; //計(jì)算日 break ; case 4: Time.Month = ( ( Byte&0xF0 )>>4 )*10+( Byte&0x0F ) ; //計(jì)算月 break ; case 5: Time.Year = ( ( Byte&0xF0 )>>4 )*10+( Byte&0x0F ) ; //計(jì)算年 break ; } }}/********************************************************************************************************* 主 函 數(shù)*********************************************************************************************************/void main(){ LCD_Init() ; LCD_Show_String( 0, 0, " 2000 - 00 - 00 " ) ; LCD_Show_String( 0, 1, " 00 : 00 : 00 " ) ; while( 1 ) { DS1302_Read_Time() ; //DS1302讀取時(shí)間 //顯示年 LCD_Write_Command( 0x80+3 ) ; //寫入顯示地址 LCD_Write_Data( 0x30+Time.Year/10 ) ; //寫入十位 LCD_Write_Data( 0x30+Time.Year%10 ) ; //寫入個(gè)位 //顯示月 LCD_Write_Command( 0x80+8 ) ; //寫入顯示地址 LCD_Write_Data( 0x30+Time.Month/10 ) ; //寫入十位 LCD_Write_Data( 0x30+Time.Month%10 ) ; //寫入個(gè)位 //顯示日 LCD_Write_Command( 0x80+13 ) ; //寫入顯示地址 LCD_Write_Data( 0x30+Time.Date/10 ) ; //寫入十位 LCD_Write_Data( 0x30+Time.Date%10 ) ; //寫入個(gè)位 //顯示時(shí) LCD_Write_Command( 0xC0+2 ) ; //寫入顯示地址 LCD_Write_Data( 0x30+Time.Hour/10 ) ; //寫入十位 LCD_Write_Data( 0x30+Time.Hour%10 ) ; //寫入個(gè)位 //顯示分 LCD_Write_Command( 0xC0+7 ) ; //寫入顯示地址 LCD_Write_Data( 0x30+Time.Minute/10 ) ; //寫入十位 LCD_Write_Data( 0x30+Time.Minute%10 ) ; //寫入個(gè)位 //顯示秒 LCD_Write_Command( 0xC0+12 ) ; //寫入顯示地址 LCD_Write_Data( 0x30+Time.Second/10 ) ; //寫入十位 LCD_Write_Data( 0x30+Time.Second%10 ) ; //寫入個(gè)位 }}總結(jié)
以上是生活随笔為你收集整理的51单片机基本刷屏测试实验_51单片机开发基础8——实时时钟实验的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何正确使用厨房炊具?
- 下一篇: 珠山瓷砖批发市场在哪里?