打印

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

[复制链接]
271|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
第三章|  楼主 | 2018-8-1 17:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/* 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
*********************************************************************************************************/

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

380

主题

380

帖子

0

粉丝