搜索
bottom↓
回复: 14

关于使用IIC连续读取数据的问题

[复制链接]

出0入0汤圆

发表于 2012-1-19 20:05:30 | 显示全部楼层 |阅读模式
都说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();//产生一个停止条件

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

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2012-1-19 20:49:16 | 显示全部楼层
我帖子里有代码。 你可以参考下

出0入0汤圆

发表于 2012-1-19 21:38:25 | 显示全部楼层
不知道有没有问题 不过用ADXL345可以用串口的吧
用串口多方便啊!

出0入0汤圆

 楼主| 发表于 2012-1-20 12:15:58 | 显示全部楼层
回复【2楼】xiaosi1102  
-----------------------------------------------------------------------

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

出0入0汤圆

 楼主| 发表于 2012-1-20 12:24:42 | 显示全部楼层
回复【1楼】Name_006  
-----------------------------------------------------------------------

谢谢哈!

出0入0汤圆

发表于 2012-1-21 20:35:59 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-1-30 10:56:44 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-8-14 16:11:33 | 显示全部楼层
关于ADXL345连续读数据,只能读一前以个数据。我也遇到这样的问题,您解决了吗? 可否告知我下,谢谢

出0入0汤圆

发表于 2012-8-15 13:14:27 | 显示全部楼层
路过

出0入0汤圆

发表于 2012-8-15 13:51:56 | 显示全部楼层
一直用STM32 IIC读ADXL345,L3G4200,HMC5883L,都没有问题,STM32的IIC只要初始化时注意一下就行了,还是好用。

出0入0汤圆

发表于 2012-8-19 02:09:34 来自手机 | 显示全部楼层
enthier 发表于 2012-8-15 13:51
一直用STM32 IIC读ADXL345,L3G4200,HMC5883L,都没有问题,STM32的IIC只要初始化时注意一下就行了,还是好 ...

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

出0入0汤圆

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

出0入0汤圆

发表于 2013-8-10 11:35:24 | 显示全部楼层
enthier 发表于 2012-8-19 15:05
/*********************************************************
功能:I2C初始化,I2C有一个BUG,先配置I2C ...

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

出0入0汤圆

发表于 2018-5-24 19:33:04 | 显示全部楼层
可能是在模拟IIC时序中,
IIC_Start();  
IIC_Send_Byte(DeviceAddr);        
IIC_Wait_Ack();
IIC_Read_Byte(1);
这些函数中没有对SDA的输入输出方向进行转换。

出0入0汤圆

发表于 2018-5-24 19:33:36 | 显示全部楼层
挖坟了
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-23 16:01

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表