找回密码
 马上注册

QQ登录

只需一步,快速开始

查看: 8275|回复: 3

NXC I2C HowTo(2)NXT I2C通讯的操作方式与步骤

  [复制链接]
发表于 2010-1-14 12:28:59 | 显示全部楼层 |阅读模式
一般的I 2C装置, 若是使用原厂提供的NXT-G Block, 只需要对于Input/Output plug的用法了解清楚, 通常很快就能够上手使用.
而使用NXC, 则必须透过NXT的I 2C通讯程序与装置进行沟通, 实作上多了一些步骤, 不过这些步骤都是标准程序, 不会因不同的装置而有所差异, 同时如前一篇的说明, 使用NXC可以对于装置的用法更具弹性, 也更能发挥装置的功能, 所以即使麻烦一些都是值得的.

NXT Firmware Digital Communication功能

I 2C通讯属非同步通讯并使用Master/Slave架构, NXT为Master端, 负责启使I 2C通讯的程序(包含: 初始化及存' 取请求), 而Slave端装置则等候接收NXT的请求(request)并回应(Response)对应的动作, 这些请求主要就是进行存取Slave装置的Register, 至于请求存取的目的则依装置具备的功能而定, 例如, 可能是NXT要求读取装置所侦测到的值或者要求装置执行特定的功能等.
此外, NXT firmware 会维护每个input ports所拥有的Internal Write buffer与Read Buffer, 做为待传送资料及接收资料的暂存空间.
同时, NXT Firmware提供了以下3个Digital I/O Communication Methods能够让使用者可以存取Internal Write / Read Buffer, 以进行I 2C通讯的处理过程.
NXT Firmware Digital I/O Communication Methods功能摘要:

NXTCommLSWrite: 起始I 2C通讯, 将Internal Write buffer资料传送至装置, 要求装置回应指定长度的资料, 读取资料并存放至Internal Read buffer.

NXTCommLSCheckStatus: 检查I 2C通讯的进行状态以及装置实际回应的资料长度.

NXTCommLSRead: 将Internal Read buffer资料复制到使用者的Buffer.

NXT I 2C通讯的步骤与方式

NXT与装置间的沟通需要按照特定的步骤进行, 这些过程属于标准的I 2C通讯协定, 与装置的类型无关, 虽然每个装置具备的功能不同, 存取的需求可能不同, 然而对于这些差异性, 只需要在I 2C处理的过程中稍微调整就能符合应用上需求. 总之, 只要了解标准I 2C通讯的进行步骤, 则任何装置, 都可以很容易的上手使用, 以下即对于NXT I 2C进行的步骤以及各个阶段NXC API的用法作一个整理与说明:

1. 初始化

要对于input port进行I 2C通讯前首先须将Input port type设成LOWSPEED或LOWSPEED_9V, 差别在于是否需要NXT的9V供电, 而NXC的API: SetSensorLowspeed(port)则会将type设成LOWSPEED_9V.
此外依据文件说明, 在设定input port type时, 须先对port的状态属性InvalidData设成TRUE, 再以循环(loop)等候直到firmware完成对input port的初始化同时更新状态值为FALSE之后, 才可以继续后续的处理.
初始化过程NXC的程式码为:

SetSensor(port, InvalidData, TRUE); //先将port状态属性设成TRUE

SetSensorLowspeed(port); //设定port type

while (SensorInvalid(port)); //等候port完成初始化

2. 启始I 2C通讯
NXT Firmware使用NXTCommLSWrite system call来启始对装置的I 2C通讯, 而NXC对应的API为LowspeedWrite(port, returnlen, buffer), 函数使用的3个参数分别为:

port – 装置所连接的Input port.

returnlen – 要求装置回传的资料长度(Bytes), 最多为16 Bytes, 若不需要读取装置资料则设为0.

buffer – 为byte型态的阵列, 存放NXT启始的通讯对象(装置)位址资讯以及准备要写入的资料(若有的话).

在启始每一次的通讯处理前, 必须先检查port的状态, 确定前一次的处理已经执行结束, 而可以接受新的处理请求, 检查的方式是使用循环(loop)等候直到LowspeedCheckStatus(port)函数的回传值不等于32(STAT_COMM_PENDING).

读取I 2C装置资料范例

以Hitechnic IRReceiver Sensor为例, 参考它的Register Layout:

Address Type Contents
======= ====== ====================

42H byte Motor 1A control
43H byte Motor 1B control
44H byte Motor 2A control
45H byte Motor 2B control
46H byte Motor 3A control
47H byte Motor 3B control
48H byte Motor 4A control
49H byte Motor 4B control



若要读取装置所侦测到的所有PFIR信号, 可以透过I 2C通讯, 要求IRReceiver装置从register 0x42的位址起回传8 Bytes资料, NXC的程式范例如下:


byte I 2C _request_buf[]; //宣告byte阵列

// 第1个元素: 装置的Device address(0x02)
// 第2个元素: 本次读取之装置register资料的起始位址(0x42)
ArrayBuild(I2C_request_buf, 0x02, 0x42);

// 检查input port 1的状态, 等候直到可以启始下一次的通讯作业
while(LowspeedCheckStatus(IN_1) == STAT_COMM_PENDING);

// 启始通讯作业, 并要求IRReceiver自register 0x42的位址回传8 Bytes资料
LowspeedWrite(IN_1, 8, I 2C _request_buf);



写入I 2C 装置资料范例

至于写入资料至I 2C装置的方式, 可以参考以下的NXTHID使用范例:

NXTHID Register layout:

Address Type Contents
======= ====== ====================

41H byte Command,
42H byte Modifier
43H byte Keyboard Data



NXTHID的主要功能在于可以模拟成为键盘而将资料输入到PC, 它提供3种指令作为控制传送的动作与资料的型态, 以下范例为传送指令至NXTHID以启动指令的执行

/* ************************************************ ********
* 写入Command到NXTHID的0x41位址以启动指令的执行
* Command: T-Transmit data to PC
* A-Setup device for Ascii mode
* D-Setup device for Direct data mode
* ************************************************* ******* */
void NXTHID_RunCmd (byte hid_cmd)
{
      byte I 2C _buf[]; //宣告byte阵列
      
      // 第1个元素: NXTHID Device address(0x02)
      // 第2个元素: NXTHID command register(0x41)
      // 第3个元素: 要写入NXTHID的command(hid_cmd)
      ArrayBuild(I 2C _buf, 0x02, 0x41, hid_cmd);
  
      // 检查input port 1的状态, 等候直到可以启始下一次的通讯作业
      while(LowspeedCheckStatus(IN_1) == STAT_COMM_PENDING);

      // 启始通讯作业, 并传送hid_cmd指令至NXTHID,要求执行该指令
      LowspeedWrite(IN_1, 0, I 2C _buf);
}



3. 检查执行状态
当使用LowspeedWrite(port, returnlen, buffer)启始通讯作业之后, 如果是对装置请求读取资料, 则资料将会被存入至Internal Read Buffer中, 此时, 可以使用NXTCommLSCheckStatus system call来检查执行状态, 一方面确认通讯作业是否正常完成, 同时也可以取得存入Internal Read Buffer中资料的实际长度(Bytes).
如果要进行以上的两个检查, 可以使用LowspeedStatus(port, BytesReady) 的NXC API, 其中BytesReady并非作为函数的传入参数, 而是存放由函数回应Internal Read buffer资料长度的变数, 稍后可参考后面的使用范例.

4. 读取资料
读取Internal Read Buffer资料的system call为NXTCommLSRead, NXC API为LowspeedRead(port, buflen, buffer), 3个参数说明如下:

port – 装置所连接的Input port.

buflen – 读取自Internal Read buffer资料的长度(Bytes), 最多为16 Bytes.

buffer – 为byte型态的阵列, 存放自Internal Read buffer所读取的资料.

就如同启始通讯作业时一样, 必须先检查port的状态, 确定前一次处理已经执行结束, 而可以接受新的处理请求,
检查的方式是使用循环(loop)等候直到LowspeedCheckStatus(port) 或LowspeedStatus(port, BytesReady)函数的回传值等于32(STAT_COMM_PENDING),而我是比较习惯使用第2个函数做检查.
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
发表于 2010-3-26 08:55:41 | 显示全部楼层
mark
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2010-4-25 12:54:54 | 显示全部楼层
唐大大,为什么那句SetSensor(S1, InvalidData, TRUE);编译过不了?
是不是需要其他的命令?
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2012-6-24 22:11:51 | 显示全部楼层
顶一下再看
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

手机版|中文乐高 ( 桂ICP备13001575号-7 )

GMT+8, 2024-11-21 21:08 , Processed in 0.087487 second(s), 19 queries .

Powered by Discuz! X3.5

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表