如题,本人在使用STM32F103C8T6模拟IIC与24C02通信,例程是移植的原子哥战舰V3的程序(把ZE移植到了C8T6),引脚改为了PB0(SCL),PB1(SDA)。但是在使用时Check失败,用示波器抓了波形,发现CLK是正常的,也就是有模拟出来的时钟波形,但是SDA一直是高电平。
单步调试下来看,IIC_start()里SDA可以拉高拉低,后面的第一个发送字节的函数里面的SDA也是可以拉高拉低的,但是再后边的SDA却“不受控制”了,也就是无论拉高拉低都是零,最终出现24C02的Check失败。有大佬能够解答一下嘛,谢谢您。萌新第一次发帖,有不足之处请见谅。注:用的板子是工厂打的样,排除了焊接问题。也尝试换过板子,已经是第二次了,之前也遇到过这种问题,只不过不是这个引脚。
注:之前用的引脚怀疑是使用了与USART有关的引脚,但是这次看来与USART关系不大。
C8T6的封装
选择的两个管脚程序如下//初始化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++; }}
啊啊啊,太感谢您了,还是我太粗心困扰许久,终于解决这个问题了,谢谢您。
一周热门 更多>