You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

294 lines
6.7 KiB
C

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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();
}