📄 smb_test1.c
字号:
SI = 0; // 释放总线
DATA_READY = 0; // 等待有效数据。
while (!DATA_READY); //
DAC0L = 0; // DAC 低字节
DAC0H = WORD; // DAC 高字节
VALID_OP = 0; // 等待新的OP_CODE
SI = 0; // 结束时释放总线
break;
// OP_CODE = WRITE_BUF – 等待有效数据字节,并将其存入DATA_BUF 数组。
// 根据OP_CODE 的高4 位确定数组下标。
case WRITE_BUF:
SI = 0; // 释放总线
index = (OP_CODE & 0xF0); // 用高4 位作为数组下标
DATA_READY = 0; // 等待有效数据。
while (!DATA_READY); //
DATA_BUF[index] = WORD; // 将数据存入数组
VALID_OP = 0; // 等待新的OP_CODE
SI = 0; // 结束时释放总线
break;
// OP_CODE = READ_BUF – 读DATA_BUF 数组并将字节存入输出缓冲区。
// 数组下标由OP_CODE 的高4 位决定。
case READ_BUF:
index = (OP_CODE & 0xF0); // 用高4 位作为数组下标
WORD = DATA_BUF[index]; // 将索引字节存入输出缓冲区
VALID_OP = 0; // 等待新的OP_CODE
SI = 0; // 结束时释放总线
break;
}
if (LOST){ // 如果LOST 被置位,说明器件在最近
COMMAND = LOST_COMMAND; // 的竞争中失败。将保存值回装到
WORD = LOST_WORD; // 传输变量并重试传输过程。
OP_CODE = LOST_CODE;
LOST = 0;
STA = 1;
}
}
}
//--------------------------------------------------------------------
// SMBus 中断服务程序
//--------------------------------------------------------------------
void SMBUS_ISR (void) interrupt 7
{
switch (SMB0STA){ // SMBus 的状态码(SMB0STA 寄存器)
// 主发送器/接收器:起始条件已发出。
// 将从器件地址装入SMB0DAT。屏蔽R/W 位,因为所有传输过程都从
// 写OP_CODE 开始。
case SMB_START:
SMB0DAT = (COMMAND & 0xFE); // 装入待访问的从器件地址
// 屏蔽R/W 位,因为第一次传输
// 总是写OP_CODE。
STA = 0; // 手动清除STA 位
SI = 0; // 清除中断标志
break;
// 主发送器/接收器:重复起始条件已发出。
// 该状态只出现在读操作,在发出OP_CODE 之后。将器件地址+ READ 装入SMB0DAT。
case SMB_RP_START:
SMB0DAT = COMMAND;
STA = 0; // 手动清除STA 位
SI = 0;
break;
// 主发送器:从地址+ WRITE 已发出。收到ACK。
// 将OP_CODE 装入到SMB0DAT。
case SMB_MTADDACK:
SMB0DAT = OP_CODE;
SI = 0; // 清除中断标志
break;
// 主发送器:从地址+ WRITE 已发出。收到NACK。
// 从器件不响应。用ACK 查询重试。
case SMB_MTADDNACK:
STO = 1;
STA = 1;
SI = 0; // 清除中断标志
break;
// 主发送器:数据字节已发出。收到ACK。
// 检查OP_CODE – 如果是读操作码,发出重复起始条件开始读。如果是写操作码,
// 将WORD 装入SMB0DAT 以待传输。如果不是有效操作码,则有两种情况:
// 1) 数据已发送,传输过程结束,或2) 这是一个错误。
// 在任何一种情况,发出停止条件结束传输。
case SMB_MTDBACK:
switch (OP_CODE & 0x0F){ // 只检查低4 位
// OP_CODE 为READ。发出重复起始条件。
case READ_BUF:
case READ_ADC:
OP_CODE = 0; // 当前OP_CODE 不再有用
STA = 1;
break;
// OP_CODE 为WRITE。将输出数据装入SMB0DAT。
case WRITE_BUF:
case WRITE_DAC:
SMB0DAT = WORD;
OP_CODE = 0; // 清除OP_CODE,使传输过程在下一次
break; // 出现该状态时结束(在发出数据之后)。
default: // 无有效OP_CODE。结束传输
STO = 1;
SM_BUSY = 0;
break;
}
SI = 0;
break;
// 主发送器:数据字节已发出。收到NACK。
// 用ACK 查询并重试传输。
case SMB_MTDBNACK:
STO = 1;
STA = 1;
SI = 0; // 清除中断标志
break;
// 主发送器:竞争失败。
case SMB_MTARBLOST:
LOST_COMMAND = COMMAND; //
LOST_WORD = WORD; // 保存变量,以备总线空闲时使用
LOST_CODE = OP_CODE; //
LOST = 1; // 设置总线空闲时的重试标志
SI = 0; // 清除中断标志
break;
// 主接收器:从地址+ READ 已发出。收到ACK。
// 设置为在下一次传输后发送NACK,因为这将是最后(唯一)字节。
case SMB_MRADDACK:
AA = 0; // 在应答周期发送NACK
SI = 0;
break;
// 主接收器:从地址+ READ 已发出。收到NACK。
// 从器件不响应。重新发送重复起始条件。
case SMB_MRADDNACK:
STA = 1;
SI = 0;
break;
// 主接收器:收到数据字节。ACK 已发出。
// 该状态不应出现,因为AA 已在前一状态被清除。
// 如果出现,发送停止条件。
case SMB_MRDBACK:
STO = 1;
SM_BUSY = 0;
SI = 0;
break;
// 主接收器:收到数据字节。NACK 已发出。
// 读操作完成。读数据寄存器并发送停止条件。
case SMB_MRDBNACK:
WORD = SMB0DAT;
STO = 1;
SM_BUSY = 0;
AA = 1; // 为下一次传输设置AA
SI = 0;
break;
// 从接收器:竞争失败,收到通用呼叫地址。
// 置位LOST 标志以备总线空闲时重试。本次传输失败。
case SMB_SRGARBLOST:
// 从接收器:竞争失败,收到自己的从地址+ WRITE。
// 置位LOST 标志以备总线空闲时重试。
// 置位STO 位以退出主方式
case SMB_SROARBLOST:
LOST_COMMAND = COMMAND; //
LOST_WORD = WORD; // 保存变量,以备总线空闲时使用
LOST_CODE = OP_CODE; //
LOST = 1; // 总线空闲时重试。
SI = 0;
break;
// 从接收器:收到自己的从地址+ WRITE。ACK 已发出。本次传输失败。
case SMB_SROADACK:
// 从接收器:收到通用呼叫地址。ACK 已发出。
case SMB_SRGADACK:
SI = 0;
break;
// 从接收器:在收到通用呼叫地址+ WRITE 之后收到数据字节。
// ACK 已发出。本次传输失败。
case SMB_SRGDBACK:
// 从接收器:在收到自己的从地址+ WRITE 之后收到数据字节。ACK 已发出。
// 根据所收到的OP_CODE 或数据进行相应操作。
case SMB_SRODBACK:
if (!VALID_OP){ // 如果VALID_OP=0,该字节为OP_CODE。
OP_CODE = SMB0DAT; // 保存OP_CODE
VALID_OP = 1; // 下一字节不是OP_CODE
}
else{
DATA_READY = 1; // 收到有效数据。
WORD = SMB0DAT; // 在OP_CODE 处理程序中处理
SI = 0;}
break;
// 从接收器:被作为从器件访问时收到数据字节。NACK 已发出。
// 该状态不应出现,因为作为从器件AA 不会被清除。本次失败,进入下一状态。
case SMB_SRODBNACK:
// 从接收器:被作为通用呼叫地址访问时收到数据字节。NACK 已发出。
// 该状态不应出现,因为作为从器件AA 不会被清除。
case SMB_SRGDBNACK:
AA = 1;
SI = 0;
break;
// 从接收器:被作为从器件访问时收到停止条件或重复起始条件。
case SMB_SRSTOP:
SI = 0;
break;
// 从发送器:收到自己的从地址+ READ。ACK 已发出。
// 将待输出数据装入到SMB0DAT。
case SMB_STOADACK:
SMB0DAT = WORD;
SI = 0;
break;
// 从发送器:作为主器件竞争失败。收到自己的从地址+ READ。ACK 已发出。
case SMB_STOARBLOST:
LOST_COMMAND = COMMAND; //
LOST_WORD = WORD; // 保存变量,以备总线空闲时使用
LOST_CODE = OP_CODE; //
LOST = 1; // 总线空闲时重试
SI = 0;
break;
// 从发送器:收到数据字节。收到ACK。失败。
case SMB_STDBACK:
// 从发送器:收到数据字节。收到NACK。失败。
case SMB_STDBNACK:
// 从发送器:最后数据字节已发送。收到ACK。无需任何操作。
case SMB_STDBLAST:
SI = 0;
break;
// 所有其它状态码无效。通信复位。
default:
STO = 1;
SM_BUSY = 0;
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -