看看这该死的 IIC 哪里搞错了?STMF4版本 24C512

2019-07-21 05:21发布

             /* Includes ------------------------------------------------------------------*/
#include <includes.h>
#define IIC_SCL_SET()    (GPIOB->BSRRL = GPIO_Pin_10)
#define IIC_SCL_CLR()    (GPIOB->BSRRH = GPIO_Pin_10)
#define IIC_SDA_SET()    (GPIOB->BSRRL = GPIO_Pin_11)
#define IIC_SDA_CLR()   (GPIOB->BSRRH = GPIO_Pin_11)
#define IIC_SDA_READ()   (GPIOB->IDR  &  GPIO_Pin_11)
#define IIC_SDA_IN()    {GPIOB->MODER  &= ~(GPIO_MODER_MODER0 << (11 * 2)); GPIOB->MODER |= (((uint32_t)GPIO_Mode_IN)  << (11 * 2));}
#define IIC_SDA_OUT()   {GPIOB->MODER  &= ~(GPIO_MODER_MODER0 << (11 * 2)); GPIOB->MODER |= (((uint32_t)GPIO_Mode_OUT) << (11 * 2));}
//#define IIC_SDA_DIR(dir) ( GPIOB->MODER  &= ~(GPIO_MODER_MODER0 << (GPIO_Pin_11 * 2)); GPIOB->MODER |= (((uint32_t)1) << (GPIO_Pin_11 * 2)); )
void delay_us(u32 nus)
{  
 u32 ticks;
 u32 told,tnow,tcnt=0;
 u32 reload=SysTick->LOAD; //LOAD的值      
 ticks=nus*21;    //需要的节拍数     
 tcnt=0;
 told=SysTick->VAL;         //刚进入时的计数器值
 while(1)
 {
  tnow=SysTick->VAL; 
  if(tnow!=told)
  {    
   if(tnow<told)tcnt+=told-tnow;//这里注意一下SYSTICK是一个递减的计数器就可以了.
   else tcnt+=reload-tnow+told;    
   told=tnow;
   if(tcnt>=ticks)break;//时间超过/等于要延迟的时间,则退出.
  } 
 };             
}
uint8_t I2C_ReadKey(void)
{
 return Key_Get();
} //初始化IIC
void IIC_Init(void)
{         
 GPIO_InitTypeDef GPIO_InitStructure;
 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); 
   
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;
 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
 GPIO_Init(GPIOB, &GPIO_InitStructure);
 
 GPIO_SetBits(GPIOB,GPIO_Pin_10|GPIO_Pin_11);  //PB10,PB11 输出高
} //产生IIC起始信号
void IIC_Start(void)
{
 IIC_SDA_OUT();
 IIC_SDA_SET();     
 IIC_SCL_SET();
 delay_us(4);
  IIC_SDA_CLR();//START:when CLK is high,DATA change form high to low
 delay_us(4);
 IIC_SCL_CLR();;//钳住I2C总线,准备发送或接收数据
}  
//产生IIC停止信号
void IIC_Stop(void)
{
 IIC_SDA_OUT();//sda线输出
 IIC_SCL_CLR();
 IIC_SDA_CLR();//STOP:when CLK is high DATA change form low to high
  delay_us(4);
 IIC_SCL_SET();
 IIC_SDA_SET();//发送I2C总线结束信号
 delay_us(4);           
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
uint8_t IIC_Wait_Ack(void)
{
 u8 ucErrTime=0;
 IIC_SDA_IN();
 IIC_SDA_SET();delay_us(1);   
 IIC_SCL_SET();delay_us(1); 
 while(IIC_SDA_READ())
 {
  ucErrTime++;
  if(ucErrTime>250)
  {
   IIC_Stop();
   return 1;
  }
 }
 IIC_SCL_CLR();//时钟输出0    
 return 0; 
}
//产生ACK应答
void IIC_Ack(void)
{
 IIC_SCL_CLR();
 IIC_SDA_OUT();
 IIC_SDA_CLR();
 delay_us(2);
 IIC_SCL_SET();
 delay_us(2);
 IIC_SCL_CLR();
}
//不产生ACK应答     
void IIC_NAck(void)
{
 IIC_SCL_CLR();
 IIC_SDA_OUT();
 IIC_SDA_SET();
 delay_us(2);
 IIC_SCL_SET();
 delay_us(2);
 IIC_SCL_CLR();
}              
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答    
void IIC_Send_Byte(uint8_t txd)
{                       
 uint8_t t;  
 IIC_SDA_OUT();  
 IIC_SCL_CLR();//拉低时钟开始数据传输
 for(t=0;t<8;t++)
 {             
   //IIC_SDA=(txd&0x80)>>7;
  if(txd&0x80)
   IIC_SDA_SET();
  else
   IIC_SDA_CLR();
  txd<<=1;   
  delay_us(2);   //对TEA5767这三个延时都是必须的
  IIC_SCL_SET();
  delay_us(2);
  IIC_SCL_CLR(); 
  delay_us(2);
 } 
}     
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK  
uint8_t IIC_Read_Byte(uint8_t ack)
{
 uint8_t i,receive=0;
 IIC_SDA_IN();//SDA设置为输入
  for(i=0;i<8;i++ )
 {
  IIC_SCL_CLR();
  delay_us(2);
  IIC_SCL_SET();
  receive<<=1;
  if(IIC_SDA_READ())receive++;  
  delay_us(1);
  }
 if(ack)
  IIC_Ack();//发送nACK
 else
  IIC_NAck(); 
   return receive;
} //在AT24CXX指定地址读出一个数据
//ReadAddr:开始读数的地址 
//返回值  :读到的数据
uint8_t IIC_ReadOneByte(uint16_t ReadAddr)
{     
 uint8_t temp=0;                         
  IIC_Start(); 
 IIC_Send_Byte(0XA0);    //发送写命令
 IIC_Wait_Ack();
 IIC_Send_Byte(ReadAddr>>8);//发送高地址
 IIC_Wait_Ack();  
  IIC_Send_Byte(ReadAddr&0xff);   //发送低地址
 IIC_Wait_Ack();    
 IIC_Start();       
 IIC_Send_Byte(0XA1);           //进入接收模式     
 IIC_Wait_Ack(); 
  temp=IIC_Read_Byte(0); 
  IIC_Stop();//产生一个停止条件    
 return temp;
}
//在AT24CXX指定地址写入一个数据
//WriteAddr  :写入数据的目的地址   
//DataToWrite:要写入的数据
void IIC_WriteOneByte(uint16_t WriteAddr,uint8_t DataToWrite)
{                               
  IIC_Start();   IIC_Send_Byte(0XA0);     //发送写命令
 IIC_Wait_Ack();
 IIC_Send_Byte(WriteAddr>>8);//发送高地址
  IIC_Wait_Ack();   
  IIC_Send_Byte(WriteAddr&0xff);   //发送低地址
 IIC_Wait_Ack();                   
 IIC_Send_Byte(DataToWrite);     //发送字节         
 IIC_Wait_Ack();           
  IIC_Stop();//产生一个停止条件
 //OSTimeDly(5); 
}
 
void IIC_WriteBuffer(uint8_t* pBuffer, uint16_t WriteAddr, uint16_t NumByteToWrite)
{
 IIC_Start(); 
 IIC_Send_Byte(0XA0);     //发送写命令
 IIC_Wait_Ack();
 IIC_Send_Byte(WriteAddr>>8);//发送高地址
  IIC_Wait_Ack();   
  IIC_Send_Byte(WriteAddr&0xff);   //发送低地址
 IIC_Wait_Ack();
 while(NumByteToWrite--)
 {
  IIC_Send_Byte(*pBuffer++);     //发送字节         
  IIC_Wait_Ack();   
 }
  IIC_Stop();//产生一个停止条件 } void IIC_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t NumByteToRead)
{
  IIC_Start(); 
 IIC_Send_Byte(0XA0);    //发送写命令
 IIC_Wait_Ack();
 IIC_Send_Byte(ReadAddr>>8);//发送高地址
 IIC_Wait_Ack();  
  IIC_Send_Byte(ReadAddr&0xff);   //发送低地址
 IIC_Wait_Ack();    
 IIC_Start();       
 IIC_Send_Byte(0XA1);           //进入接收模式     
 while(NumByteToRead--)
 {
  IIC_Wait_Ack(); 
  if(NumByteToRead == 1)
   *pBuffer++ =IIC_Read_Byte(0); 
  else
   *pBuffer++ =IIC_Read_Byte(1); 
 }
 IIC_NAck();//发送nACK
  IIC_Stop();//产生一个停止条件    
}
/*********************************************************************************************************
      END FILE
*********************************************************************************************************/
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。