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

2019-07-20 23:25发布

如题,本人在使用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 选择的两个管脚程序如下//初始化IICvoid 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,4void 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,4u32 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++;        }}



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。