VC++实现QPSK调制
正交相移鍵控(Quadrature Phase Shift Keyin,QPSK)是一種數(shù)字調(diào)制方式。
相移鍵控(PSK),是一種用載波相位表示輸入信號(hào)信息的調(diào)制技術(shù)。是一種相位調(diào)制。
調(diào)制方式基本的有三種:幅度調(diào)制,頻率調(diào)制,相位調(diào)制。
VC6新建一個(gè)單文檔工程;
// qpskView.cpp : implementation of the CQpskView class //#include "stdafx.h" #include "qpsk.h"#include "qpskDoc.h" #include "qpskView.h" #include <math.h>#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif//#define source_length 1000000 #define source_length 128 #define symbol_length source_length/2 #define SNR_start 1 #define SNR_end 10 #define SNR_step 1 #define PI 3.1415926 #define Coderate 1typedef struct {double Rpart;double Ipart; }complex;int source[source_length];//message(),modulate(),error() int change[source_length];//modulate() int resource[source_length]; //demodulate(),error() complex modulatesym[symbol_length]; //demodulate(),channel(),moudulate() int snr;//channel(),error() int errorbit, errorsym;//error() double BER,SER;//error()void message(); void modulate(int source[source_length]); void channel(complex modulatesym[symbol_length],int snr); void demodulate(); void error();/ // CQpskViewIMPLEMENT_DYNCREATE(CQpskView, CView)BEGIN_MESSAGE_MAP(CQpskView, CView)//{{AFX_MSG_MAP(CQpskView)// NOTE - the ClassWizard will add and remove mapping macros here.// DO NOT EDIT what you see in these blocks of generated code!//}}AFX_MSG_MAP// Standard printing commandsON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) END_MESSAGE_MAP()/ // CQpskView construction/destructionCQpskView::CQpskView() {// TODO: add construction code here}CQpskView::~CQpskView() { }BOOL CQpskView::PreCreateWindow(CREATESTRUCT& cs) {// TODO: Modify the Window class or styles here by modifying// the CREATESTRUCT csreturn CView::PreCreateWindow(cs); }/ // CQpskView drawingvoid CQpskView::OnDraw(CDC* pDC) {CQpskDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data hereint row=0, col=0;CString str1;for(snr=SNR_start;snr<=SNR_end;snr+=SNR_step){message();modulate(source);for(int k=0;k<source_length;k++){ str1.Format("%d",source[k]);pDC->TextOut(20+10*((k+1)%32), 20+row*32, str1);if( (k+1)%32==0){row=row+1;}}channel(modulatesym,snr);demodulate();error();} }/ // CQpskView printingBOOL CQpskView::OnPreparePrinting(CPrintInfo* pInfo) {// default preparationreturn DoPreparePrinting(pInfo); }void CQpskView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {// TODO: add extra initialization before printing }void CQpskView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {// TODO: add cleanup after printing }/ // CQpskView diagnostics#ifdef _DEBUG void CQpskView::AssertValid() const {CView::AssertValid(); }void CQpskView::Dump(CDumpContext& dc) const {CView::Dump(dc); }CQpskDoc* CQpskView::GetDocument() // non-debug version is inline {ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CQpskDoc)));return (CQpskDoc*)m_pDocument; } #endif //_DEBUG/ // CQpskView message handlers//隨機(jī)信號(hào)產(chǎn)生 void message() {int i;//以當(dāng)前時(shí)間作為時(shí)間種子srand((unsigned)time(NULL));//產(chǎn)生0,1隨機(jī)信號(hào)for(i=0;i<source_length;i++){ source[i]=rand()%2;//cout<<source[i];}//cout<<endl; }//調(diào)制 void modulate(int source[source_length]) {int i,j;//0->-1,1->1for(i=0;i<source_length;i++){ change[i]=1-2*source[i];} for(j=0;j<symbol_length;j++){ modulatesym[j].Rpart=change[2*j];//cout<<change[2*j];modulatesym[j].Ipart=change[2*j+1];//cout<<change[2*j+1];}// cout<<endl; }//調(diào)制信號(hào)通過(guò)信道 void channel(complex modulatesym[],int snr) {long int j;double r1,r2;double amp,phase;double sn,SNR,noise[2];SNR=snr+10*log10((double)Coderate);sn=pow(10.0,SNR/10.0);for(j=0;j<symbol_length;j++){r1=(double)rand()/RAND_MAX;r2=(double)rand()/RAND_MAX;if(r1<=1.0e-8) r1=1.0e-8; //防止出現(xiàn)log0的操作phase=2.0*PI*r2;amp=sqrt(-log(r1)/sn);noise[0]=amp*cos(phase);noise[1]=amp*sin(phase);modulatesym[j].Rpart=modulatesym[j].Rpart+noise[0];//cout<<modulatesym[j].Rpart;modulatesym[j].Ipart=modulatesym[j].Ipart+noise[1];//cout<<modulatesym[j].Ipart;}//cout<<endl; }//解調(diào) void demodulate() { for(int j=0;j<symbol_length;j++){if (modulatesym[j].Rpart>0)resource[2*j]=0;else //if(modulatesym[j].Rpart<=0)resource[2*j]=1;}for(int i=0;i<symbol_length;i++){if (modulatesym[i].Ipart>0)resource[2*i+1]=0;else //if(modulatesym[j].Ipart<=0)resource[2*i+1]=1;} }void error() {long int i,j;errorbit=0;errorsym=0;for(i=0;i<source_length;i++){ if(resource[i]!=source[i])errorbit++;}for(j=0;j<=symbol_length;j++){if(resource[2*j]!=source[2*j]||resource[2*j+1]!=source[2*j+1])errorsym++;}BER=(double)errorbit/source_length;SER=(double)errorsym/symbol_length;//cout<<"snr="<<snr<<endl;//cout<<"source_length="<<source_length<<endl;//cout<<"symbol_length="<<symbol_length<<endl;//cout<<"errorbit="<<errorbit<<endl;//cout<<"errorsym="<<errorsym<<endl;//cout<<"BER="<<BER<<endl;//cout<<"SER="<<SER<<endl; }原來(lái)定義的源信號(hào)長(zhǎng)度,#define source_length 1000000 ,演示改為128;
大體看一下函數(shù)功能;
源信號(hào)是用message()來(lái)生成的隨機(jī)信號(hào);這是要傳輸?shù)挠脩粜畔?#xff1b;
modulate()實(shí)現(xiàn)調(diào)制;把用戶信息轉(zhuǎn)變到載波的相位變化上;得到的調(diào)制信號(hào)modulatesym是復(fù)數(shù)形式,需要定義一個(gè)復(fù)數(shù)結(jié)構(gòu)體;
有幾個(gè)變量是模擬噪聲的;
channel()模擬調(diào)制信號(hào)通過(guò)信道;大致是把噪聲疊加到調(diào)制信號(hào)上;
demodulate()實(shí)現(xiàn)解調(diào),結(jié)果放入resource[];
error()函數(shù)大體是輸出一些噪聲和噪聲引起的錯(cuò)誤相關(guān)的信息;
先輸出一下源信號(hào)和解調(diào)后的信號(hào);調(diào)制信號(hào)是復(fù)數(shù)形式,有時(shí)間再輸出;
分2次輸出,寫(xiě)到一次里會(huì)出問(wèn)題;
另一次的OnDraw()函數(shù)如下;
void CQpskView::OnDraw(CDC* pDC) {CQpskDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data hereint row=0, col=0;CString str1;for(snr=SNR_start;snr<=SNR_end;snr+=SNR_step){message();modulate(source);channel(modulatesym,snr);demodulate();for(int i=0;i<source_length;i++){ str1.Format("%d",resource[i]);pDC->TextOut(800+10*((i+1)%32), 20+row*32, str1);if( (i+1)%32==0){row=row+1;}}error();} }輸出的結(jié)果如下;
??
原程序參閱?QPSK調(diào)制的C實(shí)現(xiàn)_bcbobo21cn的專欄-CSDN博客_qpsk調(diào)制??
總結(jié)
以上是生活随笔為你收集整理的VC++实现QPSK调制的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C语言位运算实现加法
- 下一篇: VC++更改主窗口标题栏文字