版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領
文檔簡介
1、<p><b> 摘要: </b></p><p> 近年來,隨著計算機技術(shù)及集成電路技術(shù)的發(fā)展,嵌入式技術(shù)日漸普及,在通訊、網(wǎng)絡、工控、醫(yī)療、電子等領域發(fā)揮著越來越重要的作用。</p><p> I2C是一種較為常用的串行接口標準,具有協(xié)議完善、支持芯片較多和占用I/O線少等優(yōu)點,主要在服務器管理中使用,可隨時監(jiān)控內(nèi)存、硬盤、網(wǎng)絡、系統(tǒng)溫度等多個參數(shù)
2、,增加了系統(tǒng)的安全性,便于管理。目前比較流行的串行擴展總線中,I2C總線以其嚴格的規(guī)范和眾多支持I2C接口的外圍器件而獲得了廣泛的應用。</p><p> 因此,我們對I2C接口進行了必要的探究,通過UART(異步串行接口)發(fā)送字節(jié)數(shù)據(jù),然后利用I2C串行接口對外部存儲器24C01進行讀寫,最后通過顯示器LCD1602顯示,正確驗證了I2C的通訊功能。</p><p> 關鍵字:
3、 I2C串行接口 UART 外部存儲器 顯示器LCD1602</p><p><b> 正文:</b></p><p> 設計原理與總體方案:</p><p> 本設計包含三個部分:UART發(fā)送數(shù)據(jù)部分、I2C讀寫存儲器部分、LCD1602顯示部分,下面分別介紹各部分原理。</p><p>&
4、lt;b> 異步串行接口</b></p><p> UART是異步串行接口,LPC2000系列ARM7包含2個UART:UART0和UART1,UART0只有TXD(串行輸出)和RXD(串行輸入)兩個引腳,只需設置相應的寄存器即可實現(xiàn)基本的數(shù)據(jù)收發(fā)功能。</p><p> 1.2.I2C總線基本原理</p><p> I2C總線系統(tǒng)是由SC
5、L(串行時鐘)和SDA(串行數(shù)據(jù))兩根總線構(gòu)成的,該總線有嚴格的時序要求??偩€工作時, 由串行時鐘線SCL傳送時鐘脈沖, 由串行數(shù)據(jù)線SDA 傳送數(shù)據(jù)。總線協(xié)議規(guī)定, 各主節(jié)點進行通信時都要有起始、結(jié)束、發(fā)送數(shù)據(jù)和應答信號,這些信號都是通信過程中的基本單元??偩€傳送是以幀為單位進行的, 每當發(fā)送完1 個字節(jié)后, 接收節(jié)點就相應給一應答信號。</p><p> 1.2.1. I2C總線數(shù)據(jù)傳輸中的接受/發(fā)送器&l
6、t;/p><p> I2C總線系統(tǒng)中發(fā)送器與接收器來表明數(shù)據(jù)傳輸?shù)陌l(fā)送方與接收方。</p><p> 發(fā)送器:總線上發(fā)送數(shù)據(jù)的器件。</p><p> 接收器:總線上接收數(shù)據(jù)的器件。</p><p> 1.2.2. I2C總線上數(shù)據(jù)的有效性</p><p> I2C總線數(shù)據(jù)傳輸時,在時鐘線高電平期間數(shù)據(jù)線上必須保
7、持有穩(wěn)定的邏輯電平的狀態(tài),高電平為數(shù)據(jù)1,低電平為數(shù)據(jù)0。只有在時鐘線為低電平時,才允許數(shù)據(jù)線上的電平狀態(tài)變化,如圖1所示。</p><p> 圖1 I2C總線數(shù)據(jù)位傳送</p><p> 1.2.3. I2C總線數(shù)據(jù)傳送的起始、停止與應答</p><p> I2C總線可以構(gòu)成多主數(shù)據(jù)傳送系統(tǒng),但只有帶CPU的器件可以成為主器件。 主器件發(fā)送時鐘、啟動位、數(shù)
8、據(jù)工作方式,從器件則接收時鐘及數(shù)據(jù)工作方式,接收或發(fā)送則根據(jù)數(shù)據(jù)的傳送方向決定。I2C總線上數(shù)據(jù)傳送時的啟動、結(jié)束和有效狀態(tài)都由SDA、SCL的電平狀態(tài)決定,在I2C總線規(guī)程中啟動和停止條件規(guī)定如下:</p><p> 啟動條件:在SCL為高電平時,SDA出現(xiàn)一個下降沿則啟動I2C總線。 </p><p> 停止條件:在SCL為高電平時,SDA出現(xiàn)一個上升沿則停止使用I2C總線。
9、 </p><p> 啟動條件后總線為“忙”,在結(jié)束信號過后的一定時間總線被認為是“空閑”的。在啟動和停止條件之間可轉(zhuǎn)送的數(shù)據(jù)不受限制,但每個字節(jié)必須為8位。首先傳送最高位,采用串行傳送方式,但在每個字節(jié)之后必須跟一個響應位。主器件收發(fā)每個字節(jié)后產(chǎn)生一個時鐘應答脈沖,在這期間,發(fā)送器必須保證 SDA為高,由接收器將SDA拉低,稱為應答信號(ACK)。主器件為接收器時,在接收了最后一個字節(jié)之后不發(fā)應答信號,也稱為
10、非應答信號(NOT ACK)。 當從器件不能再接收另外的字節(jié)時也會出現(xiàn)在種情況。I2C總線的數(shù)據(jù)傳送如圖2所示。</p><p> 圖2 I2C總線上的信號</p><p> 1.2.4. I2C總線數(shù)據(jù)傳送</p><p> I2C總線上連接的每個器件都有自己唯一確定的地址,啟動條件后主機發(fā)送的第一個字節(jié)就是被讀寫的從器件地址,其中第8位為方向位,“0”(
11、W)表示主器件發(fā)送,“1”(R)表示主器件接收??偩€上每個器件在啟動條件后都把自己的地址與前7位相比較,如相同則器件被選中, 產(chǎn)生應答,并根據(jù)讀寫位決定在數(shù)據(jù)傳送中是接收還是發(fā)送。如圖所示為主器件發(fā)送和接收數(shù)據(jù)的過程,無論是主發(fā)、主收還是從發(fā)、從收都是由主器件控制。</p><p> 圖3主器件發(fā)送和接收數(shù)據(jù)的過程</p><p> 在主發(fā)送方式下,由主器件先發(fā)出啟動信號(S),接著發(fā)
12、從器件的7 位地址(SLA)和主器件發(fā)送的方向位“0”(W),即這個字節(jié)為SLA+W。被尋址的從器件在收到這個字節(jié)后,返回一個應答信號(A),在確定主從應答正常后,主器件向從器件發(fā)送字節(jié)數(shù)據(jù),從器件每收到一個字節(jié)數(shù)據(jù)后都要返回一個應答信號,直到全部數(shù)據(jù)都發(fā)送完為止。在主接收方式下,主器件先發(fā)出啟動信號(S),接著發(fā)從器件的7位地址(SLA)和表明主器件接收的方向位“1”(R),即這個字節(jié)為SLA+R。在發(fā)送完這個字節(jié)后,SCL繼續(xù)輸出時
13、鐘,通過SDA接收從器件發(fā)來的串行數(shù)據(jù)。主器件每接收到一個字節(jié)后都要發(fā)送一個應答信號(A),當全部數(shù)據(jù)都發(fā)送或接收完畢后,主器件應發(fā)出停止信號(P)。</p><p> 1.3.LCD1602液晶顯示驅(qū)動原理</p><p> 1.3.1. LCD1602的引腳功能</p><p> LCD1602液晶顯示器的引腳如圖4所示,其引腳功能如下:</p>
14、;<p> (1)RS:數(shù)據(jù)和指令選擇控制端,RS=0命令狀態(tài);RS=1數(shù)據(jù)</p><p> ?。?)R/W:讀寫控制線,R/W=0寫操作;R/W=1讀操作</p><p> ?。?)A:背光控制正電源 (4) K:背光控制地</p><p> ?。?)E:數(shù)據(jù)讀寫操作控制位,E線向LCD模塊發(fā)送一個脈沖,LCD模塊與單片機間將進行一次數(shù)
15、據(jù)交換</p><p> ?。?)DB0~DB7:數(shù)據(jù)線,可以用8位連接,也可以只用高4位連接,節(jié)約單片機資源。</p><p> (7)VDD:電源端 VEE:亮度控制端(1-5V) VSS:接地端</p><p> 圖4 LCD1602液晶顯示器引腳圖</p><p> 1.3.2.LCD1602控制命令&
16、lt;/p><p> 表1 LCD控制命令</p><p> 指令3:光標和顯示模式設置。I/D:光標移動方向,高電平右移,低電平左移。S:屏幕上所有文字是否左移或者右移,高電平表示有效,低電平則無效。</p><p> 指令4:顯示開關控制。D:控制整體顯示的開與關,高電平表示開顯示,低電平表示關顯示。C:控制光標的開與關,高電平表示有光標,低電平表示無光標。
17、B:控制光標是否閃爍,高電平閃爍,低電平不閃爍。</p><p> 指令 6:功能設置命令。DL:高電平時為4位總線,低電平時為8位總線。N:低電平時為單行顯示,高電平時為雙行顯示。F:低電平時顯示5×7的點陣字符,高電平時顯示5×10的點陣字符。</p><p> 指令9:讀忙信號和光標地址。BF:為忙標志,高電平表示忙,此時模塊不能接受命令或者數(shù)據(jù),如果為低電平
18、表示不忙。</p><p><b> 軟件設計</b></p><p> 2.1流程圖及部分初始化說明</p><p><b> 圖5 主程序流程圖</b></p><p> 圖6 lcd初始化及顯示函數(shù)流程圖</p><p> 圖7 UART接受數(shù)據(jù)流程圖&l
19、t;/p><p> 圖8 I2C讀寫24C01流程圖</p><p><b> 仿真設計</b></p><p><b> 仿真電路圖</b></p><p><b> 圖9</b></p><p><b> 仿真結(jié)果圖</b&
20、gt;</p><p><b> 圖10</b></p><p><b> 調(diào)試</b></p><p> 問題1:在進行仿真調(diào)試時,出現(xiàn)了發(fā)送亂碼的現(xiàn)象(如圖11)。</p><p> 原因: ADS調(diào)試時鐘頻率與proteus仿真設置頻率不一致。 </p><p&
21、gt; 問題2:在進行仿真調(diào)試時,I2C讀數(shù)據(jù)時,出現(xiàn)非應答位導致數(shù)據(jù)不能正常讀取(如圖12)。</p><p> 原因: ADS程序?qū)懲?4C01后沒有等待總線恢復,添加延時即可。</p><p> 圖11 調(diào)試出現(xiàn)亂碼情況</p><p> 圖12 讀取數(shù)據(jù)時出現(xiàn)非應答位情況</p><p><b> 結(jié)束語</
22、b></p><p> 本次課程設計是ARM嵌入式系統(tǒng)課程設計,是在我們學習了《ARM嵌入式系統(tǒng)》的基礎上的進一步實踐與拓展,該課程設計對各方面的知識進行了融合,具有一定的挑戰(zhàn)性。我們查閱了很多資料,并且借鑒了很多不同的想法,在老師的幫助下,我們順利完成了課程設計,對嵌入式系統(tǒng)的硬件、軟件有了更為深入的了解,為以后進行軟硬件設計打下了良好的基礎。</p><p><b>
23、 參考文獻</b></p><p> [1]周立功主編.ARM嵌入式系統(tǒng)基礎教程[M].北京航空航天大學出版社,2008。</p><p> [2]吳明輝,等.基于ARM的嵌入式系統(tǒng)開發(fā)與應用[M].北京:人民郵電出版社,2004。</p><p><b> 附錄:主程序</b></p><p>
24、#include "config.h"</p><p> #include "LCD1602.h"</p><p> #include "UART.h"</p><p> #include "I2C.h"</p><p> #define Num 1<
25、;/p><p> uint8 i=0,j=0,k=0, Addr=0;</p><p> uint8 rcv_data[Num],read_data[Num],display_data[16];</p><p> int main()</p><p><b> {</b></p><p>
26、 PINSEL0 = 0x55; //設置p0.0-p0.1為UART0,p0.2-p0.3為I2C</p><p> PINSEL1 = 0; //設置p0.16-p0.24為GPIO</p><p> IODIR = 0x7ff<<16; //p0.16-p0.24為輸出</p><p> lcd_init();<
27、/p><p> UART0_init();</p><p> I2C_init(100000);</p><p><b> while(1)</b></p><p><b> { </b></p><p> UART0_RcvStr(rcv_data,Num);<
28、;/p><p> WriteC01(Addr,Num,rcv_data);</p><p> DelayMs(100);////////////</p><p> ReadC01(Addr,Num,read_data);</p><p><b> if(i<15)</b></p><p>
29、;<b> {</b></p><p> display_data[i++]=read_data[0];</p><p> display_data[i]='\0';</p><p><b> }</b></p><p><b> else</b>&l
30、t;/p><p><b> {</b></p><p> for(j=0;j<14;j++)</p><p><b> {</b></p><p> display_data[j]=display_data[j+1];</p><p> display_data[
31、14]=read_data[0];</p><p> display_data[15]='\0';</p><p><b> }</b></p><p><b> }</b></p><p> DisText(0x80,display_data); Addr++;</
32、p><p><b> }</b></p><p> return(0);</p><p><b> }</b></p><p> /****************************************************************************</p
33、><p> * File: lcd1602.h</p><p> * 功能:向LCD輸出字符(一行只能顯示16個字符)</p><p> ****************************************************************************/</p><p> #include &quo
34、t;config.h"</p><p> #define rs (1<<24)</p><p> #define rw (1<<25)</p><p> #define en (1<<26)</p><p> #define busy (1<<23)</p>&l
35、t;p><b> //檢查總線是否忙</b></p><p> void ChkBusy()</p><p><b> {</b></p><p> IODIR=0x700<<16;</p><p><b> while(1)</b></p&g
36、t;<p><b> {</b></p><p><b> IOCLR=rs;</b></p><p><b> IOSET=rw;</b></p><p><b> IOSET=en;</b></p><p> if(!(IOPI
37、N & busy))break;</p><p><b> IOCLR=en;</b></p><p><b> }</b></p><p> IODIR=0x7ff<<16;</p><p><b> }</b></p><p&
38、gt;<b> //寫函數(shù)</b></p><p> void WrOp(uint8 dat)</p><p><b> {</b></p><p> ChkBusy();</p><p> IOCLR=rs; // RS=0,RW=0</p><p>
39、 IOCLR=rw; </p><p> IOCLR=(0xff<<16); </p><p> IOSET=(dat<<16);//送數(shù)</p><p><b> IOSET=en;</b></p><p><b> IOCLR=en;</b><
40、/p><p><b> }</b></p><p><b> //寫數(shù)據(jù)函數(shù)</b></p><p> void WrDat(uint8 dat)</p><p><b> {</b></p><p> ChkBusy();</p>
41、<p> IOSET=rs; // RS=1,RW=0</p><p><b> IOCLR=rw;</b></p><p> IOCLR=(0xff<<16); </p><p> IOSET=(dat<<16);//送數(shù)</p><p><b>
42、; IOSET=en;</b></p><p><b> IOCLR=en;</b></p><p><b> }</b></p><p> //lcd初始化函數(shù)</p><p> void lcd_init(void)</p><p><b>
43、; {</b></p><p> WrOp(0x38);// 8-bit mode - 2 line.</p><p> WrOp(0x06);//光標加1</p><p> WrOp(0x0C);//開顯示</p><p><b> }</b></p><p&
44、gt;<b> //顯示文本函數(shù)</b></p><p> void DisText(uint8 addr,uint8 *p)</p><p><b> {</b></p><p> WrOp(addr);</p><p> while(*p !='\0')WrDat(*(
45、p++));</p><p><b> }</b></p><p> /****************************************************************************</p><p> * File: UART.h</p><p> * 功能:通過串口輸入
46、字節(jié)數(shù)據(jù)。</p><p> ****************************************************************************/</p><p> #include "config.h"</p><p> #define UART_BPS9600/* 定義通訊波特率 */&l
47、t;/p><p><b> //初始化串口0。</b></p><p> void UART0_init(void)</p><p><b> { </b></p><p> uint16 Fdiv;</p><p> U0LCR = 0x83;// D
48、LAB = 1,可設置波特率</p><p> Fdiv = (Fpclk / 16) / UART_BPS; // 設置波特率</p><p> U0DLM = Fdiv / 256;</p><p> U0DLL = Fdiv % 256;</p><p> U0LCR = 0x03;</p&g
49、t;<p><b> }</b></p><p> //從串口接收 1 字節(jié)數(shù)據(jù),使用查詢方式接收。</p><p> uint8 UART0_RcvByte (void)</p><p><b> { </b></p><p> uint8 rcv_dat;</p
50、><p> while ((U0LSR & 0x01) == 0); // 等待接收標志置位</p><p> rcv_dat = U0RBR; </p><p> return (rcv_dat);</p><p><b> }</b></p><p> //從串口接收字符串
51、。</p><p> void UART0_RcvStr (uint8 *s, uint32 n)</p><p><b> { </b></p><p> for ( ; n>0; n--)</p><p><b> { </b></p><p> *s+
52、+ = UART0_RcvByte();</p><p><b> }</b></p><p><b> }</b></p><p> /****************************************************************************</p>&l
53、t;p> * File: I2C.h</p><p> * 功能:讀寫外部存儲器24C01。</p><p> ****************************************************************************/</p><p> #include "config.h"</
54、p><p> #define Write_C01 0xA0 </p><p> #define Read_C01 0xA1 </p><p> #define AA (1<<2) </p><p> #define SI (1<<3) </p><p> #def
55、ine STO (1<<4) </p><p> #define STA (1<<5) </p><p> #define I2CEN (1<<6)</p><p> #define lastbyte 1</p><p><b> //I2C初始化</b>&
56、lt;/p><p> void I2C_init(uint32 fi2c)</p><p><b> {</b></p><p> if(fi2c>400000) fi2c = 400000;</p><p> PINSEL0 = (PINSEL0 & 0xffffff0f) | 0x50;</p
57、><p> I2SCLH = (Fpclk / fi2c+1) / 2;</p><p> I2SCLL = (Fpclk / fi2c) / 2;</p><p> I2CONCLR = STA | SI | AA;</p><p> I2CONSET = I2CEN; </p><p&
58、gt;<b> }</b></p><p><b> //發(fā)送起始信號</b></p><p> void I2C_Start(void)</p><p><b> {</b></p><p> I2CONSET = STA; &l
59、t;/p><p> while(I2STAT!=0x08); </p><p> I2CONCLR = STA; </p><p><b> }</b></p><p><b> //發(fā)送停止信號 </b></p><p>
60、 void I2C_Stop(void)</p><p><b> {</b></p><p> I2CONSET = STO; </p><p> I2CONCLR = SI; </p><p><b> }</b>
61、</p><p><b> //寫一字節(jié)數(shù)據(jù)</b></p><p> void WriteByte(uint8 data)</p><p><b> {</b></p><p> I2DAT = data;</p><p> I2CONCLR = SI;
62、 </p><p><b> }</b></p><p><b> //寫地址</b></p><p> void WriteAddr(uint8 Mode) </p><p><b> {</b></p><p> Wri
63、teByte(Mode);</p><p> if(Mode==Read_C01) </p><p><b> {</b></p><p> while(I2STAT!=0x40); </p><p><b> }</b></p><p><b&g
64、t; else </b></p><p><b> {</b></p><p> while(I2STAT!=0x18); </p><p><b> }</b></p><p><b> }</b></p><p>
65、;<b> //寫數(shù)據(jù) </b></p><p> void WriteData(uint8 data)</p><p><b> {</b></p><p> WriteByte(data);</p><p> while(I2STAT!=0x28); </p>
66、;<p><b> }</b></p><p><b> //讀字節(jié)數(shù)據(jù)</b></p><p> uint8 ReadByte(uint8 last) </p><p><b> {</b></p><p
67、><b> if(last) </b></p><p><b> {</b></p><p> I2CONCLR=AA;</p><p> I2CONCLR=SI; </p><p> while(I2STAT!=0x58); &
68、lt;/p><p><b> }</b></p><p><b> else</b></p><p><b> {</b></p><p> I2CONSET=AA; </p><p> I2CONCLR=SI;
69、 </p><p> while(I2STAT!=0x50); </p><p><b> }</b></p><p> return(I2DAT);</p><p><b> }</b></p><p><b&g
70、t; //寫24C01</b></p><p> void WriteC01(uint8 StartAddr,uint8 CountByte,uint8 *i2c_buf)</p><p><b> {</b></p><p> uint8 i=0;</p><p> I2C_Start(); &l
71、t;/p><p> WriteAddr(Write_C01); </p><p> WriteData(StartAddr); </p><p> for(i=0;i<CountByte;i++)</p><p><b> {</b></p>&l
72、t;p> WriteData(i2c_buf[i]);</p><p><b> }</b></p><p> I2C_Stop();</p><p><b> }</b></p><p><b> //讀24C01</b></p><p&g
73、t; void ReadC01(uint8 StartAddr,uint8 CountByte,uint8 *i2c_buf)</p><p><b> {</b></p><p> uint8 i=0;</p><p><b> //設置讀指針</b></p><p> I2C_Star
74、t(); </p><p> WriteAddr(Write_C01); </p><p> WriteData(StartAddr);</p><p> I2C_Stop(); </p><p><b> //開始讀數(shù)據(jù)</b></p><p> I2C_Start(); <
75、/p><p> WriteAddr(Read_C01);</p><p> for(i=0;i<CountByte-1;i++)</p><p><b> {</b></p><p> i2c_buf[i]=ReadByte(!lastbyte);</p><p><b>
76、}</b></p><p> i2c_buf[i]=ReadByte(lastbyte);</p><p> I2C_Stop(); </p><p><b> }</b></p><p><b> //延時函數(shù) </b></p><p> void
77、 DelayMs(uint8 dly)</p><p><b> { </b></p><p><b> uint8 i;</b></p><p> for(; dly>0; dly--)</p><p> for(i=0; i<1000; i++);</p>&
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- arm課程設計--基于arm的i2c接口設計
- 基于fpga的i2c接口程序?qū)崿F(xiàn)課程設計
- 嵌入式課程設計---i2c 總線接口設計
- 基于fpga課程設計--基于fpga的i2c接口程序?qū)崿F(xiàn)
- 片上i2c總線設計
- 基于fpga的i2c串行總線接口電路設計
- 片上I2C總線設計.pdf
- 基于dsp與cpld的i2c總線接口的設計與實現(xiàn)
- i2c與smbus的區(qū)別
- i2c總線之(二)---時序
- 同步串行通訊I2C總線的設計.pdf
- 機頂盒內(nèi)的I2C主控制器設計與I2C從設備集成方法.pdf
- 基于stm32f10的i2c接口通信設計【開題報告】
- i2c芯片的驅(qū)動程序
- 基于I2C總線接口的低功耗10bit ADC的設計.pdf
- 基于I2C總線的模塊化測試電源設計.pdf
- 集成I2C總線接口的白光LED驅(qū)動芯片的研究與設計.pdf
- 開題報告--基于i2c總線的ic卡讀寫器設計
- 基于I2C的HPC人機交互系統(tǒng)設計與實現(xiàn).pdf
- I2C總線在SOC系統(tǒng)中的設計與實現(xiàn).pdf
評論
0/150
提交評論