課設(shè)-基于MATLAB的BPSK調(diào)制-(完本)_第1頁
課設(shè)-基于MATLAB的BPSK調(diào)制-(完本)_第2頁
課設(shè)-基于MATLAB的BPSK調(diào)制-(完本)_第3頁
課設(shè)-基于MATLAB的BPSK調(diào)制-(完本)_第4頁
課設(shè)-基于MATLAB的BPSK調(diào)制-(完本)_第5頁
已閱讀5頁,還剩76頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

沈陽理工大學(xué)裝備工程學(xué)院課程設(shè)計說明書

PAGE

79

摘要

本次課程設(shè)計為基于MATLAB的BPSK原理電路仿真。本次課設(shè)著重介紹了算法的實現(xiàn),并采用MATLAB程序仿真測試了BPSK過程中單極性不歸零編碼、脈沖成形、PSK調(diào)制、信號通過AWGN信道、載波恢復(fù)、解調(diào)、解碼等過程。

關(guān)鍵詞:BPSK;2PSK;MATLAB;數(shù)字頻帶通信;

目錄

緒論

1

1BPSK數(shù)字調(diào)制原理

2

1.1數(shù)字帶通傳輸分類

2

1.2BPSK調(diào)制原理分析

2

1.2.1調(diào)制原理分析

2

1.2.2解調(diào)原理分析

4

2MATLAB軟件

6

2.1MATLAB軟件介紹

6

3基于的MATLAB的BPSK調(diào)制分析和仿真

7

3.1基于MATLAB的BPSK調(diào)制系統(tǒng)總述

7

3.2編碼過程的MATLAB實現(xiàn)

8

3.3BPSK調(diào)制的MATLAB的實現(xiàn)

11

3.4AWGN信道MATLAB的實現(xiàn)

13

3.5載波恢復(fù)的MATLAB實現(xiàn)

16

3.5.1接收端帶通濾波器

16

3.5.2通過FFT實現(xiàn)載波的直接頻率估計

20

3.5.3自適應(yīng)(迭代)算法驗證恢復(fù)頻率

22

3.6BPSK解調(diào)

25

4總結(jié)

30

附錄

31

致謝

32

參考文獻

33

緒論

數(shù)字信號傳輸方式分為數(shù)字帶通傳輸和數(shù)字基帶傳輸。對于本次課程設(shè)計二進制相移鍵控BPSK(BinaryPhaseShiftKey)是利用載波的相位變化來傳遞數(shù)字信息,而振幅和頻率保持不變的一種數(shù)字帶通調(diào)制方式。在實際應(yīng)用中,PSK具有恒包絡(luò)特性,頻帶利用率比FSK高,在相同信噪比的條件下誤碼率也較低,同時PSK調(diào)制實現(xiàn)相對簡單,故衛(wèi)星通信,遙測遙控中用得最多的是BPSK方式調(diào)制。

1BPSK數(shù)字調(diào)制原理

1.1數(shù)字帶通傳輸分類

數(shù)字帶通傳輸中一般利用數(shù)字信號的離散取值特點通過開關(guān)鍵控載波,從而實現(xiàn)數(shù)字調(diào)制,比如對載波的振幅、頻率和相位進行鍵控可獲得振幅鍵控(ASK)、頻移鍵控(FSK)和相移鍵控(PSK)。

1.2BPSK調(diào)制原理分析

1.2.1調(diào)制原理分析

相移鍵控是利用載波的相位變化來傳遞數(shù)字信息,而振幅和頻率保持不變。在BPSK中,通常用初始相位0或分別表示二進制的‘0’和‘1’。因此,BPSK信號的時域表達式為:

1-1

其中,表示第n個符號的絕對相位:

1-2

因此,式(1-1)可以改寫為:

1-3

由于表示信號的兩種碼元的波形相同,極性相反,故BPSK信號一般可以表述為一個雙極性全占空(100%dutyratio)矩形脈沖序列于一個正弦載波的相乘,即

1-4

其中,

1-5

這里,g(t)脈沖寬度為的單個矩形脈沖,而得統(tǒng)計特性為

1-6

即發(fā)送二進制符號位‘0’時(取+1),取0相位;發(fā)送二進制符號為‘1’時(取-1),取相位。這種以載波的不同相位直接去表示響應(yīng)的二進制數(shù)字信號的調(diào)制方式,稱為二進制絕對相移調(diào)制(BPSK)。

調(diào)制原理框圖如圖1.1所示:

圖1.1BPSK調(diào)制原理圖

典型波形如圖1.2所示:

圖1.2發(fā)送碼元為10011的BPSK波形

1.2.2解調(diào)原理分析

BPSK信號的解調(diào)方法是相干解調(diào)法。由于PSK信號本身就是用相位傳遞信息的,所以在接受端必須利用信號的相位信息,故采用相干解調(diào)法來解調(diào)信號。

BPSK解調(diào)原理框圖如1.3所示:

抽樣判決

低通濾波器

相乘器

帶通濾波器

圖1.3BPSK解調(diào)原理框圖

給出了一種BPSK信號想干接受設(shè)備原理框圖。圖中經(jīng)過帶通濾波的信號在相乘器與本地載波相乘,在相干解調(diào)中,如何得到與接收的BPSK信號同頻同相的相干載波是關(guān)鍵,然后用低通濾波器去除高頻分量,再進行抽樣判決,判決器是按極性進行判決,得到最終的二進制信息。圖中,假設(shè)相干載波的基準相位于BPSK信號的調(diào)制載波的基準相位一致。但是,由于在BPSK信號的載波恢復(fù)過程中存在o的相位迷糊(phaseambiguity),即恢復(fù)的本地載波與所需的相干載波可能同相,也可能反相,這種相位關(guān)系的不確定性將會造成解調(diào)出數(shù)字基帶信號與發(fā)送的數(shù)字基帶信號正好相反,即‘1’變?yōu)椤?’,‘0’變?yōu)椤?’,判決器輸出數(shù)字信號全部出錯。這種現(xiàn)象稱為BPSK方式的‘倒’現(xiàn)象。

具體波形如圖1.4所示

圖1.4解調(diào)信號示意圖

2MATLAB軟件

2.1MATLAB軟件介紹

MATLAB簡介MATLAB的名稱源自MatrixLaboratory,它是一種科學(xué)計算軟件,專門以矩陣的形式處理數(shù)據(jù)。MATLAB將高性能的數(shù)值計算和可視化集成在一起,并提供了大量的內(nèi)置函數(shù),從而被廣泛地應(yīng)用于科學(xué)計算、控制系統(tǒng)、信息處理等領(lǐng)域的分析、仿真和設(shè)計工作,而且利用MATLAB產(chǎn)品的開放式結(jié)構(gòu),可以非常容易地對MATLAB的功能進行擴充,從而在不斷深化對問題認識的同時,不斷完善MATLAB產(chǎn)品以提高產(chǎn)品自身的競爭能力。

