アプリ版:「スタンプのみでお礼する」機能のリリースについて

void outportb(unsigned int portid,unsigned char value){
_asm mov edx,portid
_asm mov al,value
_asm out dx,al


上記のように
outportb関数を定義してコンパイルすると
「問題が発生したため・・・・」
とウィンドウが開いて勝手に終了します。

アセンブラの部分を削除しコンパイルすると
portid,valueの値が1度も使用されていないという警告が出ます。

dos.hをインクルードしても同じ結果でした。

原因はWindows XPはIOポートのアクセスする権限がないから
なのでしょうか?
またC++を使用していますので
C++で解決法あれば教えてください。

A 回答 (8件)

まず、お詫びがあります。



# この部分をお使いになっていないのであれば良いのですが。

> scanf_s("%s", &buffer, 32);
> if(!strncmp(buffer, "yes", 3))

scanf_s("%s", buffer, 32);
if(strncmp(buffer, "yes", 3))

と書くべきをところを間違えておりました。

コンパイラからの警告をなくすということに気をとられて変数が元々
ポインタであることを見落としておりました。
それとコードを短く書き直す時に if 文に「!」が入ったままでした。
誠に申し訳ありませんでした。

# 慌てて回答するのは良くありませんね。(冷汗)

> 私の理解ではこのプログラムは
> input変数で出力電圧をCのピンを使ってデジタルレベル
> (1バイト=256段階)を指定し
> addr変数で電圧を変更するチャンネルをC0~C3のピンで
> 指定するものと思っていました。
> (チャンネル数が一致しないことになりますが)

データシートの波形によればパラレル端子 D0-D6 への出力順序は
ADDR(n-1) → DATA(n) → ADDR(n)

タイミングが

C0 の立ち上り下りで DATA(n) の送信開始
C1 の立ち上り下りで ADDR(n-1)の送信開始、ADDR(n) の送信開始終了

D7 は addr を 0x80 で OR している時と input変数 つまり DATA(n)が
128 以上で立ち上りの状態
(つまり DATA は D0-D7 の 8ビットということです)

というようなことを行っているようですが、私にはこの程度しかわかり
ません。

>1MHzも1秒間に100万回チャンネルにアクセスできる応答スピード
> だと思っていました。

# おそらく意味としては同じなのではないでしょうか?
クロック信号として 1MHz まで出せる能力がある、即ち On/Off が
毎秒100万回(端末によっては)可能であるという意味と思われます。
パラレルポートがその早さでデータの読み書き可能であって制御に
使えるとされているので周波数の高いパルスかと思われるのです。
(今時は 1MHz 程度を高い周波数と言わないと思いますが)

> ご教示いただいた内容ですと、オシロスコープで確認

ソースコードからもわかると思われますが幾度かポートへのデータが
書き出されています。

いい加減なことを申し上げてしまうのはよろしくないので以下のような
確認を致しました。

具体的には例のコードの _outp の部分を下記のような関数を代わりに
呼ぶように置き換えてみました。

※ このコードはかなり適当なので参考にしないでください。
void data_display(unsigned int portid, unsigned char value) {
 char buffer[9];
 int i, temp;
 temp = value;
 memset(buffer, (int)'0', 8);
 buffer[8] = 0;
 for(i = 0; i < 8; i++){
  if(temp & 0x80){
   buffer[i] = '1';
  }
  temp <<= 1;
 }
 printf("%s(0x%04x): 0x%02x(%03d,%s)\n",
  portid & 2 ? "CTRL" : "DATA",
  portid, value, value, buffer);
}

addr 1、input 255 としてみました。
※ データ部分の括弧内は10進数と 2進数です。
--------------------
input___ 255
addr___ 1
** confirmation **
address 1
input 255
are you ready? (yes/no): yes
CTRL(0x037a): 0x02(002,00000010)
DATA(0x0378): 0x80(128,10000000)
CTRL(0x037a): 0x00(000,00000000)
CTRL(0x037a): 0x01(001,00000001)
DATA(0x0378): 0xff(255,11111111)
CTRL(0x037a): 0x00(000,00000000)
CTRL(0x037a): 0x02(002,00000010)
DATA(0x0378): 0x81(129,10000001)
CTRL(0x037a): 0x00(000,00000000)
CTRL(0x037a): 0x02(002,00000010)
DATA(0x0378): 0x01(001,00000001)
CTRL(0x037a): 0x00(000,00000000)
--------------------

addr 31、input 127 としてみました。
--------------------
input___ 127
addr___ 31
** confirmation **
address 31
input 127
are you ready? (yes/no): yes
CTRL(0x037a): 0x02(002,00000010)
DATA(0x0378): 0x80(128,10000000)
CTRL(0x037a): 0x00(000,00000000)
CTRL(0x037a): 0x01(001,00000001)
DATA(0x0378): 0x7f(127,01111111)
CTRL(0x037a): 0x00(000,00000000)
CTRL(0x037a): 0x02(002,00000010)
DATA(0x0378): 0x9f(159,10011111)
CTRL(0x037a): 0x00(000,00000000)
CTRL(0x037a): 0x02(002,00000010)
DATA(0x0378): 0x1f(031,00011111)
CTRL(0x037a): 0x00(000,00000000)
--------------------

上記のようなデータが出力されているようです。
5 行目のところで input に入力した数値が出ていますが、これは一瞬で
終るので最後の電圧しかテスターには表れないのかと思われます。
こうしてみるとなんとなくでも各線のデータ波形とソースコードとの
動作イメージが湧きませんでしょうか?

> ご指摘の通りしばらくはこのまま締め切らにしておきます。

ありがとうございます、おかげさまで私のソースの誤りに気付き訂正
させて頂くことができました。

# 説明が下手なのですがお節介なので……
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
また、お礼が遅くなり申し訳ありません。

>scanf_s("%s", buffer, 32);
>if(strncmp(buffer, "yes", 3))
の部分そのまま使っていましたので、コードを訂正しました。
ご連絡ありがとうございます。


私も入力ミスをしていました。以下の部分でCのピン
と書いていますが、D0~D7と書くつもりでした。
> 私の理解ではこのプログラムは
> input変数で出力電圧をCのピンを使って


実行したプログラム上で、
input変数は電圧値を、addr変数はチャンネル
を設定しているという理解で正しいのでしょうか?

実際に電圧値とチャンネルを設定している
パラレルポートのピンの役割では、
ピンC0とC1のピンを使い、その立ち上がりと下がりによって
変更する方(チャンネル、または、電圧)の切り替えを行い
D0~D7(D7は128以上の場合のみ?)のピンで
それぞれの値(チャンネルなら40まで、電圧なら195まで)を
設定しているということなのでしょうか?


>D7 は addr を 0x80 で OR している時と input変数 つまり DATA(n)
>が128 以上で立ち上りの状態(つまり DATA は D0-D7 の 8ビットということです)
addrを0x80をORしているとは、ビット単位和している時という意味なのでしょうか?


確認のために作っていただいたデータとソースコードを
見比べると動作順序は理解できました。
確認のために作っていただいたプログラムの結果を
3行ずつで区切っていくと、ちょうど、
データシートのC0とC1のパルスの動き(C1→C0→C1→C1)に
追従しているのがわかります。

ただADDR(n-1)とADDR(n)の意味が理解できていませんので、下記のような理解をしてますが、間違っていればご指摘ください。

一回目のC1パルスAddress(0x80 | CurrentAddress)を新しいaddrとinputを入力する際のトリガとして使用し、

2回目のC1パルスAddress(0x80 | addr)でチャンネルの値(ADDR(n)?)を設定し
(これの前にC0パルスで電圧値Data(input)の設定)

3回目のC1パルスAddress(addr)でチャンネルと電圧の入力終了の意味
で使用しているということなのでしょうか?

この仮定があっているとすると、ADDR(n-1)である必要性がわからなくなります。

ハードは分野違いとのことですので、分かるところのみでも
ご回答いただければと思います。
よろしくお願いいたします。

お礼日時:2008/04/17 00:29

> それぞれの値(チャンネルなら40まで、電圧なら195まで)を


> 設定しているということなのでしょうか?

addr がチャンネルであると思いますが、input の値が電圧の 0 から 195 (V) で
あるのかは(私には)わからないです。

# 各チャンネルの最大電圧を 1 として input / 255 のように 256 通りと
# している可能性もあるのでわからないという意味です。
# これは、まず 0 から 195 の範囲で入力して確認なさってみて下さい。

> データシートのC0とC1のパルスの動き(C1→C0→C1→C1)に
> 追従しているのがわかります。
(省略)

データシートのソースコード部分に次のような記述があったと
思いますが A7(D7) をクロックとしているようです。

※ データシートからの引用
> NOTE:
> input is a 0-255 (8-bit) number corresponding to the digital voltage level.
> addr is the channel number.
> The MSB of the address bits (A7) is used as a clock.

※ この A7 はパラレル端子でいうと D7 であって address bits で
  あるので A7 としているのかと思われます。

> ただADDR(n-1)とADDR(n)の意味が理解できていませんので、下記のような
> 理解をしてますが、間違っていればご指摘ください。
(省略)
> 3回目のC1パルスAddress(addr)でチャンネルと電圧の入力終了の意味
> で使用しているということなのでしょうか?

データシートのソースコード(Voltage等)の動作はその通りです。

> この仮定があっているとすると、ADDR(n-1)である必要性がわからなく
> なります。

ソースコードの「void Address(unsigned char input)」という関数に
「CurrentAddress = input; //Save the current address as a global」と
いう記述があったと思いますが

“なぜこの値をグローバル変数として保持している必要があるのか”という
ことを考えると ADDR(n-1) がご理解できるのではないでしょうか?

つまり ADDR(n-1) というのは CurrentAddress の値であり、既にご理解
されている通りデータと出力については次のようになっています。

# ご質問された事項の復唱でしかありませんが。

※ input, addr は main 関数の変数、| はビット理論和、C0、C1、
  D0_D7 がパラレルの端子として、addr の値が 31、input の値が
  127、CurrentAddress が 0 の場合

(1) CurrentAddress (直前の addr) と C1 の出力
CTRL(0x037a): 0x02(002,00000010) C1 = 1
DATA(0x0378): 0x80(128,10000000) D0_D7 = 0x80 | CurrentAddress
CTRL(0x037a): 0x00(000,00000000) C1 = 0

(2) データ(input)と C0 の出力
CTRL(0x037a): 0x01(001,00000001) C0 = 1
DATA(0x0378): 0x7f(127,01111111) D0_D7 = input
CTRL(0x037a): 0x00(000,00000000) C0 = 0

(3) アドレス(addr)と C1 の出力
CTRL(0x037a): 0x02(002,00000010) C1 = 1
DATA(0x0378): 0x9f(159,10011111) D0_D7 = 0x80 | addr
CTRL(0x037a): 0x00(000,00000000) C1 = 0

(4) アドレス(addr)を保持した状態で C1 の出力
CTRL(0x037a): 0x02(002,00000010) C1 = 1
DATA(0x0378): 0x1f(031,00011111) D0_D7 = addr
CTRL(0x037a): 0x00(000,00000000) C1 = 0

連続的或いは次に値を書き込むような場合は input、addr の各変数の
値を変えて (1) に行くような操作であると考えられます。

CurrentAddress がグローバル変数であることや ADDR(n-1) を考えると、
実際の操作(プログラミング)は CurrentAddress (直前に設定した addr の値)を
意識した操作にすべきではないかと考えられます。

# もしかするとハードウェアの実装は ADDR (n-1) のデータはどんな値でも
# かまわないという実装であるのかもしれませんが、これらはハードウェア
# での実装によって異なります、念のためにハードウェアメーカに確認なさ
# って下さい。(申し訳ないのですが、不確実な憶測は危険ですので)

> ハードは分野違いとのことですので、分かるところのみでも
> ご回答いただければと思います。

私がわかるのはご提示されたコード(データシートのコード等)の動作と
ウェブサイトにあったデータシートの図の情報からの推測に過ぎません
ので力量不足で申し訳ないのですが、ここまでだと思います。
コーディングについて他にご不明な点があれば、可能な範囲でのアドバイスは
させて頂けるかとは思います。
    • good
    • 0
この回答へのお礼

># これは、まず 0 から 195 の範囲で入力して確認なさってみて下さい。

確認したところ200Vまでの中で変化していました。



>ソースコードの「void Address(unsigned char input)」という関数>に「CurrentAddress = input; //Save the current address as a
>global」という記述があったと思いますが

(以下省略)

ご説明の内容で動作の原理がよく分かりました。
ありがとうございます。



お礼が遅くなり申し訳ありませんでしたが、
これで、このプログラムの大体の部分はクリアできました。
(というよりも、データシートの解読になってしまいましたが・・・)
最初から最後までの丁寧なご回答があったおかげです。
本当にありがとうございます。

お礼日時:2008/04/30 10:41

> 無事に実行できました。

本当にありがとうございます。

こちらこそありがとうございます、拙いアドバイスで
申し訳ありません。

※ 以下はこのカテゴリーとは関係のない話題となって
  しまいますが。

> ただ、入力した値とパラレールポートの電圧をテスターで
> 計測すると一致しないので動作自体はおかしいようです。

# テスターを単に電圧を計るテスターと仮定しているので、
# ロジアナや二現象以上のオシロスコープなどをテスターと
# 仰られていたのであればご容赦下さい。

おそらく電圧制御の関数を通してしまうと比較的周波数の
高いパルス波形になると考えられます。
その場合は電圧を測定するだけの機能のテスターでは確認が
困難なのではないかと思われます。
実機のデータシートを拝見させて頂いた後に「オシロスコープ
等で波形を確認する必要があります」と申し上げたと……

データシートのこの箇所の記述とその上部の信号波形図からの
推測ですが。

データシートから引用
> The parallel port can be addressed at approximately 1 MHz (depending on the computer)
> making it an excellent choice for simple computer interface.

ハードウェアについての話題はカテゴリも違い、私の知識では
更に力量不足となりますので、カテゴリーを変更されてご質問
されるのがよろしいのではないかと思います。

# しばらくはここも締め切らず、うまく動作されましたら
# 知らせてください。(このサイトの規約違反とならない程度で)
# プログラミングに関することであれば可能な範囲でアドバイス
# させて頂くつもりです。(私では力量不足かもしれませんが)
    • good
    • 0
この回答へのお礼

私の理解では、このプログラムは
input変数で出力電圧をCのピンを使ってデジタルレベル(1バイト=256段階)を指定し
addr変数で電圧を変更するチャンネルをC0~C3のピンで指定するものと思っていました。(チャンネル数が一致しないことになりますが)
1MHzも1秒間に100万回チャンネルにアクセスできる応答スピードだと思っていました。
ですので、実行してinput変数にいれた値ではパラレルポートのピンの電圧は全く変化せず、addr変数に入力した値がD0~D7までの値と一致したのでおかしいと思っていました。

ご教示いただいた内容ですと、オシロスコープで確認する必要なのですね。
オシロスコープで確認すれば、ちゃんと動作していたのを見落としていただけかもしれませんので、時間があき次第試してみます。

何から何までお世話とご意見いただき誠に感謝しております。
ご指摘の通りしばらくはこのまま締め切らにしておきます。
わからないとき、とても心強かったです。
また、問題が出たときに相談いたしますので、
ご指導よろしくお願いいたします。

お礼日時:2008/04/12 03:18

> どうもヘッダーファイル内のエラーのようです。



見た目は VC++ 付属のヘッダーに関してのエラーですが、このようなエラーとなる場合にも
作ったソースに問題があるはずです。

> 手順はVC++2005 Express Editionを立ち上げ→ファイル→新規作成→
> プロジェクト→Win32→Win32コンソールアプリケーション→名前入力→
> OK→アプリケーションウィザード→コンソールアプリケーション→完了
> です。

完了を押される前に出たウィンドウで
「アプリケーションの種類」 コンソールアプリケーション
「追加オプション」 チェックなし
「共通ファイルの設定」 グレイになっていて選択不可
となっていましたでしょうか?

> エラーが回避できるようにヘッダーファイルを調べてみます。

わかっておられると思いますが、VC++ に付属のヘッダーには一切触らないでください。(念のため)

以下は私のほうで試したものです。
プロジェクト名に「VoltageControl」としたのでこのような名前のソースになっています。
コンパイル時に警告も出ないように書き直しました。
outportb は _outp にして、scanf は scanf_s にしてあります。

ファイル: VoltageControl.cpp
---------------------------------------------------------
// VoltageControl.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"

/* global valiable */
int CurrentAddress;

int main()
{
int input, addr;
char buffer[32];
HANDLE hGiveIO = INVALID_HANDLE_VALUE;

printf("input___ ");
scanf_s("%d", &input);

printf("addr___ ");
scanf_s("%d", &addr);

/* confirmation */
printf("** confirmation **\n");
printf("address %d\ninput %d\n", addr, input);
printf("are you ready? (yes/no): ");
scanf_s("%s", &buffer, 32);

if(!strncmp(buffer, "yes", 3))
{
printf("canceled!\n");
return 0;
}

/* open giveio */
#ifdef UNICODE
hGiveIO = CreateFile(L"\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
#else
hGiveIO = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
#endif

if(hGiveIO == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "Can not open GiveIO!\n");
return -1;
}
/* close giveio */
CloseHandle(hGiveIO);

/* call Voltage */
Voltage(input, addr);
return 0;
}

/* To address the control bits(C0-C4)*/
void Control(unsigned char value){_outp((unsigned int)0x037A, value);}

/* To address the parallel port data bits(D0-D7)*/
void Data(unsigned char value){_outp((unsigned int)0x378, value);}

/* To write out an address to the D40DI*/
void Address(unsigned char input){
Control(2); Data(input); Control(0);
CurrentAddress = input; //Save the current address as a global
}

/* To out a voltage to the D40DI*/
void Voltage(int input,int addr){
Address((unsigned char)(0x80 | CurrentAddress)); //Set the MSB on the addr as a clock
Control(1); Data((unsigned char)input); Control(0); //set the data buffer
Address((unsigned char)(0x80 | addr)); //Setup the address
Address((unsigned char)addr); //clock it in
}
---------------------------------------------------------

ファイル: stdafx.h
---------------------------------------------------------
// stdafx.h : 標準のシステム インクルード ファイルのインクルード ファイル、または
// 参照回数が多く、かつあまり変更されない、プロジェクト専用のインクルード ファイル
// を記述します。
//

#pragma once

#ifndef _WIN32_WINNT// Windows XP 以降のバージョンに固有の機能の使用を許可します。
#define _WIN32_WINNT 0x0501// これを Windows の他のバージョン向けに適切な値に変更してください。
#endif

#include <stdio.h>
#include <tchar.h>

// TODO: プログラムに必要な追加ヘッダーをここで参照してください。
#include <conio.h>
#include <string.h>
#include <windows.h>

/* prototype */
void Voltage(int ,int);

---------------------------------------------------------

これでもエラーとなる場合、そのエラーを知らせてください。
    • good
    • 0
この回答へのお礼

>見た目は VC++ 付属のヘッダーに関してのエラーですが、このようなエラーとなる場合にも作ったソースに問題があるはずです。

ご指摘の通りソースに問題がありました。
ご教示のコードと見比べながら直すと、エラーも警告もでなくなり
無事に実行できました。本当にありがとうございます。
ただ、入力した値とパラレールポートの電圧をテスターで計測すると
一致しないので動作自体はおかしいようです。
見直して正常動作するように試みます。


>完了を押される前に出たウィンドウで
「アプリケーションの種類」 コンソールアプリケーション
「追加オプション」 チェックなし
「共通ファイルの設定」 グレイになっていて選択不可
となっていましたでしょうか?

「追加オプション」のみチェックが入っている状態でした。


> outportb は _outp にして、scanf は scanf_s にしてあります。
作り直したソースは同じように_outp、scanf_sに変更しました。

お礼日時:2008/04/11 17:22

> ご教示していただいた手順でビルドするとエラーの種類が変わりました。



これはコンパイラの警告を気になさり過ぎて大幅にコードを書き換え
なされたのでしょうか?

> やはり正しい方法でコンパイルしていない
> もしくはSDKのパスが通っていないのでしょうか?

SDK のインストールで参考になさったサイト通りにコンパイルや動作が
成功しているのであればパスは通っていると思います。

エラーの発生した箇所のコードを見せて頂かないと、エラーの内容だけ
では詳しいことはわかりません。

> 必要な情報として何を記載すればいいのか判断しかねますので指定して
> いただければと思います。

コードに加えて、どういう手順で何をなされたか詳しくお書き下さるとよろしい
かと思います。

# 画面のキャプチャでも見せて頂ければ良いのでしょうけどここでは
# 禁止行為となっているようですので。

この回答への補足

1>c:\program files\microsoft visual studio 8\vc\include\conio.h(23) : error C2598: リンケージ指定子がグローバル スコープで宣言されていません。
1>c:\program files\microsoft visual studio 8\vc\include\conio.h(29) : error C2598: リンケージ指定子がグローバル スコープで宣言されていません。
1>c:\program files\microsoft visual studio 8\vc\include\conio.h(29) : error C2951: テンプレート 宣言は、グローバル、名前空間、またはクラス スコープのみで許可されています
1>c:\program files\microsoft visual studio 8\vc\include\string.h(25) : error C2598: リンケージ指定子がグローバル スコープで宣言されていません。
1>c:\program files\microsoft visual studio 8\vc\include\string.h(72) : error C2598: リンケージ指定子がグローバル スコープで宣言されていません。
1>c:\program files\microsoft visual studio 8\vc\include\string.h(72) : error C2951: テンプレート 宣言は、グローバル、名前空間、またはクラス スコープのみで許可されています
1>c:\program files\microsoft visual studio 8\vc\include\string.h(77) : error C2598: リンケージ指定子がグローバル スコープで宣言されていません。
1>c:\program files\microsoft visual studio 8\vc\include\string.h(77) : error C2951: テンプレート 宣言は、グローバル、名前空間、またはクラス スコープのみで許可されています
1>c:\program files\microsoft visual studio 8\vc\include\string.h(84) : error C2267: 'strnlen_s' : ブロックスコープを伴う関数は、static として宣言できません。
1>c:\program files\microsoft visual studio 8\vc\include\string.h(124) : error C2598: リンケージ指定子がグローバル スコープで宣言されていません。
1>c:\program files\microsoft visual studio 8\vc\include\string.h(124) : error C2951: テンプレート 宣言は、グローバル、名前空間、またはクラス スコープのみで許可されています
1>c:\program files\microsoft visual studio 8\vc\include\string.h(129) : error C2598: リンケージ指定子がグローバル スコープで宣言されていません。
1>c:\program files\microsoft visual studio 8\vc\include\string.h(129) : error C2951: テンプレート 宣言は、グローバル、名前空間、またはクラス スコープのみで許可されています
1>c:\program files\microsoft visual studio 8\vc\include\string.h(131) : error C2598: リンケージ指定子がグローバル スコープで宣言されていません。
1>c:\program files\microsoft visual studio 8\vc\include\string.h(131) : error C2951: テンプレート 宣言は、グローバル、名前空間、またはクラス スコープのみで許可されています
1>c:\program files\microsoft visual studio 8\vc\include\string.h(134) : error C2598: リンケージ指定子がグローバル スコープで宣言されていません。

補足日時:2008/04/10 18:07
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

>これはコンパイラの警告を気になさり過ぎて大幅にコードを書き換え
なされたのでしょうか?

コードの書き換えはoutportbを_outpに書き換えたことのみです。

エラーについては文字数の制限上、回答の捕捉に掲載いたします。
(こちらも文字数の制限のため全て載せれませんでした。)
どうもヘッダーファイル内のエラーのようです。


>コードに加えて、どういう手順で何をなされたか詳しくお書き下さるとよろしいかと思います。


手順はVC++2005 Express Editionを立ち上げ→ファイル→新規作成→プロジェクト→Win32→Win32コンソールアプリケーション→名前入力→OK→アプリケーションウィザード→コンソールアプリケーション→完了
です。
あとはコードを以前にご教示していただいたコードの下にDLD40の元のコードを貼り付けました。ソリューションのビルドをすると上記に記載したエラーが出ました。


以上です。
エラーが回避できるようにヘッダーファイルを調べてみます。

お礼日時:2008/04/10 18:10

コンパイラの操作方法をご理解されているという前提でしたが、どうも


ご理解されてないように
思えてしまうので失礼かとは存じますが、細かいことを記述致します。

>「警告でアセンブラを使うためコンパイルを再起動した」
> と出ましたので。

Boland のコンパイラであれば bcc32 の引数に -B を付ければその警告は
なくなると思います。
tasm32 にインラインアセンブラを渡すために再起動したという警告だと
思われます。

> 要はアクセス権がないために閉じる
> (アクセス権があれば閉じない)という理解で
> よろしいのでしょうか?

そうです。
giveio などが動作していない場合に outportb が呼ばれていればそうなると思います。

> 「warning C4068: 不明なプラグマがありました。」
> と大量にでました。

こちらで確認した時点での警告は引数 /W4 で scanf と int とunsigned
cahr についての警告が出ただけでした。(後述)

おそらく SDK へのパスが通ってないか、正しくパスが通っていた場合は
プロジェクトの作成が適切ではないのかと思われます。

今は SDK のバージョンが新しくなっていてこの記述とは異なっていると
思われます。

http://okwave.jp/qa2352816.html

通常であれば C:\Program Files\ の下にインストールされていると思います。
C:\Program Files\Microsoft SDK...\v6.? となっていると思われます。
説明でのパスと実際のパスと置き換えて設定してください。

またはスタートメニューからプログラムを辿ると「Microsoft Windows SDK」
というメニューがあると思います。
もしその項目に「VisualStudio Registration」と「Integrate Windows
SDK with Visual Studio 2005」という項目があればそれを実行すれば
自動で設定されると思われます。(お使いの SDK がどのバージョンの SDK か
不明なのでこれも異なるかも知れませんが)

VC++ 2005 Express Edtion からプロジェクトの作成する場合はメニューの
ファイル -> 新規作成 -> プロジェクト と進み
プロジェクトの種類で Win32 を選び
テンプレートで Win32 コンソール アプリケーションを選び
プロジェクト名に「VoltageControl」など適宜名称をつけて OK を押します。
Win32 アプリケーション ウィザードという画面が出るので次を押して、コンソール
アプリケーションを選び完了を押します。
取り敢えずコードの _tmail(){...} を例のコードに置き換えてしまってください。

コンパイルした場合に警告がでるのはコンソール画面で入力に使っている scanf に
対してと Voltage 関数の int と unsigned char の変換に対してなので今回は
無視してください。(scanf がバッファ長のチェックがなされないことや unsigned
char に明示的にキャストしなさいという意味です)

Borland のコンパイラの場合は、HANDLE に代入した値が使われないという警告だと
思います。(これも正しい方法でコンパイルしている場合)

注意: この話は以前私が例として示させて頂いた http://okwave.jp/qa3839049.html
   のコードのコンパイル方法についてです。

プロジェクトの作成手順やコンパイラの引数の指定によって動作が変わってしまうので、
もう少し詳しい状況を書いていただけるとありがたいです。

# 貴殿の問題が解決へ向かわれればよいだけですので。
    • good
    • 0
この回答へのお礼

いつも丁寧なご回答ありがとうございます。
本当に感謝の気持ちが絶えません。
また、お礼が遅くなったことお詫び申し上げます。

警告の「アセンブラを使うためコンパイルを再起動した」に関しては
bcc32 の引数に -B を付けると警告はなくなり解決致しました。

>SDK へのパスが通ってないか、正しくパスが通っていた場合は
プロジェクトの作成が適切ではないのかと思われます。

これに関しては、下記のURLに載せられている手順で
サンプルプロジェクトが作成できました。
http://www.cppdrive.jp/vc/sdk/
このURLに掲載されているサンプルプロジェクトができたということで正しくパスが通っていると考えてもよろしいのでしょうか?

また、ご教示していただいた手順でビルドすると
エラーの種類が変わりました。

エラーは
・error C2598:リンケージ指定子がグローバル スコープで宣言されていません。
・error C2951: テンプレート 宣言は、グローバル、名前空間、またはクラス スコープのみで許可されています
・fatal error C1903: 直前のエラーを修復できません。コンパイルを中止します。
・error C2267: 'strnlen_s' : ブロックスコープを伴う関数は、static として宣言できません。
と出ました。

ですので、上記の話と矛盾しますが
やはり正しい方法でコンパイルしていない
もしくはSDKのパスが通っていないのでしょうか?

なお、プロジェクトの作成手順はご教示のとおりにし、
コンパイラの引数の指定の仕方は初期設定のままだと思います。
(情けない話ですが確認の仕方がわからないという理由からですが)

プロジェクトの作成手順とコンパイルの引数指定以外の
詳しい状況について述べたいのですが、必要な情報として
何を記載すればいいのか判断しかねますので
指定していただければと思います。

また明日、明後日と手前の都合上、ご回答いただいても
すぐにお礼の返信できません。
ですので、お礼が遅くなることを先にお詫び申し上げます。
また、手とり足とりのご指導になっていることも
重ねてお詫び申し上げます。

お礼日時:2008/04/07 22:20

確認させて頂きますが。



http://okwave.jp/qa3839049.html
http://okwave.jp/qa3854037.html

上記のご質問と関連された内容でしょうか?

このインラインアセンブラのコードについてはご理解なされましたか?
# ものすごくこの部分(outportb)に拘っておられるようなので。
> void outportb(unsigned int portid,unsigned char value){
> _asm mov edx,portid
> _asm mov al,value
> _asm out dx,al
> }

これは

mov 命令で edx(32ビット)レジスタに portid(int型 なので32ビット)のデータを格納して
mov 命令で al(8ビット)レジスタに value(char型 なので8ビットのデータ)を
格納して
out 命令で dx の値で指定されたポートアドレスに al の値を出力するものです。

※ int などのビットサイズは処理系依存ですが

VC++ の _outp(8ビットデータをポートへ出力) と全く同じことをさせるものです。
# VC++ であればこの _outp に置き換えれば済むのです。

> 原因はWindows XPはIOポートのアクセスする権限がないからなのでしょうか?

その通りで、次の URL に記載されている通りです。
※ Windows 2000 や Windows XP は Windows NT 系の OS ですから。

ドキュメント:inp()とoutp()で入出力ポートは、 Windows NT に失敗します。
http://support.microsoft.com/kb/112298/ja

※ 引用が前後いたしますが
> アセンブラの部分を削除しコンパイルすると
> portid,valueの値が1度も使用されていないという警告が出ます。

なぜわざわざ削除してしまうのかが理解できません。(※1
値が定義されていても使われてないというのは、その値を使う部分を消してしまえばそうなります。

※ 引用が前後いたしますが
> outportb関数を定義してコンパイルすると
> 「問題が発生したため・・・・」
> とウィンドウが開いて勝手に終了します。

※1)
コンパイルは成功して実行なさったときの話でしょうか、であれば
これは単なるエラーではなく「成功への第一歩」です。

つまり、ポートアドレスへの書き出し部分が成功しているので、わかりやすく言うならば
OS が「特権もないのにポートへアクセスするな」との「不満」を言っているのです。

あとは giveio や porttalk など、お好みのもので"ポートに書き出す特権"を
得られるようにコードへ記述すれば良いのです。

それでも動作しないのであれば、BIOS でパラレルポートのアドレス割り当ての
確認もしてみてください。
それと USBパラレル変換ケーブルをお使いであれば動作しないと思われます。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

以前の質問内容と関連した内容です。

outportb関数をアセンブラ言語で
定義したものですので、outportb関数が入っている
dos.hなどをインクルードすれば不要ではないかと思い
削除を試してみました。
「警告でアセンブラを使うためコンパイルを再起動した」
と出ましたので。

ウィンドウが勝手に閉じるのはコンパイル後、
実行した時の話です。
要はアクセス権がないために閉じる
(アクセス権があれば閉じない)という理解で
よろしいのでしょうか?

なお、以前のご回答中のコードを
VC++2005Express EditionでSDKもインストールし試してみましたが
ビルドすると
「warning C4068: 不明なプラグマがありました。」
と大量にでました。調べてみるとセキュリティレベルの問題で
VC++の方が厳しいようなのでC++を使うことに変更しました。

USBパラレル変換ケーブルは使用していませんので
そこは問題ないと思われます。

お礼日時:2008/04/02 10:31

Visual C++6.0 で同じようなことをしました。


ただし、このようなポートアクセスは
Windows 95/98/Me でのみ有効となります。
Windows NT/2000/XP では実行しても無視されます。

Windows NT/2000/XP でポートアクセスする場合は
インターフェース社などが出している
『汎用ポートアクセスドライバ』をインストールして行いました。
※各種言語用にサンプルが付いていたと思う。
※まだ提供されているか不明なので、自信なしです。

参考URL:http://www.interface.co.jp/
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
いくつかドライバを探して挑戦してみます。
適切な言語用のポートドライバでないとエラーを
はく可能性はあるのでしょうか?

お礼日時:2008/04/02 10:06

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


このQ&Aを見た人がよく見るQ&A