chenhuizai210 发表于 2012-1-19 20:05:30

关于使用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();//产生一个停止条件

求教,以上的代码,是否有问题?为什么?

Name_006 发表于 2012-1-19 20:49:16

我帖子里有代码。 你可以参考下

xiaosi1102 发表于 2012-1-19 21:38:25

不知道有没有问题 不过用ADXL345可以用串口的吧
用串口多方便啊!

chenhuizai210 发表于 2012-1-20 12:15:58

回复【2楼】xiaosi1102
-----------------------------------------------------------------------

不能用串口吧?只能IIC和SPI的

chenhuizai210 发表于 2012-1-20 12:24:42

回复【1楼】Name_006
-----------------------------------------------------------------------

谢谢哈!

caoning10 发表于 2012-1-21 20:35:59

mark

caoning10 发表于 2012-1-30 10:56:44

mark

lxl_lxl 发表于 2012-8-14 16:11:33

关于ADXL345连续读数据,只能读一前以个数据。我也遇到这样的问题,您解决了吗? 可否告知我下,谢谢

Making 发表于 2012-8-15 13:14:27

{:lol:}{:lol:}{:lol:}{:lol:}路过

enthier 发表于 2012-8-15 13:51:56

一直用STM32 IIC读ADXL345,L3G4200,HMC5883L,都没有问题,STM32的IIC只要初始化时注意一下就行了,还是好用。

lxl_lw 发表于 2012-8-19 02:09:34

enthier 发表于 2012-8-15 13:51
一直用STM32 IIC读ADXL345,L3G4200,HMC5883L,都没有问题,STM32的IIC只要初始化时注意一下就行了,还是好 ...

我一直使用模拟的,开始没有觉得什么问题。但是最近发现模拟的实在是太耗费时间了,搞了几天硬件的,依旧一筹莫展。所以你能不能传个可以用的硬件i2c?

enthier 发表于 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错误标志
}

幽怨草 发表于 2013-8-10 11:35:24

enthier 发表于 2012-8-19 15:05 static/image/common/back.gif
/*********************************************************
功能:I2C初始化,I2C有一个BUG,先配置I2C ...

我用IIC读MPU6050的数据,读了几组之后就停住了,不知道是怎么回事

huke08@126.com 发表于 2018-5-24 19:33:04

可能是在模拟IIC时序中,
IIC_Start();
IIC_Send_Byte(DeviceAddr);      
IIC_Wait_Ack();
IIC_Read_Byte(1);
这些函数中没有对SDA的输入输出方向进行转换。

huke08@126.com 发表于 2018-5-24 19:33:36

挖坟了{:lol:}
页: [1]
查看完整版本: 关于使用IIC连续读取数据的问题