c8051f340控制EEPROM

[复制链接]
 楼主| 赵俊 发表于 2010-1-5 11:34 | 显示全部楼层 |阅读模式
请问一下,用的是新华龙的C8051F340控制CAT24WC64。写入一个固定的数到固定的地址,但发现读出的都是0xff,郁闷至极。这程序以前用过的。烦请哪位高手给看看,晕的很呀。控制的SDA外接一个1K的上拉电阴到3.3V,SCL没接。单片机设置为SCL为普通IO口,SDA为漏极开漏。
如下:
#include"main.h"
#include"eeprom.h"
#define N    10
/************************************************************
;说明:读写24C256/512标准程序段
;适用于地址为两个字节的IIC存储器
************************************************************/
void nop_delay(uint8 i)
{
while(i--)
{
  _nop_();
}
}
/************************************************************
函数名称:void start_bit(void)        
入口参数:无   
返回参数:无;            
函数说明:通信开始位
************************************************************/
void start_bit(void)
{
  nop_delay(N);
  SCL=1;
  nop_delay(N);
  SDA=1;
  nop_delay(N);
  SDA=0;
  nop_delay(N);
  SCL=0;
  nop_delay(N);
}
/************************************************************
函数名称:void stop_bit(void)        
入口参数:无   
返回参数:无;            
函数说明:通信停止位            
************************************************************/
void stop_bit(void)
{
  nop_delay(N);
  SCL=1;
  nop_delay(N);
  SDA=0;
  nop_delay(N);
  SDA=1;
  nop_delay(N);
}
/************************************************************
函数名称:void ack(void)         
入口参数:无   
返回参数:无;            
函数说明:应答函数
************************************************************/
void ack(void)
{  uint8 data i;
// P1MDOUT   = 0x7c;
  nop_delay(N);
  SDA=1;
  nop_delay(N);
  SCL=0;
  nop_delay(N);
  SCL=1;
  nop_delay(N);
  while(SDA);
  nop_delay(N);
  //while((SDA)&&(i<255))
  //  i++;   //This may make the CPU crash. 04-3-18 17:16
  SCL=0;
  nop_delay(N);
  //P1MDOUT   = 0x7e;
}
/************************************************************
函数名称:void no_ack(void)      
入口参数:无   
返回参数:无;            
函数说明:无需应答位,在读程序中用到
************************************************************/
void no_ack(void)
{
  nop_delay(N);
  SDA=1;
  nop_delay(N);
  SCL=1;
  nop_delay(N);
  //while(SDA){;}  //This may make the CPU crash. 04-3-18 17:16
  SCL=0;
  nop_delay(N);
}
/************************************************************
函数名称:void write_8bit(uint8 ch)      
入口参数:所要写入的字节  
返回参数:无;            
函数说明:写一个字节(8位)数据
************************************************************/
void write_8bit(uint8 ch)
{
  uint8 data i=8;
  nop_delay(N);
  SCL=0;
  nop_delay(N);
  while(i--)
  {
   
    SDA=(bit)(ch&0x80);
    nop_delay(N);
    ch<<=1;
    nop_delay(N);
    SCL=1;
    nop_delay(N);
    SCL=0;
  }
}
/************************************************************
函数名称:uchar read24c16(uint address)      
入口参数:所要读取的16位地址  
返回参数:读取的字节;            
函数说明:读24c512指定地址数据(字节读)
************************************************************/
uint8 ReadFm24c256(uint16 address)
{
  
  //EA=0;//避免与串口通讯等中断冲突
  uint8 data rdata;
  uint8 data i=8;
  rdata=0;
  start_bit();
  write_8bit(0xA0);
  ack();
  write_8bit(address/256);
  ack();//伪写
  write_8bit(address%256);
  ack();
  start_bit();
  write_8bit(0xA1);
  ack();
  while(i--)
  {
    rdata<<=1;
    SCL=0;
    nop_delay(N);
    SCL=1;
    if(SDA) rdata|=0x01;
  }
  no_ack();
  stop_bit();
  //EA=1;
  return rdata;
}
/************************************************************
函数名称:void write24c16(uint address,uint8 ddata)      
入口参数:所要写入的16位地址,所要写入的字节  
返回参数:无            
函数说明:写数据到24c16的指定地址(字节写)
************************************************************/
void WriteFm24c256(uint16 address,uint8 ddata)
{
  //EA=0;  //避免与串口通讯等中断冲突
  nop_delay(N);
  start_bit();
  nop_delay(N);
  write_8bit(0xA0);
  ack();
  nop_delay(N);
  write_8bit(address/256);
  ack();
  write_8bit(address%256);
  ack();
  write_8bit(ddata);
  ack();
  stop_bit();
   //EA=1;
}
xuyaqi 发表于 2010-1-5 17:04 | 显示全部楼层
楼主说以前用过,以前是用c8051f340控制CAT24WC64吗?
 楼主| 赵俊 发表于 2010-1-5 18:21 | 显示全部楼层