在通信仿真中,欲將寄載消息的信號保質(zhì)保量的傳送給接收者,就必須對它們進行加工處理,對相應(yīng)的部件進行分析和研究,而這種研討過程中會用到大量的數(shù)學(xué)計算。它是以矩陣,數(shù)組為基本處理對象,矩陣的維數(shù)不需要預(yù)先指定,且隨時可變,具有豐富的矩陣運算功能。仿真功能我們采用MATLAB語言編程,以Windows和MATLAB為軟件運行環(huán)境。將通信原理中的知識點用MATLAB來實現(xiàn)。通過靈活的菜單和界面設(shè)計使某些參數(shù)可調(diào)。同時運用Simulink軟件包,使波形在仿真的同時顯示系統(tǒng)。更加有利于在課堂上使用。

MATLAB界面:

圖2.1MATLAB界面

3基于的MATLAB的BPSK調(diào)制分析和仿真

3.1基于MATLAB的BPSK調(diào)制系統(tǒng)總述

基于MATLAB的BPSK調(diào)制解調(diào)系統(tǒng)流程框圖如3.1所示:

道信

調(diào)制

成形沖脈

編碼

文本

信息

決判樣抽

載波恢復(fù)

解碼

解調(diào)

圖3.1BPSK調(diào)制解調(diào)系統(tǒng)流程框圖

通信過程分析:

整個發(fā)送與接收過程仿真了實際中的通信過程,輸入一段信息如‘ph’經(jīng)過編碼過程,變換為一串二進制字符,再加載矩形窗進行脈沖成形,生成原始的數(shù)字基帶信號,為了發(fā)送信息,通過BPSK調(diào)制成數(shù)字帶通信號發(fā)射,發(fā)射信號進入模擬的AWGN信道,被接收機所接受,BPSK解調(diào)采用的是相干解調(diào),故需要進行載波恢復(fù),恢復(fù)載波的頻率,用已恢復(fù)的載波對接受信號進行相乘,再對其進行抽樣判決,恢復(fù)最原始的二進制字符,再進行解碼恢復(fù)原始的信息內(nèi)容。

仿真過程的要求:

本次課設(shè)使用MATLAB進行BPSK通信過程仿真,要求不僅能將原始信息轉(zhuǎn)換成二進制字符信息,解調(diào)后也能很好的恢復(fù)成原來的信息,過程中對信號觀察不僅需要從時域上進行觀察分析,也需要再頻域上進行觀察分析,以分析通過AWGN信道對信號的影響。

3.2編碼過程的MATLAB實現(xiàn)

對于輸入的文本信息,如果要進行調(diào)制發(fā)送,必然而且也可以將其轉(zhuǎn)換成由‘0’與‘1’二進制字符,這個過程是信源編碼過程。

算法原理:

對于輸入的文本信息,在MATLAB中有對于的ASCII編碼,MATLAB會自動的任意一行文檔表示為一列ASCII碼。再將十進制的ASCII碼轉(zhuǎn)換為二進制的的字符。

對于數(shù)字形式的信息,必須轉(zhuǎn)化成模擬形式,也就是脈沖成形過程,它將數(shù)字形式的每個字符轉(zhuǎn)換成合適的模擬脈沖,經(jīng)過傳輸后,接受端可以從接受到的信號中恢復(fù)出原來的二進制字符。本次課設(shè)采用矩形窗加載,即為矩形脈沖。

算法原理框圖如3.2所示:

基帶信號

脈沖成形

二進制信息

文本信息

圖3.2算法框圖

MATLAB代碼:

%編碼和脈沖成形

%采樣率100

decimalvalue=real(str);%使用自帶real函數(shù)讀取字符串的ASCII碼

binaryvalue=dec2base(decimalvalue,2,8);%dec2base函數(shù)轉(zhuǎn)成8位二進制形式字符

%因為使用dec2base函數(shù)轉(zhuǎn)換出的二進制字符是使用char型的數(shù)組

%進行將char型轉(zhuǎn)換成int型二進制字符

matrix1=size(binaryvalue);

a=matrix1(1,1);

b=matrix1(1,2);

bv=[];

fori=1:1:a;

forj=1:1:b;

bv1=binaryvalue(i,j);

bv1=bv1*1;

bv1=bv1-48;

bv=[bvbv1];

end

end

%為了能使編碼后的二進制可以進行脈沖成形需要對其進行過采樣

M=100;

N=length(bv);

bsignal=zeros(1,N*M);

bsignal(1:M:end)=bv;

%使用矩形窗進行脈沖成形

p=ones(1,M);

s=conv(p,bsignal);

%因為使用卷積,加載后的信號需要剔除后續(xù)多余部分

k1=length(s);

k1=k1-99;

signal=zeros(1,k1);

fori=1:1:k1;

signal(i)=s(i);

end

%畫圖語句

k=1;%第一幅圖

x=signal;Ts=1/100;

plotspec(x,Ts,k);%調(diào)用自編子函數(shù)

運行程序輸入str=‘ph’,輸出二進制字符的基帶信號signal,時域圖如3.3所示:

圖3.3基帶信號時域圖

基帶信號頻域圖如3.4所示:

圖3.4基帶信號頻域圖

由MATLAB的工作空間可知‘ph’轉(zhuǎn)換成的二進制字符為:011000001101000.

3.3BPSK調(diào)制的MATLAB的實現(xiàn)

數(shù)字基帶信號一般不直接進行發(fā)射,需經(jīng)過調(diào)制,本次課設(shè)要求使用BPSK調(diào)制方式進行調(diào)制。

算法原理:

在MATLAB中,可以采取脈沖成形的方式對原始信號進行調(diào)制,先將信號進行過采樣插值,將1s內(nèi)取100k個有相同幅值的點,以便使用載波進行脈沖成形,過采樣后直接使用載波對信號進行相乘,以達到調(diào)制的目的。

算法原理框圖如3.5所示:

圖3.5算法原理框圖

MATLAB代碼:

%BPSK調(diào)制

%采樣率100kHZ

t2=0:(2*pi)/100000:2*pi-0.00001;%載波一周期內(nèi)采樣點數(shù)

fc=300;%載波頻率

m1=[];

c1=[];

b1=[];

%進行過采樣插值

forn=1:1:length(bv);

ifbv(n)==0;

m=-ones(1,100000);

b=zeros(1,100000);

elsebv(n)==1;

m=ones(1,100000);

b=ones(1,100000);

end

c=cos(fc*t2);%生成相應(yīng)載波

%過采樣后插值的信號

m1=[m1,m];

c1=[c1,c];

b1=[b1,b];

end

psk=c1.*m1;%生成BPSK信號

Ts=1/100000;%采樣周期

x=psk;%畫圖

k=2;%第二幅圖

plotspec(x,Ts,k);%調(diào)用自編函數(shù)文件

運行程序得到BPSK已調(diào)信號psk,時域圖如3.6所示:

圖3.6BPSK信號時域圖(部分)

BPSK的頻域圖如3.7所示:

圖3.7BPSK信號頻域圖

從圖觀察,在HZ處附近有值,說明已用頻率300HZ的載波調(diào)制數(shù)字基帶信號。

3.4AWGN信道MATLAB的實現(xiàn)

加性高斯白噪聲AWGN(AdditiveWhiteGaussianNoise)是最基本的噪聲與干擾模型。它的幅度分布服從高斯分布,而功率譜密度是均勻分布的,它意味著除了加性高斯白噪聲外,r(t)與s(t)沒有任何失真。即H(f)失真的

