1. 程式人生 > >微機介面課程設計報告-模擬汽車控制系統

微機介面課程設計報告-模擬汽車控制系統

由於各種原因,可能存在諸多不足,歡迎斧正!

1. 課程論文題目

   設計一個模擬汽車控制系統,用簡單邏輯電平控制車的檔位(前進1,前進2,前進3,後退),用步進電機的轉速模擬車的速度(若步進電機不能用,也可以用流水燈的重新整理方向和速度,或數碼管顯示的數值來模擬車的速度),用A/D轉換器模擬車的油門大小。用Visual C++ 6.0(推薦使用)程式設計,並設計程式介面。

2. 程式設計思路(包括硬體連線結構)

    本實驗用到的晶片主要是一款8255介面晶片,利用其完成序列訊號與並行訊號的轉換,步進電機的驅動,流水燈的顯示,數碼管顯示等。由於多次用到8255介面晶片,下面首先結合我掌握的資料,介紹一下8255介面晶片

1)晶片簡介

   8255A是通用的8位並行輸入/輸出介面晶片,使用靈活,功能強大,是應用最廣的典型可程式設計並行介面晶片。共有40個引腳,採用雙列直插式封裝,各引腳功能如下:與微處理器連線的訊號線     D7D0:資料線,三態雙向8位,與系統的資料匯流排相連。     CS:片選訊號,低電平有效。     WR:寫訊號,低電平有效。     RD:讀訊號,低電平有效。     A1,A0:埠地址選擇訊號。用於選擇8255A3個數據埠和一個控制埠。      8255A與外部裝置連線的訊號線     PA7PA0A口資料線。     PB7PB0B口資料線。     PC7PC0C

口資料線

引腳圖如下:

 


2)流水燈控制平臺:

在學校的試驗平臺上LED燈的埠地址是0xc860,通過控制LED輸入電平的高低來控制LED燈的明暗,而電平的高低是通過向埠寫書據來體現的,例如向埠寫入1就代表輸入的是高電平而0是低電平。因而要實現流水燈的各種功能,只需控制各埠電平的高低也就是對埠寫入的資料的不同。燈的閃爍的實現就是在LED燈的全明與全暗之間設定一個延遲,得到閃爍的效果,從左至右或從右至左的變化是通過將初始值進行左移位或右移位即可。

(3)、小鍵盤控制

本次課程設計中我們用小鍵盤控制油門,具體做法在下面的資料結構與演算法設計方面會得到體現。

(4)、設計思想

   在以前的上機實驗中,我們分別做過流水燈和步進電機的實驗,都成果的完成了,因此這次課程設計是對以前實驗的一次綜合。對於此次實驗概況:都是有手動控制,分別是汽車檔位由LED

控制開關來控制,總共設定為04五個檔位,汽車油門大小有小鍵盤控制,小汽車的行駛速度由步進電機的轉速以及流水燈的閃爍速度來模擬,倒檔時表現為反方向轉動(此處流水燈因為閃爍方向不明顯,所以不好分辨)。

3.功能模組圖


4.資料結構設計

     由於本次微機介面課程設計對演算法的要求不高,所以在涉及演算法與資料結構的領域並沒有特別的。主要是開了些陣列。

 1.小鍵盤控制小車

     在課設時,試驗檯上的小鍵盤是4*4的,行號+列號=索引值,具體索引鍵盤上的16個位置。

        

   每一個鍵可以由行列共同索引,所以結合牆威老師給的小鍵盤參考程式碼,我們開闢瞭如下陣列:

         unsigned char pc0_3_out[]={0x01,0x02,0x04,0x08};

         unsigned char pc4_7_in[]={0x10,0x20,0x40,0x80};

   上述陣列通過行列組合的優勢在於可以快速索引到所輸入的控制資訊。在響應鍵盤時時間複雜度為O(n^2),空間複雜度為O(1)

