通信系统仿真

本实验旨在通过构建包含信源、编码器及信道等模块的通信系统,加深对通信原理的理解。利用Matlab等工具,模拟不同类型信道及编码方式,评估传输效率与误码率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 实验目的
      这是一个综合性的大型实验,通过搭建一个包括信源、信源编译码器、信道、信道编译码器等各模块在内的仿真通信系统,使学生能够加深对本课程各个重点章节的理解,更好地掌握通信的本质意义。
      
    说明:
    由于搭建一个完整通信系统的工作量较大,所以本实验可以使用Matlab等仿真工具。下面分别描述系统中各个模块的要求。
    1.离散信源:要求能以指定的概率分布(p,p-1)产生0,1符号构成的二进制信源符号序列。
    2.信源编码器:输入时上一步产生的二进制符号序列。要求能选择使用以下三种信源编码方式中的任何一种:
    (1)无编码(直通)
    (2)二进制香农-费诺编码
    (3)二进制霍夫曼编码
      当我们在上一步中指定信源的概率分布之后,就可以马上生成这几种编码的码表,实际的编码工作仅仅只是查表而已。当然,直接对上一步指定的信源进行编码是不合适的,需要先进行信源的扩展,换一句话说,需要确定信源分组的长度。这个长度N也是本系统的一个重要参数,是在系统运行之前由用户输入的。
    3.信道编码器:输入是信源编码器输出的二进制符号序列。编码方式要求能选择使用以下三种信道编码方式中的任何一种:
    (1)无编码
    (2)3次重复编码
    (3)Hamming(7,4)码
      信道编码器是个简单的一一对应的函数转换模块,没有额外的控制参数,可以事先实现这三种编码器,统一其输入输出格式,运行时按照指定的类型直接使用即可。
    4.信道:其输入时信道编码器输出的二进制符号序列。经过传输后输出被噪声干扰和损坏了的二进制符号序列。
    要求能够模拟理想信道、给定错误概率为p的BSC以及给定符号0,1各自错误概率p,q的任意二进制信道。
    5.信道译码器:由于信源经过信源编码器和信道编码器后的统计特性难以明确给出,所以此时理想译码器准则无法实施。
    因此根据第四步给出的信道统计特性,选择采用极大似然译码准则进行译码。
    6.信源译码器:在第二步确定信源编码器之后即可同时确定信源译码器。信源译码器的工作仅仅是简单的查表即可。

  • 实验要求
    输入:各个模块的相关参数
    输出:
    1.信源产生的原始符号序列
    2.信源译码器输出的符号序列
    3.信道编码后的信息传输效率
    4.整个通信过程的误比特率(BER)
    5.信道编译码过程中产生的误码率(BLER)

  • 实验程序

package com.yrwan.commSysSL;

import java.util.Map;
import java.util.Scanner;

import com.yrwan.channel.BSC;
import com.yrwan.channelCode.ChannelCodeChoose;
import com.yrwan.sourceCode.SourceCodeChoose;
import com.yrwan.sourceCode.huffman.Huffman;
import com.yrwan.sourceCode.shannonfano.ShannonFano;

//信源编码中的huffman编码来源于网上资料,香农费诺编码尚未完成
public class Main {
    private static double oriPr;//离散信源分布概率
    private static int oriLen;//二进制序列长度
    private static int sourceCodeType;//信源编码器
    private static int channelCodeType;//信道编码器
    private static int channelType;//信道选择
    private static double errPr1=0;//传输错误概率
    private static double errPr2=0;//传输错误概率

