OpenEdv-开源电子网

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

关于STM32F103C8T6使用模拟IIC遇到的问题

[复制链接]

1

主题

5

帖子

0

精华

新手上路

积分
43
金钱
43
注册时间
2019-5-4
在线时间
9 小时
发表于 2019-6-30 10:11:14 | 显示全部楼层 |阅读模式
1金钱
如题,本人在使用STM32F103C8T6模拟IIC与24C02通信,例程是移植的原子哥战舰V3的程序(把ZE移植到了C8T6),引脚改为了PB0(SCL),PB1(SDA)。但是在使用时Check失败,用示波器抓了波形,发现CLK是正常的,也就是有模拟出来的时钟波形,但是SDA一直是高电平。单步调试下来看,IIC_start()里SDA可以拉高拉低,后面的第一个发送字节的函数里面的SDA也是可以拉高拉低的,但是再后边的SDA却“不受控制”了,也就是无论拉高拉低都是零,最终出现24C02的Check失败。有大佬能够解答一下嘛,谢谢您。萌新第一次发帖,有不足之处请见谅。注:用的板子是工厂打的样,排除了焊接问题。也尝试换过板子,已经是第二次了,之前也遇到过这种问题,只不过不是这个引脚。
注:之前用的引脚怀疑是使用了与USART有关的引脚,但是这次看来与USART关系不大。

封装.png

C8T6的封装

2.png

选择的两个管脚

程序如下

//初始化IIC

void EEPROM_IIC_Init(void)

{                                             

        GPIO_InitTypeDef GPIO_InitStructure;

        RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOB, ENABLE );        //使能GPIOB时钟   

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;//   |GPIO_Pin_0,1

        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD ;   //开漏输出

        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

        GPIO_Init(GPIOB, &GPIO_InitStructure);

        GPIO_SetBits(GPIOB,GPIO_Pin_0|GPIO_Pin_1);         //PB0,PB1 输出高

}

///////其他的什么Start,Stop,Wait_Ack等程序是例程那样的


//IO方向设置

#define EEPROM_SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<4;}

#define EEPROM_SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<4;}


//IO操作函数         

#define EEPROM_IIC_SCL    PBout(0) //SCL

#define EEPROM_IIC_SDA    PBout(1) //SDA         

#define EEPROM_READ_SDA   PBin(1)  //输入SDA


//关于24C02的程序也是和例程是一样的

//所以下边参考就可以

//初始化IIC接口

void AT24CXX_Init(void)

{

        EEPROM_IIC_Init();

}

//在AT24CXX指定地址读出一个数据

//ReadAddr:开始读数的地址  

//返回值  :读到的数据

u8 AT24CXX_ReadOneByte(u16 ReadAddr)

{                                  

        u8 temp=0;                                                                                                                                                               

    EEPROM_IIC_Start();  

        if(EE_TYPE>AT24C16)

        {

                EEPROM_IIC_Send_Byte(0XA0);           //发送写命令

                EEPROM_IIC_Wait_Ack();

                EEPROM_IIC_Send_Byte(ReadAddr>>8);//发送高地址

                EEPROM_IIC_Wait_Ack();                 

        }else EEPROM_IIC_Send_Byte(0XA0+((ReadAddr/256)<<1));   //发送器件地址0XA0,写数据          


        EEPROM_IIC_Wait_Ack();

    EEPROM_IIC_Send_Byte(ReadAddr%256);   //发送低地址

        EEPROM_IIC_Wait_Ack();            

        EEPROM_IIC_Start();                     

        EEPROM_IIC_Send_Byte(0XA1);           //进入接收模式                          

        EEPROM_IIC_Wait_Ack();         

    temp=EEPROM_IIC_Read_Byte(0);                  

    EEPROM_IIC_Stop();//产生一个停止条件            

        return temp;

}

//在AT24CXX指定地址写入一个数据

//WriteAddr  :写入数据的目的地址   

//DataToWrite:要写入的数据

void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)

{                                                                                                                                                                                          

    EEPROM_IIC_Start();  

        if(EE_TYPE>AT24C16)

        {

                EEPROM_IIC_Send_Byte(0XA0);            //发送写命令

                EEPROM_IIC_Wait_Ack();

                EEPROM_IIC_Send_Byte(WriteAddr>>8);//发送高地址

        }else

        {

                EEPROM_IIC_Send_Byte(0XA0+((WriteAddr/256)<<1));   //发送器件地址0XA0,写数据

        }         

        EEPROM_IIC_Wait_Ack();          

    EEPROM_IIC_Send_Byte(WriteAddr%256);   //发送低地址

        EEPROM_IIC_Wait_Ack();                                                                                                              

        EEPROM_IIC_Send_Byte(DataToWrite);     //发送字节                                                          

        EEPROM_IIC_Wait_Ack();                                

    EEPROM_IIC_Stop();//产生一个停止条件

        delay_ms(10);         

}

//在AT24CXX里面的指定地址开始写入长度为Len的数据

//该函数用于写入16bit或者32bit的数据.

//WriteAddr  :开始写入的地址  

//DataToWrite:数据数组首地址

//Len        :要写入数据的长度2,4

void AT24CXX_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len)

{         

        u8 t;

        for(t=0;t<Len;t++)

        {

                AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff);

        }                                                                                                    

}


//在AT24CXX里面的指定地址开始读出长度为Len的数据

//该函数用于读出16bit或者32bit的数据.

//ReadAddr   :开始读出的地址

//返回值     :数据

//Len        :要读出数据的长度2,4

u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len)

{         

        u8 t;

        u32 temp=0;

        for(t=0;t<Len;t++)

        {

                temp<<=8;

                temp+=AT24CXX_ReadOneByte(ReadAddr+Len-t-1);                                            

        }

        return temp;                                                                                                    

}

//检查AT24CXX是否正常

//这里用了24XX的最后一个地址(255)来存储标志字.

//如果用其他24C系列,这个地址要修改

//返回1:检测失败

//返回0:检测成功

u8 AT24CXX_Check(void)

{

        u8 temp;

        temp=AT24CXX_ReadOneByte(255);//避免每次开机都写AT24CXX                          

        if(temp==0X55)return 0;                  

        else//排除第一次初始化的情况

        {

                AT24CXX_WriteOneByte(255,0X55);

            temp=AT24CXX_ReadOneByte(255);          

                if(temp==0X55)return 0;

        }

        return 1;                                                                                          

}


//在AT24CXX里面的指定地址开始读出指定个数的数据

//ReadAddr :开始读出的地址 对24c02为0~255

//pBuffer  :数据数组首地址

//NumToRead:要读出数据的个数

void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)

{

        while(NumToRead)

        {

                *pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);       

                NumToRead--;

        }

}  

//在AT24CXX里面的指定地址开始写入指定个数的数据

//WriteAddr :开始写入的地址 对24c02为0~255

//pBuffer   :数据数组首地址

//NumToWrite:要写入数据的个数

void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)

{

        while(NumToWrite--)

        {

                AT24CXX_WriteOneByte(WriteAddr,*pBuffer);

                WriteAddr++;

                pBuffer++;

        }

}





最佳答案

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

#define EEPROM_SDA_IN() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8CRL|=(u32)3
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

11

帖子

0

精华

新手上路

积分
43
金钱
43
注册时间
2019-5-24
在线时间
11 小时
发表于 2019-6-30 10:11:15 | 显示全部楼层
#define EEPROM_SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<4;}
#define EEPROM_SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<4;}
应该是0xffffff0f吧。
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手上路

积分
43
金钱
43
注册时间
2019-5-4
在线时间
9 小时
 楼主| 发表于 2019-6-30 21:38:51 | 显示全部楼层
中华有为 发表于 2019-6-30 14:30
#define EEPROM_SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8CRL|=(u32)3

啊啊啊,太感谢您了,还是我太粗心困扰许久,终于解决这个问题了,谢谢您。
回复

使用道具 举报

1

主题

11

帖子

0

精华

新手上路

积分
43
金钱
43
注册时间
2019-5-24
在线时间
11 小时
发表于 2019-6-30 22:11:59 | 显示全部楼层
今晚月色真美 发表于 2019-6-30 21:38
啊啊啊,太感谢您了,还是我太粗心困扰许久,终于解决这个问题了,谢谢您。

共同进步
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-7-11 01:34

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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