加性噪聲:疊加在信號上的一種噪聲,通常記為n(t),而且無論有無信號,噪聲n(t)都是始終存在的。因此通常稱它為加性噪聲或者加性干擾。

白噪聲:噪聲的功率譜密度在所有的頻率上均為一常數(shù),則稱這樣的噪聲為白噪聲。如果白噪聲取值的概率分布服從高斯分布,則稱這樣的噪聲為高斯白噪聲。

在MATLAB中有模擬AWGN信道可直接使用awgn函數(shù),y=awgn(x,SNR)

在信號x中加入高斯白噪聲。信噪比SNR以dB為單位。x的強度假定為0dBW。如果x是復(fù)數(shù),就加入復(fù)噪聲。

y=awgn(x,SNR,SIGPOWER)

如果SIGPOWER是數(shù)值,則其代表以dBW為單位的信號強度;如果SIGPOWER為'measured',則函數(shù)將在加入噪聲之前測定信號強度。

y=awgn(x,SNR,SIGPOWER,STATE)

重置RANDN的狀態(tài)。

y=awgn(…,POWERTYPE)

指定SNR和SIGPOWER的單位。POWERTYPE可以是'dB'或'linear'。如果POWERTYPE是'dB',那么SNR以dB為單位,而SIGPOWER以dBW為單位。如果POWERTYPE是'linear',那么SNR作為比值來度量,而SIGPOWER以瓦特為單位。

MATLAB代碼:

%模擬AWGN信道

e2psk=awgn(psk,100);%調(diào)用awgn

%畫圖

x=e2psk;

Ts=1/100000;%采樣率

k=3;

plotspec(x,Ts,k);

運行程序,經(jīng)過AWGN信道后的信號e2psk,其時域圖如3.8所示:

圖3.8經(jīng)過AWGN信道后的信號e2psk

信號局部放大圖如3.9所示:

圖3.9e2psk信號時域圖(部分)

可見信號經(jīng)過AWGN信道后,受到噪聲污染,時域上有失真。

e2psk信號頻譜圖如3.10所示:

圖3.10e2psk信號頻譜圖

300HZ左右處放大圖如3.11所示:

圖3.11e2psk信號300Hz左右處頻譜

分析圖可知,由于信號經(jīng)過了AWGN信號,收到噪聲干擾,頻譜圖在整個頻域上有加性白噪聲污染,都有不同程度的失真,不利于信號的解調(diào)。

3.5載波恢復(fù)的MATLAB實現(xiàn)

從接收端接收到信號后,為了進行相干解調(diào),需要從本地恢復(fù)載波。對本次課設(shè)BPSK調(diào)制方式是一種沒有抑制載波的調(diào)制方式,但是在通常情況下,載波很容易的被隱藏在接收信號中,而且需要很多額外的處理過程來恢復(fù)載波。對于剛接收到的信號可先通過FFT實現(xiàn)載波的頻率估測,得出一個頻率之后,再使用自適應(yīng)算法的方式,準確定位和驗證載波頻率值。

3.5.1接收端帶通濾波器

在接收器接受到調(diào)制信號后,由于調(diào)制信號被AWGN信道“污染”,在整個頻帶上增加了加性高斯白噪聲,故為了過濾信號需要在接受端加上一個帶通濾波器,以濾除帶外信號。

本次課設(shè)調(diào)用remez函數(shù)以使用雷米茲算法,雷米茲算法提供了求解切比雪夫逼近問題的有效方法。切比雪夫濾波器是在通帶或阻帶上頻率響應(yīng)幅度等波紋波動的濾波器。

MATLAB代碼:

%帶通濾波器生成及其頻率響應(yīng)

f1=500;%濾波器階數(shù)

fs=1000;%濾波器顯示頻率最大值的兩倍

ff=[0.51.52.68.691];%歸一化的截止頻率

fa=[001100];

h=remez(f1,ff,fa);%生成帶通濾波器

figure(4),

freqz(h,1,512,fs);%繪出濾波器的頻率響應(yīng)

r=filter(h,1,e2psk);%信號通過帶通濾波器

k=5;

plotspec(r,Ts,k)

帶通濾波器的幅頻響應(yīng)如圖3.12所示:

圖3.12帶通濾波器幅頻響應(yīng)

帶通濾波器的相頻響應(yīng)如圖3.13所示:

圖3.13帶通濾波器的相頻響應(yīng)

分析可知在通帶或阻帶上頻率響應(yīng)幅度等波紋波動的切比雪夫濾波器,帶通濾波器的頻率響應(yīng)可知帶通濾波器的中心頻率為300Hz,通帶為260Hz至340Hz,群延時為179.85度。

信號通過帶通濾波器后時域圖如3.14所示:

圖3.14信號通過帶通濾波器

通過帶通濾波后信號的局部圖如3.15所示:

圖3.15接收信號通過帶通濾波(部分)

可知經(jīng)過帶通濾波后,時域圖中信號有一定成度的改善,波形突刺減少,一定程度的恢復(fù)成原來的波形。

信號通過帶通濾波后的幅頻響應(yīng)如3.16所示:

圖3.16接受信號通過帶通濾波后的幅頻響應(yīng)

分析頻域圖,在頻帶中多余的加性白噪聲得到一定的抑制,而很好的保留了載頻附近的頻率信息。

3.5.2通過FFT實現(xiàn)載波的直接頻率估計

對于沒有抑制載波的調(diào)制信號來說,使用FFT變換后通常載波頻率幅度是最大值,可以通過檢測已調(diào)信號的整個頻率范圍最大值來確定最大值。但是,一般情況下,由于已調(diào)信號經(jīng)過信道后,頻譜受到損傷,出現(xiàn)一定程度的失真,降低了用最大值來確定載波頻率的方法的可靠性,此時需要使用另外的方法來恢復(fù)載波頻率。

載波恢復(fù)流程框圖如3.17所示:

圖3.17載波恢復(fù)流程圖

如圖3.17所示,一般可以在帶通濾波器后使用非線性模塊平方器,是接受信號,由基帶信號和載波相乘組成,平方器的輸出項為

3.1

又根據(jù)等式,改寫3.1為

3.2

將用其平均值和偏移量的和來表示

3.3

因此3.4

以為中心的窄帶帶通濾波器只能讓中的純余弦項通過,而且還會抑制當(dāng)中的直流成分,低頻部分和向上邊頻了的也不能通過。帶通濾波器的輸出約為

3.5

式中,是相位偏移,是帶通濾波器引入的。對于接受機來說,值是已知的,故可用來估算出載波的頻率。

MATLAB代碼:

rsc=r;

q=rsc.^2;%通過平方器

fl=500;ff=[0.0100.0104.0136.01401];

fa=[001100];

h=remez(fl,ff,fa);%生成帶通濾波器

rp=filter(h,1,q);%再通過帶通濾波

fftrBPF=fft(rp);%對rp信號進行FFT變換

[m,imax]=max(abs(fftrBPF(1:end/2)));%找到最大值,返回最大值和最大值所在數(shù)組點

ssf=(0:length(rp))/(Ts*length(rp));%建立儲存頻率的數(shù)組

freqS=ssf(imax);%找出存儲頻率數(shù)組對應(yīng)最大幅度的頻率

運行程序結(jié)果:

freqS=

600

由結(jié)果可知估測頻率fc=300Hz。

