OpenEdv-开源电子网

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

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

[复制链接]

27

主题

148

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
276
金钱
276
注册时间
2012-7-25
在线时间
0 小时
发表于 2012-10-29 22:01:28 | 显示全部楼层 |阅读模式

            

/* 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
*********************************************************************************************************/

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165353
金钱
165353
注册时间
2010-12-1
在线时间
2108 小时
发表于 2012-10-30 00:01:06 | 显示全部楼层
得你告诉我啊,哪里错了?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

27

主题

148

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
276
金钱
276
注册时间
2012-7-25
在线时间
0 小时
 楼主| 发表于 2012-10-30 08:57:28 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
读取似乎是对的,读的是以前的数据。

似乎是写,失败了。

先写后读,读取的是0x3D。但我写入的是其他数据。

把地址放宽些,使用空白区域,读取的是0xff。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165353
金钱
165353
注册时间
2010-12-1
在线时间
2108 小时
发表于 2012-10-30 10:37:46 | 显示全部楼层
回复【3楼】maninman1981:
---------------------------------
用我们开发板的代码试试。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

27

主题

148

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
276
金钱
276
注册时间
2012-7-25
在线时间
0 小时
 楼主| 发表于 2012-10-30 16:05:13 | 显示全部楼层
回复【4楼】正点原子:
---------------------------------
我也想啊,我的事STM32F407.
不能直接用啊。
谁有这个现成的,贡献出来。
要么是IO口操作出线问题了,悲剧不断啊,自从用了ST32.
回复 支持 反对

使用道具 举报

27

主题

148

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
276
金钱
276
注册时间
2012-7-25
在线时间
0 小时
 楼主| 发表于 2012-10-30 20:06:15 | 显示全部楼层
看看这STM32,欠揍的法国佬。
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-25 21:11

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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