通信软件基础实验02

写在前面

书接上回,本次实验对上一次实验进行了拓展,有了一定的难度,我编写的代码有些繁复杂乱,但结果还是能正常输出的。

以下为实验报告内容(再次偷个懒),有删改。

一. 引言

  1. 相关性检测:相关检测技术是信号检测领域里一种重要工具,常用于从噪声背景中检测出有用的确定性信号。它利用确定性信号在不同时刻的取值一般都具有较强相关性,而干扰噪声因为随机性较强,不同时刻取值相关性较差的特性,把确定性信号和干扰噪声区分开来。

  2. 相关性检测方法:假设确定信号序列为x[m],具有噪声背景的实际信号序列为y[n],m<n,通过滑动相关计算,找出滑动相关计算序列z[k]的最大的值,则可以求出具有噪声背景的实际信号序列y中所包含的确定信号序列x的位置。

  1. 两复数相乘,其结果的模等于两复数模的积。

二.系统设计要求

在第一次实验的基础上,完成本次实验。

总体要求:在12个候选小区中确认是否有适合接入的小区?若有,请找到终端最适合接入的小区。

强度门限,相关门限自行设定。

输出中间过程的打印信息:

  1. 打印各小区强度以及排序的结果(小区ID即文件名);

  2. 打印与3组PSS相关后所获得的各自序列的最大值;

  3. 打印设置的强度门限以及相关门限;

  4. 体现流程分支走向(无适合接入小区,驻留失败/当前小区无法接入,寻找下一小区/当前小区满足接入条件,流程结束);

三. 设计思路与方案

1.流程图:

2.全局变量及结构体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#define NUM 12  //小区文件数
#define PSS_NUM 3 //PSS文件数量
#define MAX_AREA_LINE 30000//小区文件长度
#define MAX_PSS_LINE 4096//PSS文件长度
#define SQE_LEN ((MAX_AREA_LINE/2)-(MAX_PSS_LINE/2)+1) //强度序列长度
#define DELY 50//延迟输出无意义,可删除

struct Area//小区与信号结构体
{
char ID[15]; //小区ID
double avg_strength;//小区平均信号强度
double strength[MAX_AREA_LINE / 2];//信号强度模值数组
};

struct Pss//PSS结构体
{
char ID[15];//PSS ID
double strength[MAX_PSS_LINE / 2];//PSS信号强度模值数组
};

struct Correlation//相关性序列记录结构体
{
struct Pss* p_pss;//指向组合中的PSS信号
struct Area* p_area;//指向组合中的小区
double maxnum;//记录相关性序列中的最大值
};

struct Area Areas[NUM];//小区结构体数组
struct Pss PSS[PSS_NUM];//主同步信号结构体数组
struct Correlation Correlations[NUM * PSS_NUM];//相关性序列记录结构体数组

3.各类函数

初始化函数

在此可以根据文件名称来对小区ID与PSS ID进行修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void initialization()//初始化小区ID以及PSS信号
{
strcpy(Areas[0].ID, "data12.txt");
strcpy(Areas[1].ID, "data13.txt");
strcpy(Areas[2].ID, "data14.txt");
strcpy(Areas[3].ID, "data15.txt");
strcpy(Areas[4].ID, "data16.txt");
strcpy(Areas[5].ID, "data17.txt");
strcpy(Areas[6].ID, "data18.txt");
strcpy(Areas[7].ID, "data19.txt");
strcpy(Areas[8].ID, "data20.txt");
strcpy(Areas[9].ID, "data21.txt");
strcpy(Areas[10].ID, "data22.txt");
strcpy(Areas[11].ID, "data23.txt");
strcpy(PSS[0].ID, "PSS0.txt");
strcpy(PSS[1].ID, "PSS1.txt");
strcpy(PSS[2].ID, "PSS2.txt");
}

计算核心函数

对小区数据进行计算并最终给小区结构体的平均信号强度以及各段信号模值赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int kqlt(struct Area *area,double Q,double I)//求平均强度,函数
{
static double sum; //利用static对数据进行累加
static int i = 0; //利用static对计算次数进行统计
sum = sum + sqrt(Q * Q + I * I); //信号强度计算公式并对结果求和
area->strength[i] = (sqrt(Q * Q + I * I));//将强度模值存入数组
i++;//计算次数累加
if (i == MAX_AREA_LINE /2)//当执行到MAX_AREA_LINE/2次时执行以下代码
{
area->avg_strength = sum / MAX_AREA_LINE * 2;//求平均信号强度并写入结构体
sum = 0;//总和清零
i = 0;//次数清零
return 0;//返回0表示计算完成
}
return 1;//返回1表示计算未完成
}