3.5.3自適應(yīng)(迭代)算法驗證恢復(fù)頻率

對于前面已經(jīng)估測處了載波的頻率,此時可以由freqS為假設(shè)值,利用自適應(yīng)算法對恢復(fù)的載波頻率進行再估測和驗證。

在通信中的許多問題能夠被設(shè)計成最優(yōu)化問題要解決這種問題需要三個基本的步驟:

(1)設(shè)定一個目標-選擇一個目標函數(shù)

(2)選擇一個實現(xiàn)目標的方法-最大化或最大化這個目標函數(shù)

(3)檢驗以確定這個方法能達到預(yù)期效果

“設(shè)定一個目標函數(shù)”通常包括尋找一個可以最大化或可以最小化的函數(shù),定位最大和最小值為所要解決問題提供了有用的信息。這個函數(shù)的選擇必須使它和它的導(dǎo)數(shù)的值能基于一些信息計算出來。

有很多的方法可以用來實現(xiàn)最大化或最小化過程。有的時候是可以使用直接的方法,如,如果為了找到多項式達到最小值的點,只要直接找到它的導(dǎo)數(shù)并置零就可以得到解答。但是很多時候,不可能有如此簡單的解決方法,遞歸方法(自適應(yīng)方法)通常在信號運算中有很好的應(yīng)用。

自適應(yīng)算法通常以最陡下降為目的,也可以稱之為最陡下降法,最陡下降自適應(yīng)算法從最初猜測的位置開始,算出從估計值開始哪個是最陡下降的方向,并沿著這條下降方向做出最新的估算,為了運用最陡下降法來最小化多項式,假設(shè)在時間處的的當(dāng)前估算是可以得到的,表示為在時間的估算可以用下式:

3.6

式中,是很小正數(shù),稱為步長,而的梯度是當(dāng)前點計算出來的,當(dāng)重復(fù)計算,依次迭代運算,最終接近最小值

對于接受信號為,設(shè)freqS為,合理的算法為嘗試最小化下式:

3.7

利用梯度算法重寫3.6式,得:

3.8

將平方項展開整理為:

3.9

此式即為其誤差表面函數(shù),可以用來分析性能函數(shù)。

MATLAB代碼:

%自適應(yīng)算法估測頻率

%預(yù)先恢復(fù)頻率2fc=freqS=600Hz

%本次算法初始值為300Hz,采用步長mu=0.003

Ts=1/100000;

time=5;

t=0:Ts:time-Ts;%建立時間向量

fl=300;

ff=[0.005.011];

fa=[1100];

h=remez(fl,ff,fa);%低通濾波生成

mu=.003;%步長fc=300;%freqS估測出頻率

fest=zeros(1,length(t));

fest(1)=fc+3;%起始運算的頻率303Hz

z=zeros(1,fl+1);

%進行循環(huán)運算迭代運算有3.8式得出

fork=1:length(t)-1

z=[(r(k)-cos(2*pi*fest(k)*t(k)))*sin(2*pi*fest(k)*t(k)),z(1:fl)];

update=fliplr(h)*z';

fest(k+1)=fest(k)-mu*update;

end

%畫圖

figure(6),

plot(t,fest);

title('FrequencyTrackingviatheDirectmethod')

xlabel('time');

ylabel('phaseoffset');

運行程序后,自適應(yīng)算法結(jié)果如3.18所示:

圖3.18自適應(yīng)算法結(jié)果圖

由圖可知,在一段區(qū)域內(nèi)由假定的303Hz趨近于300Hz,與之前直接頻率估計的結(jié)果相符,故可知載波的頻率為300Hz。

3.6BPSK解調(diào)

對于BPSK解調(diào),本次課設(shè)采用匹配濾波接收,匹配濾波器可使輸出信噪比達最大,有利于判決抽樣。

設(shè)接受濾波器傳輸函數(shù)為,沖擊函數(shù)為,濾波器輸入碼元的持續(xù)時間為匹配濾波器的特性可以用其沖激響應(yīng)函數(shù)來描述:

3.10

由式可知匹配濾波器的沖激響應(yīng)就是的鏡像,但在時間軸上平移了。

一個實際的匹配濾波器應(yīng)該是物理可實現(xiàn)的,其沖激響應(yīng)必須符合因果關(guān)系,在輸入沖激脈沖加入前不應(yīng)有沖激響應(yīng)出現(xiàn),即必須有:

3.11

既要求滿足條件:

3.12

或滿足條件:

3.13

式3.13的條件說明,接受濾波器輸入端的信號碼元在抽樣時刻之后必須為零。一般不希望在碼元結(jié)束之后很久才抽樣,故通常選擇在碼元末尾抽樣,即選。故匹配濾波器沖激響應(yīng)可以寫為:

3.14

這時,若匹配濾波器的輸入電壓為,則輸出信號碼元的波形,可以求出為:

3.15

式3.15表明,匹配濾波器輸出信號碼元波形是輸入信號碼元波形的自相關(guān)函數(shù)。為任意一常數(shù),通常取。

MATLAB代碼:

%匹配濾波

tm=0:1/100000:1-(1/100000);

ps=cos(2*pi*300*tm);

dm=conv(ps,r);

%畫圖

figure(7),

plot(dm);gridon

運行程序圖如3.19所示:

圖3.19匹配濾波后信號

信號局部放大圖如3.20所示:

圖3.20信號通過匹配濾波后局部方法圖

對信號匹配濾波后,則可以進行抽樣判決以恢復(fù)原始二進制信息。對于匹配濾波后的信號采樣點為nTs。

MATLAB代碼:

%抽樣賦值1和-1

dmbv=[];

fori=1:1:length(r)/100000;

dmbv1=dm(i*100000);

dmbv=[dmbvdmbv1];

end

%將雙極性不歸零碼變?yōu)閱螛O性不歸零碼,賦值0和1

fori=1:1:length(dmbv);

ifdmbv(i)>0;dmbv(i)=0;

elsedmbv(i)=1;

end

end

%畫圖

tm1=0:1:length(dmbv)-1;

figure(8),

stem(tm1,dmbv);

gridon;

axis([-0.515.5-12]);

xlabel('時間');

ylabel('幅度')

title('解調(diào)后的單極性不歸零二進制信號')

運行程序后得結(jié)果如3.21所示:

圖3.21解調(diào)后的單極性不歸零二進制信號

由圖可讀出恢復(fù)數(shù)據(jù)為0111000001101000

MATLAB代碼:

%解碼

dmbv1=dmbv(1:end/2);%8位

dmbv2=dmbv(end/2+1:end);

dmstr1=num2str(dmbv1);%數(shù)值型變成字符型

dmstr2=num2str(dmbv2);

dms1=bin2dec(dmstr1);%由二進制轉(zhuǎn)成十進制

dms2=bin2dec(dmstr2);

運行程序后,由工作空間可知都dms1為112,dms2為104。

再有代碼:char(112);char(104);

得結(jié)果為:ph

故解調(diào)出了原始的文本信息。

4總結(jié)

本次課設(shè)基于MATLAB仿真了BPSK調(diào)制方式的通信傳輸,發(fā)送端將文本信息轉(zhuǎn)換成二進制基帶信號,進行BPSK調(diào)制發(fā)送,信道為AWGN信道產(chǎn)生加性高斯白噪聲,接收端接收信號,進行載波恢復(fù),將恢復(fù)的載波對接受信號進行匹配濾波,并解調(diào),再進行抽樣判決,恢復(fù)出原始的二進制字符,在解碼成文本信息。本次課設(shè)進行了相對實際的BPSK調(diào)制通信仿真,初步驗證了BPSK調(diào)制的可行性,并對通信系統(tǒng)中遇到的問題進行了一定的探索研究。

通過本次課設(shè),使我對已掌握專業(yè)知識有了更深一層次的把握,也學(xué)到了很多新的知識并很好的掌握了這些知識,同時整個過程充分理解了理論指導(dǎo)實踐,實踐驗證理論這句話。我不僅書本上得理論知識有了進一步的理解,也同時熟練的掌握了MATLAB的仿真,使自己腦海中的理論不再只是理論而得到了實踐的驗證。

這次課設(shè)使我能很好的綜合運用自己所學(xué)的知識解決一些問題,在面對自己不懂的問題時能逐步分析并最后解決這些問題,對我以后的學(xué)習(xí)起到了拋磚引玉的作用,促使以后能不斷的進步。

附錄

%為調(diào)用的plotspec函數(shù)

functionplotspec(x,Ts,k)

%函數(shù)功能是畫出信號的時域圖和頻域圖

%x為輸入信號,Ts為抽樣率,k為圖的序號

N=length(x);

t=Ts*(1:N);

ssf=(-N/2:N/2-1)/(Ts*N);

fx=fft(x(1:N));

fxs=fftshift(fx);

figure(k)

subplot(2,1,1),plot(t,x);gridon,

xlabel('秒');ylabel('幅度');

subplot(2,1,2),plot(ssf,abs(fxs));gridon,

xlabel('頻率');ylabel('幅度')

end

致謝

感謝這次課程設(shè)計的指導(dǎo)老師李宏達老師、劉慶泉老師和伍彩云老師,也感謝指導(dǎo)過我的教研室老師和同學(xué)們。

參考文獻

[1]C.RichardJohnsonJr.等著.潘甦譯.軟件無線電機械工業(yè)出版社

[2]樊昌信等編著.通信原理.國防工業(yè)出版社

[3]郭文彬等編.通信原理-基于MATLAB的計算機仿真.北京郵電大學(xué)出版社

[4]趙鴻圖等編.通信原理MATLAB仿真教程.人民郵電出版社

附錄資料:不需要的可以自行刪除

C語言編程規(guī)范(僅供參考)

1.基本要求

1.1程序結(jié)構(gòu)清析,簡單易懂,單個函數(shù)的程序行數(shù)不得超過100行。

1.2打算干什么,要簡單,直接了當(dāng),代碼精簡,避免垃圾程序。

1.3盡量使用標準庫函數(shù)和公共函數(shù)。

1.4不要隨意定義全局變量,盡量使用局部變量。

1.5使用括號以避免二義性。

2.可讀性要求

2.1可讀性第一,效率第二。

2.2保持注釋與代碼完全一致。

2.3每個源程序文件,都有文件頭說明,說明規(guī)格見規(guī)范。

2.4每個函數(shù),都有函數(shù)頭說明,說明規(guī)格見規(guī)范。

2.5主要變量(結(jié)構(gòu)、聯(lián)合、類或?qū)ο螅┒x或引用時,注釋能反映其含義。

2.7常量定義(DEFINE)有相應(yīng)說明。

2.8處理過程的每個階段都有相關(guān)注釋說明。

2.9在典型算法前都有注釋。

2.10利用縮進來顯示程序的邏輯結(jié)構(gòu),縮進量一致并以Tab鍵為單位,定義Tab為6個

字節(jié)。

2.11循環(huán)、分支層次不要超過五層。

2.12注釋可以與語句在同一行,也可以在上行。

2.13空行和空白字符也是一種特殊注釋。

2.14一目了然的語句不加注釋。

2.15注釋的作用范圍可以為:定義、引用、條件分支以及一段代碼。

2.16注釋行數(shù)(不包括程序頭和函數(shù)頭說明部份)應(yīng)占總行數(shù)的1/5到1/3。

3.結(jié)構(gòu)化要求

3.1禁止出現(xiàn)兩條等價的支路。

3.2禁止GOTO語句。

3.3用IF語句來強調(diào)只執(zhí)行兩組語句中的一組。禁止ELSEGOTO和ELSERETURN。

3.4用CASE實現(xiàn)多路分支。

3.5避免從循環(huán)引出多個出口。

3.6函數(shù)只有一個出口。

3.7不使用條件賦值語句。

3.8避免不必要的分支。

3.9不要輕易用條件分支去替換邏輯表達式。

4.正確性與容錯性要求

4.1程序首先是正確,其次是優(yōu)美

4.2無法證明你的程序沒有錯誤,因此在編寫完一段程序后,應(yīng)先回頭檢查。

4.3改一個錯誤時可能產(chǎn)生新的錯誤,因此在修改前首先考慮對其它程序的影響。

4.4所有變量在調(diào)用前必須被初始化。

4.5對所有的用戶輸入,必須進行合法性檢查。

4.6不要比較浮點數(shù)的相等,

如:10.0*0.1==1.0,不可靠

4.7程序與環(huán)境或狀態(tài)發(fā)生關(guān)系時,必須主動去處理發(fā)生的意外事件,如文件能否

邏輯鎖定、打印機是否聯(lián)機等。

4.8單元測試也是編程的一部份,提交聯(lián)調(diào)測試的程序必須通過單元測試。

5.可重用性要求

5.1重復(fù)使用的完成相對獨立功能的算法或代碼應(yīng)抽象為公共控件或類。

5.2公共控件或類應(yīng)考慮OO思想,減少外界聯(lián)系,考慮獨立性或封裝性。

5.3公共控件或類應(yīng)建立使用模板。

附:C++編程規(guī)范,delphi作相應(yīng)的參考

1適用范圍

本標準適用于利用VisulC++,BorlandC++進行軟件程序開發(fā)的人員.。

.2變量命名

命名必須具有一定的實際意義,形式為xAbcFgh,x由變量類型確定,Abc、Fgh表示連續(xù)意

義字符串,如果連續(xù)意義字符串僅兩個,可都大寫.如OK.

具體例程:

BOOL類型bEnable;

ch*charchText

c*類對象cMain(對象實例)

h*Handle(句柄)hWnd

i*int

n*無符號整型

p*指針

sz,str*字符串

wWORD

x,y坐標

Char或者TCHAR類型與WindowsAPI有直接聯(lián)系的用szAppName[10]形式否則用

FileName[10]形式,單個字符也可用小寫字母表示;

Int類型nCmdShow;

LONG類型lParam;

UINT類型uNotify;

DWORD類型dwStart;

PSTR類型pszTip;

LPSTR類型lpCmdLine

LPTSTR類型lpszClassName;

LPVOID類型lpReserved

WPARAM類型wParam,

LPARAM類型lParam

HWND類型hDlg;

HDC類型hDC;

HINSTANCE類型hInstance

HANDLE類型hInstance,

HICON類型hIcon;

intiTmp

floatfTmp

DWORDdw*

