例のアレが出来たのでもう少しオプションつけようの記事からさらにいろんな機能をつけた。
Javaの受信側がうまくいかないから結構大変だったぞ。
写真を載せるのめんどくさいので、主要な機能を掲載する。
1.プッシュボタンでマイコン動作の切り替え
/* スイッチ回路 */
unsigned char getSwtCnt(){
int chatt;
unsigned char change;
change=0;
/*スイッチによるカウント*/
if(IO.PDRB.BIT.B1==0){
for(chatt=0;;){
if(IO.PDRB.BIT.B1==1){
change=1;
for(chatt=0;chatt<1000;chatt++);
break;
}
if(chatt<10000)
chatt++;
}
}
if(change==1)
swt_cnt++;
return swt_cnt;
}
プッシュボタンは、チャタリングが発生するので
押したときループして、ある値でそのままになり
話したら、ループをして押した信号を立てる。
ボタンを離しただけでもチャタリングが発生することは
力学的にも知ってたのでね。
FPGAの場合は、シフトレジスタを使えば良いけど。
swt_cntは押す度に加算されるようにしてある。
2.割り込み今回使ったのは、内部割込み。
HEWなら割り込みの記述は難しくない。
intprg.cに割り込みを記述するのだ。
私は、RS232Cの受信時だけに使った。
__interrupt(vect=23) void INT_SCI3(void) {
inPacket();
}
unsigned char scanSCI(unsigned char *str){
if(SCI3.SSR.BIT.OER){
SCI3.SSR.BIT.RDRF=0;
SCI3.SSR.BIT.FER=0;
SCI3.SSR.BIT.PER=0;
SCI3.SSR.BIT.OER=0;
pk_cnt=0;
frm_cnt=0;
return 0x0;
}
if(SCI3.SSR.BIT.RDRF){
*str=SCI3.RDR;
return 0xff;
}else
return 0x0;
}
unsigned char printSCI(unsigned char st){
while(!SCI3.SSR.BIT.TDRE) continue;
SCI3.TDR=st;
SCI3.SSR.BIT.TDRE=0;
return 0xff;
}
void inPacket(){
unsigned char flg=0;
flg=scanSCI(&data[pk_cnt]);
if(flg==0xff){
if(pk_cnt==31){
pk_cnt=0;
set[frm_cnt]=data[1];
if(frm_cnt==31)
frm_cnt=0;
else
frm_cnt++;
data[0]=ACK;
printSCI(data[0]);
}else
pk_cnt++;
}
}
void outPacket(unsigned char *st){
int i;
unsigned char flg;
for(i=0;i<32;i++){
flg=printSCI(*st);
if(flg!=0xff)
return ;
st++;
}
}
ACKの送信時は1パケットだけ送るようにしたけどね
内容は、プロトコルに反映させてあるので
どうでもいいさ
重要なのは1パケット受信、送信の関数。
3.Java送信受信これの受信が一番苦労した
まじで意味がわからん動作だが、
キャラクタならともかくバイナリ通信は使い方で前例が無いからな。
とりあえず
BufferedOutputStream
BufferedInputStream
を使ったのだ。
とりあえず、RS232IFのクラスを継承して
送信や受信はそのまま使えるぜ
ただ、受信はオーバーライドで記述がいる
/* RS232Cの通信を行うクラス swing実装用 */
class RS232CIF implements CommPortOwnershipListener, SerialPortEventListener {
protected SerialPort port;
protected CommPortIdentifier portID;
protected BufferedOutputStream writer;
protected BufferedInputStream reader;
protected byte [] receive;
protected JFrame jf;
public RS232CIF(JFrame frame,String portName,int rate,int packet_size){
portID = null;
jf=frame;
receive = new byte[packet_size+4];
try{
// CommPortIdentifier を取得
portID = CommPortIdentifier.getPortIdentifier(portName);
portID.addPortOwnershipListener(this);
}catch(NoSuchPortException ex){
ex.printStackTrace();
System.out.println(ex.getMessage());
new MyDialog(jf, true, "接続先が見つかりません。");
}
try{
// ポートのオープン 1分間でタイムアウト
port = (SerialPort)portID.open("RS232CIF", 60000);
}catch(PortInUseException ex){
// タイムアウトを過ぎた場合
ex.printStackTrace();
System.out.println(ex.getMessage());
new MyDialog(jf, true, "接続がタイムアウトしました。");
}
try {
// 通信条件の設定
port.setSerialPortParams(rate, // 通信速度 9600 baud
SerialPort.DATABITS_8, // データビット 8bit
SerialPort.STOPBITS_1, // ストップビット 1bit
SerialPort.PARITY_NONE); // パリティ なし
// フローコントロールの設定
// ここではフローなし
port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
} catch (UnsupportedCommOperationException ex){
ex.printStackTrace();
System.out.println(ex.getMessage());
new MyDialog(jf, false, "この接続はサポートされていません。");
}
try {
// 出力用の Writer を生成
writer = new BufferedOutputStream(port.getOutputStream());
} catch (IOException ex){
ex.printStackTrace();
System.out.println(ex.getMessage());
new MyDialog(jf, false, "Writerを生成できませんでした。");
}
try {
// SerialPortEvent を受け取るためのリスナの登録
port.addEventListener(this);
} catch(TooManyListenersException ex){
ex.printStackTrace();
System.out.println(ex.getMessage());
new MyDialog(jf, false, "EventListener登録失敗");
}
// Data Available イベントを受け取るようにする
port.notifyOnDataAvailable(true);
try {
// 入力用の Reader を生成
reader = new BufferedInputStream(port.getInputStream());
} catch (IOException ex){
ex.printStackTrace();
System.out.println(ex.getMessage());
new MyDialog(jf, false, "Readerを生成できませんでした。");
}
new MyDialog(jf,true,"ポートを開きました。");
}
public void close(){
port.close();
new MyDialog(jf,false,"ポートを閉じました。");
}
public void submit(byte[] data) throws IOException, InterruptedException {
for(int i=0;i writer.write((int)data[i]);
writer.flush();
}
}
public void ownershipChange(int type) {
switch(type){
case PORT_OWNED :
break;
case PORT_UNOWNED :
break;
case PORT_OWNERSHIP_REQUESTED :
break;
default :
new MyDialog(jf, false, "ポート開閉エラー");
break;
}
}
/* このクラス内での受信処理は記述しない */
public void serialEvent(SerialPortEvent arg0) {}
}
/* フレームを作成し送受信 */
class Luggage extends RS232CIF {
public byte version;
public String lcdData;
public short led1Ctl;
public short led2Ctl;
public short led1Lim;
public short led2Lim;
public byte swtData;
public byte clkSelect;
public byte tcoraData;
public byte tcorbData;
public short timWHData;
public short timWLData;
public boolean adChange;
public boolean flg_end;
public boolean flg_miss;
public final static byte NAF = 0x0;
public final static byte ACK = (byte) 0x10;
public final static byte DTP = (byte) 0x80;
public final static byte RTX = 0x20;
public final static byte None= 0x0;
private byte[] packData;
private JFrame jf;
private int dcnt;
private int rcnt;
private boolean flg_ack;
public Luggage(JFrame frame,String portName, int rate,int packet_size,byte packetVer) {
super(frame,portName, rate,packet_size);
jf=frame;
version=packetVer;
dcnt=0;
rcnt=0;
flg_end=false;
flg_ack=false;
flg_miss=false;
packData = new byte[32];
}
public void submitPacket(byte id){
dcnt=0;
rcnt=0;
packData[0]=id;
flg_end=false;
flg_miss=false;
flg_ack=true;
if(id==DTP){
try {
framing();
} catch (InterruptedException e) {}
}
}
public void framing() throws InterruptedException {
long start,end;
start=System.currentTimeMillis();
while(!flg_end){
Thread.sleep(10);
end=System.currentTimeMillis();
if(flg_ack){
start=System.currentTimeMillis();
if(dcnt packData[1]=(byte) lcdData.charAt(dcnt);
else
packData[1]=None;
packData[2]=None;
packData[3]=None;
packData[4]=None;
packData[5]=clkSelect;
packData[6]=None;
packData[7]=short_byte(timWHData)[0];
packData[8]=short_byte(timWHData)[1];
packData[9]=short_byte(timWLData)[0];
packData[10]=short_byte(timWLData)[1];
packData[11]=None;
packData[12]=None;
if(adChange)
packData[13]=(byte)0x80;
else
packData[13]=None;
packData[14]=None;
packData[15]=tcoraData;
packData[16]=tcorbData;
packData[17]=None;
packData[18]=None;
packData[19]=None;
packData[20]=swtData;
packData[21]=None;
packData[22]=short_byte(led1Ctl)[0];
packData[23]=short_byte(led1Ctl)[1];
packData[24]=short_byte(led2Ctl)[0];
packData[25]=short_byte(led2Ctl)[1];
packData[26]=short_byte(led1Lim)[0];
packData[27]=short_byte(led1Lim)[1];
packData[28]=short_byte(led2Lim)[0];
packData[29]=short_byte(led2Lim)[1];
packData[30]=None;
packData[31]=None;
System.out.println(dcnt+"を送信");
try {
submit(packData);
} catch (IOException e) {
/* 送信失敗時 */
Toolkit.getDefaultToolkit().beep();
new MyDialog(jf,false,"送信失敗");
flg_end=true;
dcnt=0;
return ;
}
flg_ack=false;
}
if((end-start)>=5000)
flg_miss=true;
if(flg_miss){
/* 送信中タイムアウト時 */
Toolkit.getDefaultToolkit().beep();
new MyDialog(jf,false,"タイムアウトしました");
flg_end=true;
dcnt=0;
}
}
if(!flg_miss){
Toolkit.getDefaultToolkit().beep();
new MyDialog(jf,true,"送信完了しました");
dcnt=0;
}
}
public byte[] short_byte(short dat){
byte [] bd = new byte[2];
bd[0]=(byte)((dat&0xff00)>>8);
bd[1]=(byte)(dat&0x00ff);
return bd;
}
public void serialEvent(SerialPortEvent event) {
switch(event.getEventType()) {
case SerialPortEvent.BI:
case SerialPortEvent.OE:
case SerialPortEvent.FE:
case SerialPortEvent.PE:
case SerialPortEvent.CD:
case SerialPortEvent.CTS:
case SerialPortEvent.DSR:
case SerialPortEvent.RI:
case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
// Data Available 以外のイベントは処理しない
break;
case SerialPortEvent.DATA_AVAILABLE:
// Data Available の処理
try {
if(reader.read()==ACK){
while(reader.read()==-1);
dcnt++;
if(dcnt==31)
flg_end=true;
flg_ack=true;
Thread.currentThread().interrupt();
}
System.out.println("受信:"+reader.read()+","+dcnt);
}catch (IOException e){ }
break;
}
}
}
テーマ : 研究者の生活
ジャンル : 学問・文化・芸術