5.演算法設計

  1.控制系統

    (1.小鍵盤響應演算法 

     關於小鍵盤的響應,我們組用到的是雙重迴圈結合開闢的索引陣列找到使用者輸入的命令資訊。虛擬碼如下:

     For(行從04)

     {

         For(列從04)

          如果找到使用者輸入的命令字,記錄行列下表Col,Row

     }

     根據行列算出具體命令。

  (2.步進電機演算法

      依據步進電機的基本原理,

_outp(0x0c803,0x88);//初始化步進電機,B組0方式、PB口輸出、PC口輸入。
_outp(0x0c801,0x05);
_outp(0x0c801,0x15);
_outp(0x0c801,0x14);
_outp(0x0c801,0x54);
_outp(0x0c801,0x50);
_outp(0x0c801,0x51);
_outp(0x0c801,0x41);
_outp(0x0c801,0x45);

 以雙八拍方式ABABCBCBCDCDCDADADAB控制步進電機工作。

  通過迴圈控制步進電機反覆執行,由並行介面8255控制。

3)、七段數碼管顯示演算法

     根據油門和檔位模擬出小車行駛的速度,然後結合前幾次做過的七段數碼管內在結構和外在特性,在七段數碼管顯示顯示速度,由並行介面8255控制。

  2.MFC介面

     關於介面,由於之前有些MFC程式設計經驗,也知道動畫的製作原理。於是在卡通動畫中截了幾張小車行駛的連續圖,然後結合具體的速度過載自己的定時器函式,最終達到動畫效果。

6.程式關鍵程式碼

原始碼1
Mqc類:模擬汽車控制系統關鍵程式碼
/*************************************************
*功能:“確定”功能響應函式
*
*************************************************/
void Mqc::OnOk() 
{
	CSliderCtrl*pSlide=(CSliderCtrl*)GetDlgItem(IDC_YOUMENDAXIAO);
	pSlide->SetRange(0,255);
	pSlide->SetPos(0);                
	_outp(0x0c803,0x0e);         
	SetTimer(1000,youmen,NULL);
}

/************************************************
*
*功能:”取消“功能響應函式
*
*************************************************/
void Mqc::OnCancel() 
{
	CDialog::OnCancel();
}

/************************************************
*
*功能:滑動框響應函式
*
*************************************************/
void Mqc::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	if(pScrollBar->GetDlgCtrlID()==IDC_YOUMENDAXIAO)
	{
		CSliderCtrl*pSlide=(CSliderCtrl*)pScrollBar;
		CString strText;	
		strText.Format("%d",pSlide->GetPos());	
		SetDlgItemText(IDC_YOUMEN,strText);
	}
	CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}


/************************************************
*
*功能:小鍵盤響應函式,根據鍵盤輸入控制小車油門
*
*************************************************/
unsigned char pc0_3_out[]={0x01,0x02,0x04,0x08};
unsigned char pc4_7_in[]={0x10,0x20,0x40,0x80};
char scan_key16()
{
	int i,j,key1;
	int in_i,in_j;
	unsigned char find;
	unsigned char pc_in,pc_in4_7;
	find=0;
	for(i=0;i<4;i++)
	{
		_outp(0x0c802,pc0_3_out[i]);
		pc_in=_inp(0x0c802);
		pc_in4_7=pc_in & 0xf0;
		for(j=0;j<4;j++)
		{
			if(pc4_7_in[j]==pc_in4_7)
			{
				find=1;
				in_j=j;
				in_i=i;
			}
		}
	}
	if(!find) return 0;
	key1=in_j*4+in_i;
	if(key1<9) (key1)++;
	else if(key1==9) (key1=0);
	return key1;
}


/************************************************
*
*功能:過載定時器函式,完成人機互動顯示
*
*************************************************/
void Mqc::OnTimer(UINT nIDEvent) 
{
	if(i==0)
		i=1;
	else 
		if(i==1)
			i=0;
		UpdateData(true);
		if(nIDEvent==1000)
		{
			CSliderCtrl*pSlide=(CSliderCtrl*)GetDlgItem(IDC_YOUMENDAXIAO);
			_outp(0x0c803,0x88);
			_outp(0x0c802,0x00);		
			if(_kbhit())
			{
				
				_getch();
			}	
			m_youmen=(scan_key16())*30;
			pSlide->SetPos(m_youmen);
			m_daxiao=m_youmen;
			UpdateData(false); 	
			
			//顯示油門大小
			if(m_youmen>=200)
			{
				if(i==1)		
					_outp(0x0c860,0x0e); 
						
				_outp(0x43,0xb6);
				_outp(0x42,19);
				_outp(0x42,83);
				int PB;
				PB=_inp(0x61);
				_outp(0x61,0xfc);
				PB=PB|0x3;
				_outp(0x61,PB);
				
				Sleep(1000);
				PB=PB&0xfc;
				_outp(0x61,PB);			
				
			}
			m_daxiao=pSlide->GetPos();
			UpdateData(false);
			if(_inp(0x0c860)<=4)
			{
				
				m_dangwei=_inp(0x0c860);    //  讀檔位
				UpdateData(false);
			}
			if(m_dangwei==0)
			{                             //  倒車敬示
				if(i==1) _outp(0x0c860,0xaa);
				else _outp(0x0c860,0x55);
			}
			switch(count)
			{
			case 0:_outp(0x0c801,0x05);break;
			case 1:_outp(0x0c801,0x15);break;
			case 2:_outp(0x0c801,0x14);break;
			case 3:_outp(0x0c801,0x54);break;
			case 4:_outp(0x0c801,0x50);break;
			case 5:_outp(0x0c801,0x51);break;
			case 6:_outp(0x0c801,0x41);break;
			case 7:_outp(0x0c801,0x45);break;
			default:break;
			}
			if(m_dangwei!=0)
			{
				if(count!=7)count++;
				else count=0;
			}
			if(m_dangwei==0)
			{
				if(count!=0)count--;
				else count=7;
			}
			if(m_dangwei==0)youmen=1000; //  控制電機延時
			else youmen=5+1000/m_dangwei-m_youmen;
			
			if(m_dangwei==0)
			{
				m_EDITg+=-10000*1.0/youmen;
				m_Speed=-10000*1.0/youmen;
				Direction=false;
			}
			else 
			{
				Direction=true;
				m_EDITg+=10000*1.0/youmen;
				m_Speed=10000*1.0/youmen;
			}
			m_Time+=1;
			UpdateData(false);	
			SetTimer(1000,youmen,NULL);
		}
		CDialog::OnTimer(nIDEvent);
}

/************************************************
*
*功能:“顯示”響應函式,轉入小車動畫介面
*
*************************************************/
void Mqc::OnShowbutton() 
{
	CCarShowDlg *dlg=new CCarShowDlg ;
	dlg->m_Speed=m_Speed;
	dlg->Direction=Direction;
	dlg->DoModal();
}






原始碼2
CarShowDlg類:MFC小車行駛動畫關鍵程式碼
/************************************************
*
*功能:對話方塊初始化函式
*
*************************************************/
BOOL CCarShowDlg::OnInitDialog()
{
	nowOne=1;
	CDialog::OnInitDialog();
	SetTimer(1, 1.0/m_Speed*1000, NULL);
	return true;
}

/************************************************
*
*功能:重繪對話方塊背景,模擬小車行駛動畫
*
*************************************************/
void CCarShowDlg::OnPaint() 
{
	if (IsIconic())
    {
        CPaintDC dc(this); // 用於繪製的裝置上下文
        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;	
        dc.DrawIcon(x, y, m_hIcon);// 繪製圖標
    }
    else
    {
		CPaintDC dc(this);
		CRect rc;
		GetClientRect(&rc);
		CDC dcMem;
		dcMem.CreateCompatibleDC(&dc);
		CBitmap bmpBackground;	
		if(nowOne==1)
		{
			if(Direction)
				nowOne++;
			else nowOne--;
			bmpBackground.LoadBitmap(IDB_BITMAP1);
		}
		else if(nowOne==2)
		{
			if(Direction)
				nowOne++;
			else nowOne--;
			bmpBackground.LoadBitmap(IDB_BITMAP2);
		}
		else if(nowOne==3)
		{
			if(Direction)
				nowOne++;
			else nowOne--;
			bmpBackground.LoadBitmap(IDB_BITMAP3);
		}
		else if(nowOne==4)
		{
			if(Direction)
				nowOne++;
			else nowOne--;
			bmpBackground.LoadBitmap(IDB_BITMAP4);
		}
		else if(nowOne==5)
		{
			if(Direction)
				nowOne++;
			else nowOne--;
			bmpBackground.LoadBitmap(IDB_BITMAP5);
		}
		else if(nowOne==6)
		{
			if(Direction)
				nowOne++;
			else nowOne--;
			bmpBackground.LoadBitmap(IDB_BITMAP6);
		}
		else if(nowOne==7)
		{
			nowOne=1;
			bmpBackground.LoadBitmap(IDB_BITMAP1);
		}
		else if(nowOne==0)
		{
			nowOne=6;
			bmpBackground.LoadBitmap(IDB_BITMAP6);
		}
		BITMAP bitmap;
		bmpBackground.GetBitmap(&bitmap);
		CBitmap* pbmpPri = dcMem.SelectObject(&bmpBackground);
		dc.StretchBlt(0,0,rc.Width(), rc.Height(), &dcMem,0,0,bitmap.bmWidth, bitmap.bmHeight, SRCCOPY);
    }
}

