打印
[STM32F4]

stm32读些24c64异常

[复制链接]
3127|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zhaohualiang|  楼主 | 2017-4-25 15:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
之前读些24c16可以的,改成64一直调不好,地址也都改了,读出来还是0xff?大神们帮帮。。

u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{      
u8 temp=0;

  IIC_Start();  
if(EE_TYPE>AT24C16)
{
  IIC_Send_Byte(0XA0);    //·¢ËÍдÃüÁî
  IIC_Wait_Ack();
  IIC_Send_Byte(ReadAddr>>8);//·¢Ë͸ߵØÖ·     
}
else
  IIC_Send_Byte(0XA0+((ReadAddr/256)<<1));   //·¢ËÍÆ÷¼þµØÖ·0XA0,дÊý¾Ý     
IIC_Wait_Ack();
  IIC_Send_Byte(ReadAddr%256);   //·¢Ë͵͵ØÖ·
IIC_Wait_Ack();     
IIC_Start();        
IIC_Send_Byte(0XA1);           //½øÈë½ÓÊÕģʽ      
IIC_Wait_Ack();  
  temp=IIC_Read_Byte(0);     
  IIC_Stop();//²úÉúÒ»¸öÍ£Ö¹Ìõ¼þ

return temp;
}

void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{                                
  IIC_Start();  
if(EE_TYPE>AT24C16)
{
  IIC_Send_Byte(0XA0);     //·¢ËÍдÃüÁî
  IIC_Wait_Ack();
  IIC_Send_Byte(WriteAddr>>8);//·¢Ë͸ߵØÖ·   
}
else
  IIC_Send_Byte(0XA0+((WriteAddr/256)<<1));   //·¢ËÍÆ÷¼þµØÖ·0XA0,дÊý¾Ý   
IIC_Wait_Ack();   
  IIC_Send_Byte(WriteAddr%256);   //·¢Ë͵͵ØÖ·
IIC_Wait_Ack();                    
IIC_Send_Byte(DataToWrite);     //·¢ËÍ×Ö½Ú         
IIC_Wait_Ack();            
  IIC_Stop();//²úÉúÒ»¸öÍ£Ö¹Ìõ¼þ
delay_ms(10);  
}
沙发
feelhyq| | 2017-4-25 16:17 | 只看该作者
抓波形分析

使用特权

评论回复
板凳
Prry| | 2017-4-25 18:35 | 只看该作者
单片机常用的总线如i2c、spi、uart等,将其硬件抽象层分离,相关外设在其抽象层上的应用函数接口调用。这样的好处是 :
1、外设的驱动方便移植到任何单片机;
2、外设总线方便移植到其他单片机,只需更改部分寄存器配置;
3、总线调试OK后,调试新的外设程序时,不用重重复复调试总线的程序。
比如,楼上的程序分层就不够好,i2c总线和eeprom交叉,假如我这个i2c总线要挂其他i2c设备(传感器、ADC等),那又得重新写一次总线程序?又重新配置?又调试时序对不对?做重复的工作就是浪费青春啊!假设换了一家公司,用了不同单片机,这个eeprom程序移植到其他单片机时又是重新写一遍,多吃力啊。
附上24xx系列EEPROM程序,模拟i2c,i2c作了封装,看接口函数即可,
/*
* File      : 24clxx.c
*
* This file is part of eeprom driver for 24clxx,such as at24c02/at24c16.
* COPYRIGHT (C) 2014 - 2016,
*
* Change Logs:
* Date           Author       Notes
*
*
* Depend on:
* i2c_bitops.c
*
* Note:
* 24c04 24c08 24c16 地址为8位,超过0xff地址后,注意页的选择读写
* 24c32 及以上地址为16位
* EEPROM 页读写需要作应答查询或作短暂延时以等待数据写入完成;FM24CLXX则不需要
*/


#define USE_24CLXX_EN                 1
#define USE_24CLXX_DEBUG         0


#if USE_24CLXX_EN
#include "main.h"       

