论坛大神
- 积分
- 3505
- 金钱
- 3505
- 注册时间
- 2014-8-4
- 在线时间
- 696 小时
|
发表于 2016-1-13 18:19:29
|
显示全部楼层
费了三四个小时终于移植成寄存器版本(如下),也是自己能力有限导致的,像楼主学习了~~~~~
头文件如下,在楼主基础上知识定义了一个变量IICSone作为示例:
[mw_shl_code=c,true]#ifndef __IICS__H
#define __IICS__H
#include "sys.h"
//模拟I2C结构体声明
struct SimuI2cPortType {
GPIO_TypeDef *SCLPort;//GPIO PORT
uint32_t SCLPin; //GPIO PIN
GPIO_TypeDef *SDAPort;//GPIO PORT
uint32_t SDAPin; //GPIO PIN
uint8_t address; //slave address
};
extern struct SimuI2cPortType IICSone;
//模拟I2C的SCL、SDA管脚控制宏定义
//SCL output hardware operate
#define SIMUI2C_SCL_SET HAL_GPIO_WritePin(pSimuI2cPort->SCLPort, pSimuI2cPort->SCLPin, 1)
#define SIMUI2C_SCL_CLR HAL_GPIO_WritePin(pSimuI2cPort->SCLPort, pSimuI2cPort->SCLPin, 0)
//SDA output hardware operate
#define SIMUI2C_SDA_SET HAL_GPIO_WritePin(pSimuI2cPort->SDAPort, pSimuI2cPort->SDAPin, 1)
#define SIMUI2C_SDA_CLR HAL_GPIO_WritePin(pSimuI2cPort->SDAPort, pSimuI2cPort->SDAPin, 0)
//SDA input hardware operate
#define SIMUI2C_SDA_IN HAL_GPIO_ReadPin(pSimuI2cPort->SDAPort, pSimuI2cPort->SDAPin)
//simulate i2c APIs
void bsp_SimuI2C_start(struct SimuI2cPortType *pSimuI2cPort);
void bsp_SimuI2C_stop(struct SimuI2cPortType *pSimuI2cPort);
void bsp_SimuI2C_SendAck(struct SimuI2cPortType *pSimuI2cPort);
void bsp_SimuI2C_SendNack(struct SimuI2cPortType *pSimuI2cPort);
uint32_t bsp_SimuI2C_ReadAck(struct SimuI2cPortType *pSimuI2cPort);
uint8_t bsp_SimuI2C_read_byte(struct SimuI2cPortType *pSimuI2cPort);
void bsp_SimuI2C_write_byte(struct SimuI2cPortType *pSimuI2cPort, uint8_t data);
void IICS_Init(void);
#endif /* End of module include */[/mw_shl_code]
.c文件实现如下
[mw_shl_code=c,true]#include "IICS.h"
#include "delay.h"
/*配置SCL管脚输出模式函数*/
static void config_scl_out(struct SimuI2cPortType *pSimuI2cPort)
{
if(pSimuI2cPort->SCLPin<8)
{
pSimuI2cPort->SCLPort->CRL &= ~(0X0000000F << (pSimuI2cPort->SCLPin*4));
pSimuI2cPort->SCLPort->CRL |= (u32)3 << (pSimuI2cPort->SCLPin*4);
}
else
{
pSimuI2cPort->SCLPort->CRH &= ~(0X0000000F << (pSimuI2cPort->SCLPin%8*4));
pSimuI2cPort->SCLPort->CRH |= (u32)3 << (pSimuI2cPort->SCLPin%8*4);
}
}
/*配置SDA管脚输出模式函数*/
static void config_sda_out(struct SimuI2cPortType *pSimuI2cPort)
{
if(pSimuI2cPort->SDAPin<8)
{
pSimuI2cPort->SDAPort->CRL &= ~(0X0000000F << (pSimuI2cPort->SDAPin*4));
pSimuI2cPort->SDAPort->CRL |= (u32)3 << (pSimuI2cPort->SDAPin*4);
}
else
{
pSimuI2cPort->SDAPort->CRH &= ~(0X0000000F << (pSimuI2cPort->SDAPin%8*4));
pSimuI2cPort->SDAPort->CRH |= (u32)3 << (pSimuI2cPort->SDAPin%8*4);
}
}
/*配置SDA管脚输入模式函数*/
static void config_sda_in(struct SimuI2cPortType *pSimuI2cPort)
{
if(pSimuI2cPort->SDAPin<8)
{
pSimuI2cPort->SDAPort->CRL &= ~(0X0000000F << (pSimuI2cPort->SDAPin*4));
pSimuI2cPort->SDAPort->CRL |= (u32)8 << (pSimuI2cPort->SDAPin*4);
}
else
{
pSimuI2cPort->SDAPort->CRH &= ~(0X0000000F << (pSimuI2cPort->SDAPin%8*4));
pSimuI2cPort->SDAPort->CRH |= (u32)8 << (pSimuI2cPort->SDAPin%8*4);
}
}
/*输出0 1*/
static void HAL_GPIO_WritePin(GPIO_TypeDef *Port, uint32_t Pin, u8 Value)
{
if(Value == 1) //SET
{
Port->ODR |= 1 << Pin;
}
else if(Value == 0) //RESET
{
Port->ODR &= ~(0x01 << Pin);
}
}
/*读取端口状态*/
static u16 HAL_GPIO_ReadPin(GPIO_TypeDef *Port, uint32_t Pin)
{
if(Port->IDR & (1 << Pin))
{
return 1;
}
else
{
return 0;
}
}
/* 生成一个I2C的start开始条件,或者restart重新开始条件
*********************************************************************************************************
* function : bsp_SimuI2C_start
* Description : generate a i2c start or restart
* Argument(s) : point to struct SimuI2cPortType
* Return(s) : none
*********************************************************************************************************
*/
void bsp_SimuI2C_start(struct SimuI2cPortType *pSimuI2cPort)
{
//config sda pin output
config_sda_out(pSimuI2cPort);
//here may be a stop
SIMUI2C_SCL_SET;
delay_us(1);//SCL setup time for STOP condition, 0.6uS
SIMUI2C_SDA_SET;
delay_us(4);//the bus must be free before a new transmission can start, 1.2uS
//start
SIMUI2C_SDA_CLR;
delay_us(4);//SCL hold time for START condition, 0.6uS
SIMUI2C_SCL_CLR;
delay_us(1);//SCL low period * 0.5 = 0.65uS
}
/* 生成一个I2C的stop停止条件
*********************************************************************************************************
* function : bsp_SimuI2C_stop
* Description : generate a i2c stop
* Argument(s) : point to struct SimuI2cPortType
* Return(s) : none
*********************************************************************************************************
*/
void bsp_SimuI2C_stop(struct SimuI2cPortType *pSimuI2cPort)
{
//config sda pin output
config_sda_out(pSimuI2cPort);
//set SCL and SDA low first
SIMUI2C_SCL_CLR;
delay_us(1);//SCL low period * 0.5 = 0.65uS
SIMUI2C_SDA_CLR;
delay_us(4);//SCL low period * 0.5 = 0.65uS
//stop
SIMUI2C_SCL_SET;
delay_us(1);//SCL setup time for STOP condition
SIMUI2C_SDA_SET;
delay_us(4);//Time the bus must be free before a new transmission can start, 1.2uS
}
/* 给从设备发送一个ack应答信号
*********************************************************************************************************
* function : bsp_SimuI2C_SandAck
* Description : generate a i2c ack to slave
* Argument(s) : point to struct SimuI2cPortType
* Return(s) : none
*********************************************************************************************************
*/
void bsp_SimuI2C_SendAck(struct SimuI2cPortType *pSimuI2cPort)
{
//config sda pin output
config_sda_out(pSimuI2cPort);
//set sda=0
//delay_us(1);//SCL low period * 0.5 = 0.65uS
SIMUI2C_SDA_CLR;//SDA=0
delay_us(1);//SCL low period * 0.5 = 0.65uS
//scl pulse
SIMUI2C_SCL_SET;
delay_us(1);//SCL high period, 0.6uS
SIMUI2C_SCL_CLR;
delay_us(1);//SCL low period * 0.5 = 0.65uS
}
/* 给从设备发送一个no ack非应答信号
*********************************************************************************************************
* function : bsp_SimuI2C_SandNack
* Description : generate a i2c noack to slave
* Argument(s) : point to struct SimuI2cPortType
* Return(s) : none
*********************************************************************************************************
*/
void bsp_SimuI2C_SendNack(struct SimuI2cPortType *pSimuI2cPort)
{
//config sda pin output
config_sda_out(pSimuI2cPort);
//set sda=1
//delay_us(1);//SCL low period * 0.5 = 0.65uS
SIMUI2C_SDA_SET;//SDA=1
delay_us(1);//SCL low period * 0.5 = 0.65uS
//scl pulse
SIMUI2C_SCL_SET;
delay_us(1);//SCL high period, 0.6uS
SIMUI2C_SCL_CLR;
delay_us(1);//SCL low period * 0.5 = 0.65uS
}
/* 读取从设备的ack应答信号状态, 0表示应答, 1表示非应答
*********************************************************************************************************
* function : bsp_SimuI2C_ReadAck
* Description : check i2c ack from slave
* Argument(s) : point to struct SimuI2cPortType
* Return(s) : 0: ack, 1: nack
*********************************************************************************************************
*/
uint32_t bsp_SimuI2C_ReadAck(struct SimuI2cPortType *pSimuI2cPort)
{
// uint32_t ack;
// //config sda pin input
// config_sda_in(pSimuI2cPort);
//
// delay_us(1);//SCL low period * 0.5 = 0.65uS
// SIMUI2C_SCL_SET;
// delay_us(1);//SCL high period, 0.6uS
// ack = SIMUI2C_SDA_IN;
// SIMUI2C_SCL_CLR;
// delay_us(1);//SCL low period * 0.5 = 0.65uS
// return ack;
u8 ucErrTime=0;
config_sda_in(pSimuI2cPort); //SDA设置为输入
SIMUI2C_SDA_SET;
delay_us(1);
SIMUI2C_SCL_SET;
delay_us(1);
while(SIMUI2C_SDA_IN)
{
ucErrTime++;
if(ucErrTime>250)
{
bsp_SimuI2C_stop(pSimuI2cPort);
return 1;
}
}
SIMUI2C_SCL_CLR;//时钟输出0
return 0;
}
/* 主机读取从设备,返回一个8bit数据
*********************************************************************************************************
* function : bsp_SimuI2C_read_byte
* Description : read a byte from i2c slave
* Argument(s) : point to struct SimuI2cPortType
* Return(s) : the read data
*********************************************************************************************************
*/
uint8_t bsp_SimuI2C_read_byte(struct SimuI2cPortType *pSimuI2cPort)
{
uint32_t i;
uint8_t data;
//config sda pin input
config_sda_in(pSimuI2cPort);
data = 0;
for(i=0; i<8; i++)
{
SIMUI2C_SCL_CLR;
delay_us(2);//SCL low period * 0.5 = 0.65uS
SIMUI2C_SCL_SET;
delay_us(1);//SCL high period, 0.6uS
//read data in
data<<=1;
if(1 == SIMUI2C_SDA_IN) data |= 0x01;
delay_us(1);//SCL low period * 0.5 = 0.65uS
}
bsp_SimuI2C_SendNack(pSimuI2cPort);
return data;
}
/* 主机写8bit数据到从设备
*********************************************************************************************************
* function : bsp_SimuI2C_write_byte
* Description : write a byte to i2c slave
* Argument(s) : pSimuI2cPort: point to struct SimuI2cPortType, data: data to write
* Return(s) : none
*********************************************************************************************************
*/
void bsp_SimuI2C_write_byte(struct SimuI2cPortType *pSimuI2cPort, uint8_t data)
{
uint32_t i;
//config sda pin output
config_sda_out(pSimuI2cPort);
for(i=0; i<8; i++) {
delay_us(1);//SCL low period * 0.5 = 0.65uS
//sda bit output
if(data & 0x80)
SIMUI2C_SDA_SET;
else
SIMUI2C_SDA_CLR;
delay_us(1);//SCL low period * 0.5 = 0.65uS
//scl pulse
SIMUI2C_SCL_SET;
delay_us(1);//SCL high period, 0.6uS
SIMUI2C_SCL_CLR;
//next bit
data <<= 1;
}
delay_us(1);//SCL low period * 0.5 = 0.65uS
}
/** End of bsp_SimulateI2C.c **/
/*----------------------------------------------------------------------------------------------------------------------*/
struct SimuI2cPortType IICSone;
void IICS_Init(void)
{
RCC->APB2ENR|=1<<3; //使能GPIOB时钟
IICSone.SCLPort = GPIOB;
IICSone.SCLPin = 6;
IICSone.SDAPort = GPIOB;
IICSone.SDAPin = 7;
IICSone.address = 0;
config_scl_out(&IICSone); //配置SCL工作模式
config_sda_out(&IICSone);
}
[/mw_shl_code]
|
|