OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4492|回复: 8

模拟IIC数据传输中,时不时出现错误

[复制链接]

6

主题

18

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
203
金钱
203
注册时间
2016-1-14
在线时间
69 小时
发表于 2017-12-21 11:17:24 | 显示全部楼层 |阅读模式
1金钱
这几天调试两个 Honeywell传感哭器。相同的程序一个正常,一个总是出现异常值。串口数据如下:

11.png

几天了,找不到原因。之前用原子的IIC,有问题。自己改了下程序,还是不行。
222.png
这是手册中的时序 。
下面是代码。不知道问题出在哪里
void SM3041_Init(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        //RCC->APB2ENR|=1<<4;//先使能外设IO PORTC时钟
        RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOA, ENABLE );       
          
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        SM3041_IIC_SCL=1;
        SM3041_IIC_SDA=1;
}

//产生SM3041_IIC起始信号
void SM3041_IIC_Start(void)
{
        SM3041_SDA_OUT();     //sda线输出
        SM3041_IIC_SDA=1;                    
        SM3041_IIC_SCL=1;
        delay_us(4);
        SM3041_IIC_SDA=0;//START:when CLK is high,DATA change form high to low
        delay_us(4);
        SM3041_IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
        delay_us(4);
}          
//产生SM3041_IIC停止信号
void SM3041_IIC_Stop(void)
{
        SM3041_SDA_OUT();//sda线输出
        SM3041_IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
        delay_us(4);
        SM3041_IIC_SCL=1;
        delay_us(4);
        SM3041_IIC_SDA=1;//发送I2C总线结束信号
        delay_us(4);                                                                  
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 SM3041_IIC_Wait_Ack(void)
{
        u8 ucErrTime=0;
        SM3041_SDA_IN();      //SDA设置为输入  
        SM3041_IIC_SDA=1;delay_us(3);          
        SM3041_IIC_SCL=1;delay_us(3);         
        while(SM3041_READ_SDA)
        {
                ucErrTime++;
                if(ucErrTime>250)
                {
                        SM3041_IIC_Stop();
                        return 1;
                }
        }
        SM3041_IIC_SCL=0;//时钟输出0           
        delay_us(5);
        return 0;  
}
//产生ACK应答
void SM3041_IIC_Ack(void)
{
        SM3041_IIC_SCL=0;
        SM3041_SDA_OUT();
        SM3041_IIC_SDA=0;
        delay_us(2);
        SM3041_IIC_SCL=1;
        delay_us(2);
        SM3041_IIC_SCL=0;
}
//不产生ACK应答                    
void SM3041_IIC_NAck(void)
{
        SM3041_IIC_SCL=0;
        SM3041_SDA_OUT();
        SM3041_IIC_SDA=1;
        delay_us(2);
        SM3041_IIC_SCL=1;
        delay_us(2);
        SM3041_IIC_SCL=0;
}                                                                              
//SM3041_IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答                          
void SM3041_IIC_Send_Byte(u8 txd)
{       
        u8 t;   
        SM3041_SDA_OUT();             
        SM3041_IIC_SCL=0;//拉低时钟开始数据传输
        for(t=0;t<8;t++)
        {              
                SM3041_IIC_SDA=(txd&0x80)>>7;
                txd<<=1;           
                delay_us(4);   //对TEA5767这三个延时都是必须的
                SM3041_IIC_SCL=1;
                delay_us(4);
                SM3041_IIC_SCL=0;       
                delay_us(4);
        }         
}             
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
u8 SM3041_IIC_Read_Byte(unsigned char ack)
{
        unsigned char i,receive=0;
        delay_us(5);
        SM3041_IIC_SDA = 1;
        delay_us(5);
        SM3041_SDA_IN();//SDA设置为输入
  for(i=0;i<8;i++ )
        {               
               
                receive<<=1;
                SM3041_IIC_SCL=0;
                delay_us(5);
                SM3041_IIC_SCL=1;
                delay_us(2);
                if(SM3041_READ_SDA)
                        receive++;
                delay_us(2);
        }
        SM3041_IIC_SCL = 0;
        delay_us(2);
        if (!ack)
                        SM3041_IIC_NAck();//发送nACK
        else
                        SM3041_IIC_Ack(); //发送ACK   
        return receive;
}

u16 SM3041_Read_OneByte(void)
{
        u8 temp;
        u16 ReTemp = 0;
        SM3041_IIC_Start();
        SM3041_IIC_Send_Byte((0x49<<1)+1);
        SM3041_IIC_Wait_Ack();
        temp = SM3041_IIC_Read_Byte(1);
        ReTemp = temp <<8;
        temp = SM3041_IIC_Read_Byte(0);
        ReTemp = ReTemp + temp;
        SM3041_IIC_Stop();
        return ReTemp;
}


u16 Get_SM3041_Average(u8 times)
{
        u32 temp_val=0;
        u8 t;
        for(t=0;t<times;t++)
        {
                temp_val+=SM3041_Read_OneByte();
                delay_ms(15);
        }
        return temp_val/times;
}

最佳答案

查看完整内容[请看2#楼]

延时加大一点,起码要大于手册上写的4.7US
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

207

帖子

0

精华

高级会员

Rank: 4

积分
959
金钱
959
注册时间
2017-5-27
在线时间
108 小时
发表于 2017-12-21 11:17:25 | 显示全部楼层
延时加大一点,起码要大于手册上写的4.7US
回复

使用道具 举报

6

主题

18

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
203
金钱
203
注册时间
2016-1-14
在线时间
69 小时
 楼主| 发表于 2017-12-21 11:23:02 | 显示全部楼层
用JLINK单步调试,IIC就正常,不会出现异常值。
回复

使用道具 举报

6

主题

18

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
203
金钱
203
注册时间
2016-1-14
在线时间
69 小时
 楼主| 发表于 2017-12-21 13:28:56 | 显示全部楼层
lanlzp 发表于 2017-12-21 12:44
延时加大一点,起码要大于手册上写的4.7US

把全部的延时改成10us  还是一样的。
回复

使用道具 举报

2

主题

685

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3448
金钱
3448
注册时间
2017-7-4
在线时间
869 小时
发表于 2017-12-21 14:35:17 | 显示全部楼层
看我的模拟i2c,各类器件都驱动过,EEPROM、pcf8563、ds3231、lm75a、LP55231等等,都冇问题。
https://github.com/Prry/drivers-for-mcu
回复

使用道具 举报

6

主题

18

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
203
金钱
203
注册时间
2016-1-14
在线时间
69 小时
 楼主| 发表于 2017-12-21 15:34:14 | 显示全部楼层
总算通了。把延时加到100us。就正常了
回复

使用道具 举报

1

主题

2

帖子

0

精华

新手入门

积分
15
金钱
15
注册时间
2019-4-7
在线时间
7 小时
发表于 2019-11-26 21:23:50 | 显示全部楼层
ghosttout 发表于 2017-12-21 15:34
总算通了。把延时加到100us。就正常了

楼主,我也遇到这个问题,你是把所有的延时函数都改成了100吗,
回复

使用道具 举报

0

主题

6

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
228
金钱
228
注册时间
2020-2-25
在线时间
47 小时
发表于 2020-6-18 11:39:35 | 显示全部楼层
楼主楼主,我使用的是正点原子的名字叫myiic的驱动的honeywell的型号hih8130温湿度传感器,我遇到的问题是1、不管发送的从机地址多少,IIC_Wait_Ack()函数的返回值都是0(返回0代表从机应答了)2、接收到的数据都是0,请问楼主能提供您的驱动代码给我参考参考吗?
回复

使用道具 举报

0

主题

6

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
228
金钱
228
注册时间
2020-2-25
在线时间
47 小时
发表于 2020-6-18 11:42:47 | 显示全部楼层
对了,还有这个SCL clock frequency  FSCL  100  –  400  kHz频率是什么意思呢?跟单片机的主频有关系吗?请问各位前辈
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-18 10:29

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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