Chinaunix首页 | 论坛 | 博客
  • 博客访问: 521775
  • 博文数量: 56
  • 博客积分: 1136
  • 博客等级: 少尉
  • 技术积分: 1378
  • 用 户 组: 普通用户
  • 注册时间: 2011-12-28 14:02
文章存档

2014年(1)

2013年(7)

2012年(45)

2011年(3)

分类: 嵌入式

2012-04-27 18:53:32

今天帮一同事调试裸机下的EEprom,虽然是很小CASE,但是还是记录下,我们是基于SEP4020芯片的,该芯片上没有集成IIC控制器,因此我们分了两层,协议层和功能层。下面这个EEprom.c是功能层,可以适应8位数据地址,16位数据地址,以及AT24C16的地址组成(AT24c16的数据地址是11位高三位放在Devices_addr中,剩下8位为PAG中的偏移地址),函数参数传递的时候注意EEprom的地址大小。
EEprom.c
  1. #include "eeprom.h"
  2. #include "iic.h"

  3. #define DEV_ADDR    0xA0
  4. //#define I2C_FLAG_ADDR16    
  5. #define AT_24C16    

  6. //ReadAddr:开始读数的地址,注意读地址大小,比如atAT_24C16是:0~2408
  7. //返回值 :读到的数据
  8. u8 Eeprom_ReadOneByte(u16 ReadAddr)
  9. {                
  10.     u8 temp=0,temp1;    
  11.     u8 data_addr=0,dev_real;
  12.     
  13. #ifdef AT_24C16
  14.     data_addr=ReadAddr%256;
  15.     temp = ReadAddr>>7;
  16.     temp = temp &0x0E;
  17.     dev_real = DEV_ADDR |temp;
  18. #else
  19.     dev_real=DEV_ADDR;
  20. #endif

  21.     IIC_Start();
  22.     IIC_Send_Byte(dev_real);     //发送读命令
  23.     IIC_Wait_Ack();
  24.     
  25. #ifdef I2C_FLAG_ADDR16
  26.     IIC_Send_Byte(ReadAddr>>8);//发送高地址        
  27.     IIC_Wait_Ack();
  28.     IIC_Send_Byte(ReadAddr%256); //发送低地址
  29.     IIC_Wait_Ack();    
  30. #else
  31.     IIC_Send_Byte(data_addr);//发送读地址        
  32.     IIC_Wait_Ack();
  33. #endif

  34.     IIC_Start();          
  35.     IIC_Send_Byte(dev_real | 1); //进入接收模式            
  36.     IIC_Wait_Ack();    
  37.     temp1=IIC_Read_Byte(0);        
  38.     IIC_Stop();//产生一个停止条件    
  39.     return temp1;
  40. }

  41. //WriteAddr :写入数据的目的地址 注意读地址大小,比如atAT_24C16是:0~2408
  42. //DataToWrite:要写入的数据
  43. /*
  44. 写入单个字节:
  45. 写入字节指令每次只能向芯片中的一个地址写入一个字节的数据。
  46. 首先发送开始位来通知芯片开始进行指令传输,
  47. 然后传送设置好的器件地址字节,R/W位应置0,
  48. 接着是分开传送十六位地址的高低字节,再传送要写入的数据,
  49. 最后发送停止位表示本次指令结束。
  50. 十六位地址的前3位忽略,所以可寻址的位数为13位,地址长度为213=8192,
  51. 正好为芯片资料上说的8K*8的结构,所以AT24C64可寻址的范围是0000-1FFFH。
  52. */

  53. void Eeprom_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
  54. {                                                                                           
  55.     u8 temp=0,dev_real;    
  56.     u8 data_addr=0;

  57. #ifdef AT_24C16
  58.     data_addr=WriteAddr%256;
  59.     temp = WriteAddr>>7;
  60.     temp = temp &0x0E;
  61.     dev_real = DEV_ADDR |temp;
  62. #else
  63.     dev_real=DEV_ADDR;
  64. #endif

  65.     IIC_Start();
  66.     IIC_Send_Byte(dev_real);     //发送写命令
  67.     IIC_Wait_Ack();
  68.     
  69. #ifdef    I2C_FLAG_ADDR16
  70.     IIC_Send_Byte(WriteAddr>>8);//发送高地址
  71.     IIC_Wait_Ack();    
  72.     IIC_Send_Byte(WriteAddr%256);//发送低地址
  73.     IIC_Wait_Ack();     
  74. #else
  75.     IIC_Send_Byte(data_addr);//发送写入地址
  76.     IIC_Wait_Ack();    
  77. #endif
  78.     
  79.     IIC_Send_Byte(DataToWrite); //发送字节                            
  80.     IIC_Wait_Ack();              
  81.     IIC_Stop();//产生一个停止条件
  82.     delay_ms(10);
  83. }

  84. /*
  85. *read_addr:读取地址
  86. *buf:读取的数据放入buf中
  87. *len:读取数据长度
  88. */
  89. void eeprom_read_bytes(u16 read_addr, u8 *buf, u8 len)
  90. {
  91.     u8 i = 0;
  92.     
  93.     for (i = 0; i < len; i++)
  94.         buf[i] = Eeprom_ReadOneByte(read_addr + i);
  95. }

  96. /*
  97. *write_addr:写入地址
  98. *buf:写入的数据
  99. *len:写入数据长度
  100. */
  101. void eeprom_write_bytes(u16 write_addr, u8 *buf, u8 len)
  102. {
  103.     u8 i = 0;
  104.     
  105.     for (i = 0; i < len; i++)
  106.         Eeprom_WriteOneByte(write_addr + i, buf[i]);
  107. }

  108. /* 原始密码初始化 */
  109. void Eeprom_passwd_init()
  110. {
  111.     u16 i ;
  112.     u8 system_passwd[4] = {1, 2, 3, 4};
  113.     
  114.     /* eeprom地址 0~3 为系统密码存储地址 */
  115.     for (i=1024; i < 1028; i++) {
  116.         Eeprom_WriteOneByte(i, system_passwd[i-1024]);
  117.     }

  118. }
