新手上路
- 积分
- 49
- 金钱
- 49
- 注册时间
- 2015-1-12
- 在线时间
- 0 小时
|

楼主 |
发表于 2015-1-15 09:20:07
|
显示全部楼层
回复【9楼】augustedward:
---------------------------------
这是昨天根据网上的资料改的,在中断中收发。可是SCK都没有产生时钟。。。
void I2C_Init(void)
{
////////////////I2C GPIO配置
RCC->APB2ENR |= 1<<3; //使能PORTB时钟
GPIOB->CRH &= 0xFFFF00FF; //I2C2:PB10->SCL,  B11->SDL
GPIOB->CRH |= 0x0000FF00; //复用开漏输出
////////////////I2C 寄存器配置
RCC->APB1ENR |= 1<<22; //使能外设I2C2时钟
I2C2->CR1 |= 0<<0; //禁用I2C2
RCC->APB1RSTR |= 1<<22; //复位I2C2
RCC->APB1RSTR &= ~(1<<22); //复位结束I2C2
I2C2->CR2 |= 36; //000010:2MHz ... 100100:36MHz,其他禁用(此处为36MHZ)
I2C2->CCR |= 0<<15; //I2C主模式 0:标准模式的I2C 1:快速模式的I2C
I2C2->CCR |= 90<<0; //时钟控制分频系数 =  CLK1/2/f(f为想得到的频率,此处PCLK1=36MHZ,f=200KHZ)
I2C2->TRISE |= 37; //最大允许SCL上升时间为1000ns,故TRISE[5:0]中必须写入(1us/(1/36)us = 36+1)
I2C2->CR1 |= 1<<10; //打开ACK应答,在接收到一个字节后返回一个应答
I2C2->CR1 |= 1<<6; //广播呼叫使能
I2C2->OAR1 |= 0<<15; //寻址模式 1 响应10位地址 0 响应7位地址
I2C2->OAR1 |= 1<<14; //必须始终由软件保持为 1
I2C2->OAR1 |= 0xBC<<1; //设置接口地址的 7~1位(接口地址设为0XBC)
I2C2->CR2 |= 1<<9; //事件中断使能
I2C2->CR2 |= 1<<8; //出错中断使能
I2C2->CR1 |= 1<<0; //开启I2C2
////////////////I2C 开中断
MY_NVIC_Init(1,0,I2C2_EV_IRQChannel,2); //设置抢占优先级为4,响应优先级为0,中断分组为4
MY_NVIC_Init(0,0,I2C2_ER_IRQChannel,2); //设置I2C错误中断抢占优先级为3
}
void I2C_Start(void) //I2C2产生起始条件
{
I2C2->CR1 |= 1<<8;
}
void I2C_Stop(void) //I2C2产生停止条件
{
I2C2->CR1 |= 1<<9;
}
void I2C_End(void) //关闭I2C
{
I2C2->CR1 &= ~(1<<0);
}
void I2C_Write(u8 data) //I2C2写一个字节
{
I2C2->DR = data;
}
u8 I2C_Read(void) //I2C2读一个字节
{
while(!(I2C2->SR1 & 1<<6)); //接收到数据标志位
return I2C2->DR;
}
u8 go = 0;
void I2C2_EV_IRQHandler(void)
{
u16 clear = 0;
if(I2C2 -> SR1 & 1<<0 ) //已发送起始条件,写数据寄存器的操作将清除该位
{
switch(go)
{
case 0:
{
I2C_Write(WRITE_ADDR); //写入从机地址,写指令操作地址
break;
}
case 1:
{
I2C_Write(WRITE_ADDR); //写入从机地址,写指令操作地址
break;
}
case 2:
{
I2C_Write(READ_ADDR); //写入从机地址,读数据操作地址
break;
}
}
}
if(I2C2 -> SR1 & 1<<1 ) //从机地址已发送
{
clear = I2C2 -> SR2; //读取SR2可以清除该位中断
switch(go)
{
case 0:
{
I2C_Write(0x81); //写入待写入的EEPROM单元地址
break;
}
case 1:
{
I2C_Write(0x4E); //写入待写入的EEPROM单元地址
break;
}
case 2:
{
I2C_Stop();
break;
}
}
}
if(I2C2 -> SR1 & 1<<2 ) //字节发送结束 发送地址字节时,不触发此中断
{
switch(go)
{
case 0:
{
I2C_Write(0x00); //写入数据
go = 1;
I2C_Start();
break;
}
case 1:
{
go = 2;
I2C_Start();
break;
}
case 2:
{
break;
}
}
}
}
void I2C2_ER_IRQHandler(void)
{
if(I2C2->SR1 & 1<<10) //应答失败
{
I2C2->SR1 &=~(1<<10); //清除中断
}
if(I2C2->SR1 & 1<<14) //超时
{
I2C2->SR1 &=~(1<<14); //清除中断
}
if(I2C2->SR1 & 1<<11) //过载/欠载
{
I2C2->SR1 &=~(1<<11); //清除中断
}
if(I2C2->SR1 & 1<<9) //仲裁丢失
{
I2C2->SR1 &=~(1<<9); //清除中断
}
if(I2C2->SR1 & 1<<8) //总线出错
{
I2C2->SR1 &=~(1<<8); //清除中断
}
} |
|