//eeprom/fram 参数
#define                EEPROM_TYPE                        0                //0->EEPROM 1->FRAM
#define                EEPROM_MODEL                        16                //EEPROM 类型 24c16
#define                EE24CLXX_SLAVE_ADDR           0x50                //注意读写位,实际地址为0x50
#define                EE24CLXX_PageSize             16                //AT24C16每页有16个字节   24C02->8   24c64->32

static void I2C_24CLXXWaitStandby(u8 slave_addr);

//页写延时,FRAM不用
static void I2C_24CLXXWaitStandby(u8 slave_addr)
{
#if EEPROM_TYPE
       
#else
                u16 i;
                i = 0xFFFF;
                while (i--);
#endif
}

//写多字节,需确保当前写地址+写入数据长度不能超过EEPROM的一页
static void i2c_24clxx_write( u16 WriteAddr, char* pBuffer,u16 NumByteToWrite)
{
                struct st_i2c_msg ee24_msg[2];
                u8        buf[2];
                u8  slave_addr;

                //if(WriteAddr+NumByteToWrite > EE24CLXX_PageSize)
                //                return;
                if(EEPROM_MODEL > 16)
                {//大于2k字节时,地址为16位
                                slave_addr = EE24CLXX_SLAVE_ADDR;
                                buf[0] = (WriteAddr >>8)& 0xff;
                                buf[1] = WriteAddr & 0xff;
                                ee24_msg[0].size  = 2;
                }
                else
                {
                                slave_addr = EE24CLXX_SLAVE_ADDR | (WriteAddr>>8);
                                buf[0] = WriteAddr & 0xff;
                                ee24_msg[0].size  = 1;
                }
                ee24_msg[0].addr = slave_addr;
                ee24_msg[0].flags = ST_I2C_WR;
                ee24_msg[0].buff  = buf;
                ee24_msg[1].addr = slave_addr;
                ee24_msg[1].flags = ST_I2C_WR  | ST_I2C_NO_START;       
                ee24_msg[1].buff  = (u8*)pBuffer;
                ee24_msg[1].size  = NumByteToWrite;
                i2c_bitops_bus_xfer(&i2c1_dev,ee24_msg,2);
}

/*******************************************************
**
**                                                                                         外部函数
**
*******************************************************/

//写一字节
char ee_24clxx_writebyte(u16 addr,u8 data)
{
                struct st_i2c_msg ee24_msg[2];
                u8        buf[3];
                u8  slave_addr;
       
                if(EEPROM_MODEL > 16)
                {//大于2k字节时,地址为16位
                                slave_addr = EE24CLXX_SLAVE_ADDR;
                                buf[0] = (addr >>8)& 0xff;   //高位地址在前
                                buf[1] = addr & 0xff;
                                buf[2] = data;
                                ee24_msg[0].size  = 3;
                }
                else
                {
                                slave_addr = EE24CLXX_SLAVE_ADDR | (addr>>8);
                                buf[0] = addr & 0xff;
                                buf[1] = data;
                                ee24_msg[0].size  = 2;
                }
                ee24_msg[0].addr = slave_addr;
                ee24_msg[0].flags = ST_I2C_WR;
                ee24_msg[0].buff  = buf;
                i2c_bitops_bus_xfer(&i2c1_dev,ee24_msg,1);
               
                return 0;
}

//写多字节
//新的页写
char ee_24clxx_writebytes(u16 write_addr, char* pwrite_buff, u16 writebytes)
{
                u8   write_len,page_offset;
                u16  write_remain,write_current_addr;
                char error = 0,*pbuff;
       
                pbuff                                        = pwrite_buff;                        //不要直接使用形参计算,特别是指针操作
                write_remain  = writebytes;
                write_current_addr = write_addr;
                while(write_remain > 0)
                {
                                page_offset = write_current_addr & 0x0f;                //write_current_addr%EE24CLXX_PageSize
                                write_len   = write_remain > (EE24CLXX_PageSize - page_offset) ? (EE24CLXX_PageSize - page_offset) : write_remain;
                                i2c_24clxx_write(write_current_addr,pbuff, write_len);
                                write_remain   = write_remain - write_len;
                                if(write_remain > 0)
                                {
                                                pbuff = pbuff + EE24CLXX_PageSize - page_offset;
                                                write_current_addr  =  write_current_addr + EE24CLXX_PageSize - page_offset;
                                                I2C_24CLXXWaitStandby(0);
                                }
                }
                I2C_24CLXXWaitStandby(0);
                {//校验数据
                                int i;
                                char checkdata;
                       
                                for(i = 0;i < writebytes;i++)
                                {
                                                ee_24clxx_readbytes(write_addr+i,&checkdata,1);       
                                                if(checkdata != pwrite_buff[i])
                                                {
                                                                error = 1;
                                                                break;
                                                }
                                }
                }
                return error;
}