数据读取处理函数1

读取小区文件中的数据并调用kqlt函数处理数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void fileop(int num)//读取小区文件并计算
{
FILE* fp;
double Q, I;
int flag;//设置旗标flag
if((fp = fopen(Areas[num].ID, "r")) == NULL)//打开文件
{
printf("打开文件错误");
return;
}
for (int i = 0;; i++)
{
fscanf(fp, "%lf %lf", &Q, &I);//读取文件,并将数值写入Q、I
flag = kqlt(&Areas[num], Q, I);//通过kqlt函数返回值判断是否计算完成
if (flag == 0)//flag=0时计算完成
{
fclose(fp);//关闭文件
break;//跳出循环
}
}
}

数据读取处理函数2

读取PSS文件并计算模值存入PSS数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void fileop2()//读取PSS文件并计算模值存入PSS数组
{
FILE* fp;
double Q, I;
for (int i = 0; i < PSS_NUM; i++)
{
if ((fp = fopen(PSS[i].ID, "r")) == NULL)
{
printf("打开PSS文件错误");
return;
}
for (int j = 0; j < MAX_PSS_LINE/2; j++)
{
fscanf(fp, "%lf %lf", &Q, &I);
PSS[i].strength[j] = sqrt(Q * Q + I * I);
}
fclose(fp);
}
}

冒泡排序函数

依据小区平均信号强度对小区进行排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void sort()//冒泡算法排序
{
struct Area temp;
for (int j = 0; j < NUM - 1; j++)
{
for (int i = 0; i < NUM - 1 - j; i++)
{
if (Areas[i].avg_strength < Areas[i + 1].avg_strength)
{
temp = Areas[i] ;
Areas[i] = Areas[i + 1];
Areas[i + 1] = temp;
}
}
}
}

滑动检测函数

对小区信号强度与PSS信号强度进行相关比较

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void slide(struct Area *area, struct Pss *pss)//相关性检测
{
static int pos = 0;//记录当前序列位置
int i = 0;
int j = 0;
int kz = 0;//滑动相关计算序列哨兵
double temp = 0;//记录当前位置的相关度数值
double max = 0;//记录当前位置最大值
int maxpos = 0;//确定型号的起始位置,也就是最大值的位置
//相关性检测算法
for (kz = 0; kz < SQE_LEN; kz++)
{
temp = 0;
for (i = 0; i < MAX_PSS_LINE/2; i++)
{
temp += pss->strength[i] * area->strength[i + j];
}
j++;
if (temp >= max)
{
max = temp;
maxpos = kz;
}
}
//将计算完毕的数据写入相关性序列
Correlations[pos].p_area = area;
Correlations[pos].p_pss = pss;
Correlations[pos].maxnum = max;
pos++;//当前位置+1
}

连接判断函数

判断PSS信号与小区能否连接,并输出判断及接入结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
void connect(double area_lim, double correlations_lim) //连接判断函数
{
int max_pos[PSS_NUM];//记录Correlations数组中组合下标记录不同组合间数值最大的一组,用于最后判断输出,当值为-1是表明未存入信息
int pos = 0;//max_pos数组下标
double maxnum = 0;//记录当前pss与小区相关性序列中的最大值,判断
int flag = 0;//旗标,判断是否存在满足门限条件的组合
//为max_pos数组赋初值
for (int i = 0; i < PSS_NUM; i++)
{
max_pos[i] = -1;
}
for (int i = 0; i < PSS_NUM * NUM; i++)
{
Sleep(DELY);
printf("%s检测能否接入小区%s", Correlations[i].p_pss->ID, Correlations[i].p_area->ID);
if ((Correlations[i].maxnum>=correlations_lim)&&(Correlations[i].p_area->avg_strength>=area_lim))//当相关性序列最大值大于门限并且平均强度高于强度门限
{
flag = 1;//表明存在可接入小区
printf("\t满足门限条件可接入\n");
//替换最大值
if (maxnum<=Correlations[i].maxnum)
{
maxnum = Correlations[i].maxnum;
max_pos[pos] = i;
}
}
else
{
printf("\t不满足门限条件\n");
}
if ((i!= (PSS_NUM * NUM)-1)&&(strcmp(Correlations[i].p_pss->ID, Correlations[i+1].p_pss->ID)!=0))//当PSS ID值发生变化时移动pos,并将最大值清零
{
pos++;
maxnum = 0;
}
}
printf("\n接入结果:\n");
if (flag)
{
for (int i = 0; i < PSS_NUM; i++)
{
if (max_pos[i] == -1)
{
printf("%s无接入小区,未接入。\n", Correlations[i].p_pss->ID);
}
else
printf("%s接入%s,相关强度%lf\n", Correlations[max_pos[i]].p_pss->ID, Correlations[max_pos[i]].p_area->ID, Correlations[max_pos[i]].maxnum);
}
}
else
{
printf("无满足条件的小区。\n");
}
}

主函数

显示提示信息输入数据、调用相关函数、输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
void main()//主函数
{
double area_lim;//小区强度门限
double correlations_lim;//最大相关度门限
initialization();//调用初始化函数,对结构体进行初始化
fileop2();//调用PSS文件处理函数
printf("计算数据中...\n");
for (int i = 0; i < NUM; i++)//利用for循环计算多个文件信号平均强度
{
fileop(i);
printf("ID:%s \t信号平均强度:%lf", Areas[i].ID, Areas[i].avg_strength);
/*for (int j = 0; j < MAX_AREA_LINE / 2; j++)//调试用
{
printf("%lf ", Areas[i].strength[j]);
}*/
printf("\n");
}

sort();//对数据进行排序
printf("\n排序后结果:\n");
for (int i = 0; i < NUM; i++)
{
Sleep(DELY);
printf("ID:%s \t信号平均强度:%lf\n",Areas[i].ID, Areas[i].avg_strength);
}
for (int i = 0; i < 3; i++)//调用slide函数进行滑块检测
{
for (int j = 0; j < 12; j++)
{
slide(&Areas[j], &PSS[i]);
}
}

printf("\nPSS与小区匹配结果:\n");
for (int i = 0; i < 36; i++)
{
Sleep(DELY);
printf("小区ID:%s\tPSS ID:%s\t相关性序列最大值:%lf\n", Correlations[i].p_area->ID, Correlations[i].p_pss->ID, Correlations[i].maxnum);
}

printf("请输入强度门限:");
scanf("%lf", &area_lim);//输入强度门限条件
printf("\n请输入相关门限:");
scanf("%lf", &correlations_lim);
printf("\n分析数据...\n");
connect(area_lim, correlations_lim);


/*fileop2();//调试调用
for (int j = 0; j < PSS_NUM; j++)
{
for (int i = 0; i < MAX_PSS_LINE / 2; i++)
{
printf("%lf\t", PSS[j].strength[i]);
}
printf("\n");
}
*/

}

4.整体代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
#include <stdio.h>
#include <string.h>
#include <math.h>

#define NUM 12 //小区文件数
#define PSS_NUM 3 //PSS文件数量
#define MAX_AREA_LINE 30000//小区文件长度
#define MAX_PSS_LINE 4096//PSS文件长度
#define SQE_LEN ((MAX_AREA_LINE/2)-(MAX_PSS_LINE/2)+1) //强度序列长度
#define DELY 50//延迟输出无意义,可删除

struct Area//小区与信号结构体
{
char ID[15]; //小区ID
double avg_strength;//小区平均信号强度
double strength[MAX_AREA_LINE / 2];//信号强度模值数组
};

struct Pss//PSS结构体
{
char ID[15];//PSS ID
double strength[MAX_PSS_LINE / 2];//PSS信号强度模值数组
};

struct Correlation//相关性序列记录结构体
{
struct Pss* p_pss;//指向组合中的PSS信号
struct Area* p_area;//指向组合中的小区
double maxnum;//记录相关性序列中的最大值
};

struct Area Areas[NUM];//小区结构体数组
struct Pss PSS[PSS_NUM];//主同步信号结构体数组
struct Correlation Correlations[NUM * PSS_NUM];//相关性序列记录结构体数组

void initialization()//初始化小区ID以及PSS信号
{
strcpy(Areas[0].ID, "data12.txt");
strcpy(Areas[1].ID, "data13.txt");
strcpy(Areas[2].ID, "data14.txt");
strcpy(Areas[3].ID, "data15.txt");
strcpy(Areas[4].ID, "data16.txt");
strcpy(Areas[5].ID, "data17.txt");
strcpy(Areas[6].ID, "data18.txt");
strcpy(Areas[7].ID, "data19.txt");
strcpy(Areas[8].ID, "data20.txt");
strcpy(Areas[9].ID, "data21.txt");
strcpy(Areas[10].ID, "data22.txt");
strcpy(Areas[11].ID, "data23.txt");
strcpy(PSS[0].ID, "PSS0.txt");
strcpy(PSS[1].ID, "PSS1.txt");
strcpy(PSS[2].ID, "PSS2.txt");
}


int kqlt(struct Area *area,double Q,double I)//求平均强度,函数
{
static double sum; //利用static对数据进行累加
static int i = 0; //利用static对计算次数进行统计
sum = sum + sqrt(Q * Q + I * I); //信号强度计算公式并对结果求和
area->strength[i] = (sqrt(Q * Q + I * I));//将强度模值存入数组
i++;//计算次数累加
if (i == MAX_AREA_LINE /2)//当执行到MAX_AREA_LINE/2次时执行以下代码
{
area->avg_strength = sum / MAX_AREA_LINE * 2;//求平均信号强度并写入结构体
sum = 0;//总和清零
i = 0;//次数清零
return 0;//返回0表示计算完成
}
return 1;//返回1表示计算未完成
}



void fileop(int num)//读取小区文件并计算
{
FILE* fp;
double Q, I;
int flag;//设置旗标flag
if((fp = fopen(Areas[num].ID, "r")) == NULL)//打开文件
{
printf("打开文件错误");
return;
}
for (int i = 0;; i++)
{
fscanf(fp, "%lf %lf", &Q, &I);//读取文件,并将数值写入Q、I
flag = kqlt(&Areas[num], Q, I);//通过kqlt函数返回值判断是否计算完成
if (flag == 0)//flag=0时计算完成
{
fclose(fp);//关闭文件
break;//跳出循环
}
}
}

void fileop2()//读取PSS文件并计算模值存入PSS数组
{
FILE* fp;
double Q, I;
for (int i = 0; i < PSS_NUM; i++)
{
if ((fp = fopen(PSS[i].ID, "r")) == NULL)
{
printf("打开PSS文件错误");
return;
}
for (int j = 0; j < MAX_PSS_LINE/2; j++)
{
fscanf(fp, "%lf %lf", &Q, &I);
PSS[i].strength[j] = sqrt(Q * Q + I * I);
}
fclose(fp);
}
}

void sort()//冒泡算法排序
{
struct Area temp;
for (int j = 0; j < NUM - 1; j++)
{
for (int i = 0; i < NUM - 1 - j; i++)
{
if (Areas[i].avg_strength < Areas[i + 1].avg_strength)
{
temp = Areas[i] ;
Areas[i] = Areas[i + 1];
Areas[i + 1] = temp;
}
}
}
}

void slide(struct Area *area, struct Pss *pss)//相关性检测
{
static int pos = 0;//记录当前序列位置
int i = 0;
int j = 0;
int kz = 0;//滑动相关计算序列哨兵
double temp = 0;//记录当前位置的相关度数值
double max = 0;//记录当前位置最大值
int maxpos = 0;//确定型号的起始位置,也就是最大值的位置
//相关性检测算法
for (kz = 0; kz < SQE_LEN; kz++)
{
temp = 0;
for (i = 0; i < MAX_PSS_LINE/2; i++)
{
temp += pss->strength[i] * area->strength[i + j];
}
j++;
if (temp >= max)
{
max = temp;
maxpos = kz;
}
}
//将计算完毕的数据写入相关性序列
Correlations[pos].p_area = area;
Correlations[pos].p_pss = pss;
Correlations[pos].maxnum = max;
pos++;//当前位置+1
}

void connect(double area_lim, double correlations_lim) //连接判断函数
{
int max_pos[PSS_NUM];//记录Correlations数组中组合下标记录不同组合间数值最大的一组,用于最后判断输出,当值为-1是表明未存入信息
int pos = 0;//max_pos数组下标
double maxnum = 0;//记录当前pss与小区相关性序列中的最大值,判断
int flag = 0;//旗标,判断是否存在满足门限条件的组合
//为max_pos数组赋初值
for (int i = 0; i < PSS_NUM; i++)
{
max_pos[i] = -1;
}
for (int i = 0; i < PSS_NUM * NUM; i++)
{
Sleep(DELY);
printf("%s检测能否接入小区%s", Correlations[i].p_pss->ID, Correlations[i].p_area->ID);
if ((Correlations[i].maxnum>=correlations_lim)&&(Correlations[i].p_area->avg_strength>=area_lim))//当相关性序列最大值大于门限并且平均强度高于强度门限
{
flag = 1;//表明存在可接入小区
printf("\t满足门限条件可接入\n");
//替换最大值
if (maxnum<=Correlations[i].maxnum)
{
maxnum = Correlations[i].maxnum;
max_pos[pos] = i;
}
}
else
{
printf("\t不满足门限条件\n");
}
if ((i!= (PSS_NUM * NUM)-1)&&(strcmp(Correlations[i].p_pss->ID, Correlations[i+1].p_pss->ID)!=0))//当PSS ID值发生变化时移动pos,并将最大值清零
{
pos++;
maxnum = 0;
}
}
printf("\n接入结果:\n");
if (flag)
{
for (int i = 0; i < PSS_NUM; i++)
{
if (max_pos[i] == -1)
{
printf("%s无接入小区,未接入。\n", Correlations[i].p_pss->ID);
}
else
printf("%s接入%s,相关强度%lf\n", Correlations[max_pos[i]].p_pss->ID, Correlations[max_pos[i]].p_area->ID, Correlations[max_pos[i]].maxnum);
}
}
else
{
printf("无满足条件的小区。\n");
}
}


void main()//主函数
{
double area_lim;//小区强度门限
double correlations_lim;//最大相关度门限
initialization();//调用初始化函数,对结构体进行初始化
fileop2();//调用PSS文件处理函数
printf("计算数据中...\n");
for (int i = 0; i < NUM; i++)//利用for循环计算多个文件信号平均强度
{
fileop(i);
printf("ID:%s \t信号平均强度:%lf", Areas[i].ID, Areas[i].avg_strength);
/*for (int j = 0; j < MAX_AREA_LINE / 2; j++)//调试用
{
printf("%lf ", Areas[i].strength[j]);
}*/
printf("\n");
}

sort();//对数据进行排序
printf("\n排序后结果:\n");
for (int i = 0; i < NUM; i++)
{
Sleep(DELY);
printf("ID:%s \t信号平均强度:%lf\n",Areas[i].ID, Areas[i].avg_strength);
}
for (int i = 0; i < 3; i++)//调用slide函数进行滑块检测
{
for (int j = 0; j < 12; j++)
{
slide(&Areas[j], &PSS[i]);
}
}

printf("\nPSS与小区匹配结果:\n");
for (int i = 0; i < 36; i++)
{
Sleep(DELY);
printf("小区ID:%s\tPSS ID:%s\t相关性序列最大值:%lf\n", Correlations[i].p_area->ID, Correlations[i].p_pss->ID, Correlations[i].maxnum);
}

printf("请输入强度门限:");
scanf("%lf", &area_lim);//输入强度门限条件
printf("\n请输入相关门限:");
scanf("%lf", &correlations_lim);
printf("\n分析数据...\n");
connect(area_lim, correlations_lim);


/*fileop2();//调试调用
for (int j = 0; j < PSS_NUM; j++)
{
for (int i = 0; i < MAX_PSS_LINE / 2; i++)
{
printf("%lf\t", PSS[j].strength[i]);
}
printf("\n");
}
*/

}

四. 调试

在调试进行小范围滑动检测时发现数值过小,且与手动计算数值不符,检查编写代码与给定算法代码发现,单个序列位置的值未进行累加,循环限定值使用了错误的变量,改正后运行正常。

五. 心得体会

编写代码时要认真仔细,定义的变量要见名知意。

六.附录:

结果展示

七.相关资源

凉凉不冷关于该实验的Blog

实验数据

有什么问题在下面留言吧~~~

(附三部优秀漫改作品结局图)

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2022-2023 Block Chen
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信