① 哈夫曼編碼/解碼器
注釋非常詳細,希望對你有所幫助!
#ifndef Huffman_Tree_h
#define Huffman_Tree_h
#endif
#include <stdio.h>
typedef struct {
unsigned int weight;
unsigned int parent,lchild,rchild;
}HTNode, * HuffmanTree; //存儲赫夫曼樹的結點類型
typedef char * * HuffmanCode; //用於存儲字元集中各個字元相應的赫夫曼編碼
void strcpy(char *S1,char *S2){ //將字元串S2復制到S1
int i = 0;
while( S2[i] != '\0' ){
S1[i] = S2[i];
i++;
}
S1[i] = '\0';
}
void Select(HuffmanTree HT,int t,int &s1,int &s2){ //在HT[1]到HT[t-1]中找出權值最小的兩個S1和S2
int i = 1;
s1 = s2 = 0;
HT[0].weight = 65535;
while( i <= t ){ //遍歷查找權值最小的結點S1
if( HT[i].parent == 0 && HT[i].weight < HT[s1].weight )
s1 = i;
i++;
}
i = 1;
while( i <= t ){ //遍歷查找除S1外權值最小的結點S2
if( i != s1 && HT[i].parent == 0 && HT[i].weight < HT[s2].weight )
s2 = i;
i++;
}
}
int HuffmanCoding( HuffmanTree &HT,HuffmanCode &HC,int *w,int n){ //根據各個字元的權值構造赫夫曼樹HT,將對應的赫夫曼編碼存儲在HC中
int s1,s2,m,i,start;
unsigned int c,f;
HTNode * p;
char *cd;
if( n <= 1 ) return 0;
m = 2 * n - 1; //赫夫曼樹的總結點樹為m
HT = (HuffmanTree)malloc((m + 1) * sizeof(HTNode)); //申請存儲赫夫曼樹的空間
for(p = HT + 1, i = 1; i <= n; ++i, ++p, ++w){ //將各個葉子結點的weight賦以相應的權值,parent,lchild,rchild均賦為0
p->weight = *(w+1);
p->parent = p->lchild = p->rchild = 0;
}
for( ; i <= m; ++i, ++p ){ //將各個非葉子結點的weight,parent,lchild,rchild均賦為0
p->weight = p->parent = p->lchild = p->rchild = 0;
}
for( i = n + 1; i <= m; ++i ){ //構造赫夫曼樹,給各個非葉子結點賦值
Select(HT, i - 1, s1, s2);
HT[s1].parent = i; HT[s2].parent = i;
HT[i].lchild = s1; HT[i].rchild = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight;
}
HC = (HuffmanCode)malloc((n + 1) * sizeof(char *)); //申請空間,用於存儲指向存儲各個字元相應赫夫曼編碼的字元數組的指針
cd = (char *)malloc(n * sizeof(char)); //申請用於求赫夫曼編碼
cd[n - 1] = '\0'; //編碼結束符
for( i = 1; i <= n; ++i){ //逐個字元求赫夫曼編碼
start = n -1; //編碼在數組cd[]中的最前位置
for(c = i,f = HT[i].parent; f != 0; c = f, f = HT[f].parent) //從葉子到根逆向求編碼
if(HT[f].lchild == c)
cd[ --start ] = '0';
else
cd[ --start ] = '1';
HC[i] = (char *)malloc((n - start)*sizeof(char)); //為第i個字元編碼分配空間
strcpy(HC[i], &cd[start]); //將cd[]數組的start位置到n-1位置復制給HC[i]
}
free(cd); //釋放空間
return 1;
}
以上為第一部分
#include <stdio.h>
#include <stdlib.h>
#include "Huffman_Tree.h"
#define Yes 1 //當程序已經調用過初始化赫夫曼樹的InitHuff_T()函數,或已從htfTree文件讀取過,則將Init_Mode置為Yes,否則為No
#define No 0
void InitHuff_T( HuffmanTree &HT, HuffmanCode &HC, char ch[],int &n ){ //初始化赫夫曼數,要求用戶輸入字元和相應權值
int i = 1,w[100],tem,j;
char a[20];
FILE *save;
printf("請輸入編碼字元集的大小n:");
scanf("%d",&n); //獲取用戶輸入的字元集個數
while( i <= n ){ //獲取用戶輸入的字元和相應權值,分別存儲在ch[]和w[]數組中
printf("請輸入第%d個字元和該字元的權值w:",i);
fflush(stdin);
scanf("%c%d",&ch[i],&w[i]);
i++;
}
ch[i] = '\0';
HuffmanCoding(HT,HC,w,n); //根據用戶的輸入,生成赫夫曼數及各個字元相應的赫夫曼編碼,分別存在HT樹和HC中
if(( save = fopen("htfTree","w")) == NULL ){ //打開用於存儲赫夫曼樹的文件
printf("Open file fail......\n");
exit(0);
}
tem = n; //接下來的14行是將字元集大小轉換成字元形式寫入到文件中
j = 0;
while( tem != 0 ){
tem = tem / 10;
j++;
}
tem = n;
a[j] = '\0';
while( tem != 0 ){
a[j - 1] = (char)(tem % 10 + 48);
tem = tem / 10;
j--;
}
fputs(a,save);
printf("%d\n",n); //向屏幕輸出字元集大小n
fputc('\n',save);
for( i = 1; i <= n; i++ ){ //分別向文件和屏幕輸出各個字元和相應的赫夫曼編碼
fputc(ch[i],save); printf("%c\t",ch[i]);
fputc('\t',save);
fputs(HC[i],save); printf("%s\n",HC[i]);
fputc('\n',save);
}
for(i = 1; i <= 2 * n - 1; i++ ){ //將赫夫曼樹各個結點的parent,lchild,rchild分別寫入到文件中
tem = HT[i].parent; //將i結點的parent轉換成字元並寫入到文件中
if(tem == 0){
fputc(tem + 48,save);
fputc(' ',save);
}
else{
j = 0;
while( tem != 0 ){
tem = tem / 10;
j++;
}
tem = HT[i].parent;
a[j] = '\0';
while( tem != 0 ){
a[j - 1] = (char)(tem % 10 + 48);
tem = tem / 10;
j--;
}
fputs(a,save);
fputc(' ',save);
}
tem = HT[i].lchild; //將i結點的lchild轉換成字元並寫入到文件中
if(tem == 0){
fputc(tem + 48,save);
fputc(' ',save);
}
else{
j = 0;
while( tem != 0 ){
tem = tem / 10;
j++;
}
tem = HT[i].lchild;
a[j] = '\0';
while( tem != 0 ){
a[j - 1] = (char)(tem % 10 + 48);
tem = tem / 10;
j--;
}
fputs(a,save);
fputc(' ',save);
}
tem = HT[i].rchild; //將i結點的rchild轉換成字元並寫入到文件中
if(tem == 0){
fputc(tem + 48,save);
fputc('\n',save);
}
else{
j = 0;
while( tem != 0 ){
tem = tem / 10;
j++;
}
tem = HT[i].rchild;
a[j] = '\0';
while( tem != 0 ){
a[j - 1] = (char)(tem % 10 + 48);
tem = tem / 10;
j--;
}
fputs(a,save);
fputc('\n',save);
}
}
fclose(save);
}
void Encoding(HuffmanTree &HT, HuffmanCode &HC, char ch[]){ //根據赫夫曼編碼將用戶指定的文件中的字元編成相應的編碼,並將所得編碼存儲到用戶指定文件
FILE *ToBeTran,*CodeFile;
char ToBeTran_Name[100],CodeFile_Name[100]; //存儲用戶指定文件的文件名
int i;
char c;
printf("請輸入所要進行編碼的文件的文件名:");
scanf("%s",ToBeTran_Name); //獲得所要進行編碼的文件的文件名
if(( ToBeTran = fopen(ToBeTran_Name,"r")) == NULL ){ //打開文件
printf("Open file fail......\n");
exit(0);
}
printf("請輸入編碼後編碼表示的信息所存儲到的文件的文件名:");
scanf("%s",CodeFile_Name); //獲得編碼後編碼表示的信息所存儲到的文件的文件名
if(( CodeFile = fopen(CodeFile_Name,"w")) == NULL ){ //打開文件
printf("Open file fail......\n");
exit(0);
}
c = fgetc(ToBeTran); //從文件讀取一個字元
while( c != EOF ){ //對文件中的各個字元進行編碼,直至文件結尾
i = 1;
while( c != ch[i] && ch[i] != '\0' ) //在ch[]數組中查找從文件讀取的字元
i++;
if(ch[i] == '\0'){ //未找到,c不在ch[]數組中,c無法被識別,程序出錯,退出
printf("字元%c無法識別,程序將退出。\n",c);
exit(0);
}
fputs(HC[i],CodeFile); //若找到,則將c相應的赫夫曼編碼寫入到文件中
printf("%s",HC[i]); //將c相應的赫夫曼編碼輸出到屏幕
c = fgetc(ToBeTran); //讀入文件中的下一個字元
}
printf("\n");
fclose(ToBeTran);
fclose(CodeFile);
}
void Decoding(HuffmanTree HT, char ch[] , int n){ //對指定的存儲由赫夫曼編碼表示的信息的文件進行解碼,翻譯成相應的字元表示,並存儲到指定文件
int p,i = 1;
char code[1000],c;
char CodeFile_Name[100],TextFile_Name[100]; //存儲用戶指定文件的文件名
p = 2 * n - 1;
FILE *CodeFile,*TextFile;
printf("請輸入所要譯的文件名:");
scanf("%s",CodeFile_Name); //獲得所要譯的文件的文件名
if(( CodeFile = fopen("CodeFile","r")) == NULL ){ //打開文件
printf("Open file fail......\n");
exit(0);
}
printf("請輸入譯後的字元存儲到的文件的文件名:");
scanf("%s",TextFile_Name); //獲得譯後的字元存儲到的文件的文件名
if(( TextFile = fopen(TextFile_Name,"w")) == NULL ){ //打開文件
printf("Open file fail......\n");
exit(0);
}
c = fgetc(CodeFile);
while( c != EOF ){
code[i] = c;
i++;
c = fgetc(CodeFile);
}
code[i] = '\0'; //從文件讀取字元,存儲在code[]數組中
i = 1;
while ( code[i] != '\0' && p != 0 ){ //對數組code[]中的赫夫曼編碼進行解碼
if ( code[i] == '0' )
p=HT[p].lchild; //進入左分支
else
p = HT[p].rchild; //進入右分支
if (!HT[p].lchild&& !HT[p].rchild){ //進入葉子結點
fputc(ch[p], TextFile); //將相應的字元寫入到文件中
printf("%c",ch[p]); //將相應的字元輸出到屏幕
p = 2 * n - 1; //重新從樹根出發進行解碼
}
i++;
}
printf("\n");
}
void ReadHuff_T( HuffmanTree &HT, HuffmanCode &HC, char ch[], int &n){ //從文件讀取赫夫曼樹
FILE *htfTree;
char c[100],ch1;
int i,j,t;
if(( htfTree = fopen("htfTree","r")) == NULL ){ //打開存有赫夫曼樹信息的文件
printf("Open file fail......\n");
exit(0);
}
fgets(c,10,htfTree); //獲取赫夫曼樹葉子結點個數的字元串表示形式
i = 0; //以下6行將字元串形式轉換成整數形式
while( c[i] != '\n' )
i++;
n = 0;
for( j = 0; j < i; j++ )
n = 10 * n + c[j] - '0'; //求出葉子結點數n
HC = (HuffmanCode)malloc((n + 1) * sizeof(char *)); //申請HC空間
HT = (HuffmanTree)malloc((2 * n) * sizeof(HTNode)); //申請赫夫曼樹存儲空間
i = 1;
while( i <= n ){
ch[i] = fgetc(htfTree); //讀取字元集中的一個字元
HC[i] = (char *)malloc((10)*sizeof(char)); //申請用於存儲讀取到的字元集中的字元的赫夫曼編碼的空間
fgetc(htfTree); //將『\t』輸出
ch1 = fgetc(htfTree); //讀取赫夫曼編碼,存儲在相應的HC[i][]數組里
int j = 0;
while( ch1 != '\n' ){
HC[i][j] = ch1;
j++;
ch1 = fgetc(htfTree);
}
HC[i][j] = '\0';
i++;
}
ch[i] = '\0';
i = 0;
while( i < 2 * n - 1 ){ //讀取赫夫曼樹的各個結點的parent,lchild,rchild.並賦值到赫夫曼樹HT中
ch1 = fgetc(htfTree); //讀取parent的字元串形式,存儲在c[]中,並將其轉換成整數形式,賦給HT[i].parent
j = 0;
while( ch1 != ' ' ){
c[j] = ch1;
j++;
ch1 = fgetc(htfTree);
}
HT[i+1].parent = 0;
for( t = 0; t < j; t++ )
HT[i+1].parent = 10 * HT[i+1].parent + c[t] - '0';
ch1 = fgetc(htfTree); //讀取lchild的字元串形式,並將其轉換成整數形式,賦給HT[i].lchild
j = 0;
while( ch1 != ' ' ){
c[j] = ch1;
j++;
ch1 = fgetc(htfTree);
}
HT[i+1].lchild = 0;
for( t = 0; t < j; t++ )
HT[i+1].lchild = 10 * HT[i+1].lchild + c[t] - '0';
ch1 = fgetc(htfTree); //讀取rchild的字元串形式,並將其轉換成整數形式,賦給HT[i].rchild
j = 0;
while( ch1 != '\n' ){
c[j] = ch1;
j++;
ch1 = fgetc(htfTree);
}
HT[i+1].rchild = 0;
for( t = 0; t < j; t++ )
HT[i+1].rchild = 10 * HT[i+1].rchild + c[t] - '0';
i++;
}
}
int main(){
HuffmanTree HT;
HuffmanCode HC;
char ch[100]; //用於存儲字元集
int n,Init_Mode = No; //n為字元集的大小,Init_Mode = No 表示內存中沒有赫夫曼樹的信息
char mode; //讓用戶選擇不同的操作
printf("請輸入你要選擇的功能\n");
printf("\t\tI -- 初始化\t\tE -- 編碼\n");
printf("\t\tD -- 解碼 \t\tQ -- 退出程序\n");
scanf("%c",&mode); //獲得用戶選擇的操作
while( mode != 'Q' && mode != 'q' ){ //當用戶輸入不為Q或q時,執行相應操作
switch(mode){
case 'I' :
InitHuff_T(HT,HC,ch,n);
Init_Mode = Yes;
break;
case 'i' :
InitHuff_T(HT,HC,ch,n);
Init_Mode = Yes;
break;
case 'E' :
if( No == Init_Mode )
ReadHuff_T(HT,HC,ch,n);
Encoding(HT,HC,ch);
Init_Mode = Yes;
break;
case 'e' :
if( No == Init_Mode )
ReadHuff_T(HT,HC,ch,n);
Encoding(HT,HC,ch);
Init_Mode = Yes;
break;
case 'D' :
if( No == Init_Mode )
ReadHuff_T(HT,HC,ch,n);
Decoding(HT,ch,n);
Init_Mode = Yes;
break;
case 'd' :
if( No == Init_Mode )
ReadHuff_T(HT,HC,ch,n);
Decoding(HT,ch,n);
Init_Mode = Yes;
default :
printf("您的輸入有錯,請重新選擇.\n");
}
printf("請輸入你要選擇的功能\n");
printf("\tI -- 初始化\tE -- 編碼\n");
printf("\tD -- 解碼 \tQ -- 退出程序\n");
fflush(stdin);
scanf("%c",&mode); //讓用戶繼續選擇相應的操作,直至用戶選擇退出
}
return 0;
}
② 哈夫曼樹及哈夫曼編碼解碼的實現(根據程序畫流程圖及對每句程序注釋)
這是以前寫的,可是我不想加註釋了,Huffman編碼其實原理很簡單的,你自己好好學下吧,一句一句注釋也太誇張了啊。
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
int m,s1,s2;
typedef struct {
unsigned int weight;
unsigned int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef char ** HuffmanCode;
void Select(HuffmanTree HT,int n)
{
int i,j;
for(i=1;i<=n;i++)
if(HT[i].parent==0)
{s1=i;
break;
}
for(j=i+1;j<=n;j++)
if(HT[j].parent==0)
{
s2=j;
break;
}
for(i=1;i<=n;i++)
{
if(HT[i].parent==0)
if(HT[s1].weight>HT[i].weight)
if(s2!=i)
s1=i;
}
for(j=1;j<=n;j++)
{
if(HT[j].parent==0)
if(HT[s2].weight>HT[j].weight)
if(s1!=j)
s2=j;
}
if(s1>s2)
{
int temp=s1;
s1=s2;
s2=temp;
}
}
void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n)
{
int i,j;
char *cd;
int p;
int cdlen;
if (n<=1) return;
m = 2 * n - 1;
HT = (HuffmanTree)malloc((m+1) * sizeof(HTNode));
for (i=1; i<=n; i++)
{
HT[i].weight=w[i-1];
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
for (i=n+1; i<=m; i++)
{
HT[i].weight=0;
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
//添加查看,便於調試
printf("構造過程顯示:\n");
for(i=1;i<=m;i++)
printf("%4d%4d%4d%4d%4d\n",i,HT[i].weight, HT[i].parent,HT[i].lchild, HT[i].rchild);
system("pause");
for(i=n+1;i<=m;i++)
{
Select(HT,i-1);
HT[s1].parent = i; HT[s2].parent = i;
HT[i].lchild = s1; HT[i].rchild = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight;
//添加查看,便於調試
/*printf("s1=%d,s2=%d\n",s1,s2);
for(j=1;j<=i;j++)
printf("%d%4d%4d%4d",j,HT[j].weight,HT[j].parent,HT[j].lchild, HT[j].rchild);
system("pause");
*/
}
cd = (char *)malloc(n*sizeof(char));
p=m;
cdlen=0;
for(i=1;i<=m;i++)
HT[i].weight=0;
while(p)
{
if(HT[p].weight==0)
{
HT[p].weight=1;
if(HT[p].lchild!=0)
{
p=HT[p].lchild;
cd[cdlen++]='0';
}
else if(HT[p].rchild==0)
{
HC[p]=(char *)malloc((cdlen+1)*sizeof(char));
cd[cdlen]='\0';
strcpy(HC[p],cd);
}
}
else if(HT[p].weight==1)
{
HT[p].weight=2;
if(HT[p].rchild!=0)
{
p=HT[p].rchild;
cd[cdlen++]='1';
}
}
else
{
HT[p].weight=0;
p=HT[p].parent;
--cdlen;
}
}
}
int main()
{
HuffmanTree HT;
HuffmanCode HC;
int *w,n,i;
printf("請輸入節點數:\n");
scanf("%d",&n);
HC = (HuffmanCode)malloc(n*sizeof(HuffmanCode));
w=(int *)malloc(n*sizeof(int));
printf("請輸入節點的權值:\n");
for(i=0;i<n;i++)
scanf("%d",&w[i]);
HuffmanCoding(HT,HC,w,n);
printf("輸出編碼:\n");
for(i=1;i<=n;i++)
printf("%2d(%4d):%s\n",i,w[i-1],HC[i]);
return 0;
system("pause");
}
③ 求程式控制交換PCM編譯碼實驗的畢業設計
程式控制交換原理實驗系統及控制單元實驗
一、 實驗目的
1、熟悉該程式控制交換原理實驗系統的電路組成與主要部件的作用。
2、體會程式控制交換原理實驗系統進行電話通信時的工作過程。
3、了解CPU中央集中控制處理器電路組成及工作過程。
二、 預習要求
預習《程式控制交換原理》與《MCS-51單片計算機原理與應用》中的有關內容。
三、 實驗儀器儀表
1、主機實驗箱 一台
2、三用表 一台
3、電話單機 四台
四、 實驗系統電路組成
(一)電路組成
圖1-1是該實驗系統的原理框圖
圖1-1 實驗系統的原理框圖
圖1—2是該實驗系統的方框圖,其電路的組成及主要作用如下:
1、用戶模塊電路 主要完成BORSCHT七種功能,它由下列電路組成:
A、 用戶線介面電路
B、 二\四線變換器
C、 PCM編解碼電路
用戶線介面電路 二/ 四線變換器 二/四線變換器 用戶線介面電路
用戶1 PCM CODEC電路 PCM CODEC電路 用戶3
用戶線介面電路 二/ 四線變換器 二/ 四線變換器 用戶線介面電路
用戶2 PCM CODEC電路 PCM CODEC電路 用戶4
時鍾信號電路 控制、檢測電路 輸出顯示電路 二次穩壓電路
多種信號音電路 CPU中央處理器 鍵盤輸入電路 直流電源
圖1-2實驗系統方框圖
2、交換網路系統 主要完成空分交換與時隙交換兩大功能,它由下列電路組成:
A、空分交換網路系統
B、時隙交換網路系統
3、多種信號音電路 主要完成各種信號音的產生與發送,它由下列電路組成:
A、450Hz撥號音電路
B、忙音發生電路
C、回鈴音發生電路
D、25Hz振鈴信號電路
4、CPU中央集中控制處理器電路 主要完成對系統電路的各種控制,信號檢測,號碼識別,鍵盤輸入信息,輸出顯示信息等各種功能。
5、系統工作電源 主要完成系統所需要的各種電源,本實驗系統中有+5V,-5V,+12V,-12V,-48V等5組電源,由下列電路組成:
A、內置工作電源:+5V,+12V,-12V,-48V
B、穩壓電源: -8V,-5V
控制部分就是由CPU中央處理系統、輸入電路(鍵盤)、輸出電路(數碼管)、雙音多頻DTMF檢測電路、用戶環路狀態檢測電路、自動交換網路驅動電路與交換網路轉換電路、擴展電路、信號音控制電路等電路組成。
下面簡要說明各部分電路的作用與要求:
1、鍵盤輸入電路:主要把實驗過程中的一些功能通過鍵盤設置到系統中。
2、顯示電路: 顯示主叫與被叫電路的電話號碼,同時顯示通話時間。
3、輸入輸出擴展電路:顯示電路與鍵盤輸入電路主要通過該電路進行工作。主要晶元是D8155A,SN74LS240,MC1413。
4、雙音多頻DTMF接收檢測電路:把MT8870DC輸出的DTMF四位二進制信號,接收存貯後再送給CPU中央集中控制處理系統。
5、用戶狀態檢測電路:主要識別主、被叫用戶的摘掛機狀態,送給CPU進行處理。
6、自動交換網路驅動電路:主要實現電話交換通信時,CPU發出命令信息,由此電路實現驅動自動交換網路系統,其核心集成電路為SN74LS374,D8255A,GD74LS373等晶元。
7、信號音控制電路:它完全按照CPU發出的指令進行操作,使各種信號音按照系統程序進行工作。
8、振鈴控制電路:它也是按照CPU發出的指令進行工作,具體如下:
(A)不振鈴時,要求振鈴支路與供電系統分開。
(B)振鈴時,鈴流送向話機,並且供電系統通過振鈴支路向用戶饋電,用戶狀態檢測電路同時能檢測用戶的忙閑工作狀態。
(C)當振鈴時,用戶一摘機就要求迅速斷開振鈴支路。
(D)振鈴時要求有1秒鍾振、4秒鍾停的通斷比。
以上是CPU中央集中控制處理系統的主要工作過程,要全面具體實現上述工作過程,則要有軟體支持,該軟體程序流程圖見圖1—4。
圖1-3 鍵盤功能框圖
對圖1-3所示的鍵盤功能作如下介紹:
「時間」: 該鍵可設置系統的延時時間。如久不拔號、久不應答、位間不拔號的延時,預設值為10秒,可選擇的時間值有10秒、30秒、1分鍾。按一次該鍵則顯示下一個時間值,三個值循環顯示,當按下「確認」鍵時,就選定當前顯示值供系統使用,按「復位」鍵則清除該次時間的設定。
「會議電話」: 該鍵為召開電話會議的按鍵。電話會議設置用戶1為主叫方,其他三路為被叫方,只能由主叫方主持召開會議,向其他三路發出呼叫。電路完全接通或者接通兩路後,主叫方能和任一被叫方互相通話。除「復位」鍵外,其他鍵均推失去功能。會議結束後,可按「復位」鍵重啟系統。
「中繼」: 該鍵為局內交換切向中繼交換的功能按鍵,按下此鍵,再按「確認」鍵進行確認,則工作模式由局內交換切換為中繼交換,顯示器循環顯示「d」,此時方可通過中繼撥打「長途」電話。按「復位」鍵重啟系統,進入正常局內交換模式。
「確認」: 該鍵完成對其他功能鍵的確認,防止誤按鍵,在鍵盤中除「復位」鍵外,其他功能鍵都必須加「確認」鍵才能完成所定義的功能。
「復位」: 該鍵為重啟系統按鍵。在任何時候或者系統出現不正常狀態時都可按下此鍵重啟系統(有用戶通話時,會中斷通話),所有設置均為默認值。
圖1-5是顯示電路工作示意說明圖。
主叫號碼顯示 計時顯示 被叫號碼顯示
圖1-5 顯示電路
開 始
NO
有用戶呼叫嗎?
呼叫�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1 YES
去 話 接 續
向主叫送撥號音
NO
第一位號碼來了嗎?
撥號開始�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1 YES
停送撥號音,收存號碼
內 部 處 理
撥號完畢�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1
被叫閑嗎? NO
YES
來 話 接 續 向主叫送忙音
向被叫送鈴流,向主叫送回鈴音
被叫應答否? NO
主叫掛機否?
應答�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1 YES
停送鈴流,回鈴音,接通電路 YES
話終掛機否?
掛機�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1�6�1 YES
拆線(釋放復原)
結 束
圖1-4 程序工作流程示意圖
五、實驗內容
1、測量實驗系統電路板中的TP91~TP95各測量點電壓值,並記錄。
2、從總體上初步熟悉兩部電話單機用空分交換方式進行通話。
3、初步建立程式控制交換原理系統及電話通信的概念。
4、觀察並記錄一個正常呼叫的全過程。
5、觀察並記錄一個不正常呼叫的狀態。
圖1-6 呼叫識別電路框圖
五、 實驗步驟
1、接上交流電源線。
2、將K11~K14,K21~K24,K31~K34,K41~K44接2,3腳;K70~K75接2,3腳;K60~K63接2,3腳。
3、先打開「交流開關」,指示發光二極體亮後,再分別按下直流輸出開關J8,J9。此時實驗箱上的五組電源已供電,各自發光二極體亮。
4、按 「復位」鍵進行一次上電復位,此時,CPU已對系統進行初始化處理,數碼管循環顯示「P」 ,即可進行實驗。
5、將三用表拔至直流電壓檔,然後測量TP91,TP92,TP93,TP94,TP95的電壓是否正常:TP91為-12V,TP92為-48V,TP93為+5V,TP94為+12V,TP95為-5V。(-48V允許誤差±10%,其它為±5%)
6、將四個用戶接上電話單機。
7、正常呼叫全過程的觀察與記錄。(現以用戶1為主叫,用戶4為被叫進行實驗)
A、 主叫摘機,聽到撥號音,數碼管顯示主叫電話號碼「68」 。
B、 主叫撥首位被叫號碼「8」,主叫撥號音停,主叫繼續撥完被叫號碼「9」。
C、 被叫振鈴,主叫聽到回鈴音。
D、 被叫摘機,被叫振鈴停,主叫回鈴音停,雙方通話。數碼管顯示主叫號碼和被叫號碼,並開始通話計時。
E、 掛機,任意一方先掛機(如主叫先掛機),另一方(被叫)聽到忙音,計時暫停,雙方都掛機後,數碼管循環顯示「P」 。
8、不正常呼叫的自動處理
A、 主叫摘機後在規定的系統時間內不撥號,主叫聽到忙音。(系統時間可以設置,在系統復位後按「時間」可循環顯示「10」,「30」,「100」,分別表示10秒,30秒,1分鍾,選定一個時間,按「確定」即系統時間被設置,在復位狀態時,系統時間默認為10秒。)
B、 撥完第一位號碼後在規定的系統時間內沒有撥第二位號碼時,主叫聽到忙音。
C、 號碼撥錯時(如主叫撥「56」 ),主叫聽到忙音。
D、 被叫振鈴後在規定的系統時間內不摘機,被叫振鈴音停,主叫聽到忙音。
六、 實驗注意事項
對實驗系統加電一定要嚴格遵循先打開系統工作電源的「交流開關」,然後再打開直流輸出開關J8,J9。實驗結束後,先分別關直流輸出開關J8,J9。最後再關「交流開關」,以避免實驗電路的器件損壞。
七、 實驗報告要求
1、畫出實驗系統電路的方框圖,並作簡要敘述。
2、對正常呼叫全過程進行記錄。
實驗二 用戶線介面電路及二\四線變換實驗
一、實驗目的
1、全面了解用戶線介面電路功能(BORST)的作用及其實現方法。
2、通過對MH88612C電路的學習與實驗,進一步加深對BORST功能的理解。
3、了解二\四線變換電路的工作原理。
二、預習要求
認真預習程式控制交換原理中有關用戶線介面電路等章節。
三、實驗儀器儀表
1、主機實驗箱 一台
2、電話單機 二台
3、20MHz示波器 一台
4、三用表 一台
四、電路工作過程
在現代電話通信設備與程式控制交換機中,由於交換網路不能通過鈴流、饋電等電流,因而將過去在公用設備(如繩路)實現的一些用戶功能放到「用戶電路」來完成。
用戶電路也可稱為用戶線介面電路(Subscriber Line Interface Circuit—SLIC)。任何交換機都具有用戶線介面電路。
模擬用戶線介面電路在實現上的最大壓力是應能承受饋電、鈴流和外界干擾等高壓大電流的沖擊,過去都是採用晶體管、變壓器(或混合線圈)、繼電器等分立元件構成,隨著微電子技術的發展,近十年來在國際上陸續開發多種模擬SLIC,它們或是採用半導體集成工藝或是採用薄膜、厚膜混合工藝,並已實用化。在實際中,基於實現和應用上的考慮,通常將BORSCHT功能中過壓保護由外接元器件完成,編解碼器部分另單成一體,集成為編解碼器(CODEC),其餘功能由所謂集成模擬SLIC完成。
在布控交換機中,向用戶饋電,向用戶振鈴等功能都是在繩路中實現的,饋電電壓一般是-60V,用戶的饋電電流一般是20mA~30 mA,鈴流是25HZ,
90V左右,而在程式控制交換機中,由於交換網路處理的是數字信息,無法向用戶饋電、振鈴等,所以向用戶饋電、振鈴等任務就由用戶線介面電路來承擔完成,再加上其它一些要求,程式控制交換機中的用戶線介面電路一般要具有B(饋電)、O(過壓保護)、R(振鈴)、S(監視)、C(編解碼)、H(混合)、T(測試)七項功能。
模擬用戶線介面電路的功能可以歸納為BORSCHT七種功能,具體含義是:
(1)饋電(B-Battery feeling)向用戶話機送直流電流。通常要求饋電電壓為—48伏,環路電流不小於18mA。
(2)過壓保護(O-Overvoltage protection)防止過壓過流沖擊和損壞電路、設備。
(3)振鈴控制(R-Ringing Control)向用戶話機饋送鈴流,通常為25HZ/90Vrms正弦波。
(4)監視(S-Supervision)監視用戶線的狀態,檢測話機摘機、掛機與撥號脈沖等信號以送往控制網路和交換網路。
(5)編解碼與濾波(C-CODEC/Filter)在數字交換中,它完成模擬話音與數字碼間的轉換。通常採用PCM編碼器(Coder)與解碼器(Decoder)來完成,統稱為CODEC。相應的防混疊與平滑低通濾波器佔有話路(300HZ~3400HZ)帶寬,編碼速率為64kb/s。
(6)混合(H-Hyhird)完成二線與四線的轉換功能,即實現模擬二線雙向信號與PCM發送,接收數字四線單向信號之間的連接。過去這種功能由混合線圈實現,現在改為集成電路,因此稱為「混合電路」。
(7)測試(T-Test)對用戶電路進行測試。
模擬用戶線介面功能見圖2—1。
鈴流發生器 饋電電源
發送碼流
過 振 低通 編
a 壓 測 鈴 饋 混 碼
模
擬 保 試 繼 電 合 平衡 器
用 (編碼信號)
戶 護 開 電 電 電 網路 解
線
b 電 關 器 路 路 碼
路 低通 器
接收碼流
測試 振鈴控台 用戶線
匯流排 制信號彈 狀態信號
圖2-1 模擬用戶線介面功能框
(一)用戶線介面電路
在本實驗系統中,用戶線介面電路選用的是MITEL公司的MH88612C。MH88612C是2/4線厚膜混合用戶線介面電路。它包含向用戶話機恆流饋電、向被叫用戶話機饋送鈴流、用戶摘機後自行截除鈴流,摘掛機的檢測及音頻或脈沖信號的識別,用戶線是否有話機的識別,語音信號的2/4線混合轉換,外接振鈴繼電器驅動輸出。MH88612C用戶電路的雙向傳輸衰耗均為-1dB,供電電源+5V和-5V。其各項性能指標符合郵電部制定的有關標准。
(1)該電路的基本特性
1、向用戶饋送鈴流
2、向用戶恆流饋電
3、過壓過流保護
4、被叫用戶摘機自截鈴
5、摘掛機檢測和LED顯示
6、音頻或脈沖撥號檢測
7、振鈴繼電器驅動輸出
8、語音信號的2/4線轉換
9、能識別是否有話機
10、無需偶合變壓器
11、體積小及低功耗
12、極少量外圍器件
13、厚膜混合型工藝
14、封裝形式為20引線單列直插
圖2-2是它的管腳排列圖
(2)MH88612C引出端功能的說明
0腳:IC Internal Connection:空端。
1腳:TF Tip Feed: 連接外接二極體作為保護電路連到-48V和地。。
2腳:IC Internal Connection:空端。
3腳:VR Voice Receive(input): 四線語音信號的接收端。
4腳:VRef Voltage Reference:設置向用戶電話線送恆流饋電的參考電壓,恆流通過VRef調節;也可接地,一般為21mA環流。
5腳:VEE 負供電電源,通常為-5V DC。
6腳:GNDA 供電電源和饋電電源的地端,模擬接地。
7腳:GS Gain setting(input):低電平時直接接收附加增益為-0.5 dB,
此增益除編解碼增益設置之外的,高電平時為0dB。
8腳:VX Voice Transmit(output):四線語音信號的發送端。
9腳:TIP 連接用戶電話的「TIP」線。
10腳:RING 連接用戶電話的「RING」線。
11腳:RF Ring Feed:外部連接至振鈴繼電器。
12腳:VDD 正供電電源,通常為+5V DC。
13腳:RC Relay Control(input)振鈴繼電器控制輸入端,高電平有效
14腳:RD 振鈴繼電器驅動輸出端,外接振鈴繼電器線圈至地端,內部有一線圈感應箝位二極體。
15腳:RV Ring Feed Voltage:用戶線鈴流源輸入端,外部連接至振鈴繼電器。
16腳:VRLY 振鈴繼電器正供電電源,能常為+5V DC。
17腳:IC Internal Connection:空端。
18腳:VBat 用戶線饋電電壓,通常為-48V DC
19腳:CAP 連接外部電容作為振鈴濾波控制連電阻到地。
20腳:SHK 摘掛機狀態檢測及脈沖號碼輸出端,摘機時輸出高電平。
(3)用戶線介面電路主要功能
圖2-3是MH88612C內部電路方框圖,其主要功能說明如下:
TF VR
TIP
RING VX
RF
RV
VRLY
RC
VRef
RD CAP
SHK
圖2-3 MH88612C內部電路方框圖
1、向用戶話機供電,MH88612C可對用戶話機提供恆流饋電,饋電電流由VBAT以及VDD供給。恆定的電流為25 mA。當環路電阻為2KΩ時,饋電電流為18 mA,具體如下:
A、 供電電源VBat採用-48V;
B、 在靜態情況下(不振鈴、不呼叫),-48V電源通過繼電器靜合接點至話機;
C、 在振鈴時,-48V電源通過振鈴支路經繼電器動合接點至話機;
D、 用戶掛機時,話機叉簧下壓饋電迴路斷開,迴路無電流流過;
E、 用戶摘機後,話機叉簧上升,接通饋電迴路(在振鈴時接通振鈴支路)迴路。
2、MH88612C內部具有過壓保護的功能,可以抵抗保護TIP- -RING埠間的瞬時高壓,如結合外部的熱敏與壓敏電阻保護電路,則可保護250V左右高壓。
3、振鈴電路可由外部的振鈴繼電器和用戶電路內部的繼電器驅動電路以及鈴流電源向用戶饋送鈴流:當繼電器控制端(RC端)輸入高電平,繼電器驅動輸出端(RD端)輸出高電平,繼電器接通,此時鈴流源通過與振鈴繼電器連接的15端(RV端)經TIP––RING埠向被叫用戶饋送鈴流。當控制端(RC端)輸入低電平或被叫用戶摘機都可截除鈴流。用戶電路內部提供一振鈴繼電器感應電壓抑制箝位二極體。
4、監視用戶線的狀態變化即檢測摘掛機信號,具體如下:
A、用戶掛機時,用戶狀態檢測輸出端輸出低電平,以向CPU中央集中控制系統表示用戶「閑」;
B、用戶摘機時,用戶狀態檢測輸出端輸出高電平,以向CPU中央集中控制系統表示「忙」;
5、在TIP––RING埠間傳輸的語音信號為對地平衡的雙向語音信號,在四線VR端與VX端傳輸的信號為收發分開的不平衡語音信號。MH88612C可以進行TIP––RING埠與四線VR端和VX端間語音信號的雙向傳輸和2/4線混合轉換。
6、MH88612C可以提供用戶線短路保護:TIP線與RING線間,TIP線與地間,RING線與地間的長時間的短路對器件都不會損壞。
7、MH88612C提供的雙向語音信號的傳輸衰耗均為-dB。該傳輸衰耗可以通過MH88612C用戶電路的內部調整,也可通過外部電路調整;
8、MH88612C的四線埠可供語音信號編解碼器或交換矩陣使用。
由圖1-1可知,本實驗系統共有四個用戶線介面電路,電路的組成與工作過程均一樣,因此只對其中的一路進行分析。
圖2-4是用戶1用戶線介面電路的原理圖:
圖2-4 用戶線介面電路電原理圖
為了簡單和經濟起見,反映用戶狀態的信號一般都是直流信號,當用戶摘機時,用戶環路閉合,有用戶線上有直流電流流過。主叫摘機表示呼叫信號,被叫摘機,則表示應答信號,當用戶掛機時,用戶環路斷開,用戶線上的直流電流也斷開,因此交換機可以通過檢測用戶線上直流電流的有無來區分用戶狀態。
當用戶摘機時,發光二極體D10亮表示用戶已處於摘機狀態,TP13由低電平變成高電平,此狀態送到CPU進行檢測該路是否摘機,當檢測到該路有摘機時,CPU命令撥號音及控制電路送出f=450HZ,U=3V的波形。
此時,在TP12上能檢測到如圖2—5所示波形
TP12
0 2VP-P t
f = 400~450Hz
圖2-5 450Hz撥號音波形
當用戶聽到450HZ撥號音信號時,用戶開始撥電話號碼,雙音多頻號碼檢測電路檢測到號碼時通知CPU進行處理,CPU命令450HZ撥號音發生器停止送撥號音,用戶繼續撥完號碼,CPU檢測主叫所要被叫用戶的號碼後,立即向被叫用戶送振鈴信號,提醒被叫用戶接聽電話,同時向主叫用戶送回鈴音信號,以表示線路能夠接通,當被叫用戶摘機時,CPU接通雙方線路,通信過程建立。一旦接通鏈路,CPU即開始計時,當任一方先掛機,CPU檢測到後,立即向另一方送忙音,以示催促掛機,至此,主、被叫用戶一次通信過程結束。
通過上述簡單分析,不難得出各測量點的波形。
TP11:通信時有發送話音波形;撥號時有瞬間DTMF波形;不通信時則此點無波形。
TP12:通信時有接收話音波形:摘機後撥號前有450HZ撥號音信號;不通信時則此點無波形。
TP13:摘掛機狀態檢測測量點
掛機:TP13=低電平。
摘機:TP13=高電平。
TP14:振鈴控制信號輸入,高電平有效。即工作時為高電平,常態為低電平。
由於4個用戶線介面電路的測量點相同,故對其它三個用戶線介面電路的測量點就不一一敘述,波形均相同,即:
TP11=TP21=TP31=TP41
TP12=TP22=TP32=TP42
TP13=TP23=TP33=TP43
TP14=TP24=TP34=TP44
(二)二\四線變換電路
在該實驗系統中,二\四線變換由用戶線介面電路中的語音單元電路實現,圖2-6為電路的功能框圖,該電路完成二線–––單端之間信號轉換,在MH88612C內部電路中已經完成了該變換。
T
TR
R
圖2-6 二/四線變換功能框圖
二\四線變換的作用就是把用戶線介面電路中的語音模擬信號(TR)通過該電路的轉換分成去話(T)與來話(R),對該電話的要求是:
1、將二線電路轉換成四線電路;
2、信號由四線收端到四線發端要有盡可能大的衰減,衰減越大越好;
3、信號由二線端到四線發端和由四線收端到二線端的衰減應盡可能小,越小越好;
4、應保持各傳輸端的阻抗匹配;
以便於PCM編解碼電路形成發送與接收的數字信號。
五、實驗內容
1、參考有關程式控制交換原理教材中的用戶線介面電路等單節,對照該實驗系統中的電路,了解其電路的組成與工作過程。
2、通過主叫、被叫的摘、掛機操作,了解B、R、S等功能的具體作用。
六、實驗步驟
1. 接上交流電源線。
2. 將K11~K14,K21~K24,K31~K34,K41~K44接2,3腳;K70~K75接2,3腳;K60~K63接2,3腳。
3. 先打開「交流開關」,指示發光二極體亮後,再分別按下直流輸出開關J8,J9,此時實驗箱上的五組電源已供電,各自發光二極體亮。
4. 按「復位」鍵進行一次上電復位,此時,CPU已對系統進行初始化處理,顯示電路循環顯示「P」,即可進行實驗。
5. 用戶1,用戶3接上電話單機。
6. 用戶電話單機的直流供電(B)的觀測。(現以用戶1為例)
1) 用戶1的電話處於掛機狀態,用三用表的直流檔測量TP1A,TP1B對地的電壓,TP1A為-48V,TP1B為0V,它們之間電壓差為48V。
2) 用戶1的電話處於摘機狀態,用三用表的直流檔測量TP1A,TP1B對地的電壓,TP1A為-10V左右(此時的電壓與電話的內阻抗有關,所以每部電話的測量值不一定相同),TP1B為-3.7V左右。
以上給出的電壓值只是作為參考。
7. 觀察二/四線變換的作用。
1) 用正常的呼叫方式,使用戶1、用戶3處於通話狀態。
2) 當用戶1對著電話講話時(或按電話上的任意鍵),用示波器觀察TP11上的波形,為語音信號(或雙音多頻信號),不講話時無信號。
3) 當用戶1聽到用戶3講話時(或用戶3按電話上任意鍵),用示波器觀察TP12上的波形,為語音信號(或雙音多頻信號),對方不講話時無信號。
4) 用示波器觀察TP1A。不管是用戶1講話還是用戶3講話(或按電話上的任意鍵)此測試點都有語音波形(或雙音多頻信號)。
8. 摘、掛機狀態檢測的觀測。
1) 當用戶1的電話摘機時,用示波器測量TP13為高電平(4V左右)。
2) 當用戶1的電話掛機時,用示波器測量TP13為低電平(0V左右)。
9. 被叫話機振鈴(R)的觀測。
1) 用戶1處於掛機狀態,用戶3呼叫用戶1,即用戶3撥打「68」,使用戶1振鈴。
2)當用戶1的電話振鈴時,用示波器觀察TP14,振鈴時TP14為高電平(3V左右);不振鈴時TP14為低電平(0V左右)。
七、實驗注意事項
當實驗過程中出現不正常現象時,請按一下「復位」鍵,以使系統重新啟動。
八、實驗報告要求
1、畫出本次實驗電路方框圖,並能說出其工作過程。
2、畫出各測量點在各種情況下的波形圖。
④ 通信原理實驗 pcm編解碼系統有哪些部分組成
抽樣定理在通信系統、信息傳輸理論方面佔有十分重要的地位。抽樣過程是模擬信號數字化的第一步,抽樣性能的優劣關繫到通信設備整個系統的性能指標。
利用抽樣脈沖把一個連續信號變為離散時間樣值的過程稱為抽樣,抽樣後的信號稱為脈沖調幅(PAM)信號。
⑤ pcm 編解碼晶元中的用到哪些濾波器這些濾波器的帶寬設置是如何考慮 的
1. 點到點PCM多路電話通信原理
脈沖編碼調制(PCM)技術與增量調制(ΔM)技術已經在數字通信系統中得到廣泛應用。當信道雜訊比較小時一般用PCM,否則一般用ΔM。目前速率在155MB以下的准同步數字系列(PDH)中,國際上存在A解和μ律兩種PCM編解碼標准系列,在155MB以上的同步數字系列(SDH)中,將這兩個系列統一起來,在同一個等級上兩個系列的碼速率相同。而ΔM在國際上無統一標准,但它在通信環境比較惡劣時顯示了巨大的優越性。
點到點PCM多路電話通信原理可用圖9-1表示。對於基帶通信系統,廣義信道包括傳輸媒質、收濾波器、發濾波器等。對於頻帶系統,廣義信道包括傳輸媒質、調制器、解調器、發濾波器、收濾波器等。
本實驗模塊可以傳輸兩路話音信號。採用TP3057編譯器,它包括了圖9-1中的收、發低通濾波器及PCM編解碼器。編碼器輸入信號可以是本實驗模塊內部產生的正弦信號,也可以是外部信號源的正弦信號或電話信號。本實驗模塊中不含電話機和混合電路,廣義信道是理想的,即將復接器輸出的PCM信號直接送給分接器。
2. PCM編解碼模塊原理
本模塊的原理方框圖圖9-2所示,電原理圖如圖9-3所示(見附錄),模塊內部使用+5V和-5V電壓,其中-5V電壓由-12V電源經7905變換得到。
圖9-2 PCM編解碼原理方框圖
該模塊上有以下測試點和輸入點:
• BS PCM基群時鍾信號(位同步信號)測試點
• SL0 PCM基群第0個時隙同步信號
• SLA 信號A的抽樣信號及時隙同步信號測試點
• SLB 信號B的抽樣信號及時隙同步信號測試點
• SRB 信號B解碼輸出信號測試點
• STA 輸入到編碼器A的信號測試點
• SRA 信號A解碼輸出信號測試點
• STB 輸入到編碼器B的信號測試點
• PCM PCM基群信號測試點
• PCM-A 信號A編碼結果測試點
• PCM-B 信號B編碼結果測試點
• STA-IN 外部音頻信號A輸入點
• STB-IN 外部音頻信號B輸入點
本模塊上有三個開關K5、K6和K8,K5、K6用來選擇兩個編碼器的輸入信號,開關手柄處於左邊(STA-IN、STB-IN)時選擇外部信號、處於右邊(STA-S、STB-S)時選擇模塊內部音頻正弦信號。K8用來選擇SLB信號為時隙同步信號SL1、SL2、SL5、SL7中的某一個。
圖9-2各單元與電路板上元器件之間的對應關系如下:
•晶振 U75:非門74LS04;CRY1:4096KHz晶體
•分頻器1 U78:A:U78:D:觸發器74LS74;U79:計數器74LS193
•分頻器2 U80:計數器74LS193;U78:B:U78:D:觸發器74LS74
•抽樣信號產生器 U81:單穩74LS123;U76:移位寄存器74LS164
•PCM編解碼器A U82:PCM編解碼集成電路TP3057(CD22357)
•PCM編解碼器B U83:PCM編解碼集成電路TP3057(CD22357)
•幀同步信號產生器 U77:8位數據產生器74HC151;U86:A:與門7408
•正弦信號源A U87:運放UA741
•正弦信號源B U88:運放UA741
•復接器 U85:或門74LS32
晶振、分頻器1、分頻器2及抽樣信號(時隙同步信號)產生器構成一個定時器,為兩個PCM編解碼器提供2.048MHz的時鍾信號和8KHz的時隙同步信號。在實際通信系統中,解碼器的時鍾信號(即位同步信號)及時隙同步信號(即幀同步信號)應從接收到的數據流中提取,方法如實驗五及實驗六所述。此處將同步器產生的時鍾信號及時隙同步信號直接送給解碼器。
由於時鍾頻率為2.048MHz,抽樣信號頻率為8KHz,故PCM-A及PCM-B的碼速率都是2.048MB,一幀中有32個時隙,其中1個時隙為PCM編碼數據,另外31個時隙都是空時隙。
PCM信號碼速率也是2.048MB,一幀中的32個時隙中有29個是空時隙,第0時隙為幀同步碼(×1110010)時隙,第2時隙為信號A的時隙,第1(或第5、或第7 —由開關K8控制)時隙為信號B的時隙。
本實驗產生的PCM信號類似於PCM基群信號,但第16個時隙沒有信令信號,第0時隙中的信號與PCM基群的第0時隙的信號也不完全相同。
由於兩個PCM編解碼器用同一個時鍾信號,因而可以對它們進行同步復接(即不需要進行碼速調整)。又由於兩個編碼器輸出數據處於不同時隙,故可對PCM-A和PCM-B進行線或。本模塊中用或門74LS32對PCM-A、PCM-B及幀同步信號進行復接。在解碼之前,不需要對PCM進行分接處理,解碼器的時隙同步信號實際上起到了對信號分路的作用。
3. TP3057簡介
本模塊的核心器件是A律PCM編解碼集成電路TP3057,它是CMOS工藝製造的專用大規模集成電路,片內帶有輸出輸入話路濾波器,其引腳及內部框圖如圖9-4、圖9-5所示。引腳功能如下:
圖9-4 TP3057引腳圖
(1) V一 接-5V電源。
(2) GND 接地。
(3) VFRO 接收部分濾波器模擬信號輸出端。
(4) V+ 接+5V電源。
(5) FSR 接收部分幀同信號輸入端,此信號為8KHz脈沖序列。
(6) DR 接收部分PCM碼流輸入端。
(7) BCLKR/CLKSEL 接收部分位時鍾(同步)信號輸入端,此信號將PCM碼流在FSR上升沿後逐位移入DR端。位時鍾可以為64KHz到2.048MHz的任意頻率,或者輸入邏輯「1」或「0」電平器以選擇1.536MHz、1.544MHz或2.048MHz用作同步模式的主時鍾,此時發時鍾信號BCLKX同時作為發時鍾和收時鍾。
(8) MCLKR/PDN 接收部分主時鍾信號輸入端,此信號頻率必須為1.536MHz、1.544MHz或2.048MHz。可以和MCLKX非同步,但是同步工作時可達到最佳狀態。當此端接低電平時,所有的內部定時信號都選擇MCLKX信號,當此端接高電平時,器件處於省電狀態。
(9) MCLKX 發送部分主時鍾信號輸入端,此信號頻率必須為1.536MHz、1.544MHz或2.048MHz。可以和MCLKR非同步,但是同步工作時可達到最佳狀態。
(10) BCLKX 發送部分位時鍾輸入端,此信號將PCM碼流在FSX信號上升沿後逐位移出DX端,頻率可以為64KHz到2.04MHz的任意頻率,但必須與MCLKX同步。
圖9-5 TP3057內部方框圖
(11) DX 發送部分PCM碼流三態門輸出端。
(12) FSX 發送部分幀同步信號輸入端,此信號為8KHz脈沖序列。
(13) TSX 漏極開路輸出端,在編碼時隙輸出低電平。
(14) GSX 發送部分增益調整信號輸入端。
(15) VFXi- 發送部分放大器反向輸入端。
(16) VFXi+ 發送部分放大器正向輸入端。
TP3057由發送和接收兩部分組成,其功能簡述如下。
發送部分:
包括可調增益放大器、抗混淆濾波器、低通濾波器、高通濾波器、壓縮A/D轉換器。抗混淆濾波器對采樣頻率提供30dB以上的衰減從而避免了任何片外濾波器的加入。低通濾波器是5階的、時鍾頻率為128MHz。高通濾波器是3階的、時鍾頻率為32KHz。高通濾波器的輸出信號送給階梯波產生器(采樣頻率為8KHz)。階梯波產生器、逐次逼近寄存器(S•A•R)、比較器以及符號比特提取單元等4個部分共同組成一個壓縮式A/D轉換器。S•A•R輸出的並行碼經並/串轉換後成PCM信號。參考信號源提供各種精確的基準電壓,允許編碼輸入電壓最大幅度為5VP-P。
發幀同步信號FSX為采樣信號。每個采樣脈沖都使編碼器進行兩項工作:在8比特位同步信號BCLKX的作用下,將采樣值進行8位編碼並存入逐次逼近寄存器;將前一采樣值的編碼結果通過輸出端DX輸出。在8比特位同步信號以後,DX端處於高阻狀態。
接收部分:
包括擴張D/A轉換器和低通濾波器。低通濾波器符合AT&T D3/D4標准和CCITT建議。D/A轉換器由串/並變換、D/A寄存器組成、D/A階梯波形成等部分構成。在收幀同步脈沖FSR上升沿及其之後的8個位同步脈沖BCLKR作用下,8比特PCM數據進入接收數據寄存器(即D/A寄存器),D/A階梯波單元對8比特PCM數據進行D/A變換並保持變換後的信號形成階梯波信號。此信號被送到時鍾頻率為128KHz的開關電容低通濾波器,此低通濾波器對階梯波進行平滑濾波並對孔徑失真(sinx)/x進行補嘗。
在通信工程中,主要用動態范圍和頻率特性來說明PCM編解碼器的性能。
動態范圍的定義是解碼器輸出信噪比大於25dB時允許編碼器輸入信號幅度的變化范圍。PCM編解碼器的動態范圍應大於圖9-6所示的CCITT建議框架(樣板值)。
當編碼器輸入信號幅度超過其動態范圍時,出現過載雜訊,故編碼輸入信號幅度過大時量化信噪比急劇下降。TP3057編解碼系統不過載輸入信號的最大幅度為5VP-P。
由於採用對數壓擴技術,PCM編解碼系統可以改善小信號的量化信噪比,TP3057採用A律13折線對信號進行壓擴。當信號處於某一段落時,量化雜訊不變(因在此段落內對信號進行均勻量化),因此在同一段落內量化信噪比隨信號幅度減小而下降。13折線壓擴特性曲線將正負信號各分為8段,第1段信號最小,第8段信號最大。當信號處於第一、二段時,量化雜訊不隨信號幅度變化,因此當信號太小時,量化信噪比會小於25dB,這就是動態范圍的下限。TP3057編解碼系統動態范圍內的輸入信號最小幅度約為0.025Vp-p。
常用1KHz的正弦信號作為輸入信號來測量PCM編解碼器的動態范圍。
圖9-6 PCM編解碼系統動態范圍樣板值
語音信號的抽樣信號頻率為8KHz,為了不發生頻譜混疊,常將語音信號經截止頻率為3.4KHz的低通濾波器處理後再進行A/D處理。語音信號的最低頻率一般為300Hz。TP3057編碼器的低通濾波器和高通濾波器決定了編解碼系統的頻率特性,當輸入信號頻率超過這兩個濾波器的頻率范圍時,解碼輸出信號幅度迅速下降。這就是PCM編解碼系統頻率特性的含義。
四、實驗步驟
1. 熟悉PCM編解碼單元工作原理,開關K9接通8KHz(置為1000狀態),開關K8置為SL1(或SL5、SL7),開關K5、K6分別置於STA-S、STB-S端,接通實驗箱電源。
2. 用示波器觀察STA、STB,調節電位器R19(對應STA)、R20(對應STB),使正弦信號STA、STB波形不失真(峰峰值小於5V)。
3. 用示波器觀察PCM編碼輸出信號。
示波器CH1接SL0,(調整示波器掃描周期以顯示至少兩個SL0脈沖,從而可以觀察完整的一幀信號)CH2分別接SLA、PCM-A、SLB、PCM-B以及PCM,觀察編碼後的數據所處時隙位置與時隙同步信號的關系以及PCM信號的幀結構(注意:本實驗的幀結構中有29個時隙是空時隙,SL0、SLA及SLB的脈沖寬度等於一個時隙寬度)。
開關K8分別接通SL1、SL2、SL5、SL7,觀察PCM基群幀結構的變化情況。
4. 用示波器觀察PCM解碼輸出信號
示波器的CH1接STA,CH2接SRA,觀察這兩個信號波形是否相同(有相位差)。
5. 用示波器定性觀察PCM編解碼器的動態范圍。
開關K5置於STA-IN端,將低失真低頻信號發生器輸出的1KHz正弦信號從STA-IN輸入到TP3057(U82)編碼器。示波器的CH1接STA(編碼輸入),CH2接SRA(解碼輸出)。將信號幅度分別調至大於5VP-P、等於5VP-P,觀察過載和滿載時的解碼輸出波形。再將信號幅度分別衰減10dB、20dB、30dB、40dB、45dB、50dB,觀察解碼輸出波形(當衰減45dB以上時,解碼輸出信號波形上疊加有較明顯的雜訊)。
也可以用本模塊上的正弦信號源來觀察PCM編解碼系統的過載雜訊(只要將STA-S或STB-S信號幅度調至5VP-P以上即可),但必須用專門的信號源才能較方便地觀察到動態范圍。
⑥ 求助能夠實現LDPC編解碼的c語言程序,急用,謝謝!
我回答你的問題啊!呵呵,你怎麼不給分啊????實驗命令:clc;clear all;
N=input('N=');%輸入信源符號的個數
s=0;l=0;H=0;
for i=1:N
fprintf('第%d個',i);
p(i)=input('p=');%輸入信源符號概率分布矢量,p(i)<1
if p(i)<=0
error('不符合概率分布')
end
s=s+p(i)
H=H+(- p(i)*log2(p(i)));%計算信源信息熵
end
if (s<=0.999999||s>=1.000001)
error('不符合概率分布')
end
tic;
for i=1:N-1 %按概率分布大小對信源排序
for j=i+1:N
if p(i)<p(j)
m=p(j);p(j)=p(i);p(i)=m;
end
end
end
x=f1(1,N,p,1);
for i=1:N %計算平均碼長
L(i)=length(find(x(i,:)));
l=l+p(i)*L(i);
end
n=H/l; %計算編碼效率
fprintf('按概率降序排列的碼字:\n');
disp(x) %顯示按概率降序排列的碼字
fprintf('平均碼長:\n');
disp(l)% 顯示平均碼長
fprintf('信源信息熵:\n');
disp(H)%顯示信源信息熵
fprintf('編碼效率:\n');
disp(n) %顯示編碼效率
fprintf('計算耗時time= %f\n',toc);
再建立兩個M文件:%函數f1存放於f1.m
function x=f1(i,j,p,r)
global x;
x=char(x);
if(j<=i)
return;
else
q=0;
for t=i:j %對於區間[i,j]自上而下求累加概率值
q=p(t)+q;y(t)=q;
end
for t=i:j%把所有自上而下的累加概率值與該區間總概率值減該累加概率值之差取絕對值存在一數組
v(t)=abs(y(t)-(q-y(t)));
end
for t=i:j
if(v(t)==min(v)) %求該數組中最小的一個值來確定分界點位置
for k=i:t %賦值碼字
x(k,r)='0';
end
for k=(t+1):j
x(k,r)='1';
end
d=t;
f1(i,d,p,r+1); %遞歸調用及相互調用
f2(d+1,j,p,r+1);
f1(d+1,j,p,r+1);
f2(i,d,p,r+1);
else
end
end
end
return;第二個:%函數f2存放於f2.m
function x=f2(i,j,p,r)
global x;
x=char(x);
if(j<=i)
return;
else
q=0;
for t=i:j %對於區間[i,j]自上而下求累加概率值
q=p(t)+q;y(t-i+1)=q;
end
for t=1:j-(i-1)%把所有自上而下的累加概率值與該區間總概率值減該累加概率值之差取絕對值存在一數組
v(t)=abs(y(t)-(q-y(t)));
end
for t=1:j-(i-1)
if(v(t)==min(v)) %求該數組中最小的一個值來確定分界點位置
d=t+i-1;
for k=i:d %賦值碼字
x(k,r)='0';
end
for k=(d+1):j
x(k,r)='1';
end
f2(d+1,j,p,r+1);%遞歸調用及相互調用
f1(i,d,p,r+1);
f2(i,d,p,r+1);
f1(d+1,j,p,r+1);
else
end
end
end
return;
⑦ 哈夫曼編碼與解碼
使用說明:首先建立哈夫曼樹,輸入你的信號源的個數,然後輸入每個信號的符號及其相應的頻率(最後乘以100不要出現小數的為好)我的輸入文件名為Myinput.txt即在C盤下建立文本文檔取名為Myinput.txt然後輸入你的信號的符號以空格結束,最後按提示選擇你需要實現的功能!
/********************************************************************
created: 2010/07/01
created: 1:7:2010 17:53
filename: D:\Program Files\Microsoft Visual Studio\MyProjects\課程設計\HuffmanTree.cpp
file path: D:\Program Files\Microsoft Visual Studio\MyProjects\課程設計
file base: HuffmanTree
file ext: cpp
author: xiezhong
purpose:
*********************************************************************/
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
typedef struct{
int weight;
int parent;
int lchild;
int rchild;
}HTNode,*HuffmanTree;
typedef char **HuffmanCode;
int minl(HuffmanTree t,int i);
void HuffmanCoding(HuffmanTree *HT,HuffmanCode *HC,int *w,int n);
void select(HuffmanTree t,int i,int *s1,int *s2);
void main(){
HuffmanTree HT;
HuffmanCode HC;
int *w,n,i;
cout<<"請輸入字元的個數:"<<endl;
cin>>n;
char *ch;
ch=(char *)malloc((n+1)*sizeof(char));
w=(int *)malloc(n*sizeof(int));
for (i=0;i<n;i++)
{
cout<<"請輸入字元以及對應的權值(中間以空格隔開):"<<endl;
cin>>ch[i+1];
cin>>w[i];
}//給w賦值。
HuffmanCoding(&HT,&HC,w,n);
cout<<"*******哈夫曼樹已經建成啦!*********"<<endl;
cout<<"===================================="<<endl;
while (true)
{
cout<<" 1:將哈夫曼樹存入Huffmancode文件中"<<endl;
cout<<" 2:從Myinput文件中讀取字元然後編碼存入codemyinput文件中;"<<endl;
cout<<" 3:從codemyinput讀取編碼輸入到頻幕上。"<<endl;
cout<<" 4:將codemyinput讀取編碼解碼後存檔。"<<endl;
cout<<" 0:退出系統!!!!"<<endl;
cout<<" 請輸入你的選擇:"<<endl;
int c;
cin>>c;
if (c==0)
{
cout<<"程序已經結束!謝謝使用!!!"<<endl;
break;
}
while(c>4||c<0)
{
cout<<"你輸入有誤請重新輸入:"<<endl;
cin>>c;
}
fstream file;
ofstream outfile;
ifstream printfile;
ifstream codefile;
ofstream textfile;
if(c==1){
file.open("c:\\Huffmancode.txt", ios::out);
if(!file)
{
cout<<"can not open output file."<<endl;
exit(1);
}
for(i=1;i<=n;i++){
file<<ch[i]<<"的編碼是:"<<HC[i]<<endl;
} //將哈夫曼樹存入Huffmancode文件中去、
file.close();
cout<<"哈夫曼樹已經存入Huffmancode文件中"<<endl;
cout<<"\n______________________"<<endl;
}
if(c==2){
file.open("c:\\Myinput.txt",ios::in);//從文件Myinput中讀取字元。
outfile.open("c:\\codemyinput.txt",ios::out);
//將讀取出的字元進行編碼存入codemyinput文件中去、
char read;
cout<<"從Myinput文件中讀取的數據為:"<<endl;
while(!file.eof()){
file.get(read);
cout<<read;
for(i=1;i<=n;i++)
{
if(ch[i]==read)
{
// outfile<<read<<"的哈弗曼編碼為:";
outfile<<HC[i];//將對應字元的編碼輸出到文件中。
break;
}
}
if(i>n)
{
outfile<<read;
}
}//讀取文件完畢
outfile.close();
file.close();
cout<<"\n______________________"<<endl;
}
if(c==3){
printfile.open("c:\\codemyinput.txt",ios::in);
int count=0;
char c;
cout<<"\n這些字母對應的哈夫曼編碼是:"<<endl;
while (!printfile.eof())
{
printfile.get(c);
cout<<c;
if (count%50==0&&count!=0)
{
cout<<endl;
}
count++;
}
cout<<endl;
printfile.close();
}
if(c==4){
codefile.open("c:\\codemyinput.txt",ios::in);
textfile.open("c:\\textfile.txt",ios::out);
int flag=2*n-1;
char read;
codefile.get(read);
while(!codefile.eof())
{
//cout<<read;
if(read=='0'||read=='1')
{
while(true)
{
if(flag>=1&&flag<=n) //判斷停止的條件
{
textfile<<ch[flag];
break;
}
else if(read=='0')
{
flag=HT[flag].lchild;
}
else
{
flag=HT[flag].rchild;
}
codefile.get(read);
}
}
else
{
textfile<<read;
codefile.get(read);
}
flag=2*n-1;
}
codefile.close();
textfile.close();
}
}//while循環結束的括弧。
}
int minl(HuffmanTree t,int i)
{
int a,j,flag;
int k=1000;
for(a=1;a<=i;a++)
{
if(!t[a].parent)
{
flag=a;
break;
}
}
for(j=a;j<=i;j++)
{
if(t[j].parent==0&&t[j].weight<k)
{
k=t[j].weight;
flag=j;
}
}
t[flag].parent=1; //這是必須的
return flag;
}
void Select(HuffmanTree t,int i,int *s1,int *s2)
{
int j;
*s1=minl(t,i);
*s2=minl(t,i);
if(*s1>*s2)
{
j=*s1;
*s1=*s2;
*s2=j;
}
}
void HuffmanCoding(HuffmanTree *HT,HuffmanCode *HC,int *w,int n){
if(n<=1)
return;
int s1,s2,start;
char *cd=NULL;
int m=2*n-1;
*HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
HuffmanTree p;
int i,c,f;
for(p=(*HT)+1,i=1;i<=n;i++,p++,w++){
(*p).weight=*w;
(*p).parent=0;
(*p).rchild=0;
(*p).lchild=0;
}
for(;i<=m;i++,p++){
(*p).weight=0;
(*p).parent=0;
(*p).rchild=0;
(*p).lchild=0;
}
for(i=n+1;i<=m;i++){
Select(*HT,i-1,&s1,&s2);//找出兩個權值最小的節點s1,s2.
(*HT)[s1].parent=i;
(*HT)[s2].parent=i;
(*HT)[i].lchild=s1;
(*HT)[i].rchild=s2;
(*HT)[i].weight=(*HT)[s1].weight+(*HT)[s2].weight;
}
(*HC)=(HuffmanCode)malloc((n+1)*sizeof(char *));
cd=(char *)malloc(n*sizeof(char));
cd[n-1]='\0';
for(i=1;i<=n;i++){
start=n-1;
for(c=i,f=(*HT)[i].parent;f!=0;c=f,f=(*HT)[f].parent)
if((*HT)[f].lchild==c){
cd[--start]='0';
}
else{
cd[--start]='1';
}
(*HC)[i]=(char *)malloc((n-start)*sizeof(char));
strcpy((*HC)[i],&cd[start]);
}
free(cd);
}
⑧ PCM編解碼系統由哪些部分構成各部分的作用是什麼
PCM
編解碼系統由哪些部分構成
?
各部分的作用是什麼
?
回答:
其中,低通濾波器:把話音信號帶寬限制為
3.4KHz
,把高於這個頻率的信號過濾掉。
抽樣:
對模擬信號以其信號帶寬
2
倍以上的頻率進行周期性的掃描,
把時間上連續的信號變
成時間上離散的信號。
量化:把經抽樣得到的瞬時值進行幅度離散化,即指定
M
個規定的電平,把抽樣值用最接
近的電平標示。
編碼:用二進制碼組表示有固定電平的量化值。
解碼:與編碼器的作用相反,把收到的
PCM
信號還原成相應的
PAM
信號,實現數模變換
⑨ PAM 教程:二、Linux-PAM 的配置文件
本系列講解了 Linux-PAM 的工作機制和配置方式,並利用幾個 Linux-PAM 模塊做一些有趣的小實驗。附錄中介紹了一些常用的 Linux-PAM 模塊。
本文的目標讀者是期望了解 PAM 認證機制的 Linux 用戶或者系統管理員。如果您是開發人員,希望編寫一個使用 PAM 認證的應用程序,或者是為 PAM 寫插件的開發人員,本文的內容可能並不能滿足您的需求,請參閱 《Linux-PAM應用開發指南》 (英文)和 《Linux-PAM 模塊開發指南》 (英文)。
PAM 的各個模塊一般存放在 /lib/security/ 或 /lib64/security/ 中,以動態庫文件的形式存在(可參閱 dlopen(3) ),文件名格式一般為 pam_*.so 。PAM 的配置文件可以是 /etc/pam.conf 這一個文件,也可以是 /etc/pam.d/ 文件夾內的多個文件。如果 /etc/pam.d/ 這個文件夾存在,Linux-PAM 將自動忽略 /etc/pam.conf 。
/etc/pam.conf 類型的格式如下:
/etc/pam.d/ 類型的配置文件通常以每一個使用 PAM 的程序的名稱來命令。比如 /etc/pam.d/su , /etc/pam.d/login 等等。還有些配置文件比較通用,經常被別的配置文件引用,也放在這個文件夾下,比如 /etc/pam.d/system-auth 。這些文件的格式都保持一致:
不難看出,文件夾形式的配置文件中只是沒有了服務名稱這一列:服務名稱已經是文件名了。
由於很難在時下的發行版本中找到使用 /etc/pam.conf 這一獨立文件作為 PAM 配置的例子,此處僅就 /etc/pam.d/ 格式舉例。在筆者安裝的 CentOS(x64) 7.2.1511 中, /etc/pam.d/login 的內容如下:
# 表示注釋。
每一行代表一條規則。但也可以用 \ 來放在行末,來連接該行和下一行。
例子的最後一行開頭有一個短橫線 - ,意思是如果找不到這個模塊,導致無法被載入時,這一事件不會被記錄在日誌中。這個功能適用於那些認證時非必需的、安裝時可能沒被安裝進系統的模塊。
我們在[第一篇]({% post_url 2016-03-30-pam-tutorial-1-intro %})中接觸了 Linux-PAM 的四種工作類別(type)。在上面的例子中,工作類別作為第一列出現。
講到這里,我們有必要聊一聊 PAM 的 流程棧(stack) 概念:它是認證時執行步驟和規則的堆疊。在某個服務的配置文件中,它體現在了配置文件中的自上而下的執行順序中。棧是可以被引用的,即在一個棧(或者流程)中嵌入另一個棧。我們之後和它會有更多的接觸。
第二列為 控制模式(control) ,用於定義各個認證模塊在給出各種結果時 PAM 的行為,或者調用在別的配置文件中定義的認證流程棧。該列有兩種形式,一種是比較常見的「關鍵字」模式,另一種則是用方括弧( [] )包含的「返回值=行為」模式。
「關鍵字」模式下,有以下幾種控制模式:
「返回值=行為」模式則更為復雜,其格式如下:
其中, valueN 的值是各個認證模塊執行之後的返回值。有 success 、 user_unknown 、 new_authtok_reqd 、 default 等等數十種。其中, default 代表其他所有沒有明確說明的返回值。返回值結果清單可以在 /usr/include/security/_pam_types.h 中找到,也可以查詢 pam(3) 獲取詳細描述。
流程棧中很可能有多個驗證規則,每條驗證的返回值可能不盡相同,那麼到底哪一個驗證規則能作為最終的結果呢?這就需要 actionN 的值來決定了。 actionN 的值有以下幾種:
我們在前文中已經介紹了控制模式(contro)的「關鍵字」模式。實際上,「關鍵字」模式可以等效地用「返回值=行為」模式來表示。具體的對應如下:
正如前文所述,模塊一般保存在 /lib/security 或 /lib64/security 中(取決於操作系統位數)。Linux-PAM 配置文件中的模塊位置可以是相對於上述文件夾的相對路徑,也可以是文件的全路徑。
模塊參數用空格與模塊路徑相隔。該參數將只和特定模塊相關,因此某個模塊的文檔中一定包含其參數的信息。如果需要在單個參數中使用空格,可以將整個參數用方括弧( [] )包裹起來。