//读多字节,连续读
void ee_24clxx_readbytes(u16 ReadAddr, char* pBuffer, u16 NumByteToRead)
{  
                struct st_i2c_msg ee24_msg[2];
                u8        buf[2];
                u8  slave_addr;
       
                if(EEPROM_MODEL > 16)
                {//大于2k字节时,地址为16位
                                slave_addr = EE24CLXX_SLAVE_ADDR;
                                buf[0] = (ReadAddr >>8)& 0xff;
                                buf[1] = ReadAddr & 0xff;
                                ee24_msg[0].size  = 2;
                }
                else
                {
                                slave_addr = EE24CLXX_SLAVE_ADDR | (ReadAddr>>8);
                                buf[0] = ReadAddr & 0xff;
                                ee24_msg[0].size  = 1;
                }
                ee24_msg[0].buff  = buf;
                ee24_msg[0].addr  = slave_addr;
                ee24_msg[0].flags = ST_I2C_WR;
                ee24_msg[1].addr  = slave_addr;
                ee24_msg[1].flags = ST_I2C_RD;
                ee24_msg[1].buff  = (u8*)pBuffer;
                ee24_msg[1].size  = NumByteToRead;
                i2c_bitops_bus_xfer(&i2c1_dev,ee24_msg,2);
}

//擦除EEPROM
char ee_24clxx_erasebytes(u16 WriteAddr, char Erasedata, u16 NumByteToErase)
{
                char error = 0;
                u16 i;
                //char *buff;
                char buff[2048];        //测试用,实际使用需动态分配内存
               
                //buff = (char*)malloc(2048);
                for(i = 0;i < NumByteToErase;i++)
                {
                                buff[i] = Erasedata;
                }
                error = ee_24clxx_writebytes(WriteAddr,buff,NumByteToErase);                               
                //free(buff);
                return error;
}

//eeprom test
#if USE_24CLXX_DEBUG
#define                WRSIZE                                                        2048
#define         EEP_Firstpage              0
char I2c_Buf_Write[WRSIZE];
char I2c_Buf_Read[WRSIZE];
void EE24CLXX_Test(void)
{
                u16 i,error = 0;
                       
                for ( i=0; i<WRSIZE; i++ ) //填充缓冲
                {   
                                I2c_Buf_Write[i] = i;   
                }
                ee_24clxx_readbytes(EEP_Firstpage, I2c_Buf_Read, WRSIZE);
                ee_24clxx_readbytes(EEP_Firstpage, I2c_Buf_Read, WRSIZE);
                error = ee_24clxx_writebytes(EEP_Firstpage, I2c_Buf_Write, WRSIZE);         
                Delayms(5);
                ee_24clxx_readbytes(EEP_Firstpage, I2c_Buf_Read, WRSIZE);

                for ( i=0; i<WRSIZE; i++ ) //填充缓冲
                                I2c_Buf_Write[i] = 0;   
                error = ee_24clxx_writebytes(EEP_Firstpage, I2c_Buf_Write, WRSIZE);
                Delayms(5);               
                ee_24clxx_readbytes(EEP_Firstpage, I2c_Buf_Read,WRSIZE);
                //while(error);
}
#endif

#endif

使用特权

评论回复
地板
zhaohualiang|  楼主 | 2017-4-28 14:02 | 只看该作者
SDA设置开漏就好了。多谢各位!

使用特权

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

本版积分规则

51

主题

214

帖子

1

粉丝