String,AnsiStringstr*

m_類成員變量m_nVal,m_bFlag

g_全局變量g_nMsg,g_bFlag

局部變量中可采用如下幾個通用變量:nTemp,nResult,I,J(一般用于循環(huán)變量)。

其他資源句柄同上

.3常量命名和宏定義

常量和宏定義必須具有一定的實際意義;

常量和宏定義在#include和函數(shù)定義之間;

常量和宏定義必須全部以大寫字母來撰寫,中間可根據(jù)意義的連續(xù)性用下劃線連接,每一

條定義的右側(cè)必須有一簡單的注釋,說明其作用;

資源名字定義格式:

菜單:IDM_XX或者CM_XX

位圖:IDB_XX

對話框:IDD_XX

字符串:IDS_XX

DLGINIT:DIALOG_XX

ICON:IDR_XX

.4函數(shù)命名

函數(shù)原型說明包括引用外來函數(shù)及內(nèi)部函數(shù),外部引用必須在右側(cè)注明函數(shù)來源:模

塊名及文件名,如是內(nèi)部函數(shù),只要注釋其定義文件名;

第一個字母必須使用大寫字母,要求用大小寫字母組合規(guī)范函數(shù)命名,必要時可用下劃線

間隔,示例如下:

voidUpdateDB_Tfgd(TRACK_NAME);file://ModuleName:r01/sdw.c

voidPrintTrackData(TRACK_NAME);file://ModuleName:r04/tern.c

voidImportantPoint(void);file://ModuleName:r01/sdw.c

voidShowChar(int,int,chtype);file://LocalModule

voidScrollUp_V(int,int);file://LocalModule

.5結(jié)構(gòu)體命名

結(jié)構(gòu)體類型命名必須全部用大寫字母,原則上前面以下劃線開始;結(jié)構(gòu)體變量命名必須用

大小寫字母組合,第一個字母必須使用大寫字母,必要時可用下劃線間隔。對于私有數(shù)

據(jù)區(qū),必須注明其所屬的進程。全局數(shù)據(jù)定義只需注意其用途。

示例如下:

typedefstruct

{

charszProductName[20];

charszAuthor[20];

charszReleaseDate[16];

charszVersion[10];

unsignedlongMaxTables;

unsignedlongUsedTables;

}DBS_DATABASE;

DBS_DATABASEGdataBase;

6控件的命名:

用小寫前綴表示類別

用小寫前綴表示類別:

fm窗口

cmd按鈕

cobcombo,下拉式列表框

txt文本輸入框

lablabal,標簽

imgimage,圖象

picpicture

grdGrid,網(wǎng)格

scr滾動條

lst列表框

frmfram

7注釋

原則上注釋要求使用中文;

文件開始注釋內(nèi)容包括:公司名稱、版權(quán)、作者名稱、時間、模塊用途、背景介紹等,復(fù)

雜的算法需要加上流程說明;

函數(shù)注釋包括:輸入、輸出、函數(shù)描述、流程處理、全局變量、調(diào)用樣例等,復(fù)雜的函數(shù)

需要加上變量用途說明;

程序中注釋包括:修改時間和作者、方便理解的注釋等;

引用一:文件開頭的注釋模板

/******************************************************************

**文件名:

**Copyright(c)1998-1999*********公司技術(shù)開發(fā)部

**創(chuàng)建人:

**日期:

**修改人:

**日期:

**描述:

**

**版本:

**

******************************************************************/

引用二:函數(shù)開頭的注釋模板

/*****************************************************************

**函數(shù)名:

**輸入:a,b,c

**a

**b

**c

**輸出:x

**x為1,表示...

**x為0,表示...

**功能描述:

**全局變量:

**調(diào)用模塊:

**作者:

**日期:

**修改:

**日期:

**版本

****************************************************************/

引用三:程序中的注釋模板

/**/

/*注釋內(nèi)容*/

/**/

8程序

a.程序編碼力求簡潔,結(jié)構(gòu)清晰,避免太多的分支結(jié)構(gòu)及太過于技巧性的程序,

盡量不采用遞歸模式。

b.編寫程序時,亦必須想好測試的方法,換句話說,”單元測試”的測試方案應(yīng)

在程序編寫時一并擬好。

c.注釋一定要與程序一致。

d.版本封存以后的修改一定要將老語句用/**/封閉,不能自行刪除或修改,并要

在文件及函數(shù)的修改記錄中加以記錄。

e.程序中每個block的開頭”{"及"}”必須對齊,嵌套的block每進一套,

縮進一個tab,TAB為4個空格,block類型包括if、for、while、do等關(guān)鍵字引出的。

f.對于比較大的函數(shù),每個block和特殊的函數(shù)調(diào)用,都必須注明其功能,舉例如下

count.divisor=1193280/freq;//computethepropercount

OutByte((unsignedshort)67,(unsignedchar)182);//tell8253thata

countiscoming

OutByte((unsignedshort)66,count.c[0]);//sendlow-orderbyte

OutByte((unsignedshort)66,count.c[1]);//sendhigh-orderbyte

×××××××××××××××××××××××××××××××××××××××

bcb,delphi中的變量命名:

遵循匈牙利命名法,命

名必須有意義,制定如下規(guī)定

窗體:以大寫的W開始,如About版權(quán)窗體,命名為WAbout

文件:以大寫的F開始,如About版權(quán)窗體,文件命名為FAbout.cpp

按鈕(Button):如退出按鈕,命名為btnExit

……

基類:加base標記,如報表基類,窗體命名為:WBaseRep,文件命名為FBaseRep.cpp

轉(zhuǎn)貼

>1.在.h/.cpp的開頭應(yīng)有一段格式統(tǒng)一的說明,內(nèi)容包括:

>a.文件名(FileName);

>b.創(chuàng)建人(Creater);

>c.文件創(chuàng)建時間(Date);

>d.簡短說明文件功能、用途(Comment)。

好習(xí)慣

>2.除非極其簡單,否則對函數(shù)應(yīng)有注釋說明。內(nèi)容包括:功能、入口/出口參數(shù),必

>時還可有備注或補充說明。

還是好習(xí)慣

>3.每列代碼的長度推薦為80列,最長不得超過120列;折行以對齊為準。

太寬了,我的限制是60列,因為文本方式下屏幕一共80列,如果你用BC這一類的編輯

器,窗口邊框等又要占據(jù)一定空間,所以80列太寬

>4.循環(huán)、分支代碼,判斷條件與執(zhí)行代碼不得在同一行上。

很對

>5.指針的定義,*號既可以緊接類型,也可以在變量名之前。

>

>例:可寫做:int*pnsize;

>

>也可寫做:int*pnsize;

>

>但不得寫做:int*pnsize;

建議采用第二種,除非附加另外一條規(guī)定:一次只聲明一個變量,否則就會讓人混淆,

比如:

int*a,b;

看起來b好像也是個指針,其實不是。

>6.在類的成員函數(shù)內(nèi)調(diào)用非成員函數(shù)時,在非成員函數(shù)名前必須加上"::"。

這一條我倒覺得并不是必需的,我的看法是決不要讓你的類成員函數(shù)和全局函數(shù)的名稱

相同(或類似)

>7.函數(shù)入口參數(shù)有缺省值時,應(yīng)注釋說明。

>

>例:BOOLCWpsDib::PaintDIB(CDC*pDC,CRect&rc,

>intnBrightness,file://*=0*//

>BOOLbGrayScalefile://*=FALSE*//)

每個變量寫一行,必要時加上/*in,out*/注釋

>8.elseif必須寫在一行。

應(yīng)該盡量避免elseif這樣的結(jié)構(gòu)

>9.與‘{’、‘}’有關(guān)的各項規(guī)定:

>

>9.1‘{’、‘}’應(yīng)獨占一行。在該行內(nèi)可有注釋。

>9.2‘{’必須另起一行,‘{’之后的代碼必須縮進一個Tab?!畕’與‘}’必須在

>一列上。

>9.3在循環(huán)、分支之后若只有一行代碼,雖然可省略‘{’、‘}’,但不推薦這么

>做。若省略后可能引起歧義,則必須加上‘{’、‘}’。

持保留意見,因為GNU的代碼規(guī)范是這樣的:

if(NULL==ptr)

{

//dosomethinghere

}

或者

if(NULL==ptr){

//dosomethinghere

}

爭論哪個更好并沒有意義,關(guān)鍵是統(tǒng)一,如果用VC當(dāng)然你的辦法最方便,可是如果你用

emacs或者vi,就不是這樣了。

>10.與空格有關(guān)的各項規(guī)定。

>

>10.1在所有兩目、三目運算符的兩邊都必須有空格。在單目運算符兩端不必空格。

>在‘—>’、‘::’、‘.’、‘[’、‘]’等運算符前后,及‘&’(取地址)、‘*

>’(取值)等運算符之后不得有空格。

>10.2for、while、if等關(guān)鍵詞之后應(yīng)有1個空格,再接‘(’,之后無空格;在結(jié)

>的‘)’前不得有空格。

我認為在括號兩端加空格并不是什么錯誤,尤其是在一個條件十分復(fù)雜的if語句里

>10.3調(diào)用函數(shù)、宏時,‘(’、‘)’前后不得有空格。

>10.4類型強制轉(zhuǎn)換時,‘(’‘)’前后不得有空格

同上

>11.與縮進有關(guān)的各項規(guī)定

>

>11.1縮進以Tab為單位。1個Tab為4個空格

我認為這個值應(yīng)該更大,我自己使用8個空格,如果你的代碼因為縮進幅度太大而導(dǎo)致

折行,那么幾乎可以肯定你的程序設(shè)計方案有問題。

>11.2下列情況,代碼縮進一個Tab:

>1.函數(shù)體相對函數(shù)名及'{'、'}'。

>2.if、else、for、while、do等之后的代碼。

>3.一行之內(nèi)寫不下,折行之后的代碼,應(yīng)在合理的位置進行折行。若有+-*/等

>算符,則運算符應(yīng)在上一行末尾,而不應(yīng)在下一行的行首。

這一條我反對,運算符應(yīng)該放在下一行行首,以使人能清楚的知道這一行是續(xù)上一行

的,比如

if(something

&&somethingelse

&&otherthings)

如果寫做

if(something&&

somethingelse&&

otherthings)

反而看不清楚

>11.3下列情況,不必縮進:switch之后的case、default。

編程規(guī)范與范例

目錄

1排版6

2注釋11

3標識符命名18

4可讀性20

5變量、結(jié)構(gòu)22

6函數(shù)、過程28

7可測性36

8程序效率40

9質(zhì)量保證44

10代碼編輯、編譯、審查50

11代碼測試、維護52

12宏53

1排版

1-1:程序塊要采用縮進風(fēng)格編寫,縮進的空格數(shù)為4個。

說明:對于由開發(fā)工具自動生成的代碼可以有不一致。

1-2:相對獨立的程序塊之間、變量說明之后必須加空行。

示例:如下例子不符合規(guī)范。

if(!valid_ni(ni))

{

...//programcode

}

repssn_ind=ssn_data[index].repssn_index;

repssn_ni=ssn_data[index].ni;

應(yīng)如下書寫

if(!valid_ni(ni))

{

...//programcode

}

repssn_ind=ssn_data[index].repssn_index;

repssn_ni=ssn_data[index].ni;

1-3:較長的語句(>80字符)要分成多行書寫,長表達式要在低優(yōu)先級操作符處劃分新行,操作符放在新行之首,劃分出的新行要進行適當(dāng)?shù)目s進,使排版整齊,語句可讀。

示例:

perm_count_msg.head.len=NO7_TO_STAT_PERM_COUNT_LEN

+STAT_SIZE_PER_FRAM*sizeof(_UL);

act_task_table[frame_id*STAT_TASK_CHECK_NUMBER+index].occupied

=stat_poi[index].occupied;

act_task_table[taskno].duration_true_or_false

=SYS_get_sccp_statistic_state(stat_item);

report_or_not_flag=((taskno<MAX_ACT_TASK_NUMBER)

&&(n7stat_stat_item_valid(stat_item))

&&(act_task_table[taskno].result_data!=0));

1-4:循環(huán)、判斷等語句中若有較長的表達式或語句,則要進行適應(yīng)的劃分,長表達式要在低優(yōu)先級操作符處劃分新行,操作符放在新行之首。

示例:

if((taskno<max_act_task_number)

&&(n7stat_stat_item_valid(stat_item)))

{

...//programcode

}

for(i=0,j=0;(i<BufferKeyword[word_index].word_length)

&&(j<NewKeyword.word_length);i++,j++)

{

...//programcode

}

for(i=0,j=0;

(i<first_word_length)&&(j<second_word_length);

i++,j++)

{

...//programcode

}

¹1-5:若函數(shù)或過程中的參數(shù)較長,則要進行適當(dāng)?shù)膭澐帧?/p>

示例:

n7stat_str_compare((BYTE*)&stat_object,

(BYTE*)&(act_task_table[taskno].stat_object),

sizeof(_STAT_OBJECT));

n7stat_flash_act_duration(stat_item,frame_id*STAT_TASK_CHECK_NUMBER

+index,stat_object);

¹1-6:不允許把多個短語句寫在一行中,即一行只寫一條語句。

示例:如下例子不符合規(guī)范。

rect.length=0;rect.width=0;

應(yīng)如下書寫

rect.length=0;

rect.width=0;

1-7:if、for、do、while、case、switch、default等語句自占一行,且if、for、do、while等語句的執(zhí)行語句部分無論多少都要加括號{}。

示例:如下例子不符合規(guī)范。

if(pUserCR==NULL)return;

應(yīng)如下書寫:

if(pUserCR==NULL)

{

return;

}

1-8:對齊只使用空格鍵,不使用TAB鍵。

說明:以免用不同的編輯器閱讀程序時,因TAB鍵所設(shè)置的空格數(shù)目不同而造成程序布局不整齊,不要使用BC作為編輯器合版本,因為BC會自動將8個空格變?yōu)橐粋€TAB鍵,因此使用BC合入的版本大多會將縮進變亂。

1-9:函數(shù)或過程的開始、結(jié)構(gòu)的定義及循環(huán)、判斷等語句中的代碼都要采用縮進風(fēng)格,case語句下的情況處理語句也要遵從語句縮進要求。

