📄 iic_comm.c
字号:
break;
// Default: all other cases undefined
default:
SMB0CN &= ~0x40; // Reset communication
SMB0CN |= 0x40;
break;
}
if (FAIL) // If the transfer failed,
{
SMB0CN &= ~0x40; // Reset communication
SMB0CN |= 0x40;
SMBUS_BUSY = 0; // Free SMBus
}
SI=0; // Clear SMBus interrupt flag
}
/************************************************************
-----SMBUS数据处理程序-----
功能: 根据接收到的info_id,作相应的处理
//void DataProcess(void)
*************************************************************/
void DataProcess(DATA_BUFF *RcvData)
{
UCHAR temp = 0;
static UCHAR *pTxdCnt;
static UCHAR txLen = 0;
DATA_BUFF *pSndData;
// while(DataProcess);
// DataProcess = 1;
pTxdCnt = &SndDataLen; // 指针指向发送数据长度全局变量
pSndData = &unSndDataBuf; // 指针指向发送缓冲区首址
if(RcvDataFlag) // 缓冲区中有新收到的数据
{
temp = RcvData->databuf[0]; // info_id判断
switch (temp){
case 0x30:
txLen = ReturnScanCode(RcvData);
break;
case 0x31:
txLen = ReturnBatStatus(RcvData);
break;
default:
break;
}
RcvDataFlag = 0;
}
*pTxdCnt = txLen;
if(txLen != 0)
IIC_SndData(pSndData, pTxdCnt); // 启动iic主发送
}
/************************************************************
-----回复主机查询按键程序-----
功能: 将需要发送的扫描码送入发送缓冲区
返回: 发送缓冲区中数据的长度,
如果校验出错则返回长度为0,正确则为实际长度
//UCHAR ReturnScanCode(DATA_BUFF SndData)
*************************************************************/
UCHAR ReturnScanCode(DATA_BUFF *RcvData)
{
UCHAR temp;
UCHAR retlen;
DATA_BUFF *pSndBuf;
pSndBuf = &unSndDataBuf;
temp = CompChksum(RcvData);
if(temp == 1) // 校验和正确,将发送数据填入发送缓冲区
{
pSndBuf->unDataUnion.stFRK.info_id = FRK_INFO_ID;
// if(KeyBuffer[0] == 0xd0) // KeyBuffer中保存的是通码
// {
// pSndBuf->unDataUnion.stFRK.info_len = 1;
// pSndBuf->unDataUnion.stFRK.info_scancode[0] = KeyBuffer[1];
// retlen = 4; //
// }
// else
// {
pSndBuf->unDataUnion.stFRK.info_len = 2;
pSndBuf->unDataUnion.stFRK.info_scancode[0] = KeyBuffer[0];
pSndBuf->unDataUnion.stFRK.info_scancode[1] = KeyBuffer[1];
retlen = 5;
// }
CalChksum(pSndBuf); //计算校验和并将其填入正确的位置
// pSndBuf->unDataUnion.stFRK.checksum = temp;
}
else // 校验和错误
retlen = 0;
return retlen;
}
/************************************************************
-----回复主机查询电池信息程序-----
功能: 将需要发送的电池信息送入发送缓冲区,本次暂时只支持电量
返回: 发送缓冲区中数据的长度,
如果校验出错则返回长度为0,正确则为实际长度
//UCHAR ReturnBatStatus(DATA_BUFF SndData)
*************************************************************/
UCHAR ReturnBatStatus(DATA_BUFF *RcvData)
{
UCHAR temp;
UCHAR retlen;
DATA_BUFF *pSndBuf;
pSndBuf = &unSndDataBuf;
temp = CompChksum(RcvData);
if(temp == 1) // 校验和正确,将发送数据填入发送缓冲区
{
pSndBuf->unDataUnion.stFRB.info_id = FRB_INFO_ID;
pSndBuf->unDataUnion.stFRB.info_len = 2;
pSndBuf->unDataUnion.stFRB.info_batvol[0] = BatVol[0];
pSndBuf->unDataUnion.stFRB.info_batvol[1] = BatVol[1];
CalChksum(pSndBuf);
pSndBuf->unDataUnion.stFRB.checksum = temp;
retlen = 5;
}
else // 校验和错误
retlen = 0;
return retlen;
}
/************************************************************
-----比较校验和程序-----
功能: 计算接收缓冲区数据校验和并与接收到的校验和比较
返回: 如果校验出错则返回0,正确则返回1
//UCHAR CompChksum(DATA_BUFF RcvData)
*************************************************************/
UCHAR CompChksum(DATA_BUFF *RcvData)
{
UCHAR i, temp = 0;
UCHAR len = 0;
UINT sum = 0;
len = RcvData->databuf[1] + 2; // 接收缓冲区数据长度 = 信息长度 + info_id + info_len
for(i = 0; i < len; i++)
sum += RcvData->databuf[i];
temp = (UCHAR) sum;
if(temp != RcvData->databuf[i]) // 校验和不等
return 0;
else
return 1;
}
/************************************************************
-----计算校验和程序-----
功能: 计算发送缓冲区数据校验和
返回: 校验和
//void CalChksum(DATA_BUFF SndData)
*************************************************************/
void CalChksum(DATA_BUFF *SndData)
{
UCHAR i;
UCHAR len = 0;
UINT temp = 0;
len = SndData->databuf[1] + 2; // 接收缓冲区数据长度 = 信息长度 + info_id + info_len
for(i = 0; i < len; i++)
temp += SndData->databuf[i];
SndData->databuf[i] = (UCHAR) temp; // 将计算所得校验和填入发送缓冲区
}
///************************************************************
//-----iic主发送程序-----
//功能: 将发送缓冲区的数据通过IIC总线发送出去
//返回: 发送缓冲区中数据的长度,
////void IIC_SndData(DATA_BUFF *SndData, UCHAR *SndLen)
//*************************************************************/
void IIC_SndData(DATA_BUFF *SndData, UCHAR *SndLen)
{
UCHAR i;
while(SMBUS_BUSY); // 等待总线空闲
SMBUS_BUSY = 1; // 开始发送数据前,设置总线忙
iic_reset();
iic_init(SMB_MASTER);
for(i = 0; i < *SndLen; i++)
IIC_ByteWrite(SndData, i);
while(SMBUS_BUSY); // 等待总线空闲
// SMBUS_BUSY = 1;
iic_reset();
iic_init(SMB_SLAVE); // 发送完成后,将本机设置为从模式
}
/************************************************************
-----iic总线复位程序-----
//void iic_reset(void)
*************************************************************/
void iic_reset(void)
{
SMB0CN &= ~0x40; // Disable SMBus
SMB0CN |= 0x40; // Re-enable SMBus
}
/************************************************************
-----iic主方式发送单个字节程序-----
功能: 将发送缓冲区中SndLocation位置的数据通过IIC总线发送出去
返回:
//void IIC_ByteWrite(DATA_BUFF *SndData, UCHAR SndLocation)
*************************************************************/
void IIC_ByteWrite( DATA_BUFF *SndData, unsigned char SndLocation)
{
while (SMBUS_BUSY); // Wait for SMBus to be free.
SMBUS_BUSY = 1; // Claim SMBus (set to busy)
// 设置中断中用到的参数
TARGET = MST_ADD; // 设置目标地址
SMB_RW = WRITE; // 标志总线为写操作
SMB_ACKPOLL = 1; // 中断程序将不断查询地址有无确认
// 准备要发送的数据(1字节)
SMB_SINGLEBYTE_OUT = SndData->databuf[SndLocation];
// 将要发送数据存储于SMB_SINGLEBYTE_OUT,中断程序
// 将会读取该位置的值并发送
pSMB_DATA_OUT = &SMB_SINGLEBYTE_OUT;
SMB_DATA_LEN = 1;
// Initiate SMBus Transfer
STA = 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -