|
|
#include "SWM221.h"
|
|
|
|
|
|
#include "IOI2C_SLV.h"
|
|
|
|
|
|
static char TxBuff[128] = {0};
|
|
|
static uint32_t TxSize = 0;
|
|
|
static volatile uint32_t TxIndx = 0;
|
|
|
|
|
|
static char RxBuff[128] = {0};
|
|
|
static uint32_t RxSize = 128; //最多能接收128个字节
|
|
|
static volatile uint32_t RxIndx = 0;
|
|
|
|
|
|
static volatile uint32_t BitTim = 0;
|
|
|
|
|
|
static volatile uint32_t IsBusy = 0; //检测到Start置位,检测到Stop清零
|
|
|
|
|
|
static volatile uint32_t IsNACK = 0; //发送数据时收到NACK
|
|
|
|
|
|
|
|
|
static uint32_t RxBuff2[128] = {0}; //接收到Stop时将RxBuff中数据搬运到这里,然后驱动可以继续用RxBuff接收数据位,用户可通过从RxBuff2中读走数据
|
|
|
static volatile uint32_t RxSize2 = 0; //RxBuff2中有多少个数据可以被读出
|
|
|
static volatile uint32_t RxIndx2 = 0;
|
|
|
|
|
|
static void (*IOI2C_SLV_Func)(void);
|
|
|
|
|
|
static void IOI2C_SLV_SendByte(void);
|
|
|
static void IOI2C_SLV_ReadByte(void);
|
|
|
|
|
|
extern uint32_t IOI2C_SLV_EmptyCallback(char *TxBuff);
|
|
|
|
|
|
/******************************************************************************************************************************************
|
|
|
* 函数名称: IOI2C_SLV_Init()
|
|
|
* 功能说明: IOI2C_SLV初始化
|
|
|
* 输 入: 无
|
|
|
* 输 出: 无
|
|
|
* 注意事项: 无
|
|
|
******************************************************************************************************************************************/
|
|
|
void IOI2C_SLV_Init(void)
|
|
|
{
|
|
|
#define IOI2C_PORT GPIOA
|
|
|
#define IOI2C_SCL PIN2
|
|
|
#define IOI2C_SDA PIN3
|
|
|
#define IOI2C_IRQ GPIOA_IRQn
|
|
|
#define IOI2C_ISR GPIOA_Handler
|
|
|
|
|
|
GPIO_Init(IOI2C_PORT, IOI2C_SCL, 0, 1, 0, 1);
|
|
|
#define I2C_SCL_Value() GPIO_GetBit(IOI2C_PORT, IOI2C_SCL)
|
|
|
|
|
|
GPIO_Init(IOI2C_PORT, IOI2C_SDA, 0, 1, 0, 1);
|
|
|
#define I2C_SDA_OUTPUT() IOI2C_PORT->DIR |= (1 << IOI2C_SDA);
|
|
|
#define I2C_SDA_LOW() GPIO_ClrBit(IOI2C_PORT, IOI2C_SDA)
|
|
|
#define I2C_SDA_HIGH() GPIO_SetBit(IOI2C_PORT, IOI2C_SDA)
|
|
|
|
|
|
#define I2C_SDA_INPUT() IOI2C_PORT->DIR &=~(1 << IOI2C_SDA)
|
|
|
#define I2C_SDA_Value() GPIO_GetBit(IOI2C_PORT, IOI2C_SDA)
|
|
|
|
|
|
|
|
|
EXTI_Init(IOI2C_PORT, IOI2C_SCL, EXTI_BOTH_EDGE);
|
|
|
EXTI_Init(IOI2C_PORT, IOI2C_SDA, EXTI_BOTH_EDGE);
|
|
|
|
|
|
NVIC_EnableIRQ(IOI2C_IRQ);
|
|
|
|
|
|
EXTI_Open(IOI2C_PORT, IOI2C_SCL);
|
|
|
EXTI_Open(IOI2C_PORT, IOI2C_SDA);
|
|
|
}
|
|
|
|
|
|
/******************************************************************************************************************************************
|
|
|
* 函数名称: IOI2C_SLV_RxNotEmpty()
|
|
|
* 功能说明: IOI2C从机接收缓冲区中是否有数据可取出
|
|
|
* 输 入: 无
|
|
|
* 输 出: uint32_t 0 没有可取出数据 >0 可取出的数据个数
|
|
|
* 注意事项: 无
|
|
|
******************************************************************************************************************************************/
|
|
|
uint32_t IOI2C_SLV_RxNotEmpty(void)
|
|
|
{
|
|
|
return RxSize2;
|
|
|
}
|
|
|
|
|
|
/******************************************************************************************************************************************
|
|
|
* 函数名称: IOI2C_SLV_FetchByte()
|
|
|
* 功能说明: 从IOI2C从机接收缓冲区中取出一个字节
|
|
|
* 输 入: 无
|
|
|
* 输 出: char 取出的字节
|
|
|
* 注意事项: 无
|
|
|
******************************************************************************************************************************************/
|
|
|
char IOI2C_SLV_FetchByte(void)
|
|
|
{
|
|
|
RxSize2 -= 1;
|
|
|
|
|
|
return RxBuff2[RxIndx2++];
|
|
|
}
|
|
|
|
|
|
/******************************************************************************************************************************************
|
|
|
* 函数名称: IOI2C_SLV_FetchBytes()
|
|
|
* 功能说明: 从IOI2C从机接收缓冲区中取出n个字节
|
|
|
* 输 入: char buff[] 取出的数据存入此数组
|
|
|
* uint32_t len 要取出的数据的个数,不得大于IOI2C_SLV_RxNotEmpty()返回值
|
|
|
* 输 出: 无
|
|
|
* 注意事项: 无
|
|
|
******************************************************************************************************************************************/
|
|
|
void IOI2C_SLV_FetchBytes(char buff[], uint32_t len)
|
|
|
{
|
|
|
uint32_t i;
|
|
|
|
|
|
for(i = 0; i < len; i++)
|
|
|
buff[i] = RxBuff2[RxIndx2+i];
|
|
|
RxIndx2 += len;
|
|
|
RxSize2 -= len;
|
|
|
}
|
|
|
|
|
|
|
|
|
static void IOI2C_SLV_SendByte(void)
|
|
|
{
|
|
|
if(IsNACK == 1)
|
|
|
{
|
|
|
I2C_SDA_INPUT();
|
|
|
|
|
|
goto noinc;
|
|
|
}
|
|
|
|
|
|
if(TxSize == 0)
|
|
|
{
|
|
|
TxSize = IOI2C_SLV_EmptyCallback(TxBuff);
|
|
|
|
|
|
TxIndx = 0;
|
|
|
}
|
|
|
|
|
|
if(BitTim == 0) I2C_SDA_OUTPUT(); //发送上一个字符时会将SDA切成输入脚以接收ACK
|
|
|
|
|
|
if(BitTim < 16)
|
|
|
{
|
|
|
if((BitTim % 2) == 0)
|
|
|
{
|
|
|
if(TxBuff[TxIndx] & (1 << (7 - BitTim/2)))
|
|
|
I2C_SDA_HIGH();
|
|
|
else
|
|
|
I2C_SDA_LOW();
|
|
|
}
|
|
|
}
|
|
|
else if(BitTim == 16)
|
|
|
{
|
|
|
I2C_SDA_INPUT();
|
|
|
}
|
|
|
else if(BitTim == 17)
|
|
|
{
|
|
|
if(I2C_SDA_Value()) //NACK
|
|
|
{
|
|
|
IsNACK = 1;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if(++TxIndx == TxSize)
|
|
|
{
|
|
|
TxIndx = TxSize - 1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
BitTim = 0;
|
|
|
goto noinc;
|
|
|
}
|
|
|
|
|
|
BitTim++;
|
|
|
|
|
|
noinc:
|
|
|
;
|
|
|
}
|
|
|
|
|
|
static void IOI2C_SLV_ReadByte(void)
|
|
|
{
|
|
|
if(BitTim == 0) I2C_SDA_INPUT(); //接收上一个字符时会将SDA切成输出脚以发送ACK
|
|
|
|
|
|
if(BitTim < 16)
|
|
|
{
|
|
|
if((BitTim % 2) == 1)
|
|
|
{
|
|
|
if(I2C_SDA_Value() == 1)
|
|
|
RxBuff[RxIndx] |= (1 << (7 - BitTim/2));
|
|
|
else
|
|
|
RxBuff[RxIndx] &= ~(1 << (7 - BitTim/2));
|
|
|
}
|
|
|
}
|
|
|
else if(BitTim == 16)
|
|
|
{
|
|
|
I2C_SDA_OUTPUT();
|
|
|
|
|
|
if(++RxIndx < RxSize)
|
|
|
{
|
|
|
I2C_SDA_LOW();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
I2C_SDA_HIGH();
|
|
|
}
|
|
|
}
|
|
|
else if(BitTim == 17)
|
|
|
{
|
|
|
if((RxIndx == 1) && (RxBuff[0] & 0x01))
|
|
|
{
|
|
|
TxIndx = 0;
|
|
|
|
|
|
IsNACK = 0;
|
|
|
|
|
|
IOI2C_SLV_Func = IOI2C_SLV_SendByte;
|
|
|
}
|
|
|
|
|
|
BitTim = 0;
|
|
|
goto noinc;
|
|
|
}
|
|
|
|
|
|
BitTim++;
|
|
|
|
|
|
noinc:
|
|
|
;
|
|
|
}
|
|
|
|
|
|
|
|
|
/******************************************************************************************************************************************
|
|
|
* 函数名称: IOI2C_ISR()
|
|
|
* 功能说明: IOI2C SCL、SDA引脚双边沿中断服务函数
|
|
|
* 输 入: 无
|
|
|
* 输 出: 无
|
|
|
* 注意事项: 无
|
|
|
******************************************************************************************************************************************/
|
|
|
void IOI2C_ISR(void)
|
|
|
{
|
|
|
uint32_t i;
|
|
|
|
|
|
if(EXTI_State(IOI2C_PORT, IOI2C_SDA))
|
|
|
{
|
|
|
EXTI_Clear(IOI2C_PORT, IOI2C_SDA);
|
|
|
|
|
|
if(I2C_SCL_Value() == 1) //只有在SCL高电平时SDA的跳变才是Start和Stop
|
|
|
{
|
|
|
if(I2C_SDA_Value() == 0) //Start
|
|
|
{
|
|
|
RxIndx = 0;
|
|
|
|
|
|
BitTim = 0;
|
|
|
|
|
|
IsBusy = 1;
|
|
|
|
|
|
IOI2C_SLV_Func = IOI2C_SLV_ReadByte;
|
|
|
}
|
|
|
else //Stop
|
|
|
{
|
|
|
IsBusy = 0;
|
|
|
|
|
|
for(i = 0; i < RxIndx-1; i++)
|
|
|
{
|
|
|
RxBuff2[i] = RxBuff[1+i]; //RxBuff[]中第一个字节是从机地址
|
|
|
}
|
|
|
RxSize2 = i;
|
|
|
RxIndx2 = 0;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else if(EXTI_State(IOI2C_PORT, IOI2C_SCL))
|
|
|
{
|
|
|
EXTI_Clear(IOI2C_PORT, IOI2C_SCL);
|
|
|
|
|
|
if(IsBusy) IOI2C_SLV_Func();
|
|
|
}
|
|
|
}
|