/************************************************
*
*功能:過載定時器
*
*************************************************/
void CCarShowDlg::OnTimer(UINT nIDEvent) 
{
	Invalidate();
	CDialog::OnTimer(nIDEvent);
}

7.程式執行結果

1)基於MFC建立的主視窗介面:

 

 對進入該介面,點選“確定”按鈕後,進行小車的行駛模擬,在這過程中,還有一個功能是不可見的,就是當油門大小超過200,會發出警報聲。對於介面上的“顯示”按鈕,是我們小組做的一個模擬小車行駛的一個動畫介面按鈕。

(3)、動畫介面

 

8.程式設計中遇到的困難及解決方法

1.本次課設最大的問題莫過於好的實驗箱不多,我們去得很早找到了一臺之前用過的被證明是好的實驗臺,可是做了一會發現步進電機控制的轉盤不轉,於是我和其他3個組員到處找,開機連電路然後檢測,但最終沒有找到完全可用的實驗箱,只好找了一個A/D介面壞掉的替代品,這也導致最終我們只選擇小鍵盤實現小車的控制。

2.對於晶片不熟,在使用晶片的時候還要翻看書上的介紹以及例題。但是在這個過程中,我通過帶上自己的電腦上網查閱相關晶片說明,檢視前幾次實驗程式並加以總結以及回過頭仔細看書深入瞭解了一些晶片,掌握了初始化、寫入命令字等操作,並對晶片的內部結構、執行原理有了一定的認識。

3.MFC介面的設計。老師本次實驗給了我們很大的發揮空間—沒有強制要求我們要具體做出什麼效果,另一方面導致剛開始我們組不到做些什麼,但經過一陣氣氛活躍的組內討論,我們確定下來最終在介面上完成什麼功能、營造什麼效果。

4.由於連不上網,很多資料只能通過手機查詢,帶來一定的不便,導致我們進度比較慢,本可以1天完成的任務硬是拖到第二天上午,且給老師檢查的時候沒能做出MFC模擬小車的動畫效果。下午的時候我們在原來的基礎上加以改進,添加了MFC動畫。

5.小鍵盤的使用。剛開始使用小鍵盤時由於沒看電路圖,即使牆威老師事前給過程式碼,也沒能看懂,畢竟我們之前的使用的C語言不用涉及具體到硬體層面的東西。通過問了樑老師,結合著電路圖基本摸清小鍵盤的使用方法。

6.事先規劃程式流程。由於之前聽老師說本次課設比較簡單,所以沒有事先畫流程圖,導致我們在具體程式設計的時候只能想到一點寫一點,類似大爆發模式,導致剛開始有些邏輯混亂,程式條理不清。後來我們索性推倒重來,指定組內專人設計了程式流程圖,然後有條不紊地開始程式設計,效果不錯。建議以後在程式設計的時候無論課題如何,事先明確大致方向和流程。

7.模仿與創新。由於本次實驗臺上有些原始碼,剛開始我們準備直接在原有基礎上隨便改改,但進行到具體控制系統時發現有些地方並不能直接照抄,如果只是改改又會導致自己開發出的程式結構混亂,於是我們索性在看懂源有程式碼的基礎上自己重寫,加進組內成員的點子,程式設計出真正屬於自己的東西。