没有,是用来控制AT24C01系列。但我看资料上好象时序都是一样的呀。这个东西调了好几天,实在是郁闷至极
。希望哪位高手能给解决一下。非常感谢呀
myfaith 发表于 2010-1-5 21:45 | 显示全部楼层
  1. #include "./head/Head.h"
  2. #include <intrins.h>

  3. #define        OP_READ        0xa1                // 器件地址以及读取操作
  4. #define        OP_WRITE 0xa0                // 器件地址以及写入操作
  5. #define        MAX_ADDR 0x7f                // AT24C02最大地址

  6. #define ACK 0
  7. #define NACK 1

  8. sbit SDA = P1^0;
  9. sbit SCL = P1^1;


  10. void I2C_Start();
  11. void I2C_Stop();
  12. unsigned char I2C_Shift_In(void);
  13. uchar I2C_Shift_Out(unsigned char write_data);
  14. unsigned char Eeprom_Read_Random(unsigned char random_addr,uchar RdData);
  15. uchar Eeprom_Write_Byte( unsigned char addr, unsigned char write_data);
  16. uchar Eeprom_Write_Page(uchar Addr,uchar *pWrData,uchar Len);
  17. void delay_i2c(unsigned char ms);
  18. uchar Eeprom_Read_Sequential(uchar Addr,uchar *RdBuf,uchar Len);

  19. static void SomeNop(void)
  20. {
  21.         uchar n;
  22.         for(n=0;n<30;n++)
  23.                 _nop_();
  24. }

  25. /*---------------------------------------------------------
  26. ---------------------------------------------------------*/       
  27. void I2C_ACK(void)
  28. {
  29.         SDA = 0;
  30.         SomeNop();
  31.         SCL = 1;
  32.         SomeNop();
  33.         SCL = 0;
  34.         _nop_();
  35.         SDA = 1;
  36. }       
  37. void I2C_NACK(void)
  38. {
  39.         SDA = 1;
  40.         SomeNop();
  41.         SCL = 1;
  42.         SomeNop();
  43.         SCL = 0;
  44.         SomeNop();
  45. }
  46. /*---------------------------------------------------------
  47. ---------------------------------------------------------*/
  48. void I2C_Start()
  49. // 开始位
  50. {
  51.         SDA = 1;
  52.         SomeNop();
  53.         SCL = 1;
  54.         SomeNop();
  55.         SDA = 0;
  56.         SomeNop();
  57.         SCL = 0;
  58.         SomeNop();
  59. }
  60. /*---------------------------------------------------------

  61. ---------------------------------------------------------*/
  62. void I2C_Stop()
  63. {
  64.         SCL = 0;
  65.         SomeNop();
  66.         SDA = 0;
  67.         SomeNop();
  68.         SCL = 1;
  69.         SomeNop();
  70.         SDA = 1;
  71. }
  72. /*---------------------------------------------------------
  73. // 从AT24Cxx移入数据到MCU
  74. ---------------------------------------------------------*/       
  75. unsigned char I2C_Shift_In(void)
  76. {
  77.         unsigned char i,read_data;
  78.         SomeNop();
  79.         for(i = 0; i < 8; i++)
  80.         {
  81.                 SCL = 1;                  SomeNop();
  82.                 read_data <<= 1;
  83.                 read_data |= (unsigned char)SDA;
  84.                 SCL = 0;                   SomeNop();
  85.         }
  86.         return(read_data);
  87. }
  88. /*---------------------------------------------------------
  89. // 从MCU移出数据到AT24Cxx
  90. ---------------------------------------------------------*/
  91. uchar I2C_Shift_Out(unsigned char write_data)
  92. {
  93.         unsigned char i;
  94.         uchar ack_bit;
  95.         SomeNop();
  96.         for(i = 0; i < 8; i++)                // 循环移入8个位
  97.         {
  98.                 SDA = (bit)(write_data & 0x80);
  99.                 SomeNop();
  100.                 SCL = 1;
  101.                 SomeNop();
  102.                 SCL = 0;
  103.                 write_data <<= 1;
  104.                 SomeNop();
  105.         }
  106.         SDA = 1;                        //应答已出现在数据线上,释放数据线
  107.         SomeNop();
  108.         SCL = 1;
  109.         SomeNop();                    //应答信号应在此SCL为高电平期间保持稳定
  110.         ack_bit = SDA;
  111.         SCL = 0;
  112.         SomeNop();
  113.         return ack_bit;                        // 返回AT24Cxx应答位
  114. }
  115. /*---------------------------------------------------------
  116. // 在指定地址addr处写入数据write_data
  117. ---------------------------------------------------------*/
  118. uchar Eeprom_Write_Byte(unsigned char addr, unsigned char write_data)
  119. {
  120.         I2C_Start();
  121.         if(NACK == I2C_Shift_Out(OP_WRITE))
  122.                 return FALSE;
  123.         if(NACK == I2C_Shift_Out(addr))
  124.                 return FALSE;
  125.         if(NACK == I2C_Shift_Out(write_data))
  126.                 return FALSE;
  127.         I2C_Stop();
  128.         delay_i2c(255);                // 写入周期
  129.         return TRUE;
  130. }
  131. /*---------------------------------------------------------
  132. ---------------------------------------------------------*/
  133. uchar Eeprom_Write_Page(uchar Addr,uchar *pWrData,uchar Len)
  134. {
  135.         unsigned char i;
  136.         I2C_Start();
  137.         if(NACK == I2C_Shift_Out(OP_WRITE))
  138.                 return FALSE;
  139.         if(NACK == I2C_Shift_Out(Addr))
  140.                 return FALSE;
  141.         for(i = 0; i < Len; i++)
  142.         {
  143.                 if(NACK == I2C_Shift_Out(*pWrData++))
  144.                         return FALSE;
  145.                 delay_i2c(255);                // 写入周期
  146.         }
  147.         I2C_Stop();
  148.         delay_i2c(255);
  149.         return TRUE;
  150. }
  151. /*---------------------------------------------------------
  152. // 在当前地址读取
  153. ---------------------------------------------------------*/
  154. unsigned char Eeprom_Read_Current(uchar RdData)
  155. {
  156.         I2C_Start();
  157.         if(NACK == I2C_Shift_Out(OP_READ))
  158.                 return FALSE;
  159.         RdData = I2C_Shift_In();
  160.         I2C_NACK();
  161.         I2C_Stop();
  162.         return TRUE;
  163. }
  164. /*---------------------------------------------------------
  165. // 在指定地址读取
  166. ---------------------------------------------------------*/
  167. unsigned char Eeprom_Read_Random(unsigned char random_addr,uchar RdData)
  168. {
  169.         I2C_Start();
  170.         if(NACK == I2C_Shift_Out(OP_WRITE))
  171.                 return FALSE;
  172.         if(NACK == I2C_Shift_Out(random_addr))
  173.                 return FALSE;
  174.         if(FALSE == Eeprom_Read_Current(RdData))
  175.                 return FALSE;
  176.         return        TRUE;
  177. }
  178. /*---------------------------------------------------------
  179. ---------------------------------------------------------*/
  180. uchar Eeprom_Read_Sequential(uchar Addr,uchar *RdBuf,uchar Len)
  181. {
  182.         I2C_Start();
  183.         if(NACK == I2C_Shift_Out(OP_WRITE))  //a0
  184.                 return FALSE;
  185.         if(NACK == I2C_Shift_Out(Addr))       
  186.                 return FALSE;
  187.         I2C_Start();
  188.         if(NACK == I2C_Shift_Out(OP_READ))
  189.                 return FALSE;          
  190.         while(Len)
  191.         {
  192.                 *RdBuf++ = I2C_Shift_In();
  193.                 Len--;
  194.                 if(Len == 0)
  195.                         I2C_NACK();
  196.                 else
  197.                         I2C_ACK();
  198.         }               
  199. /*
  200.         for(n=0;n<Len;n++)                 //哈哈,一字之差害我找了好久!
  201.         {
  202.                 *RdBuf++ = I2C_Shift_In();
  203.                 if(n==Len)
  204.                         I2C_NACK();
  205.                 else
  206.                         I2C_ACK();
  207.         }                 */
  208.         I2C_Stop();       
  209.         return TRUE;
  210. }       
  211.        
  212. /*---------------------------------------------------------
  213. //i=220,延时68us
  214. //i=250,延时76us
  215. //i=164,延时50.4us
  216. ---------------------------------------------------------*/
  217. void delay_i2c(unsigned char n)       
  218. // 延时子程序
  219. {
  220.         unsigned char i;
  221.         while(n--)
  222.         {
  223.                 for(i = 0; i < 164; i++);
  224.         }
  225. }
C8051F340,48M系统时钟.I2C时钟速度大概35K左右.奉献给楼主拉!
404710520 发表于 2013-1-9 10:44 | 显示全部楼层
看一下 现在也在自己写iic
ayb_ice 发表于 2013-1-9 13:27 | 显示全部楼层
多加几个NOP吧
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

11

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部

8

主题

11

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部