|
发表于 2012-8-19 15:05:37
|
显示全部楼层
/*********************************************************
功能:I2C初始化,I2C有一个BUG,先配置I2C的IO为第二功能再开启I2C时会
导致I2C忙标志一直有,解决的办法就是复位I2C见程序
输入参数:无
输出参数:无
**********************************************************/
void i2c_init(void)
{
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; //I2C1 时钟
I2C1->CR1 |= 1ul << 15; //复位IIC
__NOP(); //延时1个周期
I2C1->CR1 &= ~1ul << 15; //取消复位,清楚busy
I2C1->CR2 |= (u32)36; //IIC时钟 36M
I2C1->CCR |= I2C_CCR_FS; //快速模式
I2C1->CCR |= I2C_CCR_DUTY; //duty T LOW /T HIGH = 16/9
I2C1->CCR |= 0x0004; //400k速度
I2C1->TRISE |= 0x0009; //上升沿
I2C1->CR1 |= I2C_CR1_PE; //使能IIC
}
/*********************************************************
功能:I2C发送N个字节
输入参数:address 要发送的从机地址 P数据存储指针 data_number 读取数据的个数
输出参数:成功返回 true 失败 false
**********************************************************/
u8 i2c1_send_Nbyte(u8 address,u8 *p,u8 data_number)
{
u32 time_count = 0;
u8 irq_state = 0;
irq_state = parameter_control1.control_bit1.cpu_IRQ_state;//中断状态
close_cpu_irq();//关中断
while((I2C1->SR2 & I2C_SR2_BUSY)) //判断总线是否忙 0 总线上无数据通讯 1 有
{
time_count ++;
if(time_count > i2c_time_overflow) //失败
goto back;
}
time_count = 0;
i2c1_start_bit();//产生起始位
while(!(I2C1->SR1 & I2C_SR1_SB))//判断起始条件是否发出
{
time_count ++;
if(time_count > i2c_time_overflow) //失败
goto back;
}
time_count = 0;
while(!(I2C1->SR2 & I2C_SR2_MSL)) //判断是否是主模式
{
time_count ++;
if(time_count > i2c_time_overflow) //失败
goto back;
}
time_count = 0;
I2C1->DR = address << 1;//发送地址+写
while(!(I2C1->SR1 & I2C_SR1_ADDR)) //判断地址是否发送结束
{
time_count ++;
if(time_count > i2c_time_overflow) //失败
goto back;
}
time_count = 0;
while(!(I2C1->SR2 & I2C_SR2_TRA)) //判断数据是否发出
{
time_count ++;
if(time_count > i2c_time_overflow) //失败
goto back;
}
time_count = 0;
while((I2C1->SR1 & I2C_SR1_AF)) //判断是否应答失败 0 没有应答失败 1 应答失败
{
time_count ++;
if(time_count > i2c_time_overflow) //失败
goto back;
}
time_count = 0;
while(!(I2C1->SR1 & I2C_SR1_TXE)) //判断寄存器是否为空
{
time_count ++;
if(time_count > i2c_time_overflow) //失败
goto back;
}
time_count = 0;
while(data_number)
{
while(!(I2C1->SR1 & I2C_SR1_TXE)) //判断寄存器是否为空
{
time_count ++;
if(time_count > i2c_time_overflow) //失败
goto back;
}
time_count = 0;
I2C1->DR = *p ++;
while(!(I2C1->SR1 & I2C_SR1_BTF)) //判断字节发送是否结束
{
time_count ++;
if(time_count > i2c_time_overflow) //失败
goto back;
}
time_count = 0;
data_number --;
}
i2c1_stop_bit(); //产生停止位
if(irq_state)
open_cpu_irq(); //开中断
i2c1_tx_led(); //发送指示灯
return true;
back:
i2c1_error_reset();//错误中恢复
if(irq_state)
open_cpu_irq(); //开中断
return false;
}
/*********************************************************
功能:I2C读取N个字节
输入参数:address 要读取的从机地址 P数据存储指针 data_number 读取数据的个数
输出参数:成功返回 true 失败 false
**********************************************************/
u8 i2c1_read_Nbyte(u8 address,u8 *p,u8 data_number)
{
u32 time_count = 0;
u8 irq_state = 0;
irq_state = parameter_control1.control_bit1.cpu_IRQ_state;//中断状态
close_cpu_irq();//关中断
while((I2C1->SR2 & I2C_SR2_BUSY)) //判断总线是否忙 0 总线上无数据通讯 1 有
{
time_count ++;
if(time_count > i2c_time_overflow) //失败
goto back;
}
time_count = 0;
i2c1_start_bit();//产生起始位
while(!(I2C1->SR1 & I2C_SR1_SB))//判断起始条件是否发出
{
time_count ++;
if(time_count > i2c_time_overflow) //失败
goto back;
}
time_count = 0;
while(!(I2C1->SR2 & I2C_SR2_MSL)) //判断是否是主模式
{
time_count ++;
if(time_count > i2c_time_overflow) //失败
goto back;
}
time_count = 0;
I2C1->DR = ((address << 1) | 0x01);//发送地址+读
while(!(I2C1->SR1 & I2C_SR1_ADDR)) //判断地址是否发送结束
{
time_count ++;
if(time_count > i2c_time_overflow) //失败
goto back;
}
time_count = 0;
i2c1_ack_en_bit();
while((I2C1->SR2 & I2C_SR2_TRA)) //判断数据是否发出
{
time_count ++;
if(time_count > i2c_time_overflow) //失败
goto back;
}
time_count = 0;
while((I2C1->SR1 & I2C_SR1_AF)) //判断是否应答失败 0 没有应答失败 1 应答失败
{
time_count ++;
if(time_count > i2c_time_overflow) //失败
goto back;
}
time_count = 0;
while(data_number)
{
while(!(I2C1->SR1 & I2C_SR1_BTF)) //判断数据是否发出
{
time_count ++;
if(time_count > i2c_time_overflow) //失败
goto back;
}
time_count = 0;
while(!(I2C1->SR1 & I2C_SR1_RXNE)) //判断接收寄存器是否为空 0 空 1非空
{
time_count ++;
if(time_count > i2c_time_overflow) //失败
goto back;
}
*p ++ = I2C1->DR; //读数据
if(data_number == 1)
i2c1_ack_dis_bit(); // 返回NACK
else
i2c1_ack_en_bit(); // 返回ACK
data_number -- ;
}
i2c1_stop_bit(); //产生停止位
if(irq_state)
open_cpu_irq(); //开中断
i2c1_rx_led(); //接收指示灯
return true;
back:
i2c1_error_reset();//错误中恢复
if(irq_state)
open_cpu_irq(); //开中断
return false;
}
/*********************************************************
功能:从错误中复位IIC
输入参数:无
输出参数:无
**********************************************************/
void i2c1_error_reset(void)
{
RCC->APB1RSTR |= RCC_APB1RSTR_I2C1RST; //复位I2C1
__NOP(); //延时
__NOP(); //延时
__NOP(); //延时
RCC->APB1RSTR &= ~RCC_APB1RSTR_I2C1RST; //取消复位
delay(1); //延时,让从设备复位I2C总线
i2c_init(); //重新初始化I2C
i2c1_error_led(); //错误只是等
parameter_control1.public_data1.i2c1_error_count ++;//IIC错误标志
}
|
|