    public static void main(String[] args){
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入离散信源概率分布和二进制序列长度:");
        oriPr=scanner.nextDouble();
        oriLen=scanner.nextInt();

        System.out.println("请选择信源编码器(信源编码中的香农费诺编码尚未完成)");
        System.out.println("1.无编码");
        System.out.println("2.二进制香农-费诺编码");
        System.out.println("3.二进制霍夫曼编码");
        sourceCodeType=scanner.nextInt();

        System.out.println("请选择信道编码器");
        System.out.println("1.无编码");
        System.out.println("2.3次重复编码");
        System.out.println("3.Hamming(7,4)码");
        channelCodeType=scanner.nextInt();

        System.out.println("请选择信道");
        System.out.println("1.理想信道");
        System.out.println("2.给定错误概率为p的BSC信道");
        System.out.println("3.给定符号0,1各自错误概率p,q");
        channelType=scanner.nextInt();

        if (channelType==1){
            errPr1=0;
        }else if (channelType==2){
            System.out.println("请输入信道错误率");
            errPr1=scanner.nextDouble();
        }else if (channelType==3){
            System.out.println("请输入0,1各自错误率如 0.2 0.5");
            errPr1=scanner.nextDouble();
            errPr1=scanner.nextDouble();
        }
        scanner.close();

        /****开始运算****/
        //生成离散信源,存放在int型数组中
        int[] original = new int[oriLen];
        for (int i = 0; i < oriLen; i++) {
            if (Math.random() < oriPr) {
                original[i] = 1;
            }
            else{
                original[i] = 0;
            }
        }
        //将int型数组转化为字符串
        String originStr="";
        for (int i = 0; i < original.length; i++) {
            originStr=originStr+original[i];
        }
        //编码
        Map<Character, Integer> statistics=null;
        statistics=Huffman.statistics(originStr.toCharArray());

        int[] sourceEncodeResult= SourceCodeChoose.encode(sourceCodeType,original,statistics);
        int[] channelEncodeResult= ChannelCodeChoose.encode(channelCodeType,sourceEncodeResult);
        int[] transmitResult;

        if (channelType==1||channelType==2){
            //如果是理想信道或者给定错误概率为p的BSC
            transmitResult=BSC.send(channelEncodeResult,errPr1);
        }else {
            //如果指定0、1各自错误率
            transmitResult=BSC.send2(channelEncodeResult,errPr1,errPr2);
        }

        //解码
        int parityCount=0;//Hamming码校验位的长度
        if (channelCodeType==3){
            //如果是以海明码传输需要算出校验位的长度
            parityCount=channelEncodeResult.length-sourceEncodeResult.length;
        }
        int[] channelDecodeResult=ChannelCodeChoose.decode(channelCodeType,transmitResult,parityCount);
        int[] sourceDecodeResult=SourceCodeChoose.decode(sourceCodeType,channelDecodeResult,statistics);

        //输出结果
        println("原始序列",original);
        println("信源编码后序列",sourceEncodeResult);
        println("信道编码后序列",channelEncodeResult);
        println("信道传输后序列",transmitResult);
        println("信道解码后序列",channelDecodeResult);
        println("信源解码后序列",sourceDecodeResult);

        //BER 是在数据传输过程中比特被传错的概率
        //误码率=传输中的误码/所传输的总码数*100%
        //BLER 传输块经过CRC校验后的错误概率
        double codeEffectiveness=(double) original.length/channelEncodeResult.length;//信道编码后的传输效率
        double BER=(double)getErrorCount(sourceDecodeResult,original)/original.length;//整个过程中数据被传错的概率
        double channelEncodeError=(double)getErrorCount(channelDecodeResult,sourceEncodeResult)/sourceDecodeResult.length;//信道编译码过程中传错的概率
        System.out.printf("信道编码后的信息传输效率:%.2f%%\n",codeEffectiveness*100);
        System.out.printf("整个通信过程中的误比特率:%.2f%%\n",BER*100);
        System.out.printf("信道编译码过程中产生的误码率:%.2f%%\n",channelEncodeError*100);
    }
    private static int getErrorCount(int[] data1, int[] data2){
        if (data1.length != data2.length) return 0;
        int errorCount=0;
        for (int i = 0; i < data1.length; i++) {
            if (data1[i]!=data2[i]){
                errorCount++;
            }
        }
        return errorCount;
    }
    private static void println(String message,int[] data){
        System.out.println(message);
        for (int i:data){
            System.out.printf(i+" ");
        }
        System.out.println("\n====================");
    }
}
package com.yrwan.channel;
public class BSC {
    //经BSC传输信号,返回传输后的值
    public static int[] send(int[] data,double errPr){
        int[] x=new int[data.length];
        x = data;
        for(int i = 0; i<data.length;i++)
            if(Math.random()<errPr){
                x[i] = 1 - x[i];
            }
        return x;
    }
  //为0,1时,error1为1的错误概率,error2为0的错误概率
    public static int[] send2(int[] data,double error1,double error2){
        int[] x=new int[data.length];
        x = data;
        for(int i = 0; i<x.length;i++)
            if (x[i] == 1){
                //如果是1
                if(Math.random()<error1){
                    x[i] = 1 - x[i];
                }
            }else {
                //如果是0
                if(Math.random()<error2){
                    x[i] = 1 - x[i];
                }
            }
        return x;
    }
}
package com.yrwan.channelCode;

