【UDPプロトコルモジュール内の動作概要】
TCP/IPスタック内のUDPプロトコルモジュールは、UDPの送受信の処理を
実行する関数群から構成されています。
特にユーザーAPI関数としてユーザーが使う関数群となっており、ユーザー
がUDP通信タスクを作成するときに使う関数です。
全体の構成は下図のようなフローとなっており、いくつかの関数の集まりと
なっています。
まず、初期化の関数Init_UDP()はUDPの全ユーザバッファのクリアを行います。
UDP_Process()がUDP受信のメイン関数で、受信したデータをバッファに
コピーしてバッファを受信処理待ちとします。
UDPisReady()関数は、ユーザーがUDPでの受信があったことを知るための
関数です。
Send_UDP()関数は、UDP通信でユーザーデータを送信するときに使う関数
です。 ユーザーバッファに用意したデータを送信出力します。
Release_UDP()は指定した番号のUDPバッファをクリアし空の状態にします。
UDPで使用するユーザー用バッファの構造は、下図のようになっています。
バッファの個数をMAX_UDP_USRBUFに設定することで増やせます
デフォルトの個数は2個です。
さらにその最大サイズもユーザーの設定が可能で、MAX_UDP_USRSIZEに
最大値をバイト単位で設定します。デフォルト値は64バイトとなっています。
ここでユーザー用に開放しているバッファにはユーザーが直接書き込むことが
可能です。
ユーザーバッファには直接書き込みが
可能。
その最大サイズもユーザーが設定する
【UDPプロトコル通信での使い方】
UDPプロトコルを使ってPICROS配下のアプリケーションを作る場合には、
下記のようにします。
(1) UDPのユーザータスクを作成する。
受信したUDPデータを処理し、必要であればデータを返送する
返送のための関数はあらかじめ用意されている。(Send_UDP(socket))
(2) ユーザータスクをPICROSのタスクとして追加する
タスクリンク用のヘッダファイル(tasklink.h)と、タスクディスパッチテーブル
である(tdt.h)にUDPユーザータスクを追加する。
これでUDP通信アプリケーションが出来ます。
【UDPユーザ処理タスクの作り方】
UDPプロトコルでデータを送受信することで動作するタスクは、ユーザ自身が
作成する必要があります。
このユーザー処理タスクの構成は下記のようにします。
(1) ユーザー関数の定義とそれを含むユーザータスクファイルの作成
ユーザー関数を作成し、C言語のファイルとして格納します。
ファイル名、関数名は自由です。
(2) 受信データの格納されているバッファの番号を取り出す
UDPで送られて来たデータを格納しているバッファの番号を
UDPisReady()関数で取り出します。
☆UDP受信チェック関数のフォーマット
socket = UDPisReady()
socket:受信データのあるバッファの番号(int型)
受信データバッファが無いときは0xFFが返る
(3) ポート番号による処理分岐
ユーザーポートとして、10000から17000を使うこととしています。
そのユーザーポート番号をコマンド番号とする使い方ができます。
そのポート番号は「UDPuser[socket].PORTNO」として格納されて
いますので、それをUDPバッファから取り出してswitch文で分岐します。
☆指定ポート番号
UDPuser[socket].PORTNO に格納
(4) 受信データは UDPuser[socket].user_data[i] に格納されている
UDPでホストから送られて来たデータは配列データとして、UDPバッファ
内の「user_data[i]」に格納されています。
そして格納されているデータ個数は「user_size」として格納されています。
☆ユーザーバッファのフォーマット
格納バッファ名称 UDPuser[socket].user_data[i]
データ個数 UDPuser[socket].user_size
iは変数 socketはUDPバッファ番号
(5) ホストへ送信するときには、Send_UDP(socket)関数を使う
UDPでデバイスから送信する場合には、データを用意してUDPバッファ
に保存してから下記の関数で送信を実行します。
この関数はLANライブラリに用意されているので記述するだけで
大丈夫です。
☆UDP送信関数のフォーマット
Send_UDP (socket)
socket : UDPバッファの番号(int型)
(6) バッファの使用が完了したらバッファ開放
バッファ開放には、Release_UDP(socket)関数を使います。
☆バッファ開放関数のフォーマット
Release_UDP(socket)
socket : UDPバッファの番号(int型)
【実際のアプリ例】
では実際にアプリケーションを作成してみましょう。UDP通信のテスト用の
簡単なアプリケーションを作成してみます。
まず機能は下表のようなものとします。
《UDPテストアプリ機能》
No 機能名 使用ポート 機 能 内 容 1 データ受信
と送信10001 UDP通信で受信したデータ(文字列)を液晶表示器に表示し、
'0'から始まる64文字のASCII文字をUDP通信で返送する。
返送後UDPバッファを開放する。2 データ受信 10002 受信したデータ(文字列)を液晶表示器に表示する。
表示後UDPバッファを開放する。
この機能をPICROSの1つのタスクの形で作成します。 このタスクのリストが
下記です。
(1) 最初に受信バッファ番号を求めます。
UDPisReady()関数を実行すると、受信処理待ちのバッファの番号が
返されますので、これでバッファ番号を入手します。
処理待ちが無いときは0xFFが返されますのでこのときは何もしません。
(2) このバッファ中にあるポート番号を取り出して処理を分岐する。
バッファ番号が求まったら、UDPuser[socket].PORTNOでポート番号が
求められますので、このポート番号で上表のような機能に分岐します。
(3) 各機能の実行
受信したデータは、UDPuser[socket].user_data[i] にありますので
ここから1文字づつ取り出しては液晶表示器に出力します。
(4) データ送信
折り返しにデータ送信がある場合には、送信データをユーザーバッファ
UDPuser[socket].user_data[i]にセットし、データバイト数をやはり
UDPuser[socket].user_sizeにセットしてから、Send_UDP()関数を実行します。
これで送信が自動的に実行されます。
(5) 最後にバッファを開放
バッファを使い終わったら Release_UDP[socket]で指定バッファを
開放します。
☆ユーザーアプリの製作例 ファイル名 udp_task.c
void udp_user(void)
{
int i, socket;
//// UDP使用中フラグチェック
socket = UDPisReady(); //戻り値ソケット番号
if(socket != 0xFF) //空で無いか?
{
//// 使用中のバッファの処理
switch (UDPuser[socket].PORTNO) //ポート番号で分岐
{
case 10001: //<-----ポート番号で処理内容を区別する
lcd_clear();
//// 受信した文字列データの表示
for(i=0; i<UDPuser[socket].user_size; i++)
lcd_data(UDPuser[socket].user_data[i]);
//// 折り返し、0から64文字のASCII文字列を返送
for (i=0; i<63; i++)
UDPuser[socket].user_data[i] = 0x30 + i;
UDPuser[socket].user_data[63] = 0;
UDPuser[socket].user_size = 64;
Send_UDP(socket);
///// バッファの開放
Release_UDP(socket); //release this socket
break;
case 10002:
//// 受信した文字列データの表示
lcd_clear();
for(i=0; i<UDPuser[socket].user_size; i++)
lcd_data(UDPuser[socket].user_data[i]);
Release_UDP(socket); //release this socket
break;
default:
break;
}
}
Exit_Task(); //<--------- これで本タスク終了
}
【PICROSコンフィギュレーション設定】
上記ユーザーアプリのタスクを用意した上で、PICROSでLANライブラリ、
UDPユーザタスクを動作させるためには、下記のPICROSのヘッダファイルで
リンク指定をしてリンクを行います。
(1) PICROSのユーザーコンフィギュレーションでTCP/IPの使用を宣言追加
コンフィギュレーションファイル(usrconf.h)に下記部分を追加する。
これを記述すると、あとは初期化関数やアイドルループでのStackプロセス
の起動など、自動的に追加されます。
////// Define LAN Controller Use ////////////
// If define USE_STACK, then link LAN library
#define USE_STACK //スタックの使用宣言
/////// Define Task ID Name and Priority ////////
#define task_number 5
#define task1 1 //testtsk1()
#define task2 2 //testtsk2()
#define task3 3 //testtsk3()
#define task4 4 //udp_user()
#define task6 6
#define task7 7
#define task8 8
////// task prototyping ////
void testtsk1(void);
void testtsk2(void);
void testtsk3(void);
void udp_user(void); //UDP関数のプロトタイプ
(2) UDPユーザ処理タスクをリンクする。
PICROSの「tasklink.h」にユーザ処理関数のタスクファイルをリンクします。
tsklink.hファイルの作成例は下記のようになります。
《tasklink.hの例》
/////// Task Link //////
#include <testtsk1.c>
#include <testtsk2.c>
#include <testtsk3.c>
#IFDEF USE_UDP
#include <udp_task.c> <--- これがユーザー処理関数のファイル名
#ENDIF
(3) タスクディスパッチテーブルにユーザー処理関数を追加
PICROSの「tdt.h」にユーザー処理関数名の追加をします。この関数が
上記のユーザー処理タスクファイルの中に含まれていることになります。
実際の追加例は下記のようになりますが、この記述順がタスク優先順位と
なります。
《tdt.hの例》
////////// Task Dispatch Tabel /////
dispatch(1,testtsk1())
dispatch(2,testtsk2())
dispatch(3,testtsk3())
#IFDEF USE_UDP
dispatch(4,udp_user()) <--- これがユーザー処理関数名
#ENDIF
【制限事項】
UDPをデータ送受信に使ってユーザー処理をするときには下記の制限が
ありますので守る必要があります。
(1) UDPのデバイス側ポート番号は 10000〜17000 を使うこと。
本来は0〜65535まで使えますが、上記範囲に制限しています。
ホスト側は特に制限していませんが、Well Known Portは使えません。
(2) 一度に送信できるデータ数は送受信とも最大制限があります。
MAX_UDP_USRSIZE以上のデータを指定してもそれ以上は無視されます。
(3) 使えるPICは、PIC18シリーズに限定されています。
現状ではRAM容量制限のため、PIC18シリーズのみで動作可能と
なっています。
(4) 使用言語はCCS社C言語のPCH
PIC用のCコンパイラである、CCS社の中の PIC18用である PCH を
使用してコンパイルするものとしています。
PCHをMPLABに統合した環境にして、MPLABでコンパイル、デバッグ
作業をして下さい。
【LANライブラリソースファイル】
PICROSでUDP通信をするアプリケーション製作例のソースファイルは下記です。
PICROS本体とデバッグ用のライブラリも含んでいます。
MPLAB + PCHコンパイラ の環境を前提にしています。
UDPプロトコルモジュールの部分をポインタを使ってサイズを縮小しました。
その分高速になりました。約1kW小さくなりました。
ソースファイル変更分です。下記のファイルを前バージョンに上書きして下さい。
同じファイル名ですので気をつけて下さい。
★ ポインタを用いてサイズ縮小したUDP部分
ソースファイル1式は下記にあります。圧縮してあります。
★ PICROSとTCP/IPスタックライブラリででUDP通信するデモアプリ
この中には下表のソースファイルが含まれています。
ファイル名 機 能 内 容 概 要 stckdemo.c PICROS本体でTCP/IPスタックデモ用です。
アイドルループ内にStack_Process関数などが追加されています。usrconf.h PICROSのユーザーコンフィギュレーションファイルです。
ここで、Stackの使用を宣言します。tasklink.h
tdt.hPICROSのタスクの追加をするときのコンフィギュレーション
ファイルです。ここにtask名や関数名を追加します。usrini.c ユーザー初期化関数で、物理的な初期化処理を記述します。
最後に最初に起動しておくタスクの起動を行います。
lcd_lib.h
lcd_lib.cPICROSの液晶表示器制御用のライブラリ関数 timer1.c PICROSの基本タイマの割り込み処理関数です。 debug77.c PICROSのデバッグ用の関数ライブラリです。
printf文でデバッグ文を挿入するときには必要です。
使用するときはusrconf.hで指定します。usartrcv.c デバッグ用のUSARTの受信割り込み処理関数です。 testtask1.c
testtask2.c
tetstask3.cPICROSを使ったときのユーザータスク関数です。
ここで実際に実行する処理を記述します。
testtask3は実際には起動していません。udp_task.c UDPのテスト用のタスク関数で、UDPの処理はここに
記述します。