⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 io-port-programming.txt

📁 Linux百科宝典 书籍语言: 简体中文 书籍类型: 系统专区 授权方式: 免费软件 书籍大小: 1024 KB
💻 TXT
📖 第 1 页 / 共 3 页
字号:
6.2 游戏 (操纵□) 埠 (game port)   游戏埠的埠位址□围为 0x200-0x207. 想要控制一般的操纵□, 有一个核心层次   的操纵□驱动程式, 可参考网址   [10]ftp://sunsite.unc.edu/pub/Linux/kernel/patches/, 档名 joystick-*.      埠的脚位排列 (Pinout) 方式 (该埠是一个 15 只脚 D 字形外壳 (D-shell) 的   母头连接器):     * 1,8,9,15: +5 V (电源)     * 4,5,12: 接地     * 2,7,10,14: 分别是 BA1, BA2, BB1, 和 BB2 等数位输入     * 3,6,11,13: 分别是 AX, AY, BX, 和 BY 等``类比''输入          +5 V 的脚位似乎通常会被直接连接到主机板的电源线上, 所以他应该能够提供相   当的电力, 这还要看所使用主机板, 电源供给器, 以及游戏埠的类型.      数位输入用於操纵□的按钮可以让你连接二个操纵□的四个按钮 (操纵□ A 和   操纵□ B, 各有二个按钮) 到游戏埠也就是数位输入的四个脚位. 他们应该是一   般 TTL 电压位准的输入, 你可以直接从状态埠 (参考下面说明) 读出他们的位准   状态. 一个实际的操纵□在按钮被压下时会传回低位准 (0 V) 状态否则就是高位   准 (5V 经由 1 Kohm 的电阻连接到电源脚位) 状态.      所谓的类比输入实际是量测到的阻抗值. 游戏埠有四个单击多谐振□器   (one-shot multivibrator) (一个 558 晶片) 连接到四个类比输入脚位. 每个类   比输入脚位与多谐振□器的输出之间连接著一个 2.2 Kohm 的电阻, 而且多谐振   □器的输出与地之间连接著一个 0.01 uF 的时序电容 (timing capacitor). 一   个实际的操纵□其每个座标 (X 和 Y) 上会有一个可变电阻, 连接在 +5 V 与每   个相对的类比输入脚位之间 (脚位 AX 或 AY 是给操纵□ A 用的, 而脚位 BX 或   BY 是给操纵□ B用的).      操作的时候, 多谐振□器将其输出设定为高位准 (5 V) 并且等到时序电容上的电   压达到 3.3 V 之後将相对的输出设定为低位准. 因此操纵□中多谐振□器输出的   高位准时间周期 与可变电阻的电阻值成正比 (也就是, 操纵□在相对座标的位   置), 如下所示:        R = (t - 24.2) / 0.011,        其中 R 是可变电阻的阻抗值 (ohms) 而 t 是高位准时间周期的长度 (秒).      因此要读出类比输入脚位的数值, 首先你得启动多谐振□器 (以埠写入的方式;   请看下面), 然後查询四个座标的信号状态(以持续的埠读出方式)一直到信号状态   由高位准变成低位准, 计算其高位准时间周期的长度. 这个持续查询的动作花费   相当多的 CPU 时间, 而且在一个非即时的多工环境像是 (一般的使用者模式   (user-mode) ) Linux, 所得的结果不是非常准确因为你无法以固定的时间来查询   信号的状态 (除非你使用核心层次的驱动程式而且你得在你查询的时候抑制掉中   断的产生, 但是这样做会浪费更多的 CPU 时间). 如果你知道信号的状态将会花   费一段不短的时间 (数十毫秒) □会成为低位准, 你可以在查询之前呼叫函式   usleep() 将 CPU 的时间让给其他想要执行的行程 (processes).      游戏埠中唯一需要你来存取的埠位址是 0x201 (其他的埠位址不是动作一样就是   没用). 任何对这个埠位址所做的写入动作 (不论你写入什麽) 都会启动多谐振□   器. 对这个埠位址做读出动作会取回输入信号的状态:     * Bit 0: AX ( (1=高位准) 多谐振□器的输出状态)     * Bit 1: AY ( (1=高位准) 多谐振□器的输出状态)     * Bit 2: BX ( (1=高位准) 多谐振□器的输出状态)     * Bit 3: BY ( (1=高位准) 多谐振□器的输出状态)     * Bit 4: BA1 (数位输入, 1=高位准)     * Bit 5: BA2 (数位输入, 1=高位准)     * Bit 6: BB1 (数位输入, 1=高位准)     * Bit 7: BB2 (数位输入, 1=高位准)       6.3 串列埠 (serial port)   如果你所说的装置是支援一些像是 RS-232 那类的东西, 你应该可以如你所愿地   使用串列埠. Linux 所提供的串列埠驱动程式应该能够应用在任何地方 (你应该   不需要直接撰写串列埠程式, 或是核心的驱动程式); 他相当具有通用性, 所以像   是使用非标准的 bps 速率以及其他等等应该不是问题. 请参考 termios(3) 说明   文件, 串列埠驱动程式原始程式码 (linux/drivers/char/serial.c), 以及网页   [11]http://www.easysw.com/~mike/serial/index.html 上有更多在 Unix 作业   系统撰写串列埠程式的相关资料.   7. 提示   如果你想要有好的 I/O 品值, 你可以在并列埠上自行组装 ADC 且/或 DAC 晶片   (提示: 电源部分, 可使用游戏埠上的或将未用到的磁碟电源连接头接至 机壳之   外, 如果你的装置功率消耗低则可以拿并列埠来充当电源, 不然就是使用外部的   电源供给), 或是买 AD/DA 卡片 (大部分较旧型/较低速的产品可由 I/O 埠控   制). 或者是 Linux 音效卡驱动程式所支援的便宜音效卡 (速度还相当的快) 上   1 或 2 个不精确, (可能会) 无法归零的信号通道对你而言就够了.      使用精确的类比装置, 不当的接地可能造成类比输出入信号的误差. 如果你有这   方面的经验, 你可能会尝试以光耦合器来隔绝 (电脑与你的装置之间 所有的 信   号) 电子干扰. 试著从电脑上取得光耦合器的电源 (在埠上未用到的信号脚位可   以提供足够的电源) 以求达到最佳的隔绝效果.      如果你现在正在寻找能在 Linux 上使用的印刷电路板设计软体, 有一个称为   Pcb 免费的 X11 应用程式应该能够胜任, 只要你不要做一些太复杂的事. 许多的   Linux 发行版本 (distributions) 都内含这个程式, 同时他也被放在网址   [12]ftp://sunsite.unc.edu/pub/Linux/apps/circuits/ 上(档名为 pcb-*).   8. 问题排除   Q1.          当我存取 I/O 埠时结果碰到 segmentation faults 这个问题             A1.          不是你的程式没有 root 权限, 就是因为某些理由导致函式 ioperm() 呼          叫失败. 检查函式 ioperm() 的传回值. 同时, 检查你所存取的埠也就是          你以 函式 ioperm() 所启用的埠位址 (参考 Q3). 如果你使用的是延迟          时间的巨集指令 (inb_p(), outb_p(), 等等), 记得也要呼叫函式          ioperm() 以便存取埠位址 0x80.             Q2.          我无法找到 in*(), out*() 等函式被定义在何处, 同时 gcc 也抱怨参考          到未定义的符号 (undefined references).             A2.          你在编译程式时没有打开最佳化选项 (-O), 因此 gcc 不能解析          asm/io.h 中的巨集指令. 或是你根本就没有使用 #include          <asm/io.h>.             Q3.          out*() 没有动作, 或是动作怪怪的.             A3.          检查参数所放置的次序; 他应该是这样 outb(value, port) , 而不是          MS-DOS 上常用的那样 outportb(port, value)             Q4.          我想要控制一个标准的 RS-232 装置/连接并列埠的印表机/操纵□...             A4.          你最好能停止此事而使用现有的驱动程式 (他们存在於 Linux 的核心中          或 X 伺服器中或其他的地方) 来达成你的目标. 这些驱动程式通常相当          具通用性, 所以就算是有点不标准的装置, 他们通常都能正常运作. 这些          标准 I/O 埠的相关资讯请参考前面说过的文件指引.          9. 程式码□例   这边是一段用来存取 I/O 埠的简单的程式码□例:       ______________________________________________________________     /* * example.c: 一个用来存取 I/O 埠的非常简单的□例 * * 这个程式码并没有什麽用处, 他只是做了埠的写入, 暂停, * 以及埠的读出几个动作. 编译时请使用 `gcc -O2 -o example example.c', * 并以 root 的身份执行 `./example'. */#include <stdio.h>#include <unistd.h>#include <asm/io.h>#define BASEPORT 0x378 /* lp1 */int main(){  /* 取得埠位址的存取权限 */  if (ioperm(BASEPORT, 3, 1)) {perror("ioperm"); exit(1);}  /* 设定埠的输出资料信号 (D0-7) 全为零 (0) */  outb(0, BASEPORT);  /* 休息一下 (100 ms) */  usleep(100000);  /* 从状态埠 (BASE+1) 读出资料并显示结果 */  printf("status: %d\n", inb(BASEPORT + 1));  /* 我们不再需要这些埠位址 */  if (ioperm(BASEPORT, 3, 0)) {perror("ioperm"); exit(1);}  exit(0);}/* 结束 example.c */       ______________________________________________________________     10. 致谢   协助过我的人实在太多无法一一列出, 但还是要跟各位说声多谢了. 对所有来信   协助我的人并没有一一回覆致上抱歉之意, 并再次谢谢你们的协助.References   1. http://sunsite.unc.edu/pub/Linux/docs/HOWTO/COPYRIGHT   2. http://www.redhat.com:8080/HyperNews/get/khg.html   3. http://luz.cs.nmt.edu/~rtlinux/   4. http://sunsite.unc.edu/pub/Linux/docs/HOWTO/Hardware-HOWTO   5. http://www.hut.fi/Misc/Electronics/   6. http://sunsite.unc.edu/pub/Linux/docs/HOWTO/Printing-HOWTO   7. http://www.fapo.com/   8. http://www.senet.com.au/~cpeacock/parallel.htm   9. http://www.hut.fi/Misc/Electronics/circuits/lptpower.html  10. ftp://sunsite.unc.edu/pub/Linux/kernel/patches/  11. http://www.easysw.com/~mike/serial/index.html  12. ftp://sunsite.unc.edu/pub/Linux/apps/circuits/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -