关于使用IIC连续读取数据的问题
都说STM32的硬件IIC有问题。我也没有多加验证,相信群众的眼光是雪亮的,所以毅然选择使用IO口模拟IIC总线。
现在的问题是,使用IO口模拟的IIC总线可以读取单字节的数据,但是使用连续读取时,出现了问题,根据数据显示,连续读取时只读取到第一个的数据。
我用IIC读取时,读取L3G4200D和ADXl345,都遇到了相同的问题。
数据如下:
IIC_Start();
IIC_Send_Byte(DeviceAddr); //发送器件地址,末位是0,表示要写
IIC_Wait_Ack();
IIC_Send_Byte(RegAddr); //发送地址
IIC_Wait_Ack();
IIC_Start(); //重新启动IIC总线
IIC_Send_Byte(DeviceAddr+1); //发送器件地址,末位是1,表示要读
IIC_Wait_Ack();
for(i=0;i<Count-1;i++)
{
*pData=IIC_Read_Byte(1); //连续接收数据位
IIC_Wait_Ack(); //发送就答位
pData++;
}
*pData=IIC_Read_Byte(0); //最后一次不发送应答位
IIC_Stop();//产生一个停止条件
求教,以上的代码,是否有问题?为什么? 我帖子里有代码。 你可以参考下 不知道有没有问题 不过用ADXL345可以用串口的吧
用串口多方便啊! 回复【2楼】xiaosi1102
-----------------------------------------------------------------------
不能用串口吧?只能IIC和SPI的 回复【1楼】Name_006
-----------------------------------------------------------------------
谢谢哈! mark mark 关于ADXL345连续读数据,只能读一前以个数据。我也遇到这样的问题,您解决了吗? 可否告知我下,谢谢 {:lol:}{:lol:}{:lol:}{:lol:}路过 一直用STM32 IIC读ADXL345,L3G4200,HMC5883L,都没有问题,STM32的IIC只要初始化时注意一下就行了,还是好用。 enthier 发表于 2012-8-15 13:51
一直用STM32 IIC读ADXL345,L3G4200,HMC5883L,都没有问题,STM32的IIC只要初始化时注意一下就行了,还是好 ...
我一直使用模拟的,开始没有觉得什么问题。但是最近发现模拟的实在是太耗费时间了,搞了几天硬件的,依旧一筹莫展。所以你能不能传个可以用的硬件i2c?
/*********************************************************
功能: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错误标志
}
enthier 发表于 2012-8-19 15:05 static/image/common/back.gif
/*********************************************************
功能:I2C初始化,I2C有一个BUG,先配置I2C ...
我用IIC读MPU6050的数据,读了几组之后就停住了,不知道是怎么回事 可能是在模拟IIC时序中,
IIC_Start();
IIC_Send_Byte(DeviceAddr);
IIC_Wait_Ack();
IIC_Read_Byte(1);
这些函数中没有对SDA的输入输出方向进行转换。 挖坟了{:lol:}
页:
[1]