STM32使用模拟IIC实现24C02读取

来源:本站
导读:目前正在解读《STM32使用模拟IIC实现24C02读取》的相关信息,《STM32使用模拟IIC实现24C02读取》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《STM32使用模拟IIC实现24C02读取》的详细说明。
简介:1.与硬件IIC的比较 1.1.使用灵活 可使用任意2个IO口实现,不用受芯片管脚限制;

1.与硬件IIC的比较

1.1.使用灵活

可使用任意2个IO口实现,不用受芯片管脚限制;

1.2.速率快

通过调整延时,可以实现超过400k的速率,实际测试最大速率接近800k;

1.3.容错性强

硬件IIC在通信出错后,无法自行恢复,模拟IIC则可以迅速恢复;

2.底层接口函数

2.1. I2C_Start

static uint8_t I2C_Start(void)

{

SDA_H;//拉高数据线

SCL_H;//拉高时钟线

I2C_DELAY;

if(SDA_read == RESET)

//SDA线为低电平则总线忙,退出

{

return I2C_BUS_BUSY;

}

SDA_L;//产生下降沿

I2C_DELAY;

SCL_L;//拉低时钟线

I2C_DELAY;

if(SDA_read == SET)

//SDA线为高电平则总线出错,退出

{

return I2C_BUS_ERROR;

}

return I2C_BUS_READY;

}

2.2. I2C_Stop

static void I2C_Stop(void)

{

SCL_L;

I2C_DELAY;

SDA_L;//拉低数据线

I2C_DELAY;

SCL_H;//拉高时钟线

I2C_DELAY;

SDA_H;//产生上升沿

I2C_DELAY;

}

2.3. I2C_SendACK

static void I2C_SendACK(void)

{

SCL_L;

I2C_DELAY;

SDA_L;//应答=0

I2C_DELAY;

SCL_H;//拉高时钟线

I2C_DELAY;

SCL_L;//拉低时钟线

I2C_DELAY;

}

2.4. I2C_SendNACK

static void I2C_SendNACK(void)

{

SCL_L;

I2C_DELAY;

SDA_H;//应答=1

I2C_DELAY;

SCL_H;//拉高时钟线

I2C_DELAY;

SCL_L;//拉低时钟线

I2C_DELAY;

}

2.5. I2C_WaitAck

static uint8_t I2C_WaitAck(void)//1:ACK;0:NoACK

{

//接收从机的应答

SDA_H;

I2C_DELAY;

SCL_H;//拉高时钟线

I2C_DELAY;

if(SDA_read)//读应答信号

{

SCL_L;//拉低时钟线

return I2C_NACK;

}

else

{

SCL_L;//拉低时钟线

return I2C_ACK;

}

}

2.6. I2C_Delay

static void I2C_Delay(void)//调整波特率

{

uint16_t i= 5;//=5~400k,16~200k,38~100k,81~50k

while(i--);//屏蔽本行,对应约800k速率

}

2.7. I2C_SendByte(uint8_tData)

static void I2C_SendByte(uint8_t Data)

{

uint8_t i;

for(i = 0; i < 8; i++)

{

SCL_L;//拉低时钟线

I2C_DELAY;

if(Data & 0x80)//移出数据的最高位

{

SDA_H;

}

else

{

SDA_L;

}

Data <<= 1;

I2C_DELAY;

SCL_H;//拉高时钟线

I2C_DELAY;

}

SCL_L;

I2C_DELAY;

}

2.8. I2C_RecvByte(void)

static uint8_t I2C_RecvByte(void)

{

uint8_t i, Dat = 0;

SDA_H;//准备读取数据

SCL_L;

I2C_DELAY;

for(i = 0; i < 8; i++)

{

SCL_H;//拉高时钟线,让从机准备好数据

I2C_DELAY;

Dat <<= 1;

if(SDA_read)//读数据

{

Dat |= 0x01;

}

SCL_L;//拉低时钟线

I2C_DELAY;

}

return Dat;

}

3.硬件接口(AT24cxx)

3.1. I2C_GPIO_Configuration

void I2C_GPIO_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(I2C_SDA_GPIO_CLK | I2C_SDA_GPIO_CLK, ENABLE);

#if 1

//重启从器件,引脚配置为PP方式

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN;

GPIO_Init(I2C_SDA_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN;

GPIO_Init(I2C_SCL_GPIO_PORT, &GPIO_InitStructure);

GPIO_ResetBits(I2C_SDA_GPIO_PORT, I2C_SDA_PIN);

GPIO_ResetBits(I2C_SCL_GPIO_PORT, I2C_SCL_PIN);

GPIO_SetBits(I2C_SDA_GPIO_PORT, I2C_SDA_PIN);

GPIO_SetBits(I2C_SCL_GPIO_PORT, I2C_SCL_PIN);

#endif

//配置引脚为OC模式,依赖上拉电阻实现数据功能

GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;

GPIO_Init(I2C_SDA_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;

GPIO_Init(I2C_SCL_GPIO_PORT, &GPIO_InitStructure);

}

3.2. I2C_Write_Buf_to_AT24cxx

uint8_t I2C_Write_Buf_to_AT24cxx(uint8_t AT24cxx_addr, uint16_t start_addr, uint16_t len, uint8_t* buf, uint8_t longaddr)

{

uint8_t i= 0;

uint8_t page, addr;

addr = start_addr & 0xff;

page = (start_addr >> 8) & 0x0f;

//1.协议开始

if(I2C_Start())

{

debug_out(("I2C_W_1rn"));

return 1;

}

//2.1.发送设备地址

I2C_SendByte(AT24cxx_addr | I2C_Direction_Transmitter);

//2.2.接收ACK

if(!I2C_WaitAck())

{

debug_out(("I2C_W_2rn"));

I2C_Stop();

return 1;

}

if(longaddr)//写入地址高位

{

//3.1.发送写入地址高位

I2C_SendByte(page);

//3.2.接收ACK

I2C_WaitAck();

}

//3.3.发送写入地址低位

I2C_SendByte(addr);

//3.4.接收ACK

I2C_WaitAck();

//4.写入数据并接收ACK

for(i = 0; i < len; i++)

{

//4.1.写入数据

I2C_SendByte(buf[i]);

//4.2.接收ACK数据

if(!I2C_WaitAck())//内部寄存器数据

{

debug_out(("I2C_W_3rn"));

I2C_Stop();//发送停止信号

return 1;

}

}

//5.协议结束

I2C_Stop();//发送停止信号

return 0;

}

3.2. I2C_Read_Buf_form_AT24cxx

uint8_t I2C_Read_Buf_form_AT24cxx(uint8_t AT24cxx_addr, uint16_t start_addr, uint16_t len, uint8_t* buf, uint8_t longaddr)

{

uint8_t page, addr;

addr = start_addr & 0xff;

page = (start_addr >> 8) & 0x0f;

//1.协议开始

if(I2C_Start())

{

debug_out(("I2C_r_1rn"));

return 1;

}

//2.1.发送设备地址(写地址)

I2C_SendByte(AT24cxx_addr | I2C_Direction_Transmitter);

//2.2.接收ACK

if(!I2C_WaitAck())

{

I2C_Stop();

debug_out(("I2C_r_2rn"));

return 1;

}

if(longaddr)//写入地址高位

{

//3.1.发送写入地址高位

I2C_SendByte(page);

//3.2.接收ACK

I2C_WaitAck();

}

//3.3.发送写入地址低位

I2C_SendByte(addr);

//3.4.接收ACK

I2C_WaitAck();

//4.协议再次启动

I2C_Start();

//5.1.发送设备地址(读地址)

I2C_SendByte(AT24cxx_addr | I2C_Direction_Receiver);

//5.2.接收ACK

I2C_WaitAck();

//6.读取数据并发送ACK或NACK

while(len)

{

//6.1.读取数据

*buf = I2C_RecvByte();

buf++;

len--;

//6.2.发送ACK或NACK指令

if(len)//仍有数据需要读取,发送ACK

{

I2C_SendACK();

}

else//数据已经读取完毕,发送NACK

{

I2C_SendNACK();

}

}

//7.协议结束

I2C_Stop();

return 0;

}

4.测试程序

4.测试程序

4.1.初始化

I2C_GPIO_Configuration();

4.2.写入测试

#define IIC_SIZE 256

if(AT_24cxx_Write_Buf(xg_data,0,IIC_SIZE))

{

err++;

}

4.3.读取测试

#define IIC_SIZE 256

if(AT_24cxx_Read_Buf(tmp_buf,0,IIC_SIZE))

{

err++;

}

4.4.数据验证

for(k = 0; k < IIC_SIZE; k++)

{

if(tmp_buf[k] != xg_data[k])

{

err++;

}

}

4.5.周期测试

if(count++ == 100)

{

relay = DWT_Time_Relay(0);

count = 0;

j++;

sprintf((char*)tmp_buf,"运行%dk次,用时%dms,出错=%drn",j, (relay/1000), err);

USB_Put_Str_PC((uint8_t *)tmp_buf);

////USB_Put_MultByte_PC((uint8_t *)tmp_buf, IIC_SIZE);

DWT_Delayms(100);

DWT_Time_Start(0);

}

4.6.实际运行时间:

24C02,共256字节,写入用时330ms,读取用时6ms。

提醒:《STM32使用模拟IIC实现24C02读取》最后刷新时间 2024-03-14 00:54:10,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《STM32使用模拟IIC实现24C02读取》该内容的真实性请自行鉴别。