1-10:程序塊的分界符(如C/C++語言的大括號‘{’和‘}’)應(yīng)各獨占一行并且位于同一列,同時與引用它們的語句左對齊。在函數(shù)體的開始、類的定義、結(jié)構(gòu)的定義、枚舉的定義以及if、for、do、while、switch、case語句中的程序都要采用如上的縮進方式。

示例:如下例子不符合規(guī)范。

for(...){

...//programcode

}

if(...)

{

...//programcode

}

voidexample_fun(void)

{

...//programcode

}

應(yīng)如下書寫。

for(...)

{

...//programcode

}

if(...)

{

...//programcode

}

voidexample_fun(void)

{

...//programcode

}

1-11:在兩個以上的關(guān)鍵字、變量、常量進行對等操作時,它們之間的操作符之前、之后或者前后要加空格;進行非對等操作時,如果是關(guān)系密切的立即操作符(如->),后不應(yīng)加空格。

說明:采用這種松散方式編寫代碼的目的是使代碼更加清晰。

由于留空格所產(chǎn)生的清晰性是相對的,所以,在已經(jīng)非常清晰的語句中沒有必要再留空格,如果語句已足夠清晰則括號內(nèi)側(cè)(即左括號后面和右括號前面)不需要加空格,多重括號間不必加空格,因為在C/C++語言中括號已經(jīng)是最清晰的標志了。

在長語句中,如果需要加的空格非常多,那么應(yīng)該保持整體清晰,而在局部不加空格。給操作符留空格時不要連續(xù)留兩個以上空格。

示例:

(1)逗號、分號只在后面加空格。

inta,b,c;

(2)比較操作符,賦值操作符"="、"+=",算術(shù)操作符"+"、"%",邏輯操作符"&&"、"&",位域操作符"<<"、"^"等雙目操作符的前后加空格。

if(current_time>=MAX_TIME_VALUE)

a=b+c;

a*=2;

a=b^2;

(3)"!"、"~"、"++"、"--"、"&"(地址運算符)等單目操作符前后不加空格。

*p='a';//內(nèi)容操作"*"與內(nèi)容之間

flag=!isEmpty;//非操作"!"與內(nèi)容之間

p=&mem;//地址操作"&"與內(nèi)容之間

i++;//"++","--"與內(nèi)容之間

(4)"->"、"."前后不加空格。

p->id=pid;//"->"指針前后不加空格

(5)if、for、while、switch等與后面的括號間應(yīng)加空格,使if等關(guān)鍵字更為突出、明顯。

if(a>=b&&c>d)

1-1:一行程序以小于80字符為宜,不要寫得過長。

2注釋

2-1:一般情況下,源程序有效注釋量必須在20%以上。

說明:注釋的原則是有助于對程序的閱讀理解,在該加的地方都加了,注釋不宜太多也不能太少,注釋語言必須準確、易懂、簡潔。

2-2:說明性文件(如頭文件.h文件、.inc文件、.def文件、編譯說明文件.cfg等)頭部應(yīng)進行注釋,注釋必須列出:版權(quán)說明、版本號、生成日期、作者、內(nèi)容、功能、與其它文件的關(guān)系、修改日志等,頭文件的注釋中還應(yīng)有函數(shù)功能簡要說明。

示例:下面這段頭文件的頭注釋比較標準,當(dāng)然,并不局限于此格式,但上述信息建議要包含在內(nèi)。

/*************************************************

Copyright(C),1988-1999,HuaweiTech.Co.,Ltd.

Filename://文件名

Author:Version:Date://作者、版本及完成日期

Description://用于詳細說明此程序文件完成的主要功能,與其他模塊

//或函數(shù)的接口,輸出值、取值范圍、含義及參數(shù)間的控

//制、順序、獨立或依賴等關(guān)系

Others://其它內(nèi)容的說明

FunctionList://主要函數(shù)列表,每條記錄應(yīng)包括函數(shù)名及功能簡要說明

1.

History://修改歷史記錄列表,每條修改記錄應(yīng)包括修改日期、修改

//者及修改內(nèi)容簡述

1.Date:

Author:

Modification:

2....

*************************************************/

2-3:源文件頭部應(yīng)進行注釋,列出:版權(quán)說明、版本號、生成日期、作者、模塊目的/功能、主要函數(shù)及其功能、修改日志等。

示例:下面這段源文件的頭注釋比較標準,當(dāng)然,并不局限于此格式,但上述信息建議要包含在內(nèi)。

/************************************************************

Copyright(C),1988-1999,HuaweiTech.Co.,Ltd.

FileName:test.cpp

Author:Version:Date:

Description://模塊描述

Version://版本信息

FunctionList://主要函數(shù)及其功能

1.

History://歷史修改記錄

<author><time><version><desc>

David96/10/121.0buildthismoudle

***********************************************************/

說明:Description一項描述本文件的內(nèi)容、功能、內(nèi)部各部分之間的關(guān)系及本文件與其它文件關(guān)系等。History是修改歷史記錄列表,每條修改記錄應(yīng)包括修改日期、修改者及修改內(nèi)容簡述。

2-4:函數(shù)頭部應(yīng)進行注釋,列出:函數(shù)的目的/功能、輸入?yún)?shù)、輸出參數(shù)、返回值、調(diào)用關(guān)系(函數(shù)、表)等。

示例:下面這段函數(shù)的注釋比較標準,當(dāng)然,并不局限于此格式,但上述信息建議要包含在內(nèi)。

/*************************************************

Function://函數(shù)名稱

Description://函數(shù)功能、性能等的描述

Calls://被本函數(shù)調(diào)用的函數(shù)清單

CalledBy://調(diào)用本函數(shù)的函數(shù)清單

TableAccessed://被訪問的表(此項僅對于牽扯到數(shù)據(jù)庫操作的程序)

TableUpdated://被修改的表(此項僅對于牽扯到數(shù)據(jù)庫操作的程序)

Input://輸入?yún)?shù)說明,包括每個參數(shù)的作

//用、取值說明及參數(shù)間關(guān)系。

Output://對輸出參數(shù)的說明。

Return://函數(shù)返回值的說明

Others://其它說明

*************************************************/

2-5:邊寫代碼邊注釋,修改代碼同時修改相應(yīng)的注釋,以保證注釋與代碼的一致性。不再有用的注釋要刪除。

2-6:注釋的內(nèi)容要清楚、明了,含義準確,防止注釋二義性。

說明:錯誤的注釋不但無益反而有害。

規(guī)則2-7:避免在注釋中使用縮寫,特別是非常用縮寫。

說明:在使用縮寫時或之前,應(yīng)對縮寫進行必要的說明。

2-8:注釋應(yīng)與其描述的代碼相近,對代碼的注釋應(yīng)放在其上方或右方(對單條語句的注釋)相鄰位置,不可放在下面,如放于上方則需與其上面的代碼用空行隔開。

示例:如下例子不符合規(guī)范。

例1:

/*getreplicatesubsystemindexandnetindicator*/

repssn_ind=ssn_data[index].repssn_index;

repssn_ni=ssn_data[index].ni;

例2:

repssn_ind=ssn_data[index].repssn_index;

repssn_ni=ssn_data[index].ni;

/*getreplicatesubsystemindexandnetindicator*/

應(yīng)如下書寫

/*getrepli

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論