9.總結心得及良好建議

        為期兩天的微機介面課程設計很快過去了。在這兩天裡,我根據微機介面課程上的知識結合前幾次做過的實驗,在多次修改的基礎上,完成了自己的小車控制系統設計。下面我談談我對微機介面課程以及微機介面課程設計的理解。

        介面(interface),顧名思義,就是微處理器與“外部世界”的連線電路,是CPU與外界進行資訊交換的中轉站。之所以在計算機系統中引入微機介面概念,是因為資訊型別和訊號電平的匹配問題,(訊號線的功能、邏輯、時序),速度的匹配問題,提高了CPU的效率,使外設的發展不受限制(硬體結構不依賴CPU)。由以上可以總結出微機介面的主要功能:接受、解釋和執行CPU命令的功能;返回外設狀態的功能;資料的緩衝功能;訊號的轉換功能;裝置選擇(埠定址)功能;資料寬度與資料格式轉換功能;中斷管理功能;可程式設計功能。我們的微機介面課本就是圍繞上面的內容展開的。個人感覺微機介面是門博大精深的課程,設計的學科很多,有計算機組成原理、計算機體系結構、組合語言、C語言等。

        在學習微機介面理論課程以及進行課設時,我認為應該做到兩點:掌握硬體基本結構和原理,自主程式設計完成書上例題和課程實驗包括最後的課程設計。總結來說,就是要做到理論結合實際。在課程設計以及之前的幾個實驗過程中我是深有體會的。最開始在做基本I/O實驗時,由於之前在課下沒有認真看過書,導致對I/O基本原理不熟,本該很簡單的實驗做了較長時間。後來再做之後的CMOS實時鐘實驗、步進電機的驅動等實驗時又遇到過已經掌握基本原理和晶片結構圖,但一時無法程式設計出正確程式的問題,總的原因是理論偏離了實際。有時在邏輯上完全正確的程式碼就是在實驗臺上得不到正確結果,在一番思考嘗試之後我選擇在需要與外設讀寫交換資訊的地方加上了幾條延時指令,結果問題就迎刃而解了。我得出的結論是CPU的執行速度是很快的,但外設的速度是相對有限的,在二者進行資料交換的時候需要適當緩衝,有時緩衝作用通過特定的鎖存器、緩衝器來實現,有時則需要我們自己人為調整,比如嘗試適當加些延時指令,當然這需要在確實有需要的地方新增,不能隨意亂加導致程式效率降低,即要在功能與效率之間折中,這種折中思想在計算機體系結構以及程式設計中是經常用到的。

       關於本課程的建議,首先,我真誠的希望學校能更新一下實驗臺。雖然大家最終都做了,但有些組是在別人做完之後才找到好的機器;有的恐怕是在沒有找到好的試驗檯之後索性放棄了最後用別人的試驗箱請老師檢查。

       然後,我認為學好微機介面應該做到理論實際相結合。不能一味只看書,輕視具體程式設計體驗,撇開實際空談理論,最終一無所獲;也不能完全脫離理論,在實驗原理一知半解的情況下就動手連線電路然後敲上相應程式碼,好比囫圇吞棗。微機介面課以及微機介面課程設計有著獨有的特點,初學者要處理好理論與實際、硬體與軟體等的關係。既要掌握書上的基本原理,又要運用所學的組合語言以及C語言去獲得相應的程式設計體驗。

最後,就是要注意合作。在課程設計過程中,樑老師有意安排3個人一組(由於試驗箱有限,我們組最終有4個人,我、潘傳軍、張映紅、郭慶豔)。其實本次課設較其他課設簡單很多,我想老師可能是有意培養我們的合作意識。畢竟將來走進企事業單位碰到的問題很可能是個人無法解決的,這就需要與同事合作。合作是門藝術,合作的目的是要做到1+1>=2,雙方互利共贏,而不是兩敗俱傷。在本次課程設計過程中,我們組也積極響應樑老師的要求,各自分工,雖然沒有強制要求組員具體做事麼事,但每個人是分了工的,大家在分工中合作。最終我們在多次更改程式的情況下,依然在第2天上午成功完成任務。在此感謝我的組員。

原始碼下載地址 http://download.csdn.net/detail/xj2419174554/6845793

上述可能有很多錯誤或不足的地方,歡迎大牛斧正!