?? 打印文章.htm
字號:
<TD align=middle width="17%">1</TD>
<TD align=middle width="17%">0</TD>
<TD align=middle width="17%">176</TD></TR>
<TR class=main>
<TD align=middle width="16%">1</TD>
<TD align=middle width="16%">0</TD>
<TD align=middle width="17%">1</TD>
<TD align=middle width="17%">1</TD>
<TD align=middle width="17%">1</TD>
<TD align=middle width="17%">177</TD></TR>
<TR class=main>
<TD align=middle width="16%">0</TD>
<TD align=middle width="16%">1</TD>
<TD align=middle width="17%">1</TD>
<TD align=middle width="17%">1</TD>
<TD align=middle width="17%">0</TD>
<TD align=middle width="17%">376</TD></TR>
<TR class=main>
<TD align=middle width="16%">0</TD>
<TD align=middle width="16%">1</TD>
<TD align=middle width="17%">1</TD>
<TD align=middle width="17%">1</TD>
<TD align=middle width="17%">1</TD>
<TD align=middle width="17%">377</TD></TR>
<TR class=main>
<TD align=middle width="16%">0</TD>
<TD align=middle width="16%">1</TD>
<TD align=middle width="17%">*</TD>
<TD align=middle width="17%">*</TD>
<TD align=middle width="17%">*</TD>
<TD align=middle width="17%">未用</TD></TR></TBODY></TABLE>
<P
style="TEXT-INDENT: 30px">·數據寄存器(170R/W):這是一個16位PIO數據寄存器,用于對扇區的讀、寫和格式化操作。MCU通過該寄存器向硬盤控制寄存器寫入或從硬盤控制器讀出扇區緩沖區的數據。</P>
<P
style="TEXT-INDENT: 30px">·錯誤寄存器(171R):該寄存器是一個8位的寄存器,它反映控制寄存器在診斷方式或操作方式下的錯誤原因。</P>
<P
style="TEXT-INDENT: 30px">·扇區數寄存器(172R/W):它記錄讀、寫命令的扇區數。當多扇區傳輸時,每完成一個扇區操作,該寄存器自動減1,直至為0。如果初值為0,則表示256;如果有錯誤生,該寄存器包含已經操作成功的扇區數。</P>
<P
style="TEXT-INDENT: 30px">·扇區號寄存器(173R/W):它記錄讀、寫和校驗命令指令起始扇區號。本文用LBA模式。該寄存器記錄邏輯扇區的0字節。</P>
<P style="TEXT-INDENT: 30px">·柱面號寄存器(174 175
R/W):它記錄讀、寫、校驗、尋址和格式化命令指定的柱面號,在LBA尋址方式下,這2個寄存器包含起始扇區的1和2字節。</P>
<P
style="TEXT-INDENT: 30px">·驅動器/磁頭寄存器(176R/W):它記錄讀、寫、校驗、尋道和格式化命令指定的驅動器號、磁頭號和尋址方式。在ATA/ATAPI-4中其定義如表2所示。<BR><BR><B>表2
驅動器/磁頭寄存器在ATA/ATAPI-4中的定義</B></P>
<TABLE borderColorDark=#ffffff width="100%" borderColorLight=#000000
border=1>
<TBODY>
<TR class=main>
<TD align=middle width="12%">D7</TD>
<TD align=middle width="12%">D6</TD>
<TD align=middle width="12%">D5</TD>
<TD align=middle width="12%">D4</TD>
<TD align=middle width="13%">D3</TD>
<TD align=middle width="13%">D2</TD>
<TD align=middle width="13%">D1</TD>
<TD align=middle width="13%">D0</TD></TR>
<TR class=main>
<TD align=middle width="12%">1</TD>
<TD align=middle width="12%">L</TD>
<TD align=middle width="12%">1</TD>
<TD align=middle width="12%">DEV</TD>
<TD align=middle width="13%">HS3</TD>
<TD align=middle width="13%">HS2</TD>
<TD align=middle width="13%">HS1</TD>
<TD align=middle width="13%">HS0</TD></TR></TBODY></TABLE>
<P style="TEXT-INDENT: 30px">HS0~HS3(磁頭選擇):在LBA方式中,是邏輯扇區的高4位。</P>
<P style="TEXT-INDENT: 30px">DEV驅動器選擇:0選擇主驅動器,1選擇從驅動器。</P>
<P style="TEXT-INDENT: 30px">L(LBA方式):L=1,置驅動器為LBA模式;L=0,置驅動器為CHS模式。</P>
<P style="TEXT-INDENT: 30px">·狀態寄存器(177
R);反映了硬盤執行命令后的狀態。讀該寄存器清除中斷請求信號,為避免清除中斷,可以讀輔助狀態寄存器376h。這兩個寄存器的內容完全一樣。在ATA/ATAPI-4中其定義如表3所示。</P>
<P style="TEXT-INDENT: 30px">BSY:驅動器忙。</P>
<P style="TEXT-INDENT: 30px">DRDY:驅動器準備好。</P>
<P style="TEXT-INDENT: 30px">DRQ:請求服務,驅動器請求通過寄存器與處理器交換一個字節數據。</P>
<P style="TEXT-INDENT: 30px">ERR:命令執行錯誤。</P>
<P style="TEXT-INDENT: 30px">3.2 硬盤PIO方式下特定區域多扇區讀的操作</P>
<P
style="TEXT-INDENT: 30px">如果想從硬盤的特定扇區讀出碼流信息,首先主機(C8051F015)要對驅動器/磁頭寄存器、柱面號寄存器、扇區號寄存器、扇區數寄存器設置參數。完畢后要等待至少400ns才能去讀狀態寄存器的參數判斷以上設置是否有效。硬盤接收命令后置BSY=1,并開始執行命令。硬盤如果準備好傳送數據包,就置DRQ=1,同時清零BSY。當機循環讀狀態寄存器或輔助狀態寄存器判斷BSY=0&DRQ=1,一旦硬盤狀態符合要求,主機寫參數0x80(128扇區)到數據寄存器(0x170),并寫0x20(PIO讀)到命令寄存器(0x177),表示要求讀出硬盤相應地址里的數據塊。硬盤判斷數據寄存器被置數后立即置BSY=1&DRQ=0。主機讀到置位信息后給硬盤讀時鐘,硬盤輸出數據直到數據包傳完為止。<BR><BR><B>表3
狀態寄存器在ATA/ATAPI-4中的定義</B></P>
<TABLE borderColorDark=#ffffff width="100%" borderColorLight=#000000
border=1>
<TBODY>
<TR class=main>
<TD align=middle width="12%">D7</TD>
<TD align=middle width="12%">D6</TD>
<TD align=middle width="12%">D5</TD>
<TD align=middle width="12%">D4</TD>
<TD align=middle width="13%">D3</TD>
<TD align=middle width="13%">D2</TD>
<TD align=middle width="13%">D1</TD>
<TD align=middle width="13%">D0</TD></TR>
<TR class=main>
<TD align=middle width="12%">BSY</TD>
<TD align=middle width="12%">DRDY</TD>
<TD align=middle width="12%">#</TD>
<TD align=middle width="12%">#</TD>
<TD align=middle width="13%">DRQ</TD>
<TD align=middle width="13%">obsolete</TD>
<TD align=middle width="13%">obsolete</TD>
<TD align=middle width="13%">ERR</TD></TR></TBODY></TABLE>
<P style="TEXT-INDENT: 0px"><B>4 系統設計方案</B></P>
<P style="TEXT-INDENT: 30px">4.1 系統硬件構成</P>
<P
style="TEXT-INDENT: 30px">基于8位微控制器的系統設計方案如圖2所示。主系統中以C8051F015為控制核心,C8051F015產生硬盤和FIFO的讀寫時序(為了避免硬盤寄存器參數也被寫入FIFO,在硬件上要把二者的讀寫時鐘分開。);硬盤輸出的16位數據分離低8位分別送入兩片64KB的FIFO緩存。數據經緩存后持續地輸出到CPLD,CPLD對16位數據流進行拆分,同時識別包同步和字節同步。這樣,原始的一路HDTV碼流就被分成3路輸送給解碼器解碼。主系統通過串行總線與前面板相連,采用通用單片機AT89C51為前面板的控制核心。AT89C51接收來自鍵盤的命令并在LCD上以文字和圖形的方式展現在用戶面前,同時通過串口通信,啟動主控制器執行命令。</P>
<P style="TEXT-INDENT: 30px">4.2 系統軟件設計</P>
<P style="TEXT-INDENT: 30px">4.2.1 存碼流部分</P>
<P
style="TEXT-INDENT: 30px">本系統沒有引入操作系統和文件格式,所以碼流文件存入硬盤時就不能按文件格式,而只能按二進制流的方式從PC機的碼流文件中讀出數據,再按同樣的方式寫入裸盤。為了解決碼流的總是,試圖調用BIOS中斷,讓BIOS的硬盤服務流程負責把INT13的讀寫請求轉化為ATA界面對硬盤的請求,并執行數據I/O傳輸的物理動作。但由于BIOS本身寄存器的限制,用它去訪問硬盤有8.4G容限的問題。如果想突破這個限制而用擴展的INT13,將是一個比較復雜的過程。可以利用PC機上的Secondary
IDE
Channel(0x170~0x177)作為硬盤寄存器的端口地址。在這個硬件平臺下,可以直接將fread()函數讀出的碼流按塊寫入目標硬盤,甚至不要求大多地考慮時序問題。</P>
<P style="TEXT-INDENT: 30px">4.2.2 讀碼流部分</P>
<P
style="TEXT-INDENT: 30px">這部分軟件是在上述硬件系統平臺上直接編程。系統在啟動硬盤前要等待串行中斷,接收由前面板發出的命令,再根據接收的數據信息具體決定應該播放哪幾個節目;隨后對硬盤、FIFO進行初始化,啟動CPLD,FIFO輸出數據時鐘信號,并讓硬盤按命令輸出數據流。數據在總線穩定的時間內給FIFO寫時鐘,以采集正確的碼流信息(這里強調時序)。FIFO有“半滿”(HF)標志,用HF去觸發中斷,有中斷請求,就讓硬盤輸出64KB的數據。如此循環,保證FIFO不空。當FIFO輸出第一個數據時,CPLD開始對數據流進行拆分,并按照HDTV碼流的格式標準對數據流進行判別(HDTV碼流188字節為一個包,每個包頭是0x47),即每計數1次,就輸出一個比特同步,每計數188次并識別下一個數為0x47,就輸出一個包同步。這部分程序流程如圖3。<BR></P>
<P style="TEXT-INDENT: 30px"><IMG alt=""
src="打印文章.files/200753113118986.gif" align=absMiddle border=0><BR><FONT
size=3> </FONT><SPAN class=main1>4.2.3 應用程序</P>
<P
style="TEXT-INDENT: 30px">系統設置硬盤寄存器參數時,首先調用SetMode()函數設定硬盤的IDLE狀態和自掉電功能,可以保證硬盤在不工作的情況下,磁頭會復位到“登陸區”;然后調用SetAdress()函數選擇對應的寄存器;接下來可以調用ReadSector()函數進行多扇區讀操作。以下是寄存器選擇子函數和多扇區讀子函數。</P>
<P style="TEXT-INDENT: 30px">//寄存器選擇子函數;</P>
<P style="TEXT-INDENT: 30px">void SetAddress(unsigned char cs,unsigned
char adr){</P>
<P style="TEXT-INDENT: 30px">DA0=((adr & 0x01)= =0x01;</P>
<P style="TEXT-INDENT: 30px">DA1=((adr & 0x02) = =0x02);</P>
<P style="TEXT-INDENT: 30px">DA2=((adr & 0x04) = =0x04);</P>
<P style="TEXT-INDENT: 30px">if(cs= =CTRL) {</P>
<P style="TEXT-INDENT: 30px">nCS1FX=1;</P>
<P style="TEXT-INDENT: 30px">nCS3FX=0;</P>
<P style="TEXT-INDENT: 30px">}else {</P>
<P style="TEXT-INDENT: 30px">nCS1FX=0;</P>
<P style="TEXT-INDENT: 30px">nCS3FX=1;</P>
<P style="TEXT-INDENT: 30px">}</P>
<P style="TEXT-INDENT: 30px">}</P>
<P style="TEXT-INDENT: 30px">//多扇區讀子函數:</P>
<P style="TEXT-INDENT: 30px">unsigned char ReadSector(unsigned long
point,unsigned char *Buffer){</P>
<P style="TEXT-INDENT: 30px">unsigned int i,k;</P>
<P style="TEXT-INDENT: 30px">WriteBYTE(CMD,6,0xe0); //LBA模式</P>
<P style="TEXT-INDENT: 30px">WriteBYTE(CMD,5,point>>16);
//LBA模式下的高16位地址</P>
<P style="TEXT-INDENT: 30px">WriteBYTE(CMD,4,point>>8);
//LBA模式下的高8位地址</P>
<P style="TEXT-INDENT: 30px">WriteBYTE(CMD,3,point); //LBA模式下的低8位地址</P>
<P style="TEXT-INDENT: 30px">WriteBYTE(CMD,2,0x80); //一次讀寫的扇區數</P>
<P style="TEXT-INDENT: 30px">//Issue read sector command...</P>
<P style="TEXT-INDENT: 30px">WriteBYTE(CMD,7,0x20); //0x20多為扇區讀命令</P>
<P style="TEXT-INDENT: 30px">Timer 10mSec=10000;</P>
<P style="TEXT-INDENT: 30px">while((ReadBYTE(CMD,7)&0x08)!=0x08
&& Timer 10mSec); //等待DRQ=1或者timeout</P>
<P style="TEXT-INDENT: 30px">if(Timer 10mSec= =0)return 0xFF;</P>
<P style="TEXT-INDENT: 30px">//Fetch the sector...</P>
<P style="TEXT-INDENT: 30px">LSBDATA=ALLINPUT;</P>
<P style="TEXT-INDENT: 30px">//Select address and activate CS</P>
<P style="TEXT-INDENT: 30px">SetAddress(CMD,0);</P>
<P style="TEXT-INDENT: 30px">for(k=0;k<0x80;k++)</P>
<P style="TEXT-INDENT: 30px">for(i=0;i<512;i+=2){ //一次讀兩字節</P>
<P style="TEXT-INDENT: 30px">nDIOR=0; //硬盤的讀時鐘</P>
<P style="TEXT-INDENT: 30px">WCK=1;</P>
<P style="TEXT-INDENT: 30px">WCK=0;</P>
<P style="TEXT-INDENT: 30px">nDIOR=1;</P>
<P style="TEXT-INDENT: 30px">}</P>
<P style="TEXT-INDENT: 30px">nCS1FX=1; //復位CS</P>
<P style="TEXT-INDENT: 30px">nCS3FX=1;</P>
<P style="TEXT-INDENT: 30px">return ReadBYTE(CMD,1); //返回錯誤寄存器的信息</P>
<P style="TEXT-INDENT: 30px">}</P>
<P
style="TEXT-INDENT: 30px">本文是“第三代碼流回放機研制”課題的一個重要組成部分。本方案利用微控制器對硬盤進行基于LBA模式下的讀寫操作(不用操作系統),硬軟件簡潔可靠,技術上也解決前期產品的兩個難題:</P>
<P style="TEXT-INDENT: 30px">(1)一些舊機器的BIOS不支持INT 13h
Extension,無法訪問8.4G以上硬盤空間;</P>
<P style="TEXT-INDENT: 30px">(2)WINDOWS操作系統不支持存儲1.2G以上碼流文件。</P>
<P style="TEXT-INDENT: 30px">將此系統逆向設計,能夠研發出適時錄制TS流和衛星節目的儀器。</P></SPAN>
<TABLE cellSpacing=0 cellPadding=0 width="98%" border=0>
<TBODY>
<TR>
<TD></TD></TR>
<TR>
<TD class=main_title_760 align=right height=20><A class=class
href="javascript:window.print()"><IMG alt=打印本文
src="打印文章.files/printpage.gif" align=absMiddle
border=0> 打印本文</A> <IMG alt=關閉窗口
src="打印文章.files/pageclose.gif" align=absMiddle border=0> <A
class=class href="javascript:window.close()">關閉窗口</A>
</TD></TR></TBODY></TABLE></TR></TBODY></TABLE></BODY></HTML>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -