用Arduino做BP機POCSAG編碼程序,配合寶峰5R成功呼響大顧問機,用串口助手發送字符,發送格式a+1234567+b+信息(a=N或P向位,1234567為呼機在7位地址碼,b=1-4,為鈴聲)如:N12345671測試!
Arduino源程序如下:- #define uchar unsigned char
- #define uint unsigned int
- String comdata = "";
- unsigned long addr;
- int PTT = 10; //PTT控制端
- int TX=9;//數據輸出端
- int ys=819;//延時
- unsigned long tem;
- uchar Tx_Num;
- unsigned long calc_bch_and_parity(unsigned long cw_e) //BCH校驗和奇偶校驗函數
- {
- uchar i;
- uchar parity = 0; //奇偶校驗計數
- unsigned long local_cw; //臨時存放數
- local_cw=cw_e;//保存cw_e參數值
- for(i=1;i<=21; i++,cw_e<<=1)
- if (cw_e & 0x80000000) cw_e ^= 0xED200000;
- cw_e=cw_e&0xFFC00000;//保留前10位,BCH校驗值共11位,只保留前10位有效數據
- local_cw |= (cw_e >> 21); //BCH校驗數移至第22位到31位,BCH共10位,并和原始數據相加
- cw_e=local_cw;
- for(i=0; i<31; i++, cw_e<<=1) if(cw_e&0x80000000) parity++;
- if(parity%2) local_cw+=1;//從1至31位判斷為奇數則后面加1補充為偶數
- return local_cw;
-
- }
- unsigned long calc_addr( unsigned long add,uchar fun ) //地址轉換,第1參數為地址,第2參數為功能
- {
- unsigned long adr;
- unsigned long tem;
- Tx_Num=(uchar)(add&0x00000007);//獲取地址發射的幀位次,111位第7幀,后3位地址數據隱藏不發送,接收按幀位還原
- adr=0x00;
- adr=add&0xFFFFFFF8; //去掉地址碼后3位
- adr=adr<<10; //地址左移10位
- tem=0x00;
- tem=fun; //功能位
- tem=tem<<11;//功能位左移11位,功能位為00 01 10 11四種狀態,代表4個地址碼
- adr=adr|tem; //地址碼和功能位合成地址碼;
- return adr;
- }
- void Send_start(unsigned long s)
- {
- uchar i,n;
- unsigned long tem;
- for(i=0; i<20; i++)//發送576個前導10101010101010
- {
- tem=s;
- for (n=0; n<32; n++)
- {
- if(tem&0x80000000)
- {
- digitalWrite(TX,HIGH);
- }
- else
- {
- digitalWrite(TX,LOW);
- }
- delayMicroseconds(ys);//等待延時結束 0.833ms
- tem<<=1;
- }
- }
- }
- void Send_nill()//發送閑置位
- {
- uchar n;
- unsigned long s=0x7A89C197;
- for(n=0; n<32; n++)
- {
- if(s&0x80000000)
- {
- digitalWrite(TX,LOW);
- }
- else
- {
- digitalWrite(TX,HIGH);
- }
- delayMicroseconds(ys);//等待延時結束 0.833ms
- s<<=1;
- }
- }
- void Send_Num(unsigned long s,char npi) //發送數據
- {
- uchar n;
- int xx0,xx1;
- if(npi=='P'){xx1=1;xx0=0;}
- if(npi=='N'){xx1=0;xx0=1;}
- for (n=0; n<32; n++)
- {
- if(s&0x80000000)
- {
- digitalWrite(TX,xx1);
- //Serial.print(xx1);
- }
- else
- {
- digitalWrite(TX,xx0);
- //Serial.print(xx0);
- }
- delayMicroseconds(ys);//等待延時結束 0.833ms
- s<<=1;
- }
- }
- void setup() {
- Serial.begin(9600); //設置波特率為9600,一般是這個波特率
- pinMode(TX,OUTPUT);
- pinMode(PTT,OUTPUT);
- }
- void loop() {
- while (Serial.available() > 0) //讀取串口數據
- {
- comdata += char(Serial.read());
- delay(2);
- }
- if (comdata.length() > 0) //如果有數據進入處理
- {
- String np = comdata.substring(0,1);
- char npzf=toupper(np[0]);
- String ly=comdata.substring(8,9);
- int lyi=ly[0];
- String dz = comdata.substring(1,8); //獲取地址碼
- unsigned long az=dz.toInt(); //地址碼s轉類型
- tem=calc_addr(az,lyi-48); //地址碼移位處理
- addr=calc_bch_and_parity(tem); //地址碼BCH校驗
- String msgdata = comdata.substring(9,200); //截取信息碼內容
- int len = msgdata.length()+10; //獲取信息碼字節長度(+4為了讓長度大于1幀,就不用1個漢字還用做判斷了)
- byte hui[200]={0};
- digitalWrite(PTT,LOW); //對講機ppt
- delay(500); //延時500ms
- unsigned long mess[200]={0}; //信息碼數組
- //信息碼數組元素
- unsigned long msg;
- int ll=0;
- int wz=0;
- if(!(msgdata[0]&0x80)){hui[wz]=0x0f;wz++;}
- for(int i=0;i<len;i++)
- {
- if(!(msgdata[i]&0x80) && msgdata[i-1]&0x80 && i>0){hui[wz]=0x0f;wz++;}
- hui[wz]=msgdata[i];
- wz++;
- if(!(msgdata[i]&0x80) && msgdata[i+1]&0x80){hui[wz]=0x0e;wz++;}
- }
- wz=0;
- int k=1;
- for(int n=0;n<=len;n++)
- {
- for(int j=0;j<7;j++)
- {
- if(hui[wz]&0x01){msg|=0x00000001;}
- msg<<=1;
- hui[wz]>>=1;
- ll++;
- if(ll%20==0)
- {
- msg<<=10;
- msg|=0x80000000;
- mess[k]=calc_bch_and_parity(msg);
- msg=0;
- k++;
- }
- }
- wz++;
- }
- Send_start(0xAAAAAAAA); //發送前言碼
- Send_Num(0x7CD215D8,npzf); //發送同步碼
- mess[0]=addr; //地址碼放入信息碼第一碼字
- for(int j=0;j<120;j++) //循環發送信息碼
- {
- if(mess[j]!=0){Send_Num(mess[j],npzf);} //數組元素不為0的發送
- Serial.println(mess[j],BIN);
- if((j+1)%16==0 && j!=0){Send_Num(0x7CD215D8,npzf);} //每隔8幀發送一個同步碼
- }
- Send_Num(0x7A89C197,npzf); //末尾發送閑置碼
- comdata="";
- msgdata="";
- }
- digitalWrite(PTT,HIGH);
- }
復制代碼
|