第一篇:北郵數(shù)字邏輯小學(xué)期交通燈控制器
實(shí)驗(yàn)一交通燈控制器
一、實(shí)驗(yàn)?zāi)康?/p>
a)熟練掌握 VHDL語(yǔ)言和QuartusII軟件的使用。b)用VHDL進(jìn)行較復(fù)雜邏輯電路的設(shè)計(jì)和調(diào)試。c)熟練掌握isp期間的下載方法。d)理解狀態(tài)機(jī)的工作原理和設(shè)計(jì)方法。
二、實(shí)驗(yàn)所用設(shè)備和環(huán)境
a)實(shí)驗(yàn)設(shè)備:TEC-8實(shí)驗(yàn)箱一個(gè)、EPM7128SLC84-15芯片一個(gè)
b)實(shí)驗(yàn)環(huán)境:WinXP+QuartusII
三、實(shí)驗(yàn)任務(wù)及功能介紹
在十字路口,每條道路各有一組紅、黃、綠燈,用以指揮車輛和行人有序的通行。其中紅燈亮表示禁止通行,黃燈亮表示停車,綠燈亮表示可以通行。設(shè)計(jì)一交通燈控制器用于自動(dòng)控制十字路口的交通燈,指揮各種車輛和行人安全通行。a)東西和南北方向各有一組綠、黃、紅等用于指揮交通,綠燈、黃燈和紅燈的持續(xù)時(shí)間分別為5s,1s和6s。其中初始狀態(tài)為東西南北四個(gè)方向紅黃綠燈全亮,持續(xù)1秒。后東西方向綠燈,南北方向紅燈,持5秒。后東西方向黃燈閃爍,南北方向持續(xù)紅燈,維持1秒。后東西、南北方向交換。b)有緊急狀況時(shí),如有消防車、救護(hù)車或者其他需要優(yōu)先放行的車輛時(shí),各方向上均是紅燈亮。當(dāng)緊急狀況解除時(shí),回復(fù)原來(lái)的狀態(tài),繼續(xù)正常運(yùn)行。
c)當(dāng)復(fù)位開關(guān)置1時(shí),切換到初始狀態(tài),即四個(gè)方向紅黃綠燈全亮。
四、課題分析及流程圖:
一共六個(gè)狀態(tài):S0, S1, S2, S3, S4, 緊急狀態(tài)。
五、設(shè)計(jì)思路
a)本題主要是紅黃綠燈時(shí)間的計(jì)時(shí)(即分頻),和狀態(tài)的切換。由于外部時(shí)鐘信號(hào)CLK信號(hào)為1kHz,而我們需要1Hz,因此需要分頻。
b)對(duì)于計(jì)時(shí),采用計(jì)數(shù)器方式,根據(jù)外部時(shí)鐘信號(hào)CLK,在上升沿時(shí),將計(jì)數(shù)器加一,分別定義T1,T1,T3,T4的整型數(shù),范圍分別是0~999,0~1999,0~4999和0~199,分別表示1秒、2秒、5秒和0.2秒,其中0.2秒用于黃燈閃爍。引入TIMER數(shù)組來(lái)表示該進(jìn)行何種時(shí)間的計(jì)數(shù),每一位依次表示紅黃綠燈,為分頻后信號(hào)。
c)設(shè)計(jì)六個(gè)狀態(tài):S0, S1, S2, S3, S4和緊急狀態(tài)。對(duì)于狀態(tài)切換,引入currentSTATE和nextSTATE兩個(gè)狀態(tài)變量,取值在STATE中選擇:TYPE STATE IS(S0, S1, S2, S3, S4);d)東西南北方向燈的表示:有三個(gè)4位二進(jìn)制數(shù),RED、YELLOW和GREEN進(jìn)行輸出,從高位到地位依次表示東西南北四個(gè)方向的燈的狀態(tài),1亮,0滅。
e)為了得知什么時(shí)候切換狀態(tài),需引入數(shù)組SWITCH,4位二進(jìn)制數(shù),每一位依次表示紅黃綠燈計(jì)時(shí)器是否計(jì)時(shí)結(jié)束,若結(jié)束則置1,各位相或,得到CTRL信號(hào)若有效,則需要切換狀態(tài),反之則不用。
f)對(duì)于緊急狀態(tài)信號(hào)URGENT和復(fù)位信號(hào)CLR,則由開關(guān)控制,若置1,則有效,立即切換到緊急狀態(tài)或初始狀態(tài)S0。
六、詳細(xì)設(shè)計(jì)
a)交通燈控制器實(shí)體
b)arc中信號(hào)
c)分頻進(jìn)程,以計(jì)數(shù)器形式得出T1,T2,T3,T4四種時(shí)間。
d)判斷何時(shí)切換狀態(tài)
e)控制黃燈閃爍進(jìn)程,每0.2s閃爍一次
f)六種狀態(tài)的表現(xiàn)形式及緊急狀態(tài)的切換
七、心得體會(huì)
這次雖然小學(xué)期有兩周,但時(shí)間仍然是非常緊張。我由于身體原因在上學(xué)期期末申請(qǐng)了緩考,所以在小學(xué)期的同時(shí)還要準(zhǔn)備6門緩考考試,顯得非常忙碌,能夠分給小學(xué)期的時(shí)間也不多。所以在第一天老師布置課題后,我們小組經(jīng)過(guò)討論,讓我選擇了簡(jiǎn)單一些的交通燈控制器。
在最開始的時(shí)候,顯得無(wú)從下手。雖然我們編寫過(guò)LED燈顯示和各種譯碼器,但都只是很簡(jiǎn)單的一個(gè)進(jìn)程,如今要自己設(shè)計(jì)整個(gè)控制器,覺(jué)得有點(diǎn)不知所措。后來(lái)用編寫C++等程序的經(jīng)驗(yàn),我仔細(xì)分析題目,將它分解成更小的模塊,來(lái)分別實(shí)現(xiàn),最后再整合在一起。
狀態(tài)切換和顯示部分的編碼還比較簡(jiǎn)單,但是分頻部分又有點(diǎn)不知所云,查閱了網(wǎng)上的例子和書籍后,感覺(jué)看不太懂他們的分頻方式,詢問(wèn)同學(xué),同學(xué)們也還不太清楚。后來(lái)借到第一天老師課上說(shuō)的參考書,發(fā)現(xiàn)上面的分頻方式是以計(jì)數(shù)器的形式,利用外部時(shí)鐘,來(lái)一個(gè)上升沿計(jì)數(shù)器加一,簡(jiǎn)單容易理解,所以采用了。
每一次編寫大作業(yè)的時(shí)候我都喜歡全部編寫完畢后再編譯、測(cè)試,但是這樣就造成錯(cuò)誤過(guò)多而引起不知道從何下手。因此我這一次采取的是逐部分編譯、測(cè)試的方式。但是由于對(duì)VHDL已經(jīng)一個(gè)多學(xué)期沒(méi)有碰過(guò),生疏了很多,語(yǔ)法錯(cuò)誤非常多。而且編譯通過(guò)后還經(jīng)常不能運(yùn)行。再反復(fù)完善代碼卻不能運(yùn)行的時(shí)候,詢問(wèn)下同學(xué),發(fā)現(xiàn)自己的管腳接的大有問(wèn)題。是我自己忽略了有特殊指向的管腳,導(dǎo)致我的外部時(shí)鐘CLK沒(méi)有輸入進(jìn)去,程序無(wú)法繼續(xù)進(jìn)行。并且也發(fā)生了沒(méi)有改代碼,但是換了個(gè)實(shí)驗(yàn)箱就運(yùn)行不了的情況,檢查了很久發(fā)現(xiàn)是模式控制沒(méi)有打到硬布線模式,影響了整體程序的運(yùn)行,這些都是不通過(guò)自己調(diào)試、檢驗(yàn)無(wú)法學(xué)習(xí)到的。
這兩周的時(shí)間,我將自己的效率放大到最大,但是仍然因時(shí)間問(wèn)題無(wú)法完成交通燈倒計(jì)時(shí)顯示部分,也是小學(xué)期的一個(gè)遺憾。不過(guò)這兩周,我不但又一次加深理解了自己動(dòng)手操作的重要性,也對(duì)于芯片的設(shè)計(jì)思路有了更好的理解。由于交通燈控制器是一個(gè)簡(jiǎn)單一些的程序,因此我沒(méi)有分模塊實(shí)現(xiàn),沒(méi)有用到原理圖,也沒(méi)有遇到芯片的邏輯塊溢出的問(wèn)題,但是在每天的最后,小組討論時(shí),我們都會(huì)討論解決這些問(wèn)題,也讓我從中學(xué)到了很多。總體來(lái)說(shuō),這一次的小學(xué)期算是收獲頗豐。附件一:VHDL源代碼 LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;USE IEEE.STD_LOGIC_ARITH.ALL;USE IEEE.STD_LOGIC_UNSIGNED.ALL;ENTITY trafficLight IS
PORT(CLR, CLK, URGENT : IN STD_LOGIC;GREEN : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);YELLOW : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);RED : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
--CLOCK : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));END trafficLight;ARCHITECTURE lightARC OF trafficLight IS TYPE STATE IS(S0, S1, S2, S3, S4);SIGNAL currentSTATE, nextSTATE : STATE;SIGNAL CTRL : STD_LOGIC;SIGNAL SWITCH : STD_LOGIC_VECTOR(3 DOWNTO 0);
--切換狀態(tài)
SIGNAL TIMER : STD_LOGIC_VECTOR(3 DOWNTO 0);
--時(shí)鐘計(jì)時(shí) SIGNAL T1 : INTEGER RANGE 0 TO 999;
--1s SIGNAL T2 : INTEGER RANGE 0 TO 1999;
--2s SIGNAL T3 : INTEGER RANGE 0 TO 4999;
--5s SIGNAL T4 : INTEGER RANGE 0 TO 199;
--0.2s
--SIGNAL T5 : INTEGER RANGE 0 TO 999;
BEGIN PROCESS(CLK, SWITCH)
BEGIN
IF(CLK'event AND CLK = '1')THEN
IF(SWITCH(0)= '0')THEN TIMER(0)<= '0';
T1 <= 0;
ELSE IF(T1 = 999 AND URGENT = '0')THEN
T1 <= 0;
TIMER(0)<= '1';
ELSE IF(URGENT = '0')THEN
T1 <= T1 + 1;TIMER(0)<= '0';
END IF;END IF;END IF;
IF(SWITCH(1)= '0')THEN TIMER(1)<= '0';
T2 <= 0;
ELSE IF(T2 = 1999 AND URGENT = '0')THEN
T2 <= 0;
TIMER(1)<= '1';
ELSE IF(URGENT = '0')THEN
T2 <= T2 + 1;
TIMER(1)<= '0';
END IF;
END IF;
END IF;
IF(SWITCH(2)= '0')THEN
T3 <= 0;TIMER(2)<= '0';
ELSE IF(T3 = 4999 AND URGENT = '0')THEN
T3 <= 0;TIMER(2)<= '1';
ELSE IF(URGENT = '0')THEN
T3 <= T3 + 1;
TIMER(2)<= '0';
END IF;
END IF;
END IF;
END IF;END PROCESS;
CTRL <= TIMER(0)OR TIMER(1)OR TIMER(2);切換狀態(tài)
PROCESS(CLK, SWITCH(3))
BEGIN
IF(CLK'event AND CLK = '1')THEN
IF(T4 = 199 AND SWITCH(3)= '1')THEN
T4 <= 0;
TIMER(3)<= NOT TIMER(3);
ELSIF(SWITCH(3)= '1')THEN
T4 <= T4 + 1;
END IF;
END IF;
END PROCESS;
PROCESS(CTRL, CLR)
BEGIN
--倒計(jì)時(shí)完成IF(CLR = '1')THEN currentSTATE<= s0;
ELSIF(CTRL'event AND CTRL = '0')THEN currentSTATE<= nextSTATE;
END IF;
END PROCESS;
PROCESS(currentSTATE, URGENT)
BEGIN
IF(URGENT = '1')THEN
--緊急狀態(tài),所有方向點(diǎn)亮紅燈
GREEN <= “0000”;YELLOW <= “0000”;RED <= “1111”;
ELSE
CASE currentSTATE IS
WHEN s0 => SWITCH <= “0001”;
GREEN <= “1111”;
YELLOW <= “1111”;
RED <= “1111”;
--CLOCK <= “0000”;nextSTATE<= s1;
WHEN s1 => SWITCH <= “0100”;
GREEN <= “1100”;
YELLOW <= “0000”;
RED <= “0011”;
--CLOCK <= “0110”;nextSTATE<= s2;WHEN s2 => SWITCH <= “1010”;
GREEN <= “0000”;
YELLOW(3)<= TIMER(3);--閃爍 YELLOW(2)<= TIMER(3);YELLOW(1 DOWNTO 0)<= “00”;nextSTATE<= s3;WHEN s3 => SWITCH <= “0100”;
GREEN <= “0011”;
YELLOW <= “0000”;
RED <= “1100”;
--CLOCK <= “0110”;nextSTATE<= s4;
WHEN s4 => SWITCH <= “1010”;
GREEN <= “0000”;
YELLOW(3 DOWNTO 2)<= “00”;
YELLOW(1)<= TIMER(3);--閃爍 YELLOW(0)<= TIMER(3);
RED <= “1100”;nextSTATE<= s1;
END CASE;
END IF;
END PROCESS;
--
PROCESS(CLK, CLOCK)
--
BEGIN----------IF(CLK'event AND CLK = '1')THEN
IF(CLOCK = “0000”)THEN CLOCK <= “0110”;ELSE CLOCK <= CLOCK-1;END IF;IF(T5 = 999)THEN T5 <= 0;--
ELSE T5 <= T5 + 1;--
END IF;--
END IF;
--
END PROCESS;END lightARC;
附件二:調(diào)試日志 2015/9/8周二:
復(fù)習(xí)VHDL基礎(chǔ)知識(shí)及語(yǔ)法,了解交通燈大致編寫思路。2015/9/9周三:
分解交通燈控制器:分頻部分,狀態(tài)切換部分,顯示部分
今日計(jì)劃:初步完成分頻部分,考慮程序流程和各個(gè)進(jìn)程間的配合。學(xué)習(xí)時(shí)鐘分頻的方式:途徑:去圖書館借書查閱《VHDL數(shù)字電路設(shè)計(jì)與應(yīng)用實(shí)踐教程》,采用計(jì)數(shù)器的方式,針對(duì)外部時(shí)鐘所給的1kHz分成1Hz,從而得到想要的5s、1s、0.2s等時(shí)間。
遇到問(wèn)題:能夠得到時(shí)間,但不知道該怎么將時(shí)間運(yùn)用到狀態(tài)切換中。解決方案:上網(wǎng)查閱資料。2015/9/10周四:
今日計(jì)劃:完成狀態(tài)切換部分和顯示部分,考慮如何將分頻好的時(shí)鐘信號(hào)用在狀態(tài)切換部分。
遇到問(wèn)題:切換狀態(tài)部分和顯示部分比較簡(jiǎn)單,只是需要注意if-else語(yǔ)句使用,因?yàn)閂HDL語(yǔ)法不熟悉導(dǎo)致語(yǔ)法報(bào)錯(cuò)很多。定義的狀態(tài)太多,重復(fù)性大。
解決方案:開始在狀態(tài)切換時(shí),沒(méi)想好要幾個(gè)狀態(tài),零零散散分了很多個(gè),導(dǎo)致很多狀態(tài)其實(shí)根本是重合的,刪減后得到最精簡(jiǎn)的6個(gè)狀態(tài)。對(duì)于分頻時(shí)鐘,引入TIMER數(shù)組記錄時(shí)鐘是否計(jì)時(shí)完畢,若完畢則需要切換狀態(tài),將分頻部分與其他部分串接在一起。2015/9/11周五:
今日計(jì)劃:完成程序,在TEC-8上進(jìn)行初步調(diào)試。
遇到問(wèn)題:忘記如何下載芯片,詢問(wèn)同學(xué)后解決。成功下載芯片后發(fā)現(xiàn)不能運(yùn)行,燈的顯示也是亂的。
解決方案:回頭看代碼,發(fā)現(xiàn)在TIMER信號(hào)表示出計(jì)時(shí)完畢后,并沒(méi)有給激勵(lì)進(jìn)行狀態(tài)切換,引入CTRL信號(hào)給予激勵(lì),當(dāng)CTRL有效時(shí)切換狀態(tài),為了方便觀察CTRL信號(hào)的變化,將其連接到燈上。遇到問(wèn)題:下載芯片后仍舊不能繼續(xù)運(yùn)行,但CTRL信號(hào)有改變。2015/9/14周一:
今日計(jì)劃:完善程序,在TEC-8上運(yùn)行成功。
遇到問(wèn)題:下載芯片后仍舊不能繼續(xù)運(yùn)行,但CTRL信號(hào)有改變。解決方案:能夠判斷計(jì)時(shí)結(jié)束,能夠給激勵(lì)改變狀態(tài),卻沒(méi)有改變狀態(tài)。發(fā)現(xiàn)沒(méi)有信號(hào)表示紅黃綠燈的切換,用S0~S4來(lái)判斷狀態(tài)并切換,但發(fā)現(xiàn)紅黃綠燈有對(duì)稱,而S2和S4、S1和S3對(duì)于計(jì)時(shí)器來(lái)說(shuō)沒(méi)有任何區(qū)別,不需要重復(fù)判斷,因此引入SWITCH數(shù)組,每一位代表一種燈,使得能夠判斷計(jì)時(shí)結(jié)束后切換到何種狀態(tài),減少重復(fù)。修改編譯報(bào)錯(cuò)。2015/9/15周二:
今日計(jì)劃:完成程序,并在TEC-8上正確運(yùn)行。
遇到問(wèn)題:下載芯片后仍舊不能運(yùn)行。發(fā)現(xiàn)管腳配置有問(wèn)題。解決方案:按照老師給的ppt上的管腳配置,CLK接57管腳,CLR、URGENT分別接81,80開關(guān)上。RED,YELLOW,GREEN按順序接到20到34的紅黃綠燈上。(開始將CLR接到1號(hào)管腳上,發(fā)現(xiàn)必須一直按著CLR才可以運(yùn)行程序,后將CLR改接開關(guān)上。)
遇到問(wèn)題:在上午運(yùn)行成功后,下午換了一臺(tái)電腦,發(fā)現(xiàn)下載芯片后程序不動(dòng)了。
解決方案:在完全沒(méi)有改代碼的情況下只能檢查實(shí)驗(yàn)箱是否有誤碰情況。排除燈顯示問(wèn)題后,確定是外部時(shí)鐘沒(méi)有走,發(fā)現(xiàn)開關(guān)置于獨(dú)立而非硬布線模式,導(dǎo)致程序無(wú)法運(yùn)行。撥回獨(dú)立后運(yùn)行正常。2015/9/16周三:
完成交通燈控制器,改正紅綠燈顯示不合理的地方,在考慮加入倒計(jì)時(shí)模塊未果后,接受驗(yàn)收。
第二篇:數(shù)字系統(tǒng)課程設(shè)計(jì)交通燈控制器
東南大學(xué)
《數(shù)字系統(tǒng)課程設(shè)計(jì)》
設(shè)計(jì)報(bào)告
項(xiàng)目名稱: 交通燈控制器
姓
名:
學(xué)
號(hào):
專
業(yè):
實(shí) 驗(yàn) 室: 電工電子實(shí)驗(yàn)中心
組
別:
無(wú)
同組人員:
無(wú)
設(shè)計(jì)時(shí)間: 2016 年月 26 日
——
2016 年 9 月 20日 評(píng)定成績(jī):
審閱教師:
目錄
一.設(shè)計(jì)方案及論證……………………………………………… 3 二.模塊設(shè)計(jì)……………………………………………………… 5 三.總體設(shè)計(jì)與仿真……………………………………………… 10 四.總結(jié)…………………………………………………………… 12 一.設(shè)計(jì)方案及論證
1.設(shè)計(jì)使用環(huán)境
本交通燈控制系統(tǒng)設(shè)計(jì)利用Verilog HDL語(yǔ)言進(jìn)行設(shè)計(jì)編程,利用Cyclone EP1C6Q240C8芯片和一些外圍器件組成硬件電路,利用Quartus II軟件將編寫好的程序進(jìn)行編譯和仿真,并將調(diào)試完成的程序下載到Cyclone EP1C6Q240C8芯片上,通過(guò)觀測(cè)電路板上的紅綠信號(hào)燈以及數(shù)碼管顯示來(lái)分析系統(tǒng)的性能。
2.設(shè)計(jì)任務(wù)分析
主干道與鄉(xiāng)村公路十字交叉路口在現(xiàn)代化的農(nóng)村星羅棋布,為確保車輛安全、迅速地通過(guò),在交叉路口的每個(gè)入口處設(shè)置了紅、綠、黃三色信號(hào)燈。紅燈禁止通行;綠燈允許通行;黃燈亮則給行駛中的車輛有時(shí)間行駛到禁行線之外。主干道和鄉(xiāng)村公路都安裝了傳感器,檢測(cè)車輛通行情況,用于主干道的優(yōu)先權(quán)控制。
設(shè)計(jì)要求:
1)當(dāng)鄉(xiāng)村公路無(wú)車時(shí),始終保持鄉(xiāng)村公路紅燈亮,主干道綠燈亮。2)當(dāng)鄉(xiāng)村公路有車時(shí),而主干道通車時(shí)間已經(jīng)超過(guò)它的最短通車時(shí)間時(shí),禁止主干道通行,讓鄉(xiāng)村公路通行。主干道最短通車時(shí)間為25s。
3)當(dāng)鄉(xiāng)村公路和主干道都有車時(shí),按主干道通車25s,鄉(xiāng)村公路通車16s交替進(jìn)行。4)不論主干道情況如何,鄉(xiāng)村公路通車最長(zhǎng)時(shí)間為16s。
5)在每次由綠燈亮變成紅燈亮的轉(zhuǎn)換過(guò)程中間,要亮5s時(shí)間的黃燈作為過(guò)渡。6)用開關(guān)代替?zhèn)鞲衅髯鳛闄z測(cè)車輛是否到來(lái)的信號(hào)。用紅、綠、黃三種顏色的發(fā)光二極管作交通燈。7)數(shù)碼管倒計(jì)時(shí)顯示
3.測(cè)量控制原理
1)通過(guò)乒乓開關(guān)來(lái)控制FPGA輸入信號(hào)的電平,從而控制交通燈工作。
2)利用FPGA輸出的電平信號(hào)去驅(qū)動(dòng)靜態(tài)數(shù)碼管及三色小燈來(lái)模擬交通燈。
4.頂層設(shè)計(jì)方案框圖及說(shuō)明
1)交通燈控制器框圖
C表示鄉(xiāng)村道路是否有車到來(lái),1表示有,0表示無(wú);SET用來(lái)控制系統(tǒng)的開始及停止;RST是復(fù)位信號(hào),高電平有效,當(dāng)RST為1時(shí),恢復(fù)到初始設(shè)置;CLK是外加時(shí)鐘信號(hào);MR、MY、MG分別表示主干道的紅燈、黃燈和綠燈;CR、CY、CG分別表示鄉(xiāng)村道路的紅燈、黃燈和綠燈,1表示亮,0表示滅。
2)流程圖
MGCR表示主干道綠燈,鄉(xiāng)村道路紅燈;MYCR表示主干道黃燈,鄉(xiāng)村道路紅燈;MRCG表示主干道紅燈,鄉(xiāng)村道路綠燈;MRCY表示主干道紅燈,鄉(xiāng)村道路黃燈;T0=1表示主干道最短通車時(shí)間到,T1=1表示5秒黃燈時(shí)間到,T2=1表示鄉(xiāng)村道路最長(zhǎng)通車時(shí)間到。二.模塊設(shè)計(jì)
1.模塊功能及端口說(shuō)明
1)分頻模塊
輸入端為clk_in,即實(shí)驗(yàn)箱自帶脈沖輸入信號(hào),輸出端為clk,即想得到的頻率。2)主控制模塊
輸入端為CLK、RST、C。其中c為鄉(xiāng)村道路開關(guān),為1時(shí)表示鄉(xiāng)村道路有車;rst為初始化開關(guān),為1時(shí)表示初始化為主干道綠燈,鄉(xiāng)村道路紅燈的狀態(tài)。
輸出端為MG、MY、MR、CG、CY、CR分別表示主干道和鄉(xiāng)村道路的紅黃綠燈,與LED燈相連;mh、ml、ch、cl分別表示主干道和鄉(xiāng)村道路倒計(jì)時(shí)顯示的高低位,與數(shù)碼管相連。
3)數(shù)碼管顯示模塊
輸入端為clk和count,輸出端為L(zhǎng)ED。
2.主要功能的設(shè)計(jì)方法
1)分頻模塊
試驗(yàn)箱可選晶振有2M和50M,選擇使用2M后,設(shè)置分頻系數(shù)為2000000,每計(jì)數(shù)到1000000,則輸出取反,最終可得到1HZ的時(shí)鐘信號(hào)。
2)主控制模塊
設(shè)置兩個(gè)外部控制條件:初始化(RST);鄉(xiāng)村干道是否有車(C);
設(shè)置一個(gè)內(nèi)部計(jì)數(shù)變量:NUM,通過(guò)相關(guān)運(yùn)算取余取整得到數(shù)碼管顯示高低位;
通過(guò)有限狀態(tài)機(jī)實(shí)現(xiàn)四個(gè)狀態(tài)的循環(huán)切換。
3.Verilog設(shè)計(jì)程序及說(shuō)明
1)分頻模塊
module fre(clk_in,clk);input clk_in;output clk;reg clk;reg [31:0]k;always @(negedge clk_in)begin
if(k>=1000000)//1000000分頻 begin clk<=~clk;//取反
k<=0;end else
k<=k+1;//計(jì)數(shù)
end endmodule 2)主控制模塊
module traffic(CLK,RST,C,MG,MY,MR,CG,CY,CR,mh,ml,ch,cl);input CLK,RST,C;output [3:0]mh,ml,ch,cl;output MG,MY,MR,CG,CY,CR;reg [3:0] mh,ml,ch,cl;reg MG,MY,MR,CG,CY,CR;reg [31:0] COUNT;reg [5:0]state;parameter s1=6'b100001,s2=6'b010001,s3=6'b001100,s4=6'b001010;always @(posedge CLK)if(RST)//初始化
begin
state = s1;//最初狀態(tài),主通行,鄉(xiāng)村不通行 MG=1;MY=0;MR=0;CG=0;CY=0;CR=1;COUNT = 0;
mh=2;//主干道綠燈25s,鄉(xiāng)村道路紅燈5s
ml=5;
ch=3;
cl=0;
end else case(state)s1: begin COUNT = COUNT+1;
if((COUNT>=25)&&(C==1))//25s已計(jì)完且鄉(xiāng)村道路來(lái)車,跳轉(zhuǎn)到s2狀態(tài)
begin
state = s2;//主干道黃燈,鄉(xiāng)村道路紅燈
MG=0;MY=1;MR=0;CG=0;CY=0;CR=1;COUNT = 0;mh=0;ml=5;ch=0;cl=5;end else if(COUNT<25)//25s沒(méi)有計(jì)完,保持s1狀態(tài)
begin
state = s1;
MG=1;MY=0;MR=0;CG=0;CY=0;CR=1;
mh=(25-COUNT)/10;//取整取余換算,倒計(jì)時(shí)顯示
ml=(25-COUNT)%10;ch=(30-COUNT)/10;cl=(30-COUNT)%10;end else if(COUNT >= 25 && C == 0)//25s計(jì)完,鄉(xiāng)村道路仍然沒(méi)有車
begin
state = s1;//保持s1 MG=1;MY=0;MR=0;CG=0;CY=0;CR=1;mh=0;//數(shù)碼管顯示0
ml=0;
ch=0;
cl=0;
end
end s2: begin COUNT = COUNT+1;
if(COUNT==5)//5s黃燈已計(jì)完
begin
state = s3;//主干道紅燈,鄉(xiāng)村道路綠燈 MG=0;MY=0;MR=1;CG=1;CY=0;CR=0;COUNT = 0;
mh=2;//主干道21s紅燈,鄉(xiāng)村道路16s綠燈
ml=1;
ch=1;
cl=6;
end else
begin
state = s2;//5s黃燈未計(jì)完時(shí),保持s2狀態(tài)
MG=0;MY=1;MR=0;CG=0;CY=0;CR=1;
mh=0;
ml=5-COUNT;
ch=0;
cl=5-COUNT;
end end s3: begin COUNT = COUNT+1;
if(((COUNT>=16)&&(C==1))||(C==0))//鄉(xiāng)村道路16s通行時(shí)間已結(jié)束,不管有無(wú)來(lái)車,均跳轉(zhuǎn)s4狀態(tài)
begin
state = s4;//主干道紅燈,鄉(xiāng)村道路黃燈
MG=0;MY=0;MR=1;CG=0;CY=1;CR=0;
COUNT = 0;
mh=0;
ml=5;
ch=0;
cl=5;
end else
begin
state = s3;//16s未結(jié)束,仍保持s3狀態(tài)
MG=0;MY=0;MR=1;CG=1;CY=0;CR=0;
mh=(21-COUNT)/10;
ml=(21-COUNT)%10;
ch=(16-COUNT)/10;
cl=(16-COUNT)%10;
end end s4: begin COUNT = COUNT+1;if(COUNT==5)//5s黃燈時(shí)間結(jié)束
begin
state = s1;//回到s1狀態(tài)
MG=1;MY=0;MR=0;CG=0;CY=0;CR=1;
COUNT = 0;
mh=2;
ml=5;
ch=3;
cl=0;
end else
begin
state = s4;//否則保持s4狀態(tài)
MG=0;MY=0;MR=1;CG=0;CY=1;CR=0;
mh=0;
ml=5-COUNT;
ch=0;
cl=5-COUNT;
end end default:
begin
state = s1;
MG=1;MY=0;MR=0;CG=0;CY=0;CR=1;
COUNT = 0;
mh=0;
ml=5-COUNT;
ch=0;
cl=5-COUNT;
end endcase endmodule 3)數(shù)碼管顯示模塊 module led(clk,count,LED);input clk;input [3:0]count;output [7:0]LED;reg [7:0]LED;always @(posedge clk)begin case(count)
4'b0000:LED=8'b00000011;
4'b0001:LED=8'b10011111;
4'b0010:LED=8'b00100101;
4'b0011:LED=8'b00001101;
4'b0100:LED=8'b10011001;
4'b0101:LED=8'b01001001;
4'b0110:LED=8'b01000001;
4'b0111:LED=8'b00011111;
4'b1000:LED=8'b00000001;
4'b1001:LED=8'b00001001;
default:LED=8'b00000001;endcase end endmodule 4.仿真圖及說(shuō)明
(1)分頻模塊
由于實(shí)際應(yīng)用中分頻較大,仿真時(shí)為方便觀察,將分頻頻數(shù)設(shè)置為20。輸入為clk_in,周期為10ns;輸出為clk,其周期為200ns,與理論值相符。(2)主控制模塊
與總體仿真相同,在此不再贅述。
三.總體設(shè)計(jì)與仿真
1.頂層設(shè)計(jì)圖及說(shuō)明
fre為分頻模塊,traffic為主控制模塊,led為數(shù)碼管顯示模塊。輸入端有clk_in、c和rst,輸出端有MG、MY、MR、CG、CY、CR和mh、ml、ch、cl。
2.仿真圖及說(shuō)明
輸入有:C、CLK和RST 輸出有:CG、CR、CY、MG、MR、MY、ch、cl、mh和ml C為鄉(xiāng)村道路是否來(lái)車,1表示來(lái)車,0表示無(wú)車;CLK為時(shí)鐘信號(hào);RST為初始化功能,1有效;CG、CR、CY、MG、MR、MY分別表示鄉(xiāng)村道路綠燈、紅燈、黃燈,主干道綠燈、紅燈、黃燈;ch、cl、mh、ml分別表示鄉(xiāng)村道路和主干道紅綠燈倒數(shù)顯示高低位。
3.實(shí)驗(yàn)結(jié)果
(1)鄉(xiāng)村道路無(wú)車時(shí)
鄉(xiāng)村道路無(wú)車時(shí),主干道25s倒數(shù),鄉(xiāng)村道路30s倒數(shù)結(jié)束后,保持0,且主干道綠燈亮,鄉(xiāng)村道路紅燈亮。(2)鄉(xiāng)村道路有車時(shí)
若鄉(xiāng)村道路一直有車,主干道25s(即S1狀態(tài))倒計(jì)時(shí)結(jié)束后,主干道切換黃燈,鄉(xiāng)村道路保持紅燈(即S2狀態(tài));5s黃燈倒計(jì)時(shí)結(jié)束后,主干道切換紅燈,時(shí)間21s,鄉(xiāng)村道路切換綠燈,時(shí)間16s(即S3狀態(tài));鄉(xiāng)村道路16s綠燈結(jié)束后,切換黃燈,主干道保持紅燈(即S4狀態(tài)),5s黃燈結(jié)束后,回到S1狀態(tài),即主干道25s綠燈,鄉(xiāng)村道路30s紅燈,若一直有車,則循環(huán)進(jìn)行。
四.總結(jié)
1.實(shí)驗(yàn)結(jié)果分析
(1)輸入與輸出
兩個(gè)開關(guān):一個(gè)初始化控制開關(guān),一個(gè)鄉(xiāng)村道路開關(guān)。初始化開關(guān)打開后復(fù)位,交通燈開始工作,鄉(xiāng)村道路打開表示鄉(xiāng)村公路上有車。
輸出:四個(gè)數(shù)碼管,兩個(gè)顯示主干道交通燈時(shí)間,兩個(gè)顯示鄉(xiāng)村道路時(shí)間;六個(gè)led燈,兩紅兩黃兩綠分別表示主干道和鄉(xiāng)村公路的紅黃綠燈。(2)運(yùn)行過(guò)程
1)初始狀態(tài)(S1)
左側(cè)為主干道倒計(jì)時(shí),右側(cè)為鄉(xiāng)村道路倒計(jì)時(shí);主干道綠燈亮,鄉(xiāng)村道路紅燈亮。K1為初始化按鍵,K2為鄉(xiāng)村道路有無(wú)來(lái)車。
2)主干道25s綠燈結(jié)束后切換黃燈,鄉(xiāng)村道路紅燈(S2)
3)主干道5s黃燈結(jié)束,切換紅燈21s,鄉(xiāng)村道路切換綠燈16s(S3)
4)鄉(xiāng)村道路16s綠燈結(jié)束,切換黃燈,主干道紅燈(S4)
5s黃燈倒計(jì)時(shí)結(jié)束,回到S1狀態(tài),若一直有車,則循環(huán)S1-S2-S3-S4-S1。
2.問(wèn)題解決方法
問(wèn)題1:數(shù)碼管顯示與紅綠燈切換不同時(shí)。
解決方法:紅綠燈輸出后面增加一延時(shí)模塊,延時(shí)一個(gè)CLK,使其與數(shù)碼管顯示同步。問(wèn)題2:理解錯(cuò)題意,在S3狀態(tài)(即主干道紅燈,鄉(xiāng)村道路綠燈)時(shí),此時(shí)若鄉(xiāng)村道 路無(wú)車通過(guò),應(yīng)立即切換為S4狀態(tài)(即主干道紅燈,鄉(xiāng)村道路黃燈),而不是等當(dāng)前計(jì)數(shù)結(jié)束再切換。
解決方法:將代碼修改為if(((COUNT>=16)&&(C==1))||(C==0)),修改后符合要求,解決了問(wèn)題。
3.心得體會(huì)
通過(guò)此次系統(tǒng)設(shè)計(jì),我對(duì)verilog HDL語(yǔ)言有了初步了解,并對(duì)利用quartus來(lái)進(jìn)行系統(tǒng)設(shè)計(jì)有了更加深入的理解,操作也更加熟練。在設(shè)計(jì)過(guò)程中應(yīng)該先設(shè)計(jì)好總體架構(gòu),再進(jìn)行模塊的具體設(shè)計(jì),通過(guò)分析每個(gè)模塊要實(shí)現(xiàn)的功能來(lái)寫代碼,并注意編寫注釋,便于以后的理解修改。編譯時(shí)要注意設(shè)置頂層文件,先進(jìn)行仿真觀察結(jié)果是否正確,對(duì)代碼進(jìn)行修改,仿真結(jié)果正確后再下載到硬件,測(cè)試系統(tǒng)功能。
參考書目: [1] 夏宇聞,《Verilog數(shù)字系統(tǒng)設(shè)計(jì)教程》,北京,北京航空航天大學(xué)出版社,2013年 [2] 王金明,《數(shù)字系統(tǒng)設(shè)計(jì)與Verilog HDL》,北京,電子工業(yè)出版社,2011年
第三篇:北郵小學(xué)期c++文檔
1.++程序設(shè)計(jì)實(shí)驗(yàn)報(bào)告
姓名: 班級(jí): 學(xué)號(hào): C
要求:
猜價(jià)格游戲
編寫C++程序完成以下功能:
(1)假定有一件商品,程序用隨機(jī)數(shù)指定該商品的價(jià)格(1-1000的整數(shù));
(2)提示用戶猜價(jià)格,并輸入:若用戶猜的價(jià)格比商品價(jià)格高或低,對(duì)用戶作出相應(yīng)的提示;(3)直到猜對(duì)為止,并給出提示。
算法:
int main(){ int price,input;srand(time(NULL));price=rand()%1000;cout<<“請(qǐng)輸入數(shù)字,1到1000之間n”;cin>>input;while(input!=price){ if(input>price)cout<<“錯(cuò)誤,大了,請(qǐng)重新輸入n”;else cout<<“錯(cuò)誤,小了,請(qǐng)重新輸入n”;cin>>input;} cout<<“答對(duì)了n”;system(“pause”);} 思路:
使用srand()函數(shù)產(chǎn)生隨機(jī)數(shù),調(diào)用time.h的time()函數(shù)讀取系統(tǒng)時(shí)間作為產(chǎn)生隨機(jī)數(shù)的種子。采用循環(huán)結(jié)構(gòu),使函數(shù)運(yùn)行至猜對(duì)價(jià)格,用cout輸出,用cin輸入。
2.要求:
矩形
編寫C++程序完成以下功能:
(1)定義一個(gè)Point類,其屬性包括點(diǎn)的坐標(biāo),提供計(jì)算兩點(diǎn)之間距離的方法;(2)定義一個(gè)矩形類,其屬性包括左上角和右下角兩個(gè)點(diǎn),提供計(jì)算面積的方法;
(3)創(chuàng)建一個(gè)矩形對(duì)象,提示用戶輸入矩形左上角和右下角的坐標(biāo);
(4)觀察矩形對(duì)象以及Point類成員的構(gòu)造函數(shù)與析構(gòu)函數(shù)的調(diào)用;(5)計(jì)算其面積,并輸出。
算法:
class point { private: float x1,y1,x2,y2;public:
};
class rectangle { private: point a;public: rectangle(){ point(){
} x1=0;y1=0;x2=0;y2-0;float dis(){ return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));} float getx(){ return x2-x1;} float gety(){ return y1-y2;} void set(float a1,float b1,float a2,float b2){
} x1=a1;y1=b1;x2=a2;y2=b2;
};
} float x1,y1,x2,y2;cout<<“請(qǐng)輸入左上角點(diǎn)的橫坐標(biāo)”<
本題的關(guān)鍵在于創(chuàng)建point和rectangle兩個(gè)類,在point中聲明四個(gè)private成員分別是兩個(gè)點(diǎn)的橫坐標(biāo)和縱坐標(biāo)。聲明返回private值的函數(shù)。Rectangle中將point類作為其private成員,在public中聲明構(gòu)造函數(shù),讀入兩個(gè)點(diǎn)的橫坐標(biāo)和縱坐標(biāo),傳給point。并聲明計(jì)算面積的函數(shù),利用point中返回x,y的函數(shù)得到長(zhǎng)方形的x,y值計(jì)算其面積。
3.要求:
友元
編寫C++程序完成以下功能:
(1)定義一個(gè)Boat和Car兩個(gè)類,他們都具有私用屬性——重量;(2)編寫一個(gè)函數(shù),計(jì)算兩者的重量和。
double TotalWeight(Boat& b, Car& c);
算法:
class boat;class car { private: double w;public:
car(){
cout<<“請(qǐng)輸入車的重量:n”;
};
cin>>w;} friend double TotalWeight(boat& b,car& c);class boat { private: double w;public:
boat(){
cout<<“請(qǐng)輸入船的重量:n”;
cin>>w;} friend double TotalWeight(boat& b,car& c);};
double TotalWeight(boat& b,car& c){ return(c.w+b.w);}
void main(){
} car c;boat b;cout<<“總重量是:n”< 聲明car,boat兩個(gè)類,兩者中都包含w這個(gè)private成員,用來(lái)記錄重量,在car和boat的public中都聲明友元函數(shù)TotalWeight()。這樣TotalWeight()就能同時(shí)訪問(wèn)到car和boat的private成員了。 4.要求: 矩形 編寫C++程序完成以下功能: (6)定義一個(gè)Point類,其屬性包括點(diǎn)的坐標(biāo),提供計(jì)算兩點(diǎn)之間距離的方法;(7)定義一個(gè)矩形類,其屬性包括左上角和右下角兩個(gè)點(diǎn),提供計(jì)算面積的方法; (8)創(chuàng)建一個(gè)矩形對(duì)象,提示用戶輸入矩形左上角和右下角的坐標(biāo);(9)觀察矩形對(duì)象以及Point類成員的構(gòu)造函數(shù)與析構(gòu)函數(shù)的調(diào)用;(10)計(jì)算其面積,并輸出。 算法: void init(int a[][5]){ } for(int i=0;i<=3;i++){ } cin>>a[i][0]>>a[i][1]>>a[i][2]>>a[i][3]>>a[i][4]; void print(int a[][5]){ } void add(int a1[][5],int a2[][5],int a3[][5]){ for(int i=0;i<=3;i++) } void subtract(int a1[][5],int a2[][5],int a3[][5]){ } for(int i=0;i<=3;i++){ } for(int n=0;n<=4;n++)a3[i][n]=a1[i][n]-a2[i][n];{ } for(int n=0;n<=4;n++)a3[i][n]=a1[i][n]+a2[i][n];for(int i=0;i<=3;i++){ } for(int n=0;n<=4;n++)cout< void main(){ int a1[4][5],a2[4][5],a3[4][5];cout<<“請(qǐng)輸入第一個(gè)矩陣:n”; init(a1);getchar();cout<<“請(qǐng)輸入第二個(gè)矩陣:n”;init(a2);cout<<“和為:n”;add(a1,a2,a3);print(a3);cout<<“差為:n”;subtract(a1,a2,a3);print(a3);system(“pause”);思路: 聲明三個(gè)4行5列的數(shù)組,讀入矩陣的元素存入數(shù)組,用二重遞歸的方式遍歷數(shù)組,執(zhí)行加,減,輸出操作。 5.要求: 編寫C++程序完成以下功能: (1)假定矩陣大小為4×5(整型); (2)矩陣空間采用new動(dòng)態(tài)申請(qǐng),保存在指針中; (3)定義矩陣初始化函數(shù),可以從cin中輸入矩陣元素;(4)定義矩陣輸出函數(shù),將矩陣格式化輸出到cout; (5)定義矩陣相加的函數(shù),實(shí)現(xiàn)兩個(gè)矩陣相加的功能,結(jié)果保存在另一個(gè)矩陣中;(6)定義矩陣相減的函數(shù),實(shí)現(xiàn)兩個(gè)矩陣相減的功能,結(jié)果保存在另一個(gè)矩陣中;(7)動(dòng)態(tài)申請(qǐng)三個(gè)矩陣:A1、A2、A3;(8)初始化A1、A2; (9)計(jì)算并輸出A3 = A1加A2,A3 = A1減A2;(10)釋放矩陣空間。 算法: void main(){ int **a1,**a2,**a3;a1=new int*[4];for(int i=0;i<=4;i++) } a1[i]=new int[5];a2=new int*[4];for(int i=0;i<=4;i++)a2[i]=new int[5];a3=new int*[4];for(int i=0;i<=4;i++)a3[i]=new int[5];cout<<“請(qǐng)輸入第一個(gè)矩陣:n”;init(a1);//getchar();cout<<“請(qǐng)輸入第二個(gè)矩陣:n”;init(a2);cout<<“和為:n”;add(a1,a2,a3);print(a3);cout<<“差為:n”;subtract(a1,a2,a3);print(a3);ifree(a1);ifree(a2);ifree(a3);system(“pause”);思路: 聲明a為指向指針的指針,先申請(qǐng)一個(gè)四個(gè)元素的數(shù)組,類型為int**,用來(lái)儲(chǔ)存每行第一個(gè)元素的指針。如此聲明之后就可以用a[i][j]來(lái)訪問(wèn)某個(gè)元素了。 6.要求: 編寫C++程序完成以下功能: (1)用類來(lái)實(shí)現(xiàn)矩陣,定義一個(gè)矩陣的類,屬性包括: ? 矩陣大小,用 lines, rows(行、列來(lái)表示); ? 存貯矩陣的數(shù)組指針,根據(jù)矩陣大小動(dòng)態(tài)申請(qǐng)(new)。 (2)矩陣類的方法包括: ? ? ? ? ? ? ? 構(gòu)造函數(shù),參數(shù)是矩陣大小,需要?jiǎng)討B(tài)申請(qǐng)存貯矩陣的數(shù)組; 析構(gòu)函數(shù),需要釋放矩陣的數(shù)組指針; 拷貝構(gòu)造函數(shù),需要申請(qǐng)和復(fù)制數(shù)組; 輸入,可以從cin中輸入矩陣元素; 輸出,將矩陣格式化輸出到cout; 矩陣相加的函數(shù),實(shí)現(xiàn)兩個(gè)矩陣相加的功能,結(jié)果保存在另一個(gè)矩陣類,但必須矩陣大小相同; 矩陣相減的函數(shù),實(shí)現(xiàn)兩個(gè)矩陣相減的功能,結(jié)果保存在另一個(gè)矩陣 類,但必須矩陣大小相同。 (3)(4)(5)(6)定義三個(gè)矩陣:A1、A2、A3; 初始化A1、A2; 計(jì)算并輸出A3 = A1加A2,A3=A1減A2; 用new動(dòng)態(tài)創(chuàng)建三個(gè)矩陣類的對(duì)象:pA1、pA1、pA3; (7)初始化pA1、pA2; (8)計(jì)算并輸出pA3=pA1加pA2,pA3=pA1減pA2;(9)釋放pA1、pA1、pA3。 算法: class matric{ private: int lines,rows;int **a;public: void init(){ cin>>lines>>rows;a=new int*[lines];for(int n=0;n<=lines-1;n++) a[n]=new int[rows]; } void input(){ } for(int i=0;i<=lines-1;i++)for(int n=0;n<=rows-1;n++)cin>>a[i][n];void output(){ } for(int i=0;i<=lines-1;i++){ } for(int n=0;n<=rows-1;n++)cout< int getlines(){ return lines;} void copy(int** &b) for(int i=0;i<=lines-1;i++)for(int n=0;n<=rows-1;n++)b[i][n]=a[i][n];b=new int*[lines];for(int i=0;i<=lines-1;i++)b[i]=new int[rows]; { } void add(matric A1,matric A2) { int**a1,**a2;lines=A1.getlines();rows=A1.getrows();A1.copy(a1);A2.copy(a2); a=new int*[lines];for(int i=0;i<=lines-1;i++) a[i]=new int[rows]; for(int i=0;i<=lines-1;i++){ } for(int n=0;n<=rows-1;n++)a[i][n]=a1[i][n]+a2[i][n];} void Free() { int**temp=a; for(int i=0;i<=lines-1;i++){ delete a[i]; } } void sub(matric A1,matric A2){ int**a1,**a2;lines=A1.getlines();rows=A1.getrows(); };A1.copy(a1);A2.copy(a2); a=new int*[lines];for(int i=0;i<=lines-1;i++) a[i]=new int[rows]; } for(int i=0;i<=lines-1;i++){ } for(int n=0;n<=rows-1;n++)a[i][n]=a1[i][n]-a2[i][n];思路: 首先需要讀入數(shù)組的行列,用上題動(dòng)態(tài)申請(qǐng)數(shù)組的方法來(lái)動(dòng)態(tài)申請(qǐng)。本題的關(guān)鍵在于編寫copy函數(shù),從private中傳出數(shù)組的值,只是將上題4,5這兩個(gè)常量改成了lines,rows這兩個(gè)變量。使用copy函數(shù)的好處在與只允許單向傳出數(shù)組的元素,而不允許指令來(lái)修改數(shù)組的元素從而保護(hù)了數(shù)據(jù)的安全。執(zhí)行加減法時(shí)可以聲明兩個(gè)int**類型元素用來(lái)指向數(shù)組,用矩陣類中的copy函數(shù),分別從A1,A2中拷貝出數(shù)組的元素,拷貝出值之后,加減操作與上題一樣,用a[i][j]來(lái)訪問(wèn)數(shù)組元素即可。 7.要求: 形狀 (一)編寫C++程序完成以下功能: (1)聲明一個(gè)基類Shape(形狀),其中包含一個(gè)方法來(lái)計(jì)算面積;(2)從Shape派生兩個(gè)類矩形和圓形;(3)從矩形派生正方形; (4)分別實(shí)現(xiàn)派生類構(gòu)造函數(shù)、析構(gòu)函數(shù)和其他方法; (5)創(chuàng)建派生類的對(duì)象,觀察構(gòu)造函數(shù)、析構(gòu)函數(shù)調(diào)用次序;(6)不同對(duì)象計(jì)算面積。 算法: class shape { public: shape() { cout<<“shape 的構(gòu)造函數(shù)”< };cout<<“shape 的析構(gòu)函數(shù)”< rectangle(float a,float b){ x=a;y=b;cout<<“rectangle的構(gòu)造函數(shù)”< { } };class circle:public shape { private: float r;public: circle(float a){ } r=a;cout<<“circle的構(gòu)造函數(shù)”< { };} return 3.1416*r*r;class square:public rectangle { private: float a;public: };square(float x):rectangle(x,x){ a=x;cout<<“square的構(gòu)造函數(shù)”< 長(zhǎng)方形類和圓類繼承shape類之后,只要重載area()函數(shù)即可正確地計(jì)算出面積,正方形類繼承了長(zhǎng)方形類,不需要重載長(zhǎng)方形類的area()函數(shù),只要給長(zhǎng)方形類的x,y賦相同的值,然后就可以直接調(diào)用從長(zhǎng)方形類中繼承的area()函數(shù),直接計(jì)算面積。 8.要求: 形狀 (二)——虛函數(shù) (1)將【形狀 (一)】中的基類計(jì)算面積的方法定義為虛函數(shù),比較與【形狀 (一)】程序的差異;(2)將【形狀 (一)】中的基類定義抽象類,比較與【形狀 (一)】程序的差異。 算法: 算法與上題大致相同,只需要在area()函數(shù)前加上virtual即可。 思路: 算法與上題大致相同,只需要在area()函數(shù)前加上virtual即可,即將area()函數(shù)聲明為虛函數(shù)。 將shape()類聲明抽象類,只要把shape()中的area()函數(shù)聲明成如下形式: Virtual float area()=0;純虛函數(shù)即可。這樣shape類就是一個(gè)抽象類,抽象類可以作 為基類被繼承,但是不實(shí)例化,例如,shape a;這樣聲明一個(gè)a就是錯(cuò)誤的。 9.要求: 對(duì)Point類重載++和――運(yùn)算符 編寫C++程序完成以下功能: (1)Point類的屬性包括點(diǎn)的坐標(biāo)(x,y);(2)實(shí)現(xiàn) Point類重載++和――運(yùn)算符: ? ? ++p,--p,p++,p--。 ++和――分別表示x,y增加或減少1。 算法: class point { private: int x,y;public: point operator++(int) { } point a=*this;x++;y++;return a;point operator++(){ x++;y++;return *this;} point operator--(int){ point a=*this;x--;y--;return a;} point operator--(){ x--;y--; };return *this;} void ini(){ cin>>x;} cin>>y;point(){ } cout<<“請(qǐng)輸入x:”< 本題的關(guān)鍵在于表示出a++和++a的不同,a++是先引用a的值然后再執(zhí)行++,++a是先執(zhí)行++然后再引用a的值。在對(duì)++的重載時(shí)可以在()中加入int加以區(qū)分a++和++a,如下point operator++(int),point operator++()。要做出a++的效果就需要申請(qǐng)point temp,這個(gè)中間變量,temp=this,把當(dāng)前對(duì)象賦給a,然后再對(duì)當(dāng)前對(duì)象執(zhí)行++操作,最后返回temp,因?yàn)閠emp儲(chǔ)存的是未執(zhí)行++之前的值,所以能夠做出先引用a的值在執(zhí)行++的效果?!倪^(guò)程與++完全相同。要求: 流式IO (一)編寫C++程序完成以下功能: (1)使用ofstream 向一個(gè)文本文件中輸出各種類型的數(shù)據(jù),并打開文件觀察結(jié)果: ? 整數(shù)、無(wú)符號(hào)整型、長(zhǎng)整型、浮點(diǎn)型、字符串、?? (2)用十進(jìn)制、八進(jìn)制、十六進(jìn)制方式向文本文件中輸出整數(shù);(3)使用控制符和成員函數(shù)來(lái)控制輸出的格式: ? set()precision()...算法: void main(){ } ofstream outfile(“xx.txt”);int integer;unsigned int uint;long int lint;float f;string s;cout<<“輸入整數(shù):n”;cin>>integer;cout<<“輸入無(wú)符號(hào)整型:n”;cin>>uint;cout<<“輸入長(zhǎng)整型:n”;cin>>lint;cout<<“輸入浮點(diǎn)型:n”;cin>>f;cout<<“輸入字符串:n”;cin>>s;outfile<<“十進(jìn)制:”< .進(jìn)行對(duì)文件的操作需要聲明頭文件#include 11.要求: 流式IO (三)編寫C++程序完成以下功能:(1)輸入一個(gè)文本文件名; (2)打開文件名,在該文件的每一行前面加上一個(gè)行號(hào),保存在另外一個(gè)文本文件中。 算法: void main(){ } string a;cout<<“請(qǐng)輸入文件名:n”;cin>>a;ifstream in(a);ofstream out(“out.txt”);string s;int i=1;while(getline(in,s)){ out< 本實(shí)驗(yàn)比較簡(jiǎn)單。只需要聲明一個(gè)字符串a(chǎn)用來(lái)儲(chǔ)存讀入的文件名,再用ifstream類來(lái)聲明一個(gè)對(duì)象,打開a這個(gè)文件。利用getline()函數(shù),geiline函數(shù)能夠自動(dòng)從文件中讀入一行數(shù)據(jù),每讀入一行數(shù)據(jù)就在其前面加上行號(hào),行號(hào)可以用變量i來(lái)計(jì)數(shù),每讀一行就加1,并將這個(gè)就上行號(hào)的一行數(shù)據(jù)寫入out.txt中,知道無(wú)法讀入,就結(jié)束程序。 12.要求: 電話本 編寫C++程序完成以下功能: (1)實(shí)現(xiàn)簡(jiǎn)單電話本功能,用姓名來(lái)搜索電話號(hào)碼;(2)用戶輸入姓名,程序查找并輸出結(jié)果;(3)用戶可以通過(guò)輸入,添加姓名和電話號(hào)碼;(4)用戶可以刪除姓名和電話號(hào)碼;(5)電話本可以保存在指定文件中; (6)電話可被從指定文件中讀入到內(nèi)存。 算法: #include class record { private: string name[50],number[50];public: record(){ int i=0; string na,nu; ifstream file(“phonenumber.txt”); file>>na>>nu; while(na.compare(“..”)) { name[i]=na; number[i]=nu; file>>na>>nu; i++; } for(i;i<=49;i++) { name[i]=“..”; number[i]=“..”; } } void search(){ int i=0; string na; cout<<“請(qǐng)輸入名字:”< cin>>na; while(name[i].compare(“..”)) { if(!name[i].compare(na)) { cout<<“結(jié)果是:”< return;} i++;} cout<<“無(wú)該記錄”;} void add(){ string na,nu;cout<<“請(qǐng)輸入名字:”< if(!name[i].compare(“..”)){ //cout< return;} } cout<<“已滿,無(wú)法插入”< } ofstream file(“phonenumber.txt”);for(int i=0;i<=49;i++){ } if(!name[i].compare(“..”))break;if(name[i].compare(“,”)) file< };void del(){ } int i=0;string na;cout<<“請(qǐng)輸入要?jiǎng)h除的名字:”< if(!name[i].compare(na)){ } i++;name[i]=“,”;number[i]=“,”;cout<<“刪除成功?!? for(int i=0;i<=49;i++){ cout< ”< } for(int i=0;i<=49;i++){ } if(name[i].compare(“..”)&&name[i].compare(“,”))cout< number:”< void main(){ int choice; int i=0;record temp;while(1) { cout<<“nnn功能列表:n 1.代表用姓名來(lái)搜索電話號(hào)碼n 2.代表添加姓名和號(hào)碼n 3.代表刪除一條記錄n 4.代表儲(chǔ)存電話本n 5.輸出所有記錄nn請(qǐng)選擇你要的功能:”< cin>>choice; } switch(choice){ } case 1: temp.search();break;case 2: temp.add();break;case 3: temp.del();break;case 4: temp.store();break;case 5: temp.show();break;} system(“pause”);思路: 程序的大體思路是:聲明電話本類,private成員是一個(gè)50個(gè)元素的string型數(shù)組,運(yùn)行程序時(shí)就將文件中的電話記錄讀入到內(nèi)存中(string數(shù)組),方便操作。從內(nèi)存中讀入記錄的語(yǔ)句寫在電話本類的構(gòu)造函數(shù)中,使得聲明類時(shí)就可以自動(dòng)讀入記錄。文件中最后一行用”....”來(lái)標(biāo)記記錄的結(jié)束。對(duì)于所有操作都寫進(jìn)了電話本類中,本程序可以執(zhí)行五個(gè)基本操作:1.按名字查找記錄,查找成功返回該條記錄,查找失敗輸出“無(wú)該記錄” 2.添加記錄,添加記錄會(huì)要求輸入名字與電話,如果記錄數(shù)小于50條會(huì)顯示“成功插入”,如果記錄已經(jīng)等于50條會(huì)顯示“插入失敗” 3.按名字刪除某條記錄,執(zhí)行刪除操作時(shí)會(huì)先查詢?cè)撚涗?,如果存在該記錄就將該記錄賦為“,,”表示刪除,如果不存在該記錄返回”不存在該記錄” 4.存儲(chǔ)命令,可以將內(nèi)存中的記錄再次存入到文件當(dāng)中 5.輸出命令,輸出當(dāng)前內(nèi)存中的所有記錄。命令的選擇可以用switch語(yǔ)句實(shí)現(xiàn)。 感想: 經(jīng)過(guò)一學(xué)期的學(xué)習(xí),我已經(jīng)對(duì)c++有了初步的掌握,了解了類這 個(gè)全新的概念。類的應(yīng)用可以方便管理函數(shù),不需要像c那樣凌亂得寫一大堆函數(shù),要調(diào)用時(shí)需要向上找到這個(gè)這個(gè)函數(shù),產(chǎn)看它的功能與傳入傳出的要求。我認(rèn)為類更大作用是可以有效地保護(hù)數(shù)據(jù),不被隨意地更改,也方便了他人的二次開發(fā),只需要了解頭文件中包含的類,類的方法,就可以方便地實(shí)現(xiàn)他人早已實(shí)現(xiàn)的功能,方便后人開發(fā)。比如試驗(yàn)中用到的 面向?qū)ο蟪绦蛟O(shè)計(jì)與實(shí)踐 c++實(shí)驗(yàn)總結(jié)報(bào)告 ——網(wǎng)絡(luò)工程14班饒思哲 ——學(xué)號(hào):2013211574 實(shí)驗(yàn)一簡(jiǎn)單C++程序設(shè)計(jì) 1.猜價(jià)格游戲 編寫C++程序完成以下功能: (1)假定有一件商品,程序用隨機(jī)數(shù)指定該商品的價(jià)格(1-1000的整數(shù)); (2)提示用戶猜價(jià)格,并輸入:若用戶猜的價(jià)格比商品價(jià)格高或低,對(duì)用戶作出相應(yīng)的提示; (3)直到猜對(duì)為止,并給出提示。 題目1-1總結(jié): 1)本題需要隨機(jī)生成整數(shù),我開始只使用rand(),即price=rand();來(lái)生成隨機(jī)整數(shù) 但這樣只是一個(gè)偽隨機(jī)函數(shù),每一次重新打開程序生成的數(shù)都是一致的。因此加入時(shí)間隨機(jī)種子:srand((unsigned)time(NULL))2)個(gè)人改進(jìn)1:定義最大值最小值,在每次猜測(cè)數(shù)字時(shí)顯示應(yīng)猜的數(shù)字范圍,作為提示。 想到這個(gè)是因?yàn)橛幸淮尾铝撕芏啾槎紱](méi)猜到,一時(shí)突然忘記猜到什么范圍,然后往前翻猜過(guò)的數(shù)字和大小感覺(jué)相當(dāng)麻煩,所以就添上了應(yīng)猜范圍,方便再一次猜數(shù)。3)個(gè)人改進(jìn)2:本來(lái)有一個(gè)判斷條件判斷生成的隨機(jī)數(shù)是不是1~1000范圍內(nèi),而后更進(jìn)為隨機(jī)生成整數(shù)對(duì)1000取余得到0~999整數(shù),再+1得到1~1000的整數(shù)。 實(shí)驗(yàn)二類與對(duì)象 1.矩形 編寫C++程序完成以下功能: (1)定義一個(gè)Point類,其屬性包括點(diǎn)的坐標(biāo),提供計(jì)算兩點(diǎn)之間距離的方法;(2)定義一個(gè)矩形類,其屬性包括左上角和右下角兩個(gè)點(diǎn),提供計(jì)算面積的方法;(3)創(chuàng)建一個(gè)矩形對(duì)象,提示用戶輸入矩形左上角和右下角的坐標(biāo);(4)觀察矩形對(duì)象以及Point類成員的構(gòu)造函數(shù)與析構(gòu)函數(shù)的調(diào)用;(5)計(jì)算其面積,并輸出。 題目2-1總結(jié): 1)這一題是第一次用到class類的題目,開始并不明白為何要定義class,然后還需要區(qū)分public和private。而后來(lái)去圖書館借了書看到c++最大特色就是可以封裝,定義私有屬性和公有函數(shù),以確保有些函數(shù)和參數(shù)不會(huì)被輕易訪問(wèn)到,降低錯(cuò)誤率。2)class類在最起初定義時(shí)總是在class Rectangle那一行報(bào)錯(cuò),經(jīng)查書發(fā)現(xiàn)class定義最后一個(gè)大括號(hào)后有分號(hào),開始并沒(méi)有加上。 3)起初在調(diào)用class中函數(shù)時(shí)用c調(diào)用的方式,沒(méi)有跟面向的對(duì)象結(jié)合,導(dǎo)致編譯出錯(cuò),而后從distance()改為p.distance()就正確了。 4)計(jì)算兩點(diǎn)距離和面積運(yùn)用開方和絕對(duì)值函數(shù),前面若沒(méi)有加頭文件math.h則會(huì)報(bào)錯(cuò)。5)輸入左上角右下角坐標(biāo)時(shí),若輸入不當(dāng),可能會(huì)出現(xiàn)面積為負(fù)值的情況,所以加上絕對(duì)值函數(shù)保證面積非負(fù)。 6)起初不知道構(gòu)造函數(shù)和析構(gòu)函數(shù)的定義和用法,經(jīng)翻閱書籍和運(yùn)行程序得知構(gòu)造函數(shù)在創(chuàng)建對(duì)象時(shí)調(diào)用,可以有多個(gè)。而析構(gòu)函數(shù)則在釋放對(duì)象時(shí)調(diào)用,一般每一個(gè)class中都只有一個(gè)默認(rèn)析構(gòu)函數(shù)。且構(gòu)造函數(shù)與類名稱一致,析構(gòu)函數(shù)則在類名稱前加~。 2.友元 編寫C++程序完成以下功能: (1)定義一個(gè)Boat和Car兩個(gè)類,他們都具有私用屬性——重量; (2)編寫一個(gè)函數(shù),計(jì)算兩者的重量和。double TotalWeight(Boat& b, Car& c); 題目2-3總結(jié): 1)友元函數(shù):在兩個(gè)對(duì)象中都使用到時(shí),可以使用友元函數(shù),并在類外單獨(dú)定義。 友元函數(shù)是允許在類外訪問(wèn)類中的任何成員的。開始在類外單獨(dú)定義時(shí)跟類的成員函數(shù)單獨(dú)定義混淆,寫成了double Boat::TotalWeight(),導(dǎo)致編譯錯(cuò)誤,而后發(fā)現(xiàn)友元函數(shù)直接用函數(shù)名和函數(shù)返回值類型定義即可,不需要加上class類的名稱。 2)起初定義完class Boat和class Car后發(fā)現(xiàn)編譯錯(cuò)誤,在友元函數(shù)的聲明那一行出錯(cuò),而后發(fā)現(xiàn)在這行之前沒(méi)有定義Car類,于是將其在最開頭聲明出來(lái),通過(guò)。 3)起初并沒(méi)有加上boat和car類的構(gòu)造函數(shù)和析構(gòu)函數(shù),可是經(jīng)上網(wǎng)查閱,默認(rèn)構(gòu)造函數(shù)和析構(gòu)函數(shù)可以系統(tǒng)自動(dòng)生成,但析構(gòu)函數(shù)只能刪除成員指針,并不能釋放指針指向的空間,所以若沒(méi)有申請(qǐng)動(dòng)態(tài)內(nèi)存,析構(gòu)函數(shù)可不寫出,若申請(qǐng),則需自行在析構(gòu)函數(shù)中delete。 實(shí)驗(yàn)三數(shù)組與指針 1.矩陣 (一)編寫C++程序完成以下功能: (1)假定矩陣大小為4×5(整型數(shù)組表示); (2)定義矩陣初始化函數(shù),可以從cin中輸入矩陣元素;(3)定義矩陣輸出函數(shù),將矩陣格式化輸出到cout; (4)定義矩陣相加的函數(shù),實(shí)現(xiàn)兩個(gè)矩陣相加的功能,結(jié)果保存在另一個(gè)矩陣中;(5)定義矩陣相減的函數(shù),實(shí)現(xiàn)兩個(gè)矩陣相減的功能,結(jié)果保存在另一個(gè)矩陣中;(6)定義三個(gè)矩陣:A1、A2、A3;(7)初始化A1、A2; (8)計(jì)算并輸出:A3 = A1加A2,A3 = A1減A2。 題目3-1總結(jié): 1)起初在矩陣相加相減的賦值中所用語(yǔ)句為:m.matrix[i][j]=a.matrix[i][j]+b.matrix[i][j] 但是運(yùn)行程序發(fā)現(xiàn)m矩陣所有元素都是0。經(jīng)單步調(diào)試,發(fā)現(xiàn)并沒(méi)有賦值成功。經(jīng)查閱書籍,了解到this指針是指向類的對(duì)象的地址,便改用this->matrix[i][j]作為賦值對(duì)象,最后程序正確。 2)個(gè)人改進(jìn):將行數(shù)列數(shù)在文件開頭用define定義,可以隨時(shí)更改。 3)經(jīng)多次調(diào)試后,程序運(yùn)行結(jié)果正確,但矩陣看起來(lái)非?;靵y,因?yàn)椴](méi)有行列對(duì)齊,于是在打印矩陣中每列直接用table空格隔開,保證美觀。2.矩陣 (二)編寫C++程序完成以下功能: (1)假定矩陣大小為4×5(整型); (2)矩陣空間采用new動(dòng)態(tài)申請(qǐng),保存在指針中; (3)定義矩陣初始化函數(shù),可以從cin中輸入矩陣元素;(4)定義矩陣輸出函數(shù),將矩陣格式化輸出到cout; (5)定義矩陣相加的函數(shù),實(shí)現(xiàn)兩個(gè)矩陣相加的功能,結(jié)果保存在另一個(gè)矩陣中;(6)定義矩陣相減的函數(shù),實(shí)現(xiàn)兩個(gè)矩陣相減的功能,結(jié)果保存在另一個(gè)矩陣中;(7)動(dòng)態(tài)申請(qǐng)三個(gè)矩陣:A1、A2、A3;(8)初始化A1、A2; (9)計(jì)算并輸出A3 = A1加A2,A3 = A1減A2;(10)釋放矩陣空間。 題目3-2總結(jié): 1)與3-1題目的區(qū)別在int main中用new函數(shù)動(dòng)態(tài)申請(qǐng)內(nèi)存,然后析構(gòu)函數(shù)需要釋放申請(qǐng)的空間而不只是自動(dòng)刪除指向空間的指針。析構(gòu)函數(shù)如圖。 一開始并不知道該怎么動(dòng)態(tài)申請(qǐng)內(nèi)存,在c中使用malloc可是c++中并不一樣。經(jīng)查閱書籍,發(fā)現(xiàn)c++中申請(qǐng)釋放內(nèi)存用new和delete非常簡(jiǎn)便。2)指針調(diào)用類成員函數(shù)一開始不知道該怎么寫,寫成A1.input()結(jié)果編譯錯(cuò)誤。經(jīng)查閱書籍,得知指針調(diào)用成員函數(shù)需寫成A1->input()的形式。 3)在釋放動(dòng)態(tài)內(nèi)存時(shí),用到delete函數(shù)。但開始的時(shí)候?qū)慸elete matrix時(shí)候會(huì)出問(wèn)題。上網(wǎng)查詢后得到以下delete用法。 Delete用法:當(dāng)釋放內(nèi)部類型,如int double型時(shí),直接delete a 即可。若是釋放自己定義的class類型,需用delete[]matrix來(lái)釋放內(nèi)存。3.矩陣 (三)編寫C++程序完成以下功能: (1)用類來(lái)實(shí)現(xiàn)矩陣,定義一個(gè)矩陣的類,屬性包括: ? 矩陣大小,用 lines, rows(行、列來(lái)表示); ? 存貯矩陣的數(shù)組指針,根據(jù)矩陣大小動(dòng)態(tài)申請(qǐng)(new)。(2)矩陣類的方法包括: ? 構(gòu)造函數(shù),參數(shù)是矩陣大小,需要?jiǎng)討B(tài)申請(qǐng)存貯矩陣的數(shù)組; ? 析構(gòu)函數(shù),需要釋放矩陣的數(shù)組指針; ? 拷貝構(gòu)造函數(shù),需要申請(qǐng)和復(fù)制數(shù)組; ? 輸入,可以從cin中輸入矩陣元素; ? 輸出,將矩陣格式化輸出到cout; ? 矩陣相加的函數(shù),實(shí)現(xiàn)兩個(gè)矩陣相加的功能,結(jié)果保存在另一個(gè)矩陣類,但必須矩陣大小相同; ? 矩陣相減的函數(shù),實(shí)現(xiàn)兩個(gè)矩陣相減的功能,結(jié)果保存在另一個(gè)矩陣類,但必須矩陣大小相同。 (3)定義三個(gè)矩陣:A1、A2、A3;(4)初始化A1、A2; (5)計(jì)算并輸出A3 = A1加A2,A3=A1減A2; (6)用new動(dòng)態(tài)創(chuàng)建三個(gè)矩陣類的對(duì)象:pA1、pA1、pA3;(7)初始化pA1、pA2; (8)計(jì)算并輸出pA3=pA1加pA2,pA3=pA1減pA2;(9)釋放pA1、pA1、pA3。 題目3-3總結(jié): 1)拿到這道題我認(rèn)為要定義一個(gè)矩陣類對(duì)象,其中包括3-1和3-2一樣的input函數(shù),print函數(shù),plus函數(shù),subtract函數(shù),還有新增的構(gòu)造函數(shù)析構(gòu)函數(shù)。一上來(lái)我認(rèn)為class中屬性不再是之前的某行某列的數(shù)值,而是行數(shù)和列數(shù)還有矩陣的頭指針。根據(jù)輸入的行數(shù)列數(shù)來(lái)申請(qǐng)內(nèi)存,再將數(shù)值存入不同的位置。然后在主函數(shù)中分為兩個(gè)部分,一個(gè)是直接創(chuàng)建對(duì)象,另一個(gè)是創(chuàng)建矩陣數(shù)組指針。 2)第一部分跟前兩題類似,所以很快就調(diào)試完成并且得到了正確的結(jié)果,但是指針部分一直出現(xiàn)問(wèn)題。最開始是三個(gè)矩陣分別申請(qǐng)內(nèi)存,這樣的后果就是要輸入三次行數(shù)和列數(shù)的數(shù)值,有可能出現(xiàn)行列數(shù)不相等的情況,給之后的加減操作帶來(lái)麻煩。因此想到讓A1矩陣申請(qǐng)內(nèi)存,而讓A2、A3矩陣都與A1相等,就可以避免多次輸入行列數(shù),且保證了矩陣大小相等。但這樣輸入第一個(gè)矩陣數(shù)值后,矩陣元素獲取正常。可當(dāng)輸入第二個(gè)矩陣的數(shù)值以后,A1和A2矩陣的元素都變?yōu)榈诙€(gè)矩陣的元素,即第一個(gè)矩陣的元素被覆蓋掉。導(dǎo)致和矩陣為第二個(gè)矩陣的2倍,差矩陣都是零。經(jīng)過(guò)反復(fù)調(diào)試,曾經(jīng)試過(guò)將含參構(gòu)造函數(shù)中輸入行列數(shù)改到主函數(shù)中,再給A1申請(qǐng)動(dòng)態(tài)內(nèi)存。但是因?yàn)锳2和A3還是初始化跟A1相等,結(jié)果并沒(méi)有改變,還是錯(cuò)誤的。而后想到用含參構(gòu)造函數(shù)來(lái)申請(qǐng)動(dòng)態(tài)內(nèi)存,輸入固定的行列數(shù)后,用確定的行列數(shù)來(lái)new Matrix(x,y),這樣一來(lái)不僅矩陣大小相等,而且也不會(huì)存在前一個(gè)矩陣的值被后一個(gè)覆蓋掉的問(wèn)題。經(jīng)過(guò)調(diào)試,終于得到了正確的結(jié)果。 3)調(diào)試過(guò)程中我了解到指針初始化和賦值過(guò)程中是容易發(fā)生樹脂覆蓋的,所以盡量不要將指針初始化成跟某個(gè)指針相等。 實(shí)驗(yàn)四繼承與派生 1、形狀 (一)編寫C++程序完成以下功能: (1)聲明一個(gè)基類Shape(形狀),其中包含一個(gè)方法來(lái)計(jì)算面積;(2)從Shape派生兩個(gè)類矩形和圓形;(3)從矩形派生正方形; (4)分別實(shí)現(xiàn)派生類構(gòu)造函數(shù)、析構(gòu)函數(shù)和其他方法; (5)創(chuàng)建派生類的對(duì)象,觀察構(gòu)造函數(shù)、析構(gòu)函數(shù)調(diào)用次序;(6)不同對(duì)象計(jì)算面積。 題目4-1總結(jié): 1)這一題主要是函數(shù)的派生方法使用,經(jīng)過(guò)查閱書籍,得知在class定義后加上:: public(基類名稱)便是作為一個(gè)派生類的定義,可以沿用基類中的成員函數(shù)。 2)并且經(jīng)過(guò)對(duì)構(gòu)造函數(shù)和析構(gòu)函數(shù)調(diào)用,得知是先調(diào)用基類的構(gòu)造函數(shù),再調(diào)用派生類的構(gòu)造函數(shù)創(chuàng)建派生類對(duì)象,在程序結(jié)束時(shí),先調(diào)用派生類的析構(gòu)函數(shù)釋放派生類對(duì)象,再調(diào)用基類的析構(gòu)函數(shù)釋放基類對(duì)象。 2、形狀 (二)——虛函數(shù)(1)將【形狀 (一)】中的基類計(jì)算面積的方法定義為虛函數(shù),比較與【形狀 (一)】程序的差異; (2)將【形狀 (一)】中的基類定義抽象類,比較與【形狀 (一)】程序的差異。 題目4-2總結(jié): 1)起初并不知道虛函數(shù)的作用,后來(lái)經(jīng)過(guò)查閱書籍得知在基類中定義虛函數(shù),是為了在派生類中定義這一函數(shù)的不同操作方式。并且起初只改變了基類中area函數(shù),在其前面加了virtual,但并沒(méi)有體現(xiàn)出虛函數(shù)的運(yùn)用。而后看到書上虛函數(shù)的應(yīng)用,發(fā)現(xiàn)虛函數(shù)是可以讓一個(gè)基類指針調(diào)用派生類相應(yīng)函數(shù)的。于是經(jīng)過(guò)改進(jìn),在主函數(shù)中定義了3個(gè)基類指針,分別指向派生矩形類對(duì)象、派生圓形類對(duì)象、派生正方形對(duì)象,然后并非通過(guò)對(duì)象名稱調(diào)用成員函數(shù),而是用基類指針調(diào)用派生類中的area函數(shù),充分體現(xiàn)出對(duì)虛函數(shù)的應(yīng)用。 2)這一題雖然跟上一題相似,但卻因?yàn)檫\(yùn)用了虛函數(shù)而變得不同。這一題讓我對(duì)虛函數(shù)有了更加深入的了解。也了解到調(diào)用類中的成員函數(shù)不一定非要用對(duì)象名或者對(duì)象指針調(diào)用,也可以用其基類的指針通過(guò)虛函數(shù)調(diào)用。 實(shí)驗(yàn)五多態(tài)性 1、對(duì)Point類重載++和――運(yùn)算符 編寫C++程序完成以下功能: (1)Point類的屬性包括點(diǎn)的坐標(biāo)(x,y);(2)實(shí)現(xiàn) Point類重載++和――運(yùn)算符: ? ++p,--p,p++,p--。 ? ++和――分別表示x,y增加或減少1。 題目5-1總結(jié): 1)對(duì)于符號(hào)的重載開始并不理解什么意思,后來(lái)得知是重新定義一下++、--操作的過(guò)程,包括自加自減和賦值。 2)通過(guò)這一道題,對(duì)于自加符號(hào)的前后置的區(qū)別又有了更深的印象。起初在—p和++p的時(shí)候都只是將x和y加一,并沒(méi)有賦值,導(dǎo)致在主函數(shù)中寫q=++p和q=--p時(shí)q保持原值,造成結(jié)果錯(cuò)誤。單步調(diào)試后發(fā)現(xiàn)這一錯(cuò)誤,及時(shí)改正過(guò)來(lái)。3)程序結(jié)果正確后編寫菜單界面,使其操作步驟更加清晰明了。實(shí)驗(yàn)六流式IO 1、流式IO (一)編寫C++程序完成以下功能: (1)使用ofstream向一個(gè)文本文件中輸出各種類型的數(shù)據(jù),并打開文件觀察結(jié)果: ? 整數(shù)、無(wú)符號(hào)整型、長(zhǎng)整型、浮點(diǎn)型、字符串、…… (2)用十進(jìn)制、八進(jìn)制、十六進(jìn)制方式向文本文件中輸出整數(shù);(3)使用控制符和成員函數(shù)來(lái)控制輸出的格式: ? set()precision()...題目6-1總結(jié): 1)文件流主要是向文件中輸入信息和從文件讀取信息。而跟c語(yǔ)言不同的是c需要fopen來(lái)打開一個(gè)文件,而c++中只需要用fstream函數(shù)。且文件輸入方式也比c語(yǔ)言簡(jiǎn)便很多。2)轉(zhuǎn)換進(jìn)制開始想到的是用數(shù)學(xué)的方法算出不同進(jìn)制下的數(shù)值,再輸入文件中,但非常的麻煩。后經(jīng)查閱書籍,看到有指定進(jìn)制的函數(shù),可以用來(lái)修改默認(rèn)的十進(jìn)制:oct和hex。3)最后程序正確后,編輯menu顯示菜單,使操作更加清晰明了。 2、流式 (三)編寫C++程序完成以下功能:(1)輸入一個(gè)文本文件名; (2)打開文件名,在該文件的每一行前面加上一個(gè)行號(hào),保存在另外一個(gè)文本文件中。 題目6-3總結(jié): 1)因?yàn)榈谝活}流式已經(jīng)嘗試過(guò)向文件中輸入信息,而經(jīng)過(guò)翻閱書籍得知從文件中可以用getline整行讀取字符串,便可以輕易的將文件內(nèi)容加上行數(shù),并輸出到另一個(gè)文本文件中。 2)本題我覺(jué)得最大的困難在于輸入文本文件名,并打開文件名。書上也并沒(méi)有關(guān)于打開文件名的相關(guān)資料,于是上網(wǎng)查詢,發(fā)現(xiàn)可以用string.h中的c_str()函數(shù)來(lái)獲取鍵盤輸入的文件名字符串,并打開文件名。 3)因?yàn)槲募幚聿](méi)有在屏幕上有所顯示,為了讓每一步操作更加明了,在復(fù)制完一行后會(huì)在屏幕上打出某某行復(fù)制成功,使程序運(yùn)行過(guò)程更清晰。實(shí)驗(yàn)七 C++程序設(shè)計(jì)應(yīng)用 1、電話本 編寫C++程序完成以下功能: (1)實(shí)現(xiàn)簡(jiǎn)單電話本功能,用姓名來(lái)搜索電話號(hào)碼;(2)用戶輸入姓名,程序查找并輸出結(jié)果;(3)用戶可以通過(guò)輸入,添加姓名和電話號(hào)碼;(4)用戶可以刪除姓名和電話號(hào)碼;(5)電話本可以保存在指定文件中;(6)電話可被從指定文件中讀入到內(nèi)存。 題目7-1總結(jié): 1)電話本分為幾大部分:讀到內(nèi)存、輸出到文件、新增聯(lián)系人、刪除聯(lián)系人、查找聯(lián)系人。因?yàn)槭亲x到內(nèi)存,就想到了可以用數(shù)組或者鏈表來(lái)構(gòu)成電話本的框架。而這兩種方式在c語(yǔ)言用過(guò),所以邏輯方便很熟悉,于是選擇了比較簡(jiǎn)便的數(shù)組,這樣不易出現(xiàn)指針錯(cuò)誤的情況。 2)個(gè)人改進(jìn)1: 新增聯(lián)系人函數(shù)中,就是將聯(lián)系人信息從鍵盤逐項(xiàng)讀入,然后選擇將聯(lián)系人插入到什么位置。若一共6個(gè)聯(lián)系人,插入位置輸入3,則插入第三個(gè)位置,后面的聯(lián)系人依次向后移一位。但若是一共6個(gè)聯(lián)系人,插入位置輸入8,則會(huì)提醒輸入位置不當(dāng),直接將聯(lián)系人插入到最后一個(gè)位置,即第七。 3)刪除、查找、修改函數(shù)中都用到了用姓名查找,于是將其單獨(dú)摘出來(lái)定義findposition,找到聯(lián)系人位置。起初寫的是將輸入的字符串逐個(gè)跟name比較,即a == name,但卻發(fā)現(xiàn)這樣程序查找出來(lái)聯(lián)系人永遠(yuǎn)不存在。經(jīng)上網(wǎng)查閱,發(fā)現(xiàn)字符串相等不能直接像字符一樣用==來(lái)判斷,而是用><來(lái)判斷,于是將其改為>=&&<=。但一開始由于疏忽,將&&且關(guān)系寫成||或關(guān)系,導(dǎo)致查找出來(lái)永遠(yuǎn)是第一個(gè)聯(lián)系人。后來(lái)單步調(diào)試發(fā)現(xiàn)錯(cuò)誤,改正過(guò)來(lái)。 4)個(gè)人改進(jìn)2: 刪除、查找、修改中,若是聯(lián)系人不存在,需要輸出提示。而我另外又加了一句,并不是說(shuō)不存在就直接返回,而是讓用戶自己選擇是繼續(xù)輸入姓名還是返回主菜單。也讓手誤的時(shí)候不再把前面的操作進(jìn)行一遍,留有手誤的余地。5)修改聯(lián)系人模塊,一開始class類中只有setPhone函數(shù),并沒(méi)有setname,setmobile等等,而是直接將所有屬性值組合起來(lái)構(gòu)建聯(lián)系人。這樣的后果就是在修改聯(lián)系人的時(shí)候,只修改了一項(xiàng),但是并不能賦值進(jìn)去。表面上雖然修改了,可查找后發(fā)現(xiàn)聯(lián)系人的信息并沒(méi)有改變。后來(lái)將每一項(xiàng)信息都分別set,經(jīng)過(guò)調(diào)試最終結(jié)果正確。 6)從指定文件將電話本讀入內(nèi)存,就跟實(shí)驗(yàn)6第三題的流式很相似,都是逐行讀取信息,只是讀取后是存入數(shù)組的不同屬性值中。開始不知道該怎么確定文本文件中不再有聯(lián)系人信息,而后上網(wǎng)查資料發(fā)現(xiàn)當(dāng)文件中不再有信息可以讀的時(shí)候,infile>>name>>mobile…的值就是0,便可停止操作。而姓名等信息也可以逐個(gè)賦值到phone類數(shù)組里。 7)個(gè)人改進(jìn)3: 電話本不需要手動(dòng)保存在指定文件中,主菜單也不再顯示這一操作,而是當(dāng)選擇退出電話本時(shí)自動(dòng)保存到輸出的output.txt中。 8)最后程序執(zhí)行結(jié)果正確,編寫menu菜單界面,美化界面并且讓操作編號(hào)更加清晰。 北京郵電大學(xué)信息與通信工程學(xué)院 小學(xué)期AVR單片機(jī)實(shí)驗(yàn)報(bào)告 實(shí)驗(yàn)題目: 基于ATmega16L單片機(jī)的電子琴設(shè)計(jì) 學(xué)生姓名:學(xué)渣 班 級(jí):2012XXXXXX 班內(nèi)序號(hào):XX 學(xué) 號(hào):2012XXXXXX 日 期:2014年9月30日 同組同學(xué):學(xué)渣 第1頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 目錄: 一、實(shí)驗(yàn)介紹......................................3 1.1實(shí)驗(yàn)課題名稱.................................3 1.2實(shí)驗(yàn)平臺(tái).....................................3 1.3實(shí)驗(yàn)課題關(guān)鍵字 ..............................3 1.4實(shí)驗(yàn)摘要.....................................3 二、小組分工......................................3 三、基本題目訓(xùn)練——流水燈與數(shù)碼管秒表計(jì)時(shí)器.......3 3.1實(shí)現(xiàn)功能......................................3 3.2程序代碼分析..................................4 3.3實(shí)驗(yàn)結(jié)果圖片...................................7 四、有關(guān)發(fā)聲的基礎(chǔ)知識(shí)............................7 五、電子琴的設(shè)計(jì)與測(cè)試..............................9 5.1設(shè)計(jì)過(guò)程......................................9 5.2實(shí)驗(yàn)所需元器件.................................9 5.3實(shí)驗(yàn)程序主要流程圖.............................10 5.4實(shí)驗(yàn)原理及原理圖...............................10 5.4.1實(shí)驗(yàn)原理....................................10 5.4.2原理圖.....................................11 5.5各個(gè)模塊的設(shè)計(jì)與講解............................11 5.6程序源代碼及程序分析..........................14 5.7實(shí)驗(yàn)結(jié)果.......................................24 六、排錯(cuò)過(guò)程.........................................26 七、心得體會(huì)..........................................29 八、參考文獻(xiàn)..........................................32 九、意見與建議........................................33 第2頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 一、實(shí)驗(yàn)介紹: 1.1實(shí)驗(yàn)課題名稱:基于ATmega16L單片機(jī)的電子琴設(shè)計(jì) 1.2實(shí)驗(yàn)平臺(tái):本實(shí)驗(yàn)所用平臺(tái)為AVR Studio 4 1.3實(shí)驗(yàn)課題關(guān)鍵字: ATmega16L型單片機(jī) 電子琴 鍵盤按鍵 LCD液晶顯示屏 1.4實(shí)驗(yàn)摘要: 本實(shí)驗(yàn)設(shè)計(jì)的電子琴擁有可視化操作界面,能實(shí)現(xiàn)即時(shí)彈奏音樂(lè)、音樂(lè)播放、音樂(lè)變速、音樂(lè)變調(diào),并可以進(jìn)行任意長(zhǎng)度錄音(通過(guò)按鍵記錄音階)等功能 二、小組分工: ? XXX負(fù)責(zé)電路硬件的連接和報(bào)告的撰寫 ? XXX負(fù)責(zé)程序代碼的編寫 ? XXX負(fù)責(zé)資料的收集整理和查閱 三、基本題目訓(xùn)練——流水燈與數(shù)碼管秒表計(jì)時(shí)器 3.1功能:八盞LED二極管按順序依次循環(huán)點(diǎn)亮,實(shí)現(xiàn)流水燈的效果,同時(shí)兩只數(shù)碼管分別代表秒和十分之一秒,進(jìn)行秒表計(jì)時(shí),配有 第3頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 兩個(gè)按鍵,實(shí)現(xiàn)計(jì)時(shí)過(guò)程中的暫停和繼續(xù),同時(shí)在按下暫停鍵的時(shí)候蜂鳴器會(huì)響一聲。利用ATmega16的寄存器中斷功能,實(shí)現(xiàn)流水燈和數(shù)碼管秒表計(jì)時(shí)器在實(shí)驗(yàn)板上同時(shí)工作,并且互相獨(dú)立不影響。 3.2程序代碼分析: #include char b[10] = { 0b11111010,//0 0b00110000,//1 0b11011001,//2 0b01111001,//3 0b00110011,//4 0b01101011,//5 0b11101011,//6 0b00111000,//7 0b11111011,//8 0b01111011,//9 };char a[10] = { 0b11111010,//0 0b00110000,//1 0b11011001,//2 0b01111001,//3 0b00110011,//4 0b01101011,//5 0b11101011,//6 0b00111000,//7 0b11111011,//8 0b01111011,//9 }; volatile char temp; int main(void){ DDRA = 0xff;PORTA = 0b10000000;DDRC = 0xff; 第4頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 DDRD = 0b11111011;DDRB = 0b11111011; TCNT0 = 55;PORTB = b[0];PORTD = a[0];PORTC |=(1 << 0);TCCR0 |=(1 << CS01);int count1 = 0,count2 = 0,i; MCUCR |=(1 << ISC00)|(1 << ISC01);//INT0上升沿觸發(fā) GICR |=(1 << INT0);//使能INT0,INT1 sei();//使能全局中斷 while(1){ for(i = 0;i<9000;i++) { while(!(TIFR &(1< TCNT0=55; } count1++; if(count1!=10) PORTD = a[count1]; else { count2++; count1 = 0; if(count2 == 10) count2 = 0; temp = PORTA; PORTA = PORTA >> 1; if(temp & 0b00000001) { PORTA = PORTA | 0b10000000; } PORTB = b[count2]; PORTD = a[0]; } } } SIGNAL(SIG_INTERRUPT0)//INT0中斷服務(wù)程序 { int count3 = 0,count4=0; 第5頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 while(!(PINB &(1<<2))) { count3++; if(count3 == 10) { count4++; count3 = 0; temp = PORTA; PORTA = PORTA >> 1; if(temp & 0b00000001) { PORTA = PORTA | 0b10000000; } } for(int i=0;i<9000;i++) { while(!(TIFR &(1< TCNT0=55; } } } 第6頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 3.3實(shí)驗(yàn)結(jié)果: 四、有關(guān)發(fā)聲的基礎(chǔ)知識(shí): 聲波是振動(dòng)產(chǎn)生的。頻率即表示每秒鐘振動(dòng)的次數(shù),采用CTC方式時(shí)AVR單片機(jī)通過(guò)特定的端口(PD4及PD5)輸出一定頻率的方波,TCCR1A設(shè)為比較匹配時(shí)OC1A/OC1B電平取反,TCCR1B的計(jì)數(shù)上限為 第7頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 OC1A,根據(jù)公式OCnA=f/2N(1+OCRnA)計(jì)算出7個(gè)頻率音階所需的OCR1A,則只需將喇叭接在PD4或PD5,通過(guò)程序控制端口輸出特定頻率的方波波形(發(fā)聲使用正弦波最好,方波效果稍次但影響不大),喇叭就會(huì)發(fā)出七種不同的聲音,依照人聽覺(jué)分辨7個(gè)音階分為三組,分別為高中,低音階頻率,經(jīng)計(jì)算可得,當(dāng)OCR1A=(500000/musicmem[i]-1)時(shí),{131,147,165,175,196,220,247}存放低音階頻率,{262,294,330,349,392,440,494}存放中音階頻率,{524,588,660,698,784,880,988}則存放高音階頻率,所以需要定義三個(gè)數(shù)組存放各音階的頻率值。除了音符頻率以外還需要音長(zhǎng),所以定義1個(gè)2位數(shù)組表示一段音樂(lè),第一個(gè)表示頻率,第二個(gè)表示音長(zhǎng),播放時(shí)先訪問(wèn)頻率數(shù)組,使喇叭發(fā)聲,之后訪問(wèn)音長(zhǎng)數(shù)組,確定喇叭發(fā)聲時(shí)間。而有了音符頻率數(shù)組,只要再得到任意一首歌的簡(jiǎn)譜,就可以將其轉(zhuǎn)化為兩個(gè)數(shù)組的形式,由音符對(duì)應(yīng)的頻率得出頻率數(shù)組,然后再根據(jù)每個(gè)音符的音長(zhǎng),將其通過(guò)樂(lè)曲的節(jié)拍和音符的拍數(shù)計(jì)算出音符持續(xù)時(shí)間即可得出音長(zhǎng)數(shù)字。 第8頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 五、電子琴的設(shè)計(jì)過(guò)程: 5.1設(shè)計(jì)過(guò)程: 5.2 實(shí)驗(yàn)所需元器件: ATmega16L型單片機(jī),JTAG下載器,揚(yáng)聲器,4*4矩陣鍵盤,液晶屏,LM386,實(shí)驗(yàn)盒(內(nèi)裝剪刀、鑷子、導(dǎo)線等用品)等 第9頁(yè) 1602LCD北京郵電大學(xué)信息與通信工程學(xué)院 5.3實(shí)驗(yàn)程序主要流程圖: 5.4實(shí)驗(yàn)原理及原理圖 : 5.4.1實(shí)驗(yàn)原理 : 以ATmega16單片機(jī)作為整個(gè)系統(tǒng)的控制中心,外加琴鍵控制模塊、播放模塊、顯示模塊,使制作的電子琴完成設(shè)想的功能。琴鍵控制模塊為4*4矩陣鍵盤,可以通過(guò)按下不同的琴鍵彈奏出不同的音階,每個(gè)音階對(duì)應(yīng)著不同的頻率,一段音樂(lè)是由許多不同的音階組成,這樣我們就可以根據(jù)不同的頻率組合得到我們想要的音樂(lè),同時(shí)在錄制模式下,還可以通過(guò)按不同的按鍵記錄下不同的音階,由此記錄一段音樂(lè)。播放模塊接收對(duì)應(yīng)頻率的方波,由此播放琴鍵彈奏的音階以 第10頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 及播放預(yù)先存放在單片機(jī)里的音樂(lè)。顯示模塊顯示出當(dāng)前所處的模式。 5.4.2 原理圖: 5.5各模塊的設(shè)計(jì)與詳解: ? 中央處理器——ATmega16: 第11頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 實(shí)驗(yàn)中,PB0~PB7全部設(shè)置為輸出,分配給LCD液晶顯示屏D0~D7管腳;PA0~PA7連接4*4矩陣鍵盤的八個(gè)引腳;PD4、PD6和PD7設(shè)置為輸出狀態(tài),分別連接到LCD顯示屏的RS、R/W和E端口上;PD5置為輸出狀態(tài),接到揚(yáng)聲器的一個(gè)管腳,揚(yáng)聲器的另一管腳接地;VCC為電源,向LCD顯示屏供電;GND為公共接地。 ? 琴鍵控制模塊——4*4矩陣鍵盤: 工作原理:按鍵設(shè)置在行、列線交點(diǎn)上,行、列線分別連接到按鍵開關(guān)的兩端。行線通過(guò)上拉電阻接到+5V 電源上。無(wú)按鍵按下時(shí),行線處于高電平的狀態(tài),而當(dāng)有按鍵按下時(shí),行線電平由與此行線相連的列線的電平?jīng)Q定。 ? 顯示模塊——LCD液晶顯示屏: 第12頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 引腳詳解: 第1腳:VSS為地電源。第2腳:VDD接5V正電源。 第3腳:VL為液晶顯示器對(duì)比度調(diào)整端,接正電源時(shí)對(duì)比度最弱,接地時(shí)對(duì)比度最高,對(duì)比度過(guò)高時(shí)會(huì)產(chǎn)生“鬼影”,使用時(shí)可以通過(guò)一個(gè)10K的電位器調(diào)整對(duì)比度。 第4腳:RS為寄存器選擇,高電平時(shí)選擇數(shù)據(jù)寄存器、低電平時(shí)選擇指令寄存器。 第5腳:R/W為讀寫信號(hào)線,高電平時(shí)進(jìn)行讀操作,低電平時(shí)進(jìn)行寫操作。當(dāng)RS和R/W共同為低電平時(shí)可以寫入指令或者顯示地址,當(dāng)RS為低電平R/W為高電平時(shí)可以讀忙信號(hào),當(dāng)RS為高電平R/W為低電平時(shí)可以寫入數(shù)據(jù)。 第6腳:E端為使能端,當(dāng)E端由高電平跳變成低電平時(shí),液晶模塊執(zhí)行命令。 第7~14腳:D0~D7為8位雙向數(shù)據(jù)線。 第13頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 第15腳:背光源正極。第16腳:背光源負(fù)極。 ? 播放模塊——揚(yáng)聲器: 原先以為單片機(jī)本身的電源電壓不足以驅(qū)動(dòng)揚(yáng)聲器工作,所以設(shè)計(jì)了有LM386的功放模塊,后來(lái)在實(shí)際操作的過(guò)程中測(cè)試發(fā)現(xiàn),單片機(jī)本身的電源足以驅(qū)動(dòng)揚(yáng)聲器播放音樂(lè)音調(diào),因此舍棄了LM386功放模塊的設(shè)置。 5.6程序源代碼及程序分析: #include #define uchar unsigned char #define uint unsigned int const uchar table[]=“HELLO WELCOME!”; volatile uint num=0,count=0;volatile uint Mode=0,list=2,pause=0,aim=0,sure=0,del=0;volatile int state=0, S=1; //定義全局變量,S為變速變量 const uint Mode_Data[16]={0,440,494,523,587,659,698,784,880,998,1046,1156,1318,1396,1568};//存放聲音的頻率 //音高對(duì)應(yīng)定時(shí)器初始化數(shù)值(低la~高la+休止符),cpu頻率1MHz,用8分頻 const uchar tone[]={0x00,0x8E,0x7E,0x77,0x6A,0x5E,0x59,0x4F,0x47,0x3F,0x3B,0x35,0x2F,0x2C,0x27,0x23,0X19,0X15}; uint Ssong[10][2]={{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}}; //******************************************** void delay_us(int n) //微妙級(jí)延時(shí)函數(shù); { 第14頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 while(n--){ asm(“nop”);//自動(dòng)延時(shí)一個(gè)時(shí)鐘周期什么也不做 } } void delay_ms(int n) //毫秒級(jí)延時(shí)函數(shù); { int m=14500*n;while(m--){ asm(“nop”);} } //********************************************** /************************ 屏幕顯示函數(shù) ************************/ void write_com(uchar com){ PORTD&=~(1<<4); //低電平指令模式。高電平數(shù)據(jù); PORTD&=~(1<<6); //低電平寫; PORTB=com;PORTD|=(1<<7); //高電平使能 delay_ms(1);PORTD&=~(1<<7); } void write_dat(uchar dat){ PORTD|=(1<<4);PORTD&=~(1<<6);PORTB=dat;PORTD|=(1<<7);delay_ms(1);PORTD&=~(1<<7);} /*********************************** * 音樂(lè)產(chǎn)生函數(shù) * * 功能:輸出頻率為x的方波* * 范圍:x:100-20000Hz,0:不發(fā)聲 * * ***********************************/ 第15頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 void sound(int i) { TIMSK|=(1<<2);sei(); if(i&&i<17) //按了音符鍵了,且在0到F鍵這16個(gè)發(fā)音鍵上,才發(fā)聲 { OCR1A=tone[i]; TCCR1A=0X50; //控制寄存器,選擇可翻轉(zhuǎn)功能,產(chǎn)生方波; TCCR1B=0X0a; PORTD=(1<<5);} else { TCCR1A = 0x00; //頻率為0,休止符,不發(fā)聲 TCCR1B=0X00; OCR1A=0; } } /************************************ 彈奏函數(shù) ************************************/ void play(int n) //參數(shù)為鍵盤上的數(shù)字; { write_com(0X80+0X40+n);write_dat(16);sound(n); //彈奏音符; delay_ms(1);write_dat(20); TCCR1A=0x00; TCCR1B=0X00; //中斷,為下一個(gè)節(jié)拍做準(zhǔn)備; PORTD|=(1<<5); //PD5作為輸出管腳,接揚(yáng)聲器; } //___________________________________________ void INI_POTR(void){ DDRD|=0xff;DDRB=0xff; PORTD=(1<<5);PORTD&=~(1<<7);DDRA=0xff; //A口作為鍵盤輸入口; DDRB=0xff; } //_____________________________________ 第16頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 void INN_DEVICE(void){ MCUCR=0X00; // 中斷寄存器置零; } //____________________________________ //檢測(cè)鍵盤是否被按下的函數(shù) uint isKeyPress(){ DDRA=0xff; //初始設(shè)置端口均為輸出 PORTA=0xf0; //設(shè)置端口的初值為11110000 DDRA=0xf0; //將低四位設(shè)為輸入 if(PINA == 0xf0) //當(dāng)沒(méi)有按下時(shí),PINA仍然為11110000 { DDRA=0xff; return 0; //返回0,代表未按下 } else //當(dāng)按下后,PINA不再是11110000 { DDRA=0xff; return 1; //返回1,代表按下了 } } //鍵盤輸入檢測(cè)函數(shù); //_______________________________ int key_in(void) { DDRA = 0xff; //先全部設(shè)置為輸出,再將后四位置為輸入 PORTA = 0xf0; //設(shè)置高低電平 DDRA = 0xf0;uint i = 0,j = 16,Key = 17; unsigned char temp1,temp2; if(isKeyPress()){ temp1 = PINA; temp1 &= 0x0f; //只關(guān)心低四位的情況 switch(temp1) { case 0b00000001: j = 0; break; case 0b00000010: j = 1; 第17頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 break; case 0b00000100: j = 2; break; case 0b00001000: j = 3; break; } temp2 = PINA; temp2 &= 0x0f; if(temp1!= temp2) return 17; DDRA = 0xff; PORTA= 0x0f; DDRA = 0x0f; temp1 = PINA; temp1 &= 0xf0; switch(temp1) { case 0b00010000: i = 0; break; case 0b00100000: i = 1; break; case 0b01000000: i = 2; break; case 0b10000000: i = 3; break; } temp2 = PINA; temp2 &= 0xf0; if(temp1!= temp2) return 17; Key = i*4 + j+1;// return Key; } } /***************************** //去抖動(dòng) //只關(guān)心高四位的情況第18頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 音樂(lè)播放函數(shù); *****************************/ void m_sound(uint a){ int m=(62500/a)-1; //發(fā)聲原理 OCR1A=m; TCCR1A=0X50; //控制寄存器,選擇可翻轉(zhuǎn)功能,產(chǎn)生方波; TCCR1B=0X0a;} //**********************************播放函數(shù); void music_play(uint a[][2]){ const char Mtable[]=“Music Mode”; write_com(0X01); //清屏; for(int i=0;i<5;i++) { write_dat(Mtable[i]); } int i=0; char tem=aim,T=1; while((a[i][1]!=0)&&(tem==aim)&&state) { //A 返回 B 暫停 F 模式 C 上一曲你 D 播放 E 下一曲; num=key_in(); switch(num) { case 16: state=0; // F STATE = 0彈奏 break; case 15: aim=1; //下一首E break; case 14: pause=1; //播放D break; case 13: aim=0; ///上一首C break; case 12: pause=0; ///暫停B break; case 11: 第19頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 T=2; break;case 10: T=1; break;case 9: T=0;break;case 5: //變速,1代表正常速度A //慢速0 //快速9 //5 降調(diào) S=0.5; break; case 6: S=1; break; default: break; } while(a[i][0]&&pause) { num=key_in(); if(num==12) { pause=0; } else { if(S == 0.5) m_sound(a[i][0]*S); else m_sound(a[i][0]); if(T==2) delay_ms(a[i][1]-100); else if(T==0) delay_ms(a[i][1]+100); else delay_ms(a[i][1]); i++; TCCR1A=0x00; TCCR1B=0X00; } } pause=0; //6 正常調(diào) //加減速 //下一個(gè)音符; 第20頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 TCCR1A=0x00; TCCR1B=0X00; //中斷,為下一個(gè)節(jié)拍做準(zhǔn)備; } if(a[i][1]==0){ aim =(++aim)% list; } } /***************** 錄制音樂(lè)函數(shù); *****************/ void record(void){ write_com(0X01); const uchar R_table[]=“Recording Mode”; for(int i=0;i<9;i++){ write_dat(R_table[i]);} pause=1;while(pause){ uint Skey = key_in(); if((Skey>0)&&(Skey<11)) { int i=0;//count=0; while(i<10) { Skey=key_in(); OCR1A=0; TCCR1A=0x00; TCCR1B=0X00; if((Skey>0)&&(Skey<11)) { play(Skey); Ssong[i][0]=tone[Skey]; Ssong[i][1]=600; i++; delay_ms(20); } if(Skey==14) 第21頁(yè) //清屏;//開始錄制 //先清零計(jì)數(shù)器 //錄制完成,北京郵電大學(xué)信息與通信工程學(xué)院 按D鍵結(jié)束錄制 { i=10; } } pause=0; //借助 PAUSE 來(lái)標(biāo)記一下什么時(shí)候退出while } } } //***************************歌曲數(shù)據(jù) uint music_data[][2]= { {440,400},{440,400},{659,400},{659,400},{740,400},{740,400},{659,800}, {587,400},{587,400},{554,400},{554,400},{494,400},{494,400},{440,800}, {659,400},{659,400},{587,400},{587,400},{554,400},{554,400},{497,800}, {659,400},{659,400},{587,400},{587,400},{554,400},{554,400},{497,800}, {440,400},{440,400},{659,400},{659,400},{740,400},{740,400},{659,800}, {587,400},{587,400},{554,400},{554,400},{494,400},{494,400},{440,800}, {0,0} }; // abcdefg uint music_1[][2]= {{262,400},{294,400},{330,400},{262,400},{262,400}, //樂(lè)譜 {294,400},{330,400},{262,400},{330,400},{349,400}, {392,800},{330,400},{349,400},{392,800},{392,300}, {440,100},{392,300},{349,100},{262,400},{392,400}, {440,300},{392,100},{349,300},{330,100},{262,400}, {294,400},{196,400},{262,400},{294,800},{196,400}, {262,400},{294,800},{0,0}};//music_1 int main(void){ INI_POTR(); //初始化 write_com(0X38); //顯示光標(biāo)等; write_com(0X01); //清屏; write_com(0X0f); //打開光標(biāo); write_com(0X06); write_com(0X80+0X02); for(int i=0;i<8;i++) 第22頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 { write_dat(table[i]); } write_com(0X80+0X11); delay_ms(5); while(1) { num = key_in(); if(num==16) //模式選擇 { if(state==1) state=0; else state=1; } 放模式 if(state==1) { (state==1) { switchaim() { case 0: music_play(music_data); break; case 1: music_play(Ssong); break; default: break; }while delay_ms(10); } } else if(num==11) //錄制模式; { record(); delay_ms(10); } else { write_com(0X01); 第23頁(yè) //播 北京郵電大學(xué)信息與通信工程學(xué)院 } const uchar Ptable[]=“playing Mode”; for(int i=0;i<7;i++) { write_dat(Ptable[i]); } while((num!=16)&&(num!=11)) { play(num); num=key_in(); } } } //彈奏模式 5.7實(shí)驗(yàn)結(jié)果: 實(shí)現(xiàn)了最初設(shè)想的功能,所設(shè)計(jì)的電子琴可以進(jìn)行即興彈奏、錄制音樂(lè)、播放音樂(lè)以及音樂(lè)變速。測(cè)試圖片如下: 第24頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 第25頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 接通電源后,顯示屏以每次顯示一個(gè)字符的形式顯示出“HELLO WELCOM!”的歡迎文字,接著自動(dòng)進(jìn)入彈奏模式,并在LCD的第一行顯示出“Playing Mode”的文字,用戶每次按下按鍵都會(huì)在LCD的第二行的相應(yīng)位置出現(xiàn)對(duì)應(yīng)按鍵順序的光標(biāo)閃爍。在彈奏模式下,按下F鍵會(huì)進(jìn)入播放模式,LCD顯示出“Music Mode”字樣,此時(shí)按下D鍵是播放/繼續(xù),按下B鍵是暫停,C鍵和E鍵分別代表上一首和下一首,9鍵則是將音樂(lè)速度調(diào)整為慢速,再次按下F鍵會(huì)回到彈奏模式。在彈奏模式下,按下A鍵會(huì)進(jìn)入錄制模式,此時(shí)LCD顯示“Recording Mode”字樣,可以使用1~0十個(gè)按鍵進(jìn)行錄音,想要聽聽錄制好的音樂(lè),可以切換到播放模式下進(jìn)行欣賞。 六、排錯(cuò)過(guò)程: ? 基礎(chǔ)題目訓(xùn)練階段: 1.硬件連接好之后,在進(jìn)行編程的過(guò)程中發(fā)現(xiàn)端口不夠用,因?yàn)镻B3和PD3這兩個(gè)能產(chǎn)生中斷的端口必須空出來(lái)作為暫停和開 第26頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 始按鍵的接口,于是我重新布線,將數(shù)碼管顯示小數(shù)點(diǎn)的右下角的引腳改接到PC0,同時(shí)在代碼中將此端口設(shè)置為高電平輸出,這樣就解決了該問(wèn)題。 2.當(dāng)我們簡(jiǎn)單地把流水燈和計(jì)時(shí)器代碼合并在一起然后編譯運(yùn)行時(shí),卻發(fā)現(xiàn)流水燈在工作,計(jì)時(shí)器卻停止了工作。經(jīng)過(guò)仔細(xì)排查,發(fā)現(xiàn)簡(jiǎn)單地將代碼合并會(huì)導(dǎo)致單片機(jī)陷入流水燈的工作循環(huán),而沒(méi)有進(jìn)入計(jì)時(shí)器的工作進(jìn)程。經(jīng)過(guò)一番思考,我們將流水燈的代碼加以修改寫入計(jì)時(shí)器的工作循環(huán)中,解決了計(jì)時(shí)器不工作的問(wèn)題。 3.但是新問(wèn)題又出現(xiàn)了,我們發(fā)現(xiàn)按下計(jì)時(shí)器的暫停按鈕后,會(huì)導(dǎo)致流水燈也停止工作。經(jīng)過(guò)小組的討論,我們決定在中斷程序函數(shù)里面加上流水燈工作的代碼并加以修改使其能夠在中斷函數(shù)里面運(yùn)行。經(jīng)過(guò)多次調(diào)試,終于實(shí)現(xiàn)了計(jì)時(shí)器的計(jì)時(shí)、暫停、繼續(xù)功能,并且流水燈能夠一直工作不受計(jì)時(shí)器的暫停影響。 4.在調(diào)整計(jì)時(shí)器計(jì)時(shí)精讀的過(guò)程中,我們發(fā)現(xiàn)本實(shí)驗(yàn)中使用的ATmega16頻率不是16MHz,也不是1MHz,為了盡可能的實(shí)現(xiàn)秒表計(jì)時(shí),試驗(yàn)了很多的數(shù)字組合,最后達(dá)到了30秒誤差1秒的精確度,當(dāng)然還可以達(dá)到更高的精確度。 ? 電子琴設(shè)計(jì)與實(shí)現(xiàn)階段: 1.在硬件連接的時(shí)候,沒(méi)想到LCD液晶顯示屏的每根管腳都需要 第27頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 連接,導(dǎo)致在進(jìn)行程序下載驗(yàn)證的時(shí)候,顯示屏總是不能顯示出應(yīng)有的文字,后來(lái)參考了相關(guān)文檔資料發(fā)現(xiàn)是V0這個(gè)管腳也必須接地才可以,解決了問(wèn)題。 2.在安插矩陣鍵盤的時(shí)候,費(fèi)了很多功夫,首先,不知道哪根管腳是行線哪根管腳是列線,其次不知道所連接的端口的輸出輸入模式應(yīng)該怎么設(shè)置,導(dǎo)致設(shè)計(jì)過(guò)程受阻,后來(lái)觀看了視頻并查閱相關(guān)資料解決了此問(wèn)題。 3.在初步完成電子琴的彈奏功能程序時(shí),我們開始對(duì)單片機(jī)進(jìn)行測(cè)試,發(fā)現(xiàn)在按下數(shù)次按鈕后單片機(jī)就會(huì)卡死,我們仔細(xì)檢查了彈奏功能的代碼,經(jīng)過(guò)多次排查,我們小組最終將鍵盤檢測(cè)函數(shù)key_in()和彈奏函數(shù)play()兩條語(yǔ)句的執(zhí)行順序交換,以達(dá)到比較好的邏輯順序效果,提高了程序的穩(wěn)定性,把多次按下按鈕會(huì)導(dǎo)致單片機(jī)卡死的問(wèn)題給基本解決了。 4.播放音樂(lè)功能也是我們?cè)O(shè)想的一個(gè)重要功能。剛開始,按照我們的思路去實(shí)現(xiàn)該功能時(shí),在測(cè)試時(shí)播放音樂(lè)是實(shí)現(xiàn)了,但是暫停和繼續(xù)功能都沒(méi)能夠?qū)崿F(xiàn)。我們小組對(duì)代碼進(jìn)行重新檢查,檢查出幾個(gè)比較嚴(yán)重的邏輯錯(cuò)誤。我們重新調(diào)整播放音樂(lè)函數(shù)的判斷語(yǔ)句和循環(huán)結(jié)構(gòu),并加入一個(gè)pause變量來(lái)標(biāo)志暫停狀態(tài),在按下暫停按鈕時(shí)將pause標(biāo)志為0,使程序退出播放循環(huán)。經(jīng)過(guò)一番努力,我們順利完成了暫停播放和繼續(xù)播放的功能。 5.錄制音樂(lè)功能的實(shí)現(xiàn)是整個(gè)實(shí)驗(yàn)過(guò)程里面最為困難的一環(huán)。我第28頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 們預(yù)先設(shè)想的實(shí)現(xiàn)方法是每按下一個(gè)按鍵,將對(duì)應(yīng)音階的數(shù)字和節(jié)拍存入數(shù)組中,然后錄制完成后自動(dòng)播放錄制的音樂(lè)。但是,我們實(shí)際測(cè)試時(shí)發(fā)現(xiàn)錄制的音樂(lè)并沒(méi)有能自動(dòng)播放。經(jīng)過(guò)小組討論,我們決定將錄制好的音樂(lè)在播放音樂(lè)模式里面播放,根據(jù)這個(gè)思路,我們將錄制的音樂(lè)對(duì)應(yīng)的數(shù)組用播放音樂(lè)函數(shù)進(jìn)行播放,成功地實(shí)現(xiàn)了錄制音樂(lè)并播放的功能。 七、心得體會(huì): 為期9天的單片機(jī)小學(xué)期圓滿結(jié)束,不得不說(shuō),我從中學(xué)到了很多知識(shí),從一個(gè)對(duì)單片機(jī)一竅不通的小白,蛻變成了一個(gè)熟悉單片機(jī)各個(gè)端口的作用和使用方法、懂得如何編程實(shí)現(xiàn)相應(yīng)功能的技術(shù)人員。 在這九天中,我們通過(guò)觀看老師給的視頻資料和文檔,加上查閱的資料,獨(dú)立完成了所布置的任務(wù)。由于有C++的基礎(chǔ),加上有硬件的端口以及相應(yīng)設(shè)備的使用說(shuō)明文檔的幫助,因此在我看來(lái),在AVR Studio上進(jìn)行C語(yǔ)言的編程從邏輯上比C++更容易理解,所需要的只是在編程時(shí)將端口的配置和邏輯函數(shù)結(jié)合到一起,實(shí)現(xiàn)編寫的函數(shù)對(duì)單片機(jī)端口以及內(nèi)部中斷的控制。 第一天剛接到流水燈和數(shù)碼管秒表計(jì)時(shí)器的任務(wù)的時(shí)候,內(nèi)心真的十分激動(dòng),心想:實(shí)現(xiàn)了這個(gè)不就實(shí)現(xiàn)了街邊廣告牌上滾動(dòng)的文字了么!但是一看到ATmega16芯片時(shí)還是傻了眼,心想:這么多的管腳都該怎么用???“視頻里有”,同學(xué)告訴我,于是我就開始認(rèn)真地 第29頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 研究起老師給的單片機(jī)教學(xué)視頻和它的技術(shù)文檔。由此發(fā)現(xiàn),只需要將單片機(jī)的端口設(shè)置好,再套上一個(gè)循環(huán)結(jié)構(gòu),就可以實(shí)現(xiàn)流水燈的功能了。說(shuō)做就做,于是最初的流水燈就實(shí)現(xiàn)了,可以一個(gè)一個(gè)依次循環(huán)點(diǎn)亮。那時(shí)真是好高興!在做數(shù)碼管的時(shí)候,由于不知道數(shù)碼管的顯示與管腳之間的關(guān)系,于是我先創(chuàng)建了一個(gè)數(shù)組,數(shù)組中的元素都是8位二進(jìn)制數(shù),其中只有一位是1,其余位都是0,如下: char a[8] = { 0b00000001,0b00000010,0b00000100,0b00001000,0b00010000,0b00100000,0b01000000,0b10000000 }; 然后我采用一個(gè)循環(huán),將端口PORTX每次等于一個(gè)a[i],單步運(yùn)行,找出了數(shù)碼管的顯示與管腳之間的對(duì)應(yīng)關(guān)系。這樣,之后的工作就輕松許多,只需要在該亮的位置將對(duì)應(yīng)的PORTX端口置為1,就可以顯示出自己想要的數(shù)字了。流水燈和數(shù)碼管秒表計(jì)時(shí)器都分別完成了,最后只需將它們合在一起共同工作即可。不過(guò)這個(gè)過(guò)程也不是一帆風(fēng)順的,因?yàn)橹袛嗟母拍钗覄傞_始覺(jué)得很難理解,也不知道該將中斷的有關(guān)函數(shù)放在代碼的哪個(gè)位置,因此反復(fù)糾結(jié)反復(fù)研究視頻和技術(shù)文檔,持續(xù)了一段時(shí)間。后來(lái)我和同學(xué)決定將兩份流水燈的程序,一份放在主程序main中,和秒表計(jì)時(shí)器的程序放在一起,即實(shí)現(xiàn)兩者同時(shí)工作,且流水燈的閃爍間隔是一秒,另一份放在中斷服務(wù)程序中SIGNAL()中,即實(shí)現(xiàn)按下按鈕進(jìn)入中斷服務(wù)程序后,秒表計(jì)時(shí)器暫停 第30頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 工作,而流水依舊在依次循環(huán)閃爍。由此實(shí)現(xiàn)了流水燈和秒表計(jì)時(shí)器的獨(dú)立工作,互不影響。 完成了基礎(chǔ)題目的訓(xùn)練任務(wù),我信心滿滿,迎來(lái)了我的下一個(gè)任務(wù)——電子琴。剛開始選題的時(shí)候覺(jué)得電子琴蠻有趣的,可以彈奏可以錄音可以播放,而且原理看起來(lái)也比較簡(jiǎn)單。但是其實(shí)不是這樣的,拿到元器件的時(shí)候,我發(fā)現(xiàn),LCD液晶顯示屏有16個(gè)管腳!矩陣鍵盤有8個(gè)管腳!但是有了前面對(duì)付ATmega16芯片的經(jīng)驗(yàn),我沉住氣,查閱了有關(guān)LCD液晶顯示屏和矩陣鍵盤的技術(shù)文檔,以及一些經(jīng)驗(yàn)之作,初步定下了鍵盤接到A端口,LCD的8個(gè)數(shù)據(jù)口接到B端口,D端口用于LCD的讀寫控制使能端以及揚(yáng)聲器的輸入端。至此,硬件的連接工作就完成了,根據(jù)硬件的連接,我們開始了程序的編寫。鍵盤檢測(cè)函數(shù)、播放函數(shù)、液晶顯示函數(shù),彈奏功能,錄制功能??一步一步,一個(gè)完整的系統(tǒng)漸漸完善。由于有硬件,因此我們編寫的程序可以馬上下載到板子里驗(yàn)證效果,并及時(shí)修改,大大方便了我們排錯(cuò)和系統(tǒng)優(yōu)化。期間由于JTAG下載器和AVR Studio總是出現(xiàn)連接失敗的情況,浪費(fèi)了我們?cè)S多寶貴的時(shí)間,個(gè)人總結(jié)原因是驅(qū)動(dòng)可能用了一段時(shí)間會(huì)失效,解決辦法是重新啟動(dòng)計(jì)算機(jī),并將WINAVR這個(gè)環(huán)境卸載后再次裝上,并且是裝到與上一次不同的盤中,同時(shí)編譯AVR程序的時(shí)候先接上JTAG下載器,試驗(yàn)了許多次,這個(gè)方法很管用,之后就沒(méi)有出現(xiàn)該問(wèn)題了。最終,電子琴的功能基本完成,并且達(dá)標(biāo),能實(shí)現(xiàn)彈奏、播放、錄制、變速等最初設(shè)想的功能,但是可能還有一些小BUG沒(méi)有調(diào)出來(lái),導(dǎo)致電子琴在運(yùn)行的過(guò)程中有不穩(wěn)定的現(xiàn)象,第31頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 也不能排除是板子的問(wèn)題。 最終,單片機(jī)小學(xué)期圓滿結(jié)束了!9天的時(shí)間,完全的自己動(dòng)手實(shí)驗(yàn),不僅增加了自己對(duì)單片機(jī)的理解,提高了自己的編程能力,而且在這個(gè)過(guò)程中,我覺(jué)得團(tuán)隊(duì)的合作至關(guān)重要,自己連接的電路或者自己編寫的程序,在自己看來(lái)都是對(duì)的,但是旁觀者清,隊(duì)友能很容易地幫你找出其中的錯(cuò)誤;在和隊(duì)友的討論中,我能了解對(duì)方的想法和思路,多種想法和思路的碰撞能讓我收獲更多新的東西;組內(nèi)的分工能讓每個(gè)人都盡到自己的責(zé)任,發(fā)揮自己所長(zhǎng)。 總之,這次單片機(jī)小學(xué)期是一次難忘的過(guò)程,一次豐富知識(shí)、提升技能的歷程,也激起了我對(duì)單片機(jī)的興趣,我今后會(huì)多多研究單片機(jī),爭(zhēng)取更上一層樓! 八、參考文獻(xiàn): 1.AVR C庫(kù)函數(shù)介紹.pdf 2.AVR C語(yǔ)言開發(fā)入門指導(dǎo).pdf 3.AVR單片機(jī)原理及應(yīng)用.pdf 4.AVR高速嵌入式單片機(jī)原理及應(yīng)用(修訂版).pdf 5.深入淺出AVR單片機(jī).pdf 6.1602液晶說(shuō)明.pdf 7.AVR系統(tǒng)板說(shuō)明.doc 8.cn_mega16-16L.pdf 9.EN_TC1602.pdf 第32頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院 10.字符手冊(cè).pdf 11.百度百科《樂(lè)理》 12.AVR單片機(jī)軟硬件設(shè)計(jì)視頻教程-入門篇-第二講-AVR硬件電路設(shè)計(jì)教程 13.AVR單片機(jī)軟硬件設(shè)計(jì)視頻教程-入門篇-第三講-AVR開發(fā)基礎(chǔ)知識(shí) 14.AVR單片機(jī)軟硬件設(shè)計(jì)視頻教程-入門篇-第四講-C語(yǔ)言的流水燈驗(yàn)證 15.AVR單片機(jī)軟硬件設(shè)計(jì)視頻教程-入門篇-第五講-按鍵與數(shù)碼管的程序設(shè)計(jì) 16.AVR單片機(jī)軟硬件設(shè)計(jì)視頻教程-入門篇-第六講-中斷與定時(shí)器 九、意見與建議: 1.建議老師能稍微講解一下實(shí)驗(yàn)室AVR軟件的用法(視頻中講的是沒(méi)有JTAG下載器的,與實(shí)驗(yàn)室不同,剛開始還以為是板子有問(wèn)題); 2.實(shí)驗(yàn)室的元器件老舊,個(gè)別元器件特別是單片機(jī)芯片有問(wèn)題之后,調(diào)BUG好久都不知道錯(cuò)在哪里,建議更新。 第33頁(yè)第四篇:北郵小學(xué)期c++實(shí)驗(yàn)報(bào)告
第五篇:北郵小學(xué)期AVR單片機(jī)電子琴實(shí)驗(yàn)報(bào)告