public class ChannelCodeChoose {
    public static int[] encode(int type,int[] data){
        int[] result;
        switch (type){
            case 1:
                //无编码
                result=data;
                break;
            case 2:
                //3次重复编码
                result= ThreeTimes.encode(data);
                break;
            case 3:
                //Hamming(7,4)编码
                result= Hamming.generateHamming(data);
                break;
            default:
                System.out.println("请选择正确的信道编码器");
                result=new int[0];
                System.exit(0);
                break;
        }
        return result;
    }
    public static int[] decode(int type,int[] data,int length){
        int[] result;
        switch (type){
            case 1:
                //无编码
                result=data;
                break;
            case 2:
                //3次重复编码
                result= ThreeTimes.decode(data);
                break;
            case 3:
                //Hamming(7,4)编码
                result=Hamming.decode(data,length);
                break;
            default:
                System.out.println("请选择正确的信道编码器");
                result=new int[0];
                System.exit(0);
                break;
        }
        return result;
    }
}
package com.yrwan.channelCode;

import java.util.ArrayList;
import java.util.List;

public class ThreeTimes {
    //生成三次重复码
    public static int[] encode(int[] data){
        List<Integer> list=new ArrayList<>();
        for (int i = 0; i < data.length; i++) {
            list.add(data[i]);
            list.add(data[i]);
            list.add(data[i]);
        }

        int[] r=new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            r[i]=list.get(i);
        }
        return r;
    }
    //解码三次重复码
    public static int[] decode(int[] data){
        int[] result=new int[data.length/3];
        for (int i = 0,m=0; i < data.length; i=i+3,m++) {
            int i1=data[i];
            int i2=data[i+1];
            int i3=data[i+2];
             if (i1==i2||i2==i3){
                result[m]=i2;
            }else if (i1==i3){
                result[m]=i1;
            }
        }
        return result;
    }
}
package com.yrwan.channelCode;

import java.util.ArrayList;
//本节程序在网上查阅资料得到
public class Hamming {

    //生成hamming 码
    static public int[] generateHamming(int[] a) {
        int b[];
        int i=0, parity_count=0 ,j=0, k=0;
        while(i < a.length) {

            if(Math.pow(2,parity_count) == i+parity_count + 1) {
                parity_count++;
            }
            else {
                i++;
            }
        }

        b = new int[a.length + parity_count];

        for(i=1 ; i <= b.length ; i++) {
            if(Math.pow(2, j) == i) {

                b[i-1] = 2;
                j++;
            }
            else {
                b[k+j] = a[k++];
            }
        }
        for(i=0 ; i < parity_count ; i++) {

            b[((int) Math.pow(2, i))-1] = getParity(b, i);
        }
        return b;

    }
    static int getParity(int b[], int power) {
        int parity = 0;
        for(int i=0 ; i < b.length ; i++) {
            if(b[i] != 2) {

                int k = i+1;
                String s = Integer.toBinaryString(k);

                int x = ((Integer.parseInt(s))/((int) Math.pow(10, power)))%10;
                if(x == 1) {
                    if(b[i] == 1) {
                        parity = (parity+1)%2;
                    }
                }
            }
        }
        return parity;
    }

    //将收到的hamming码解码出来
    //a 收到的hamming码数组 校验码个数(生成的hamming码长度-原始长度)
    public static int[] decode(int a[], int parity_count) {
        int power;
        int parity[] = new int[parity_count];
        String syndrome = new String();
        for(power=0 ; power < parity_count ; power++) {

            for(int i=0 ; i < a.length ; i++) {

                int k = i+1;
                String s = Integer.toBinaryString(k);
                int bit = ((Integer.parseInt(s))/((int) Math.pow(10, power)))%10;
                if(bit == 1) {
                    if(a[i] == 1) {
                        parity[power] = (parity[power]+1)%2;
                    }
                }
            }
            syndrome = parity[power] + syndrome;
        }

        int error_location = Integer.parseInt(syndrome, 2);
        if(error_location != 0) {
            a[error_location-1] = (a[error_location-1]+1)%2;

        }

        power = parity_count-1;
        ArrayList<Integer> list=new ArrayList<>();
        for(int i=a.length ; i > 0 ; i--) {
            if(Math.pow(2, power) != i) {
                list.add(a[i-1]);
            }
            else {
                power--;
            }
        }
        int[] result=new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            result[i]=list.get(list.size()-1-i);
        }
        return result;
    }
}
package com.yrwan.sourceCode;

import java.util.Map;

import com.yrwan.sourceCode.huffman.Huffman;
import com.yrwan.sourceCode.shannonfano.ShannonFano;

public class SourceCodeChoose {
    public static int[] encode(int type, int[] data, Map<Character, Integer> statistics){
        int[] result=new int[0];
        String oriStr="";
        for (int aData : data) {
            oriStr = oriStr + aData;
        }

        String strResult="";
        switch (type){
            case 1:
                //无编码
                result=data;
                break;
            case 2:
                //二进制香农-费诺编码
                //strResult = ShonnonFano.encode(oriStr);
                break;
            case 3:
                //二进制霍夫曼编码
                strResult = Huffman.encode(oriStr,statistics);
                break;
            default:
                System.out.println("请选择正确的信源编码器");
                break;
        }
      //如果是ShannonFano或者Huffman编码将其转化为数组
        if (strResult!=null&&strResult.length()!=0){
            char[] charResult=strResult.toCharArray();
            result=new int[charResult.length];
            for (int i = 0; i < charResult.length; i++) {
                if (charResult[i]=='1')
                    result[i]=1;
                else
                    result[i]=0;
            }
        }

        return result;
    }
    public static int[] decode(int type, int[] data, Map<Character, Integer> statistics){
        int[] result = new int[0];
        String oriStr="";
        for (int i = 0; i < data.length; i++) {
            oriStr=oriStr+data[i];
        }

        String strResult="";
        switch (type){
        case 1:
            //无编码
            result=data;
            break;
        case 2:
            //二进制香农-费诺编码
            //strResult = ShonnonFano.decode(oriStr);
            break;
        case 3:
            //二进制霍夫曼编码
            strResult = Huffman.decode(oriStr,statistics);
            break;
        default:
            System.out.println("请选择正确的信源编码器");
            break;
        }
      //如果是ShannonFano或者Huffman编码将其转化为数组
        if (strResult!=null&&strResult.length()!=0){
            char[] charResult=strResult.toCharArray();
            result=new int[charResult.length];
            for (int i = 0; i < charResult.length; i++) {
                if (charResult[i]=='1')
                    result[i]=1;
                else
                    result[i]=0;
            }
        }

        return result;
    }
}
package com.yrwan.sourceCode.huffman;

import java.nio.charset.Charset;
import java.util.*;
public class Huffman {
    /**
     * 参考来源:http://blog.youkuaiyun.com/kimylrong/article/details/17022319
     * 既然要按频率来安排编码表,那么首先当然得获得频率的统计信息。
     * 如果已经有统计信息,那么转为Map<Character,Integer>即可。
     * 如果你得到的信息是百分比,乘以100或1000,或10000。总是可以转为整数。
     * 比如12.702%乘以1000为12702,Huffman编码只关心大小问题。
     * @param charArray
     * @return
     */
    public static Map<Character, Integer> statistics(char[] charArray) {
        Map<Character, Integer> map = new HashMap<Character, Integer>();
        for (char c : charArray) {
            Character character = new Character(c);
            if (map.containsKey(character)) {
                map.put(character, map.get(character) + 1);
            } else {
                map.put(character, 1);
            }
        }

        return map;
    }

