全站数据
8 4 2 0 5 8 1

stm32f103普通io口可以作为i2c通信接口吗

学习俱乐部 | 简单学习,快乐成才!         
问题更新日期:2024-10-13 12:42:30

问题描述

stm32f103普通io口可以作为i2c通信接口吗,麻烦给回复
精选答案
最佳答案

可以,模拟i2c即可,举例:

void IIC_Init(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure);

IIC_SCL=1;

IIC_SDA=1;

}

//产生IIC起始信号

void IIC_Start(void)

{

SDA_OUT(); //sda线输出

IIC_SDA=1;

IIC_SCL=1;

delay_us(4);

IIC_SDA=0;//START:when CLK is high,DATA change form high to low

delay_us(4);

IIC_SCL=0;//钳住I2C总线,准备发送或接收数据

}

//产生IIC停止信号

void IIC_Stop(void)

{

SDA_OUT();//sda线输出

IIC_SCL=0;

IIC_SDA=0;//STOP:when CLK is high DATA change form low to high

delay_us(4);

IIC_SCL=1;

IIC_SDA=1;//发送I2C总线结束信号

delay_us(4);

}

//等待应答信号到来

//返回值:1,接收应答失败

//0,接收应答成功

u8 IIC_Wait_Ack(void)

{

u8 ucErrTime=0;

SDA_IN();//SDA设置为输入

IIC_SDA=1;delay_us(1);

IIC_SCL=1;delay_us(1);

while(READ_SDA)

{

ucErrTime++;

if(ucErrTime>250)

{

IIC_Stop();

return 1;

}

}

IIC_SCL=0;//时钟输出0

return 0;

}

//产生ACK应答

void IIC_Ack(void)

{

IIC_SCL=0;

SDA_OUT();

IIC_SDA=0;

delay_us(2);

IIC_SCL=1;

delay_us(2);

IIC_SCL=0;

}

//不产生ACK应答

void IIC_NAck(void)

{

IIC_SCL=0;

SDA_OUT();

IIC_SDA=1;

delay_us(2);

IIC_SCL=1;

delay_us(2);

IIC_SCL=0;

}

//IIC发送一个字节

//返回从机有无应答

//1,有应答

//0,无应答

void IIC_Send_Byte(u8 txd)

{

u8 t;

SDA_OUT();

IIC_SCL=0;//拉低时钟开始数据传输

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

{

IIC_SDA=(txd&0x80)>>7;

txd<<=1;

delay_us(2); //对TEA5767这三个延时都是必须的

IIC_SCL=1;

delay_us(2);

IIC_SCL=0;

delay_us(2);

}

}

//读1个字节,ack=1时,发送ACK,ack=0,发送nACK

u8 IIC_Read_Byte(unsigned char ack)

{

unsigned char i,receive=0;

SDA_IN();//SDA设置为输入

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

{

IIC_SCL=0;

delay_us(2);

IIC_SCL=1;

receive<<=1;

if(READ_SDA)receive++;

delay_us(1);

}

if (!ack)

IIC_NAck();//发送nACK

else

IIC_Ack(); //发送ACK

return receive;

}

void I2C_WriteByte(uint16_t addr,uint8_t data,uint8_t device_addr)

{

IIC_Start();

if(device_addr==0xA0) //eeprom地址大于1字节

IIC_Send_Byte(0xA0 + ((addr/256)<<1));//发送高地址

else

IIC_Send_Byte(device_addr); //发器件地址

IIC_Wait_Ack();

IIC_Send_Byte(addr&0xFF); //发送低地址

IIC_Wait_Ack();

IIC_Send_Byte(data); //发送字节

IIC_Wait_Ack();

IIC_Stop();//产生一个停止条件

if(device_addr==0xA0) //

delay_ms(10);

else

delay_us(2);

}

uint16_t I2C_ReadByte(uint16_t addr,uint8_t device_addr,uint8_t ByteNumToRead)//读寄存器或读数据

{

uint16_t data;

IIC_Start();

if(device_addr==0xA0)

IIC_Send_Byte(0xA0 + ((addr/256)<<1));

else

IIC_Send_Byte(device_addr);

IIC_Wait_Ack();

IIC_Send_Byte(addr&0xFF); //发送低地址

IIC_Wait_Ack();

IIC_Start();

IIC_Send_Byte(device_addr+1); //发器件地址

IIC_Wait_Ack();

if(ByteNumToRead == 1)//LM75温度数据为11bit

{

data=IIC_Read_Byte(0);

}

else

{

data=IIC_Read_Byte(1);

data=(data<<8)+IIC_Read_Byte(0);

}

IIC_Stop();//产生一个停止条件

return data;

}