IIC.c文件实现IIC协议的模拟层
  1. #include"iic.h"
  2.                  
  3. //us延时函数
  4. void delay_nus(u8 nus)
  5. {
  6.     u16 i;
  7.     while(nus--)for(i=30;i>0;i--);
  8. }

  9. void delay_ms(u8 n)
  10. {
  11.     u32 i = 0;
  12.     
  13.     while (n--) {
  14.         for (i = 0; i < 2000; i++)
  15.             ;
  16.     }
  17. }

  18. void IIC_Init(void)
  19. {
  20.     *(RP)GPIO_PORTE_SEL    |= IIC_CLK | IIC_SDA;
  21.     *(RP)GPIO_PORTE_DIR &= ~(IIC_CLK | IIC_SDA);
  22.     *(RP)GPIO_PORTE_DATA |= IIC_CLK | IIC_SDA; // SDA, SCL 输出高
  23. }


  24. //产生IIC起始信号
  25. //CHECK OK 09/05/18
  26. void IIC_Start(void)
  27. {
  28.     SDA_OUT(); //sda线输出
  29.     IIC_SDA_SET(1);         
  30.     IIC_SCL_SET(1);
  31.     delay_nus(4);
  32.      IIC_SDA_SET(0);//START:when CLK is high,DATA change form high to low
  33.     delay_nus(4);
  34.     IIC_SCL_SET(0);//钳住I2C总线,准备发送或接收数据
  35. }    
  36. //产生IIC停止信号
  37. //CHECK OK 09/05/18
  38. void IIC_Stop(void)
  39. {
  40.     SDA_OUT();//sda线输出
  41.     IIC_SCL_SET(0);
  42.     IIC_SDA_SET(0);//STOP:when CLK is high DATA change form low to high
  43.      delay_nus(4);
  44.     IIC_SCL_SET(1);
  45.     IIC_SDA_SET(1);//发送I2C总线结束信号                                 
  46. }
  47. //等待应答信号到来
  48. //返回值:0,接收应答失败
  49. // 1,接收应答成功
  50. //CHECK OK 09/05/18
  51. u8 IIC_Wait_Ack(void)
  52. {
  53.     u8 ucErrTime=0;
  54.     SDA_IN(); //SDA设置为输入
  55.     IIC_SDA_SET(1);delay_nus(1);    
  56.     IIC_SCL_SET(1);    
  57.     while(READ_SDA())
  58.     {
  59.         ucErrTime++;
  60.         if(ucErrTime>250)
  61.         {
  62.             IIC_Stop();
  63.             return 0;
  64.         }
  65.     }
  66.     IIC_SCL_SET(0);//时钟输出0     
  67.     return 1;
  68. }
  69. //产生ACK应答
  70. //CHECK OK 09/05/18
  71. void IIC_Ack(void)
  72. {
  73.     IIC_SCL_SET(0);
  74.     SDA_OUT();
  75.     IIC_SDA_SET(0);
  76.     delay_nus(1);
  77.     IIC_SCL_SET(1);
  78.     delay_nus(1);
  79.     IIC_SCL_SET(0);
  80. }
  81. //不产生ACK应答
  82. //CHECK OK 09/05/18
  83. void IIC_NAck(void)
  84. {
  85.     IIC_SCL_SET(0);
  86.     SDA_OUT();
  87.     IIC_SDA_SET(1);
  88.     delay_nus(1);
  89.     IIC_SCL_SET(1);
  90.     delay_nus(1);
  91.     IIC_SCL_SET(0);
  92. }                                     
  93. //IIC发送一个字节
  94. //返回从机有无应答
  95. //1,有应答
  96. //0,无应答
  97. //CHECK OK 09/05/18
  98. void IIC_Send_Byte(u8 txd)
  99. {
  100.     u8 t;
  101.     SDA_OUT();     
  102.     IIC_SCL_SET(0);//拉低时钟开始数据传输
  103.     for(t=0;t<8;t++)
  104.     {
  105.         IIC_SDA_SET((txd&0x80)>>7);
  106.         txd<<=1;     
  107.         delay_nus(1); //对TEA5767这三个延时都是必须的
  108.         IIC_SCL_SET(1);
  109.         delay_nus(1);
  110.         IIC_SCL_SET(0);    
  111.         delay_nus(1);
  112.     }    
  113. }     
  114. //读1字节,ack=1时,发送ACK,ack=0,发送nACK
  115. //CHECK OK 09/05/18
  116. u8 IIC_Read_Byte(unsigned char ack)
  117. {
  118.     unsigned char i,receive=0;
  119.     SDA_IN();//SDA设置为输入
  120.     for(i=0;i<8;i++ )
  121.     {
  122.         IIC_SCL_SET(0);
  123.         delay_nus(1);
  124.         IIC_SCL_SET(1);
  125.         receive<<=1;
  126.         if(READ_SDA())receive++;
  127.     }                    
  128.     if (!ack)
  129.         IIC_NAck();//发送nACK
  130.     else
  131.         IIC_Ack(); //发送ACK
  132.     return receive;
  133. }


阅读(3538) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~