1 Star 4 Fork 8

vtor3478/vtor_elec_module

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
vtor_i2c_slave.c 5.88 KB
一键复制 编辑 原始数据 按行查看 历史
#include "vtor_i2c.h"
#ifdef __VTOR_I2C_SLAVE__
void VtorI2cSlave_SclHandler(VtorI2c* i2c)
{
if(i2c == NULL)
{
return ;
}
int8_t sclLevel = VtorI2cSlave_ReadScl(i2c);
int8_t sdaLevel = VtorI2cSlave_ReadSda(i2c);
if(i2c->oldSclLevel == sclLevel)
{
return ;
}
i2c->oldSclLevel = sclLevel;
if(sclLevel == 1)
{
i2c->sclRisingCnt ++;
}
// 8bit下降沿正处理
// 读模式下,从机在低电平写入sda
if((i2c->sclRisingCnt % 9) != 7 && 0 == sclLevel)
{
if(i2c->slaveState == VTOR_I2C_SLAVE_STATE_READ)
{
VtorI2cSlave_WriteSda(i2c, i2c->serialRegister >> 7);
i2c->serialRegister <<= 1;
}
}
// 8bit上升沿正处理
// 写模式下,从机在上升沿读取sda
if((i2c->sclRisingCnt % 9) <= 7 && 1 == sclLevel)
{
if(i2c->slaveState == VTOR_I2C_SLAVE_STATE_WRITE)
{
i2c->serialRegister <<= 1;
i2c->serialRegister |= sdaLevel;
// 收集到第
}
}
// 8bit再处理
// 主机写,从机处理接收字节
if((i2c->sclRisingCnt % 9) == 7 && 1 == sclLevel)
{
if(i2c->slaveState == VTOR_I2C_SLAVE_STATE_WRITE)
{
// 传输完成8个bit,该判断是否回应
//printf("i2c slave rx 0x%x\r\n", i2c->serialRegister);
// 做好接收的这个字节的处理,到底是设备地址还是寄存器地址,还是数据
if(i2c->sclRisingCnt / 9 == 0)
{
i2c->devAddr = i2c->serialRegister; // 首次传输设备地址
}
else if(i2c->sclRisingCnt / 9 == 1)
{
if((i2c->devAddr & 0xfe) == (i2c->selfDevAddr & 0xfe))
{
i2c->regAddr = i2c->serialRegister; // 接下来传输寄存器地址
}
}
else
{
if((i2c->devAddr & 0xfe) == (i2c->selfDevAddr & 0xfe))
{
i2c->regData[i2c->regAddr] = i2c->serialRegister; // 数据
VtorI2cSlave_WriteRegCallback(i2c);
i2c->regAddr++;
}
}
i2c->serialRegister = 0;
}
}
// ack预处理
// 调整sda输入输出
if((i2c->sclRisingCnt % 9) == 7 && 0 == sclLevel)
{
if(i2c->slaveState == VTOR_I2C_SLAVE_STATE_WRITE)
{
if((i2c->devAddr & 0xfe) == (i2c->selfDevAddr & 0xfe))
{
// 设备地址匹配,从机向主机回应
VtorI2cSlave_SetSdaDir(i2c, GPIO_DIR_OUTPUT);
VtorI2cSlave_WriteSda(i2c, 0);
}
}
if(i2c->slaveState == VTOR_I2C_SLAVE_STATE_READ)
{
// 设备地址匹配,从机向主机回应
VtorI2cSlave_SetSdaDir(i2c, GPIO_DIR_IT_2EDGE);
}
}
// ack正处理
// 从机处理主机的nack
if(i2c->sclRisingCnt % 9 == 8 && 1 == sclLevel)
{
if(i2c->slaveState == VTOR_I2C_SLAVE_STATE_READ)
{
// 主机发送nack,说明通信即将结束,从机即将释放sda
if(sdaLevel == 1)
{
i2c->slaveState = VTOR_I2C_SLAVE_STATE_NACK;
}
}
}
// ack再处理
// 恢复sda为原本模式,和判断下一个字节将是什么模式
if(i2c->sclRisingCnt % 9 == 8 && 0 == sclLevel)
{
if(i2c->slaveState == VTOR_I2C_SLAVE_STATE_NACK)
{
VtorI2cSlave_SetSdaDir(i2c, GPIO_DIR_IT_2EDGE);
}
else
{
// ack再处理内判断是写模式还是读模式
if(i2c->devAddr == (i2c->selfDevAddr & 0xfe))
{
i2c->slaveState = VTOR_I2C_SLAVE_STATE_WRITE;
// ack已完成,将sda设置成输入边沿中断
VtorI2cSlave_SetSdaDir(i2c, GPIO_DIR_IT_2EDGE);
}
// 首次写完地址,判断是不是模式
if(i2c->devAddr == (i2c->selfDevAddr | 0x01))
{
i2c->slaveState = VTOR_I2C_SLAVE_STATE_READ;
VtorI2cSlave_SetSdaDir(i2c, GPIO_DIR_OUTPUT);
}
}
}
// 8bit预处理
// 之所以放在最后,是因为 8bit正处理 是从上升沿开始的,
// 但对sda修改,需要在上升沿之前
if((i2c->sclRisingCnt % 9) == 8 && 0 == sclLevel)
{
if(i2c->slaveState == VTOR_I2C_SLAVE_STATE_READ)
{
i2c->serialRegister = i2c->regData[i2c->regAddr];
VtorI2cSlave_ReadRegCallback(i2c);
//printf("i2c slave will tx [0x%x]=0x%x\r\n",
// i2c->regAddr, i2c->serialRegister);
// 如果继续操作,增加当前寄存器坐标
i2c->regAddr++;
VtorI2cSlave_WriteSda(i2c, i2c->serialRegister >> 7);
i2c->serialRegister <<= 1;
}
}
}
void VtorI2cSlave_SdaHandler(VtorI2c* i2c)
{
if(i2c == NULL)
{
return ;
}
int8_t sclLevel = VtorI2cSlave_ReadScl(i2c);
int8_t sdaLevel = VtorI2cSlave_ReadSda(i2c);
// 如果电平没变化,直接返回
if(i2c->oldSdaLevel == sdaLevel)
{
return ;
}
i2c->oldSdaLevel = sdaLevel;
if(sclLevel)
{
if(0 == sdaLevel)
{
// scl为高,sda下降沿,起始
i2c->slaveState = VTOR_I2C_SLAVE_STATE_START;
i2c->slaveState = VTOR_I2C_SLAVE_STATE_WRITE;
i2c->sclRisingCnt = -1;
}
else
{
VtorI2cSlave_SetSdaDir(i2c, GPIO_DIR_IT_2EDGE);
// 只有是访问当前地址,才好触发stop信号
if((i2c->devAddr & 0xfe) == (i2c->selfDevAddr & 0xfe))
{
// scl为高,sda上升沿,结束
i2c->slaveState = VTOR_I2C_SLAVE_STATE_STOP;
i2c->devAddr = 0; // 清空总线上的设备地址
VtorI2cSlave_StopCallback(i2c);
}
}
}
}
uint8_t VtorI2cSlave_WriteBuffer(VtorI2c* i2c, uint8_t* txbuf, uint8_t txLen)
{
if(i2c == NULL)
{
return 0;
}
// 从机读取数据后会 将tx len寄存器清零
// 只有tx len寄存器为0,才能放入新数据
if(0 == i2c->regData[VTOR_I2C_REG_SLAVE_TX_LEN])
{
// 复制到内存中,等待i2c主机获取
memcpy(&i2c->regData[VTOR_I2C_REG_SLAVE_TX_BUF], txbuf, txLen);
i2c->regData[VTOR_I2C_REG_SLAVE_TX_LEN] = txLen;
return txLen;
}
return 0;
}
uint8_t VtorI2cSlave_ReadBuffer(VtorI2c* i2c, uint8_t* rxBuf, uint8_t rxLen)
{
if(i2c == NULL)
{
return 0;
}
uint8_t masterTxLen = i2c->regData[VTOR_I2C_REG_SLAVE_RX_LEN];
// 如果rx len寄存器为0,说明没数据,直接返回
if(0 == masterTxLen)
{
return 0;
}
// rxLen使用两者中较小的数字
if(rxLen > masterTxLen)
{
rxLen = masterTxLen;
}
// 复制到内存中,等待i2c主机获取
memcpy(rxBuf, &i2c->regData[VTOR_I2C_REG_SLAVE_RX_BUF], rxLen);
i2c->regData[VTOR_I2C_REG_SLAVE_RX_LEN] = 0;
rxBuf[rxLen] = '\0';
return rxLen;
}
#endif // __VTOR_I2C_SLAVE__
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/vtor3478/vtor_elec_module.git
git@gitee.com:vtor3478/vtor_elec_module.git
vtor3478
vtor_elec_module
vtor_elec_module
main

搜索帮助

0d507c66 1850385 C8b1a773 1850385