中级会员
 
- 积分
- 280
- 金钱
- 280
- 注册时间
- 2019-12-26
- 在线时间
- 134 小时
|
本帖最后由 无敌是多么寂寞1 于 2020-3-27 21:28 编辑
F103的硬件IIC读写AT24C02,已经可以实现读取了,但是会时不时出现小bug,也想请大家指教
void I2C_Init(u8 ADDR)
{
RCC->APB2ENR |=1<<3;//开启PORTB时钟
RCC->APB1ENR |=1<<21;//开启I2C1时钟
RCC->APB1RSTR |= 1<<21; //复位I2C1
RCC->APB1RSTR &= ~(1<<21); //复位结束I2C1
I2C1->CR1 |= 1<<15; //复位寄存器
I2C1->CR1 &= ~(1<<15); //复位结束
GPIOB->CRL &=0X00FFFFFF;//初始化PB6、PB7
GPIOB->CRL |=0XFF000000;//复用开漏50MHZ
I2C1->CR2|=36<<0;//I2C时钟频率8M
I2C1->CCR |= 180<<0; //标准模式时钟控制 分频系数=PCLK1/2/f,f为想得到的频率 100KHz
I2C1->TRISE |= 37; //最大允许SCL上升时间为1000ns,故TRISE[5:0]中必须写入(1us/(1/36)us = 36+1)
I2C1->CCR &= ~(1<<15);//I2C主模式 0:标准模式的I2C 1:快速模式的I2C
I2C1->OAR1 |= 1<<14; //必须始终由软件保持为1
I2C1->OAR1 |=ADDR<<1;//设置地址
I2C1->CR1 |=1<<0;//启用I2C
}
void I2C1_GPIO_Set(u8 mode)
{
if(mode)
{
GPIOB->CRL &=0X00FFFFFF;//初始化PB6、PB7
GPIOB->CRL |=0X33000000;//复用开漏50MHZ
GPIOB->ODR &=~(3<<6);//强制拉低总线
delay_us(1);
GPIOB->ODR |=3<<6;//强制拉高总线
delay_us(4);
}
else
{
GPIOB->CRL &=0X00FFFFFF;//初始化PB6、PB7
GPIOB->CRL |=0XFF000000;//复用开漏50MHZ
}
}
void I2C_WriteDate(u8 Data_Addr,u8 data)
{
int clear;
clear=clear;
I2C1_GPIO_Set(I2C_GPIOPP);
while(I2C1->SR2&(1<<1));//等待SR2.Busy=0(总线空闲)
I2C1->CR1 |= 1<<8; //I2C1产生起始条件
I2C1_GPIO_Set(I2C_GPIOAF);
while(!(I2C1->SR1&=1<<0));//等待SR1.SB=1开始位已经发送
I2C1->SR1 &= ~(1<<10);//SR1.AF清零
I2C1->DR = AT24C02_Addr_Write;//写入AT24C02的地址Addr,写指令,SR1.SB清零
while(!(I2C1->SR1&=1<<1));//等待SR1.ADDR=1,从设备应答
clear=I2C1->SR1;
clear=I2C1->SR2;//SR1.ADDR清零
I2C1->DR = Data_Addr;//写入字节地址
while(!(I2C1->SR1&(1<<2)));//等待SR1.BTF=1,字节地址发送完毕
clear=I2C1->SR1;//SR1.BTF清零
I2C1->DR = data;//发送要写入的数据
while(!(I2C1->SR1&(1<<2)));//数据发送完成
I2C1->CR1 |= 1<<9; //I2C1产生停止条件
}
u8 I2C_Read_Data(u8 Data_Addr)
{
int clear;
clear=clear;
while(I2C1->SR2&(1<<1)); //等待SR2.Busy=0(总线空闲)
I2C1->CR1 |= 1<<8; //I2C1产生起始条件
while(!(I2C1->SR1&(1<<0)));//等待SR1.SB=1开始位已经发送
I2C1->SR1 &= ~(1<<10);//SR1.AF清零
I2C1->DR = AT24C02_Addr_Write;//写入AT24C02的地址Addr,写指令,SR1.SB清零
while(!(I2C1->SR1&(1<<1)));//等待SR1.ADDR=1,从设备应答
clear=I2C1->SR1;
clear=I2C1->SR2;//SR1.ADDR清零
I2C1->DR = Data_Addr;//读取字节地址
I2C1->CR1 |= 1<<8; //I2C1产生起始条件
while(!(I2C1->SR1&(1<<0)));//等待SR1.SB=1开始位已经发送
I2C1->SR1 &= ~(1<<10);//SR1.AF清零
I2C1->DR = AT24C02_Addr_Read;//写入AT24C02的地址Addr,读指令,SR1.SB清零
while(!(I2C1->SR1&(1<<1)));//等待SR1.ADDR=1,从设备应答
clear=I2C1->SR1;
clear=I2C1->SR2;//SR1.ADDR清零
while(!(I2C1->SR1&(1<<6)));//等待SR1.RxNE=1,接收到数据
I2C1->CR1 |= 1<<9; //I2C1产生停止条件
return I2C1->DR;
}
|
|