    /**构建树
     * 构建树是Huffman编码算法的核心步骤。
     * 思想是把所有的字符挂到一颗完全二叉树的叶子节点,
     * 任何一个非页子节点的左节点出现频率不大于右节点。
     * 算法为把统计信息转为Node存放到一个优先级队列里面,每一次从队列里面弹出两个最小频率的节点,
     * 构建一个新的父Node(非叶子节点), 字符内容刚弹出来的两个节点字符内容之和,
     * 频率也是它们的和,最开始的弹出来的作为左子节点,后面一个作为右子节点,
     * 并且把刚构建的父节点放到队列里面。重复以上的动作N-1次,N为不同字符的个数(每一次队列里面个数减1)。
     * 结束以上步骤,队列里面剩一个节点,弹出作为树的根节点。
     */
    private static Tree buildTree(Map<Character, Integer> statistics,List<Node> leafs) {
        Character[] keys = statistics.keySet().toArray(new Character[0]);

        PriorityQueue<Node> priorityQueue = new PriorityQueue<Node>();
        for (Character character : keys) {
            Node node = new Node();
            node.chars = character.toString();
            node.frequence = statistics.get(character);
            priorityQueue.add(node);
            leafs.add(node);
        }

        int size = priorityQueue.size();
        for (int i = 1; i <= size - 1; i++) {
            Node node1 = priorityQueue.poll();
            Node node2 = priorityQueue.poll();

            Node sumNode = new Node();
            sumNode.chars = node1.chars + node2.chars;
            sumNode.frequence = node1.frequence + node2.frequence;

            sumNode.leftNode = node1;
            sumNode.rightNode = node2;

            node1.parent = sumNode;
            node2.parent = sumNode;

            priorityQueue.add(sumNode);
        }

        Tree tree = new Tree();
        tree.root = priorityQueue.poll();
        return tree;
    }

    /**编码
     * 某个字符对应的编码为,从该字符所在的叶子节点向上搜索,
     * 如果该字符节点是父节点的左节点,编码字符之前加0,
     * 反之如果是右节点,加1,直到根节点。
     * 只要获取了字符和二进制码之间的mapping关系,编码就非常简单。
     */
    public static String encode(String originalStr,Map<Character, Integer> statistics) {
        if (originalStr == null || originalStr.equals("")) {
            return "";
        }

        char[] charArray = originalStr.toCharArray();
        List<Node> leafNodes = new ArrayList<Node>();
        buildTree(statistics, leafNodes);
        Map<Character, String> encodInfo = buildEncodingInfo(leafNodes);

        StringBuffer buffer = new StringBuffer();
        for (char c : charArray) {
            Character character = new Character(c);
            buffer.append(encodInfo.get(character));
        }

        return buffer.toString();
    }

    private static Map<Character, String> buildEncodingInfo(List<Node> leafNodes) {
        Map<Character, String> codewords = new HashMap<Character, String>();
        for (Node leafNode : leafNodes) {
            Character character = new Character(leafNode.getChars().charAt(0));
            String codeword = "";
            Node currentNode = leafNode;

            do {
                if (currentNode.isLeftChild()) {
                    codeword = "0" + codeword;
                } else {
                    codeword = "1" + codeword;
                }

                currentNode = currentNode.parent;
            } while (currentNode.parent != null);

            codewords.put(character, codeword);
        }

        return codewords;
    }

    /**解码
     * 因为Huffman编码算法能够保证任何的二进制码都不会是另外一个码的前缀,解码非常简单,
     * 依次取出二进制的每一位,从树根向下搜索,1向右,0向左,到了叶子节点(命中),退回根节点继续重复以上动作。
     */
    public static String decode(String binaryStr,
                                Map<Character, Integer> statistics) {
        if (binaryStr == null || binaryStr.equals("")) {
            return "";
        }

        char[] binaryCharArray = binaryStr.toCharArray();
        LinkedList<Character> binaryList = new LinkedList<Character>();
        int size = binaryCharArray.length;
        for (int i = 0; i < size; i++) {
            binaryList.addLast(new Character(binaryCharArray[i]));
        }

        List<Node> leafNodes = new ArrayList<Node>();
        Tree tree = buildTree(statistics, leafNodes);

        StringBuffer buffer = new StringBuffer();

        while (binaryList.size() > 0) {
            Node node = tree.root;

            do {
                Character c = binaryList.removeFirst();
                if (c.charValue() == '0') {
                    node = node.leftNode;
                } else {
                    node = node.rightNode;
                }
            } while (!node.isLeaf());

            buffer.append(node.chars);
        }

        return buffer.toString();
    }


    public static String getStringOfByte(String str, Charset charset) {
        if (str == null || str.equals("")) {
            return "";
        }

        byte[] byteArray = str.getBytes(charset);
        int size = byteArray.length;
        StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < size; i++) {
            byte temp = byteArray[i];
            buffer.append(getStringOfByte(temp));
        }

        return buffer.toString();
    }

    public static String getStringOfByte(byte b) {
        StringBuffer buffer = new StringBuffer();
        for (int i = 7; i >= 0; i--) {
            byte temp = (byte) ((b >> i) & 0x1);
            buffer.append(String.valueOf(temp));
        }

        return buffer.toString();
    }
}
package com.yrwan.sourceCode.huffman;
/**
 * 参考来源:http://blog.youkuaiyun.com/kimylrong/article/details/17022319
 * Huffman编码算法主要用到的数据结构是完全二叉树(full binary tree)和优先级队列。
 * 后者用的是Java.util.PriorityQueue,前者自己实现(都为内部类),
 */
public class Node  implements Comparable<Node> {
    public String chars = "";
    public int frequence = 0;
    public Node parent;
    public Node leftNode;
    public Node rightNode;

    public int compareTo(Node n) {
        return frequence - n.frequence;
    }

    public boolean isLeaf() {
        return chars.length() == 1;
    }

    public boolean isRoot() {
        return parent == null;
    }

    public boolean isLeftChild() {
        return parent != null && this == parent.leftNode;
    }

    public int getFrequence() {
        return frequence;
    }

    public void setFrequence(int frequence) {
        this.frequence = frequence;
    }

    public String getChars() {
        return chars;
    }

    public void setChars(String chars) {
        this.chars = chars;
    }

    public Node getParent() {
        return parent;
    }

    public void setParent(Node parent) {
        this.parent = parent;
    }

    public Node getLeftNode() {
        return leftNode;
    }

    public void setLeftNode(Node leftNode) {
        this.leftNode = leftNode;
    }

    public Node getRightNode() {
        return rightNode;
    }

    public void setRightNode(Node rightNode) {
        this.rightNode = rightNode;
    }

}
class Tree{
    public Node root;

    public Node getRoot() {
        return root;
    }

    public void setRoot(Node root) {
        this.root = root;
    }
}
本书是作者从事大型现代通信系统仿真工作20余年的经验总结,利用C++语言系统地讲解了复杂无线通信系统中各类模块的仿真原理与方法,并给出了大量实用的模型源代码。作者在本书编写过程中开发了工具包PracSim,这是一个由仿真模型和可互连的仿真结构组成的模块集,可以为用户提供一个可修改及开发的基础模型,以便能更接近用户所需仿真的系统。书中仿真结构和模型的源代码均可在Prentice Hall的网站上获得。通过本书的学习可使读者掌握无线通信系统仿真的基本方法,从而加深对无线通信和面向对象编程的理解,为从事通信领域的相关研究工作打下坚实的基础。. 本书内容丰富、实用性强,非常适合国内目前的需求。可作为高等院校信息类专业高年级本科生和研究生的通信系统仿真课程的教材,也可供相关工程技术人员参考使用。... 第1章 仿真:背景及回顾 1.1 通信系统 1.2 仿真过程 1.3 仿真程序 第2章 仿真基础结构 2.1 参数输入 2.1.1 各参数值 2.1.2 参数数组 2.1.3 枚举类型参数 2.1.4 系统参数 2.1.5 信号绘图参数 2.2 信号 2.2.1 信号管理策略 2.2.2 信号管理系统的实现 2.3 控制信号 2.4 结果报告 附录2A 源代码实例 第3章 信号发生器 3.1 基本信号发生器 3.1.1 单位阶跃函数 3.1.2 矩形脉冲 3.1.3 单位冲激 3.1.4 软件实现 3.2 音频信号发生器 3.2.1 软件实现 3.3 基带信号采样 3.3.1 采样的频域特性 3.4 基带数据波形发生器 3.4.1 非归零NRZ基带信号 3.4.2 双相位基带信号 3.4.3 延迟调制 3.4.4 应用中的问题 3.5 为带通信号建模 附录3A 源代码实例 第4章 随机过程模型 4.1 随机序列 4.1.1 离散分布 4.1.2 离散随机过程 4.2 随机过程发生器 4.2.1 线性同余序列 4.2.2 软件实现 4.2.3 随机数发生器的评价 4.3 连续时间噪声过程 4.3.1 连续随机变量 4.3.2 随机过程 4.4 加性高斯噪声发生器 4.4.1 高斯分布 4.4.2 误差函数 4.4.3 谱特性 4.4.4 噪声功率 4.4.5 高斯随机数发生器 4.5 通带噪声 4.5.1 包络和相角 4.5.2 瑞利随机数发生器 4.6 随机过程的参数模型 4.6.1 自回归噪声模型 附录4A 源代码实例 第5章 离散变换 5.1 离散傅里叶变换 5.1.1 参数选择 5.1.2 离散傅里叶变换的性质 5.2 时域抽取算法 5.2.1 软件注释 5.3 频域抽取算法 5.4 小采样数N的离散傅里叶变换 5.5 素因数算法 5.5.1 软件注释 附录 5A 源代码实例 第6章 谱估计 6.1 采样频谱 6.1.1 软件实现 6.2 Daniell 周期图 6.2.1 软件实现 6.3 Bartlett 周期图 6.3.1 软件实现 6.4 加窗和其他问题 6.4.1 三角窗 6.4.2 软件考虑 6.4.3 von Hann 窗 6.4.4 汉明窗 6.4.5 软件实现 6.5 Welch周期图 6.5.1 软件实现 6.6 Yule-Walker方法 6.6.1 软件实现 附录6A 源代码实例 第7章 系统表征工具 7.1 线性系统 7.1.1 线性系统的特性 7.1.2 传递函数 7.1.3 传递函数的计算机表示方法 7.1.4 幅频响应、相频响应和时延响应 7.2 星座图 7.2.1 眼图 附录7A 源代码实例 第8章 滤波器模型 8.1 建模方法 8.1.1 数值积分 8.1.2 频率响应采样 8.1.3 数字滤波器 8.2 模拟滤波器响应 8.2.1 低通滤波器幅频响应特性 8.2.2 滤波器转换 8.3 经典模拟滤波器 8.3.1 巴特沃斯滤波器 8.3.2 切比雪夫滤波器 8.3.3 椭圆滤波器 8.3.4 贝塞尔滤波器 8.4 由数值积分来仿真滤波器 8.4.1 双二次型 8.4.2 软件设计 8.5 用IIR数字滤波器仿真模拟滤波器 8.5.1 IIR滤波器的性质 8.5.2 模拟滤波器映射为IIR数字滤波器 8.5.3 软件设计 8.6 频域内滤波 8.6.1 快速卷积 8.6.2 软件设计 附录 8A 源代码实例 第9章 调制与解调 9.1 仿真的要点 9.1.1 利用恢复的载波 9.2 正交相移键控 9.2.1 非理想特性 9.2.2 正交调制器模型 9.2.3 QPSK相关解调器模型 9.2.4 正交解调器模型 9.2.5 QPSK仿真 9.2.6 QPSK信号的性质 9.2.7 偏移 QPSK 9.3 二进制相移键控 9.3.1 BPSK调制器模型 9.3.2 BPSK解调 9.3.3 BPS
基于MATLAB的移动通信系统仿真-基于matlab的移动通信系统仿真.rar 希望对大家有用! 基于TCH/FS的GSM系统仿真实现 摘 要从第一代模拟移动通信系统到目前的第三代数字移动通信系统,蜂窝移动通信已经历了20余年的发展历程。作为欧洲一个数字蜂窝移动通信标准的GSM系统于1991年正式在欧洲面世,由于其公开的规范标准以及强大的漫游能力,从而获得了空前的发展。 本课题主要任务是用C语言对基于TCH/FS信道的GSM系统进行仿真,由于移动无线信道受到各种干扰、多径衰落和阴影衰落等影响,对于数字和数据信号的传输,会造成突发性误码和随机性错误。为了解决无线信道传输带来的问题,从原始的用户数据到无线电波所携带的信息,再还原成用户数据,需要进行一系列的变换和反变换,实现对所传输信号的必要保护。这些变换大致包括:信源编码与解码、信道编码与解码、交织与解交织、调制以及均衡等模块。本课题在对上述各模块依次进行仿真时,依据协议GSM05.03的编码方案对数据进行编码,除采用新型的信源编码技术外,还采用检、纠错信息编码以及信道编码保护的交织重排等手段,以提高传输效果和通信质量。同时采用GMSK调制、信道均衡和Viterbi译码等处理方法,来获得在不同信道模型下(AWGN、GSM HTx和GSM EQx模型)的不同信噪比Eb/N0的编码性能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值