首先声明这里没有打开STM32的事件中断。本人菜鸟玩了两天I2C。
#include"stm32f10x_lib.h"
#include"stm32f10x_it.h"
#include"sys.h"
#define AT24C02_Addr_Write 0XA0;
#define AT24C02_Addr_Read(0XA0+1);
void IIC1_Init(u8 Addr);
void AT24C02_WriteByte(u8 ByteAddr,u8 Data);
int AT24C02_ReadByte(u8 ByteAddr);
int N;
int main(void)
{
Stm32_Clock_Init(9); //中断向量表映射到flash区,(SYSTEM=72MHZ AHB=72MHZAPB1=36MHZ APB2=72MHZ PLL=72MHZ PLL2=40MHZ)
delay_init(72);//延时初始化
RCC->APB2ENR |= 1<<3; //使能PORTB时钟;
GPIOB->CRL &= 0x00FFFFFF; //PB6 I2C1_SCL ,PB7I2C1_SDL
GPIOB->CRL |= 0xFF000000; //复用开漏输出
IIC1_Init(0X30);//初始化IIC1接口地址为0X30
AT24C02_WriteByte(0X02,0XAA);//向AT24C02的0X02单元写入0XAA
delay_ms(3);//延时不可小于2ms
N=AT24C02_ReadByte(0X02); //从AT24C02的0X02单元读出数据
while(1)
{
}
}
//IIC1初始化,Addr为IIC1的自身地址
void IIC1_Init(u8 Addr)
{
RCC->APB1ENR |= 1<<21; //打开I2C1时钟
RCC->APB1RSTR |= 1<<21; //复位I2C1
RCC->APB1RSTR &= ~(1<<21); //复位结束I2C1
I2C1->CR1 |= 1<<15; //复位寄存器
I2C1->CR1 &= ~(1<<15); //复位结束
//I2C模块时钟频率,2~36MHz之间
I2C1->CR2 |= 36 ; //000000:禁用 000001:禁用
I2C1->CCR &= ~(1<<15); //I2C主模式 0:标准模式的I2C1:快速模式的I2C
//I2C1->CCR &= ~(1<<14); //快速模式时的占空比 0:Tlow/Thigh=21:Tlow/Thigh=16/9 (标准模式时Tlow/Thigh=1/1)
//得到200KHZ频率
I2C1->CCR |= 90<<0;//标准模式时钟控制分频系数=PCLK1/2/f,f为想得到的频率
I2C1->TRISE |= 37;//最大允许SCL上升时间为1000ns,故TRISE[5:0]中必须写入(1us/(1/36)us =36+1)。
//I2C1->CR1 |= 1<<10;//打开ACK应答,在接收到一个字节后返回一个应答
I2C1->CR1 |= 1<<6; //广播呼叫使能
I2C1->CR1 &= ~(1<<1); //0:I2C模式1:SMBus模式
I2C1->OAR1 &= ~(1<<15);//寻址模式 1:响应10位地址0:响应7位地址
I2C1->OAR1 |= 1<<14; //必须始终由软件保持为1
I2C1->OAR1 |= Addr<<1; //设置接口地址的7~1位
//I2C1->CR2 |= 1<<10; //缓冲器中断使能
//I2C1->CR2 |= 1<<9; //事件中断使能
I2C1->CR2 |= 1<<8; //出错中断使能
I2C1->CR1 |= 1<<0; //开启I2C1
}
//向AT24C02写一个字节,ByteAddr字节地址(0~255),Data所要写入的数据
void AT24C02_WriteByte(u8 ByteAddr,u8 Data)
{
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 = ByteAddr;//写入字节地址
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产生停止条件
}
//从AT24C02读出一个字节,ByteAddr字节地址(0~255)
int AT24C02_ReadByte(u8 ByteAddr)
{
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 = ByteAddr;//写入字节地址
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;
}
void I2C1_ER_IRQHandler(void)
{
if(I2C1->SR1 & 1<<10) //应答失败
{
I2C1->SR1 &=~(1<<10); //清除中断
}
if(I2C1->SR1 & 1<<14) //超时
{
I2C1->SR1 &=~(1<<14); //清除中断
}
if(I2C1->SR1 & 1<<11) //过载/欠载
{
I2C1->SR1 &=~(1<<11); //清除中断
}
if(I2C1->SR1 & 1<<9) //仲裁丢失
{
I2C1->SR1 &=~(1<<9); //清除中断
}
if(I2C1->SR1 & 1<<8) //总线出错
{
I2C1->SR1 &=~(1<<8); //清除中断
}
}
|