|
|
#include "SWM221.h"
|
|
|
|
|
|
#include "IOI2C_MST.h"
|
|
|
|
|
|
static char TxBuff[128] = {0};
|
|
|
static uint32_t TxSize = 0;
|
|
|
static volatile uint32_t TxIndx = 0;
|
|
|
|
|
|
static char *RxBuff = 0;
|
|
|
static uint32_t RxSize = 0;
|
|
|
static volatile uint32_t RxIndx = 0;
|
|
|
|
|
|
static volatile uint32_t BitTim = 0;
|
|
|
|
|
|
static volatile uint32_t IsRead = 0;
|
|
|
|
|
|
static volatile uint32_t IsBusy = 0;
|
|
|
|
|
|
|
|
|
static void (*IOI2C_MST_Func)(void);
|
|
|
|
|
|
static void IOI2C_MST_Start(void);
|
|
|
static void IOI2C_MST_SendByte(void);
|
|
|
static void IOI2C_MST_ReadByte(void);
|
|
|
static void IOI2C_MST_Stop(void);
|
|
|
|
|
|
static void delayuS(uint32_t dly) { uint32_t i; for(i = 0; i < SystemCoreClock/1000000 * dly; i++) __NOP(); }
|
|
|
|
|
|
/******************************************************************************************************************************************
|
|
|
* 函数名称: IOI2C_MST_Init()
|
|
|
* 功能说明: IOI2C主机初始化
|
|
|
* 输 入: uint32_t baud IOI2C主机波特率,即位传输速率,单位bps
|
|
|
* 输 出: 无
|
|
|
* 注意事项: 无
|
|
|
******************************************************************************************************************************************/
|
|
|
void IOI2C_MST_Init(uint32_t baud)
|
|
|
{
|
|
|
#define IOI2C_PORT GPIOA
|
|
|
#define IOI2C_SCL PIN2
|
|
|
#define IOI2C_SDA PIN3
|
|
|
#define IOI2C_TMR BTIMR0
|
|
|
#define IOI2C_ISR BTIMR0_Handler
|
|
|
|
|
|
GPIO_Init(IOI2C_PORT, IOI2C_SCL, 1, 0, 0, 0);
|
|
|
#define I2C_SCL_LOW() { GPIO_ClrBit(IOI2C_PORT, IOI2C_SCL); delayuS(1); }
|
|
|
#define I2C_SCL_HIGH() { GPIO_SetBit(IOI2C_PORT, IOI2C_SCL); delayuS(1); }
|
|
|
|
|
|
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)
|
|
|
|
|
|
I2C_SDA_HIGH();
|
|
|
I2C_SCL_HIGH();
|
|
|
|
|
|
TIMR_Init(IOI2C_TMR, TIMR_MODE_TIMER, 10, SystemCoreClock/10/(baud*2), 1); //波特率为baud,则时钟翻转速率为baud*2
|
|
|
|
|
|
NVIC_SetPriority(BTIMR0_IRQn, 3); // 将I2C主机的中断优先级设置的比从机低,因为从机来不及处理的话会返回NAK
|
|
|
}
|
|
|
|
|
|
/******************************************************************************************************************************************
|
|
|
* 函数名称: IOI2C_MST_Send()
|
|
|
* 功能说明: IOI2C主机发送数据
|
|
|
* 输 入: char slvaddr 从机地址
|
|
|
* char buff[] 要发送的数据
|
|
|
* uint32_t size 要发送的数据的个数,最多128个
|
|
|
* 输 出: 无
|
|
|
* 注意事项: 只能在 IOI2C_MST_IsBusy() == 0 时发送
|
|
|
******************************************************************************************************************************************/
|
|
|
void IOI2C_MST_Send(char slvaddr, char buff[], uint32_t size)
|
|
|
{
|
|
|
uint32_t i;
|
|
|
|
|
|
TxBuff[0] = (slvaddr << 1) | 0;
|
|
|
for(i = 1; i <= size; i++)
|
|
|
TxBuff[i] = buff[i-1];
|
|
|
TxSize = i;
|
|
|
TxIndx = 0;
|
|
|
|
|
|
BitTim = 0;
|
|
|
|
|
|
IsRead = 0;
|
|
|
|
|
|
IsBusy = 1;
|
|
|
|
|
|
IOI2C_MST_Func = IOI2C_MST_Start;
|
|
|
TIMR_Start(IOI2C_TMR);
|
|
|
}
|
|
|
|
|
|
/******************************************************************************************************************************************
|
|
|
* 函数名称: IOI2C_MST_Read()
|
|
|
* 功能说明: IOI2C主机读取数据
|
|
|
* 输 入: char slvaddr 从机地址
|
|
|
* char buff[] 读取到的数据存入此数组
|
|
|
* uint32_t size 要读取的数据的个数,最多128个
|
|
|
* 输 出: 无
|
|
|
* 注意事项: 只能在 IOI2C_MST_IsBusy() == 0 时读取,当再次 IOI2C_MST_IsBusy() == 0 时读取到的数据已经存储在buff[]中
|
|
|
******************************************************************************************************************************************/
|
|
|
void IOI2C_MST_Read(char slvaddr, char buff[], uint32_t size)
|
|
|
{
|
|
|
uint32_t i;
|
|
|
|
|
|
TxBuff[0] = (slvaddr << 1) | 1;
|
|
|
for(i = 1; i <= size; i++)
|
|
|
TxBuff[i] = buff[i-1];
|
|
|
TxSize = i;
|
|
|
TxIndx = 0;
|
|
|
|
|
|
RxBuff = buff;
|
|
|
for(i = 0; i < size; i++)
|
|
|
RxBuff[i] = 0;
|
|
|
RxSize = i;
|
|
|
RxIndx = 0;
|
|
|
|
|
|
BitTim = 0;
|
|
|
|
|
|
IsRead = 1;
|
|
|
|
|
|
IsBusy = 1;
|
|
|
|
|
|
IOI2C_MST_Func = IOI2C_MST_Start;
|
|
|
TIMR_Start(IOI2C_TMR);
|
|
|
}
|
|
|
|
|
|
/******************************************************************************************************************************************
|
|
|
* 函数名称: IOI2C_MST_IsBusy()
|
|
|
* 功能说明: IOI2C主机否正在发送/接收
|
|
|
* 输 入: 无
|
|
|
* 输 出: uint32_t 1 IOI2C正忙于发送/接收 0 IOI2C当前空闲,可以发起新的发送
|
|
|
* 注意事项: 无
|
|
|
******************************************************************************************************************************************/
|
|
|
uint32_t IOI2C_MST_IsBusy(void)
|
|
|
{
|
|
|
return IsBusy;
|
|
|
}
|
|
|
|
|
|
static void IOI2C_MST_Start(void)
|
|
|
{
|
|
|
I2C_SDA_LOW();
|
|
|
|
|
|
IOI2C_MST_Func = IOI2C_MST_SendByte;
|
|
|
}
|
|
|
|
|
|
static void IOI2C_MST_SendByte(void)
|
|
|
{
|
|
|
if(BitTim < 16)
|
|
|
{
|
|
|
if((BitTim % 2) == 0)
|
|
|
{
|
|
|
I2C_SCL_LOW();
|
|
|
|
|
|
if(BitTim == 0) I2C_SDA_OUTPUT(); //发送上一个字符时会将SDA切成输入脚以接收ACK
|
|
|
|
|
|
if(TxBuff[TxIndx] & (1 << (7 - BitTim/2)))
|
|
|
I2C_SDA_HIGH();
|
|
|
else
|
|
|
I2C_SDA_LOW();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
I2C_SCL_HIGH();
|
|
|
}
|
|
|
}
|
|
|
else if(BitTim == 16)
|
|
|
{
|
|
|
I2C_SCL_LOW();
|
|
|
|
|
|
I2C_SDA_INPUT();
|
|
|
}
|
|
|
else if(BitTim == 17)
|
|
|
{
|
|
|
I2C_SCL_HIGH();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if(I2C_SDA_Value()) //NACK
|
|
|
{
|
|
|
IOI2C_MST_Func = IOI2C_MST_Stop;
|
|
|
}
|
|
|
else if((TxIndx == 0) && IsRead)
|
|
|
{
|
|
|
IOI2C_MST_Func = IOI2C_MST_ReadByte;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if(++TxIndx == TxSize)
|
|
|
{
|
|
|
IOI2C_MST_Func = IOI2C_MST_Stop;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
BitTim = 0;
|
|
|
goto noinc;
|
|
|
}
|
|
|
|
|
|
BitTim++;
|
|
|
|
|
|
noinc:
|
|
|
;
|
|
|
}
|
|
|
|
|
|
static void IOI2C_MST_ReadByte(void)
|
|
|
{
|
|
|
if(BitTim < 16)
|
|
|
{
|
|
|
if((BitTim % 2) == 0)
|
|
|
{
|
|
|
I2C_SCL_LOW();
|
|
|
|
|
|
if(BitTim == 0) I2C_SDA_INPUT(); //接收上一个字符时会将SDA切成输出脚以发送ACK
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
I2C_SCL_HIGH();
|
|
|
|
|
|
RxBuff[RxIndx] |= I2C_SDA_Value() << (7 - BitTim/2);
|
|
|
}
|
|
|
}
|
|
|
else if(BitTim == 16)
|
|
|
{
|
|
|
I2C_SCL_LOW();
|
|
|
|
|
|
I2C_SDA_OUTPUT();
|
|
|
|
|
|
if(++RxIndx < RxSize)
|
|
|
{
|
|
|
I2C_SDA_LOW();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
I2C_SDA_HIGH();
|
|
|
}
|
|
|
}
|
|
|
else if(BitTim == 17)
|
|
|
{
|
|
|
I2C_SCL_HIGH();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if(RxIndx == RxSize)
|
|
|
{
|
|
|
IOI2C_MST_Func = IOI2C_MST_Stop;
|
|
|
}
|
|
|
|
|
|
BitTim = 0;
|
|
|
goto noinc;
|
|
|
}
|
|
|
|
|
|
BitTim++;
|
|
|
|
|
|
noinc:
|
|
|
;
|
|
|
}
|
|
|
|
|
|
static void IOI2C_MST_Stop(void)
|
|
|
{
|
|
|
if(BitTim == 0)
|
|
|
{
|
|
|
I2C_SCL_LOW();
|
|
|
|
|
|
I2C_SDA_LOW();
|
|
|
I2C_SDA_OUTPUT(); //发送上一个字符时会将SDA切成输入脚以接收ACK
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
I2C_SCL_HIGH();
|
|
|
|
|
|
I2C_SDA_HIGH();
|
|
|
|
|
|
IsBusy = 0;
|
|
|
|
|
|
TIMR_Stop(IOI2C_TMR);
|
|
|
}
|
|
|
|
|
|
BitTim++;
|
|
|
}
|
|
|
|
|
|
/******************************************************************************************************************************************
|
|
|
* 函数名称: IOI2C_ISR()
|
|
|
* 功能说明: TIMER中断服务程序,以2倍SCL时钟频率执行
|
|
|
* 输 入: 无
|
|
|
* 输 出: 无
|
|
|
* 注意事项: 无
|
|
|
******************************************************************************************************************************************/
|
|
|
void IOI2C_ISR(void)
|
|
|
{
|
|
|
TIMR_INTClr(IOI2C_TMR);
|
|
|
|
|
|
if(IsBusy) IOI2C_MST_Func();
|
|
|
}
|