| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505 |
- /******************************************************************************
- 版权所有:
- 文件名称: e2prom_24lc.c
- 文件版本: 01.01
- 创建作者: sunxi
- 创建日期: 2008-08-06
- 功能说明: MICROCHIP 24LC系列的E2PROM驱动程序。
- 其它说明: 在I2C总线频率357k(周期2.8us)的情况下,写256bytes需要22206us,读256bytes
- 需要6836us。
- 修改记录:
- */
- /*------------------------------- 头文件 --------------------------------------
- */
- #include "bspconfig.h"
- #include "i2c.h"
- #include "ustimer.h"
- #include "gpio.h"
- #include "e2prom.h"
- #if 0
- /*------------------------------- 宏定义 --------------------------------------
- */
- #if CFG_BSP_DEBUG
- #define _DEBUG_E2PROM
- #endif
- #define E2PROM_I2C_ID 0XA0
- /*------------------------------ 全局变量 -------------------------------------
- */
- /*------------------------------ 函数声明 -------------------------------------
- */
- int _ac_e2prom_write(unsigned char addr,uint32_t offset,unsigned char * buffer,uint32_t length);
- /*------------------------------ 外部函数 -------------------------------------
- */
- /******************************************************************************
- 函数名称: ac_e2prom_init
- 函数版本: 01.01
- 创建作者: sunxi
- 创建日期: 2008-08-06
- 函数说明: ac_e2prom初始化。
- 参数说明: 无
- 返回值: 成功返回0.
- 修改记录:
- */
- int ac_e2prom_init(void)
- {
- return 0;
- }
- /******************************************************************************
- 函数名称: ac_e2prom_read
- 函数版本: 01.01
- 创建作者: sunxi
- 创建日期: 2008-08-06
- 函数说明: 从E2PROM中读出数据。
- 参数说明:
- offset(in):需要读的数据在E2PROM中的偏移量,和length之和不能大于
- CFG_E2PROM_SIZE.
- buffer(out):读出数据的buffer。
- length(in): 需要读出数据的长度,和offset之和不能大于CFG_E2PROM_SIZE。
- 返回值: 成功返回0.
- 修改记录:
- */
- int ac_e2prom_read(unsigned char addr,uint32_t offset,unsigned char * buffer,uint32_t length)
- {
- unsigned char c;
- int h_i2c,ret;
-
- //检查参数
- if(addr >= 8)
- {
- return -11;
- }
-
- if(buffer == 0 || (offset + length) > CFG_E2PROM_SIZE)
- {
-
- return -1;
- }
-
- if(length == 0)
- {
-
- return 0;
- }
-
- h_i2c = i2c_open(I2C_ID_E2PROM);
- if(h_i2c < 0)
- {
-
- return -1;
- }
-
- ret = -2;
-
- //等待总线释放
- I2C_WAIT_BUS_IDLE();
-
- //发送模式
- MCF_I2CR |= MCF_I2C_I2CR_MTX;
-
- //发送START信号
- MCF_I2CR |= MCF_I2C_I2CR_MSTA;
-
- //发送控制字节
- MCF_I2DR = E2PROM_I2C_ID | (addr<<1);
- I2C_WAIT_COMPLETION();
- I2C_CHECK_ACK();
-
- //发送地址0
- MCF_I2DR = (unsigned char)(offset>>8);
- I2C_WAIT_COMPLETION();
- I2C_CHECK_ACK();
- //发送地址1
- MCF_I2DR = (unsigned char)(offset);
- I2C_WAIT_COMPLETION();
- I2C_CHECK_ACK();
-
- //发送重开始信号,方向改为读
- MCF_I2CR |= MCF_I2C_I2CR_RSTA;
- MCF_I2DR = E2PROM_I2C_ID | (addr<<1) | 0x01;
- I2C_WAIT_COMPLETION();
- I2C_CHECK_ACK();
-
-
- //接收模式
- MCF_I2CR &= ~MCF_I2C_I2CR_MTX;
-
- //接收数据,最后一个字节不发ACK.
- if(length == 1)
- {
- MCF_I2CR |= MCF_I2C_I2CR_TXAK; //不发ACK
- c = MCF_I2DR; //空读,启动下一个字节的读
- I2C_WAIT_COMPLETION();
- *buffer++ = MCF_I2DR;
- I2C_WAIT_COMPLETION();
-
- }
- else
- {
- //循环接收length个字节。
- MCF_I2CR &= ~MCF_I2C_I2CR_TXAK; //发送ACK
- c = MCF_I2DR; //空读,启动下一个字节的读
- I2C_WAIT_COMPLETION();
- while(length--)
- {
- if(length == 1)
- {
-
- MCF_I2CR |= MCF_I2C_I2CR_TXAK; //不发ACK
- }
- *buffer++ = MCF_I2DR; //读数据,并启动下一个字节的读。
- I2C_WAIT_COMPLETION();
- }
- }
-
- ret = 0;
-
- LABEL_END:
- //发送STOP信号
- MCF_I2CR &= ~MCF_I2C_I2CR_MSTA;
-
- i2c_close(h_i2c);
-
- return ret;
- }
- /******************************************************************************
- 函数名称: ac_e2prom_write
- 函数版本: 01.01
- 创建作者: sunxi
- 创建日期: 2008-08-06
- 函数说明: 将数据写入E2PROM中。注意:E2PROM按页写的速度比按字节写的速度快,
- 所以如果应用程序将要写入的数据组织成
- 参数说明:
- offset(in):需要写入的数据在E2PROM中的偏移量,和length之和不能大于
- CFG_E2PROM_SIZE.
- buffer(in):写入数据的buffer。
- length(in): 需要写入数据的长度,和offset之和不能大于CFG_E2PROM_SIZE。
- 返回值: 成功返回0.
- 修改记录:
- */
- int ac_e2prom_write(unsigned char addr,uint32_t offset,unsigned char * buffer,uint32_t length)
- {
- int ret;
- uint32_t length_once,length_spare;
-
- //检查参数
- if(addr >= 8)
- {
- return -11;
- }
-
- if(buffer == 0 || (offset + length) > CFG_E2PROM_SIZE)
- {
- return -1;
- }
-
- if(length == 0)
- {
-
- return 0;
- }
-
- //初始化length_spare
- length_spare = length;
-
- //写起始不完整页
- length_once = CFG_E2PROM_PAGE_SIZE - (offset&(CFG_E2PROM_PAGE_SIZE - 1));
- if(length_once > length_spare)
- {
-
- length_once = length_spare;
- }
-
- if(length_once)
- {
- ret = _ac_e2prom_write(addr,offset,buffer,length_once);
- if(ret != 0)
- {
-
- return ret;
- }
-
- offset += length_once;
- buffer += length_once;
- length_spare -= length_once;
- }
-
- //循环写完整页。
- length_once = CFG_E2PROM_PAGE_SIZE;
- while(length_spare > CFG_E2PROM_PAGE_SIZE)
- {
- ret = _ac_e2prom_write(addr,offset,buffer,length_once);
- if(ret != 0)
- {
-
- return ret;
- }
-
- offset += length_once;
- buffer += length_once;
- length_spare -= length_once;
- }
-
- //写末尾不完整页。
- length_once = length_spare;
- if(length_once)
- {
- ret = _ac_e2prom_write(addr,offset,buffer,length_once);
- if(ret != 0)
- {
-
- return ret;
- }
- }
-
- return 0;
- }
- /*------------------------------ 内部函数 -------------------------------------
- */
- /******************************************************************************
- 函数名称: _ac_e2prom_write
- 函数版本: 01.01
- 创建作者: sunxi
- 创建日期: 2008-08-06
- 函数说明: 内部函数,将数据写入E2PROM中。
- 参数说明:
- offset(in):需要写入的数据在E2PROM中的偏移量,和length之和不能大于CFG_E2PROM_SIZE.
- buffer(in):写入数据的buffer。
- length(in): 需要写入数据的长度,和offset之和不能大于CFG_E2PROM_PAGE_SIZE。
- 返回值: 成功返回0.
- 修改记录:
- */
- int _ac_e2prom_write(unsigned char addr,uint32_t offset,unsigned char * buffer,uint32_t length)
- {
- int h_i2c,ret;
- unsigned long us0,us;
-
- //打开总线
- h_i2c = i2c_open(I2C_ID_E2PROM);
- if(h_i2c < 0)
- {
-
- return -1;
- }
-
- //打开写保护.
- //GPIO_WP_E2PROM_LOW();
-
- ret = -2;
-
- //等待总线释放
- I2C_WAIT_BUS_IDLE();
-
- //发送模式
- MCF_I2CR |= MCF_I2C_I2CR_MTX;
-
- //发送START信号
- MCF_I2CR |= MCF_I2C_I2CR_MSTA;
-
- //发送控制字节
- MCF_I2DR = E2PROM_I2C_ID | (addr<<1);
- I2C_WAIT_COMPLETION();
- I2C_CHECK_ACK();
-
- //发送地址0
- MCF_I2DR = (unsigned char)(offset>>8);
- I2C_WAIT_COMPLETION();
- I2C_CHECK_ACK();
- //发送地址1
- MCF_I2DR = (unsigned char)(offset);
- I2C_WAIT_COMPLETION();
- I2C_CHECK_ACK();
-
-
- //发送数据
- while(length--)
- {
- MCF_I2DR = *buffer++;
- I2C_WAIT_COMPLETION();
- I2C_CHECK_ACK();
- }
-
- //发送STOP信号,启动E2PROM内部写
- MCF_I2CR &= ~MCF_I2C_I2CR_MSTA;
-
- //等待总线释放
- I2C_WAIT_BUS_IDLE();
- //等待完成
- //发送START信号
- MCF_I2CR |= MCF_I2C_I2CR_MSTA;
-
- us0= ustimer_get_origin();
- while(1)
- {
- // 得到超时值
- us = ustimer_get_duration(us0);
-
- //发送控制字节
- MCF_I2DR = E2PROM_I2C_ID | (addr<<1);
- I2C_WAIT_COMPLETION();
-
- //如果有ACK,内部写已经完成,退出。
- if((MCF_I2SR & MCF_I2C_I2SR_RXAK) == 0)
- {
- ret = 0;
- break;
- }
-
- //最大写时间为5ms.
- if(us > 5*USTIMER_MS)
- {
- ret = -3;
- break;
- }
-
- //发送重开始信号
- MCF_I2CR |= MCF_I2C_I2CR_RSTA;
- }
-
- LABEL_END:
- //发送STOP信号
- MCF_I2CR &= ~MCF_I2C_I2CR_MSTA;
-
- //关闭写保护
- //GPIO_WP_E2PROM_HIGH();
-
- //关闭总线
- i2c_close(h_i2c);
-
- return ret;
- }
- /*------------------------------ 测试函数 -------------------------------------
- */
- #ifdef _DEBUG_E2PROM
- #include "rt.h"
- #define E2PROM_TEST_SIZE 1002 //必须是偶数
- //#define E2PROM_TEST_SUM CFG_E2PROM_SIZE
- #define E2PROM_TEST_SUM 4096
- int ac_e2prom_test(void)
- {
- int ret;
- unsigned long us0,us;
- unsigned long i,offset,length;
- unsigned short buffer[E2PROM_TEST_SIZE/2];
- unsigned char addr;
-
- rt_printf("ac_e2prom_test start...\r\n");
- addr = 0;
- for(addr=0; addr<4; addr++)
- {
- rt_printf("addr=%d.\r\n",addr);
-
- offset = 0;
- while(offset < E2PROM_TEST_SUM)
- {
- //写
- length = (E2PROM_TEST_SUM - offset) > E2PROM_TEST_SIZE ? E2PROM_TEST_SIZE : (E2PROM_TEST_SUM - offset);
- for(i=0;i<length/2;i++)
- {
-
- buffer[i] = (unsigned short)(offset + i + 0x5555);
- }
- us0 = ustimer_get_origin();
- ret = ac_e2prom_write(addr,offset,(unsigned char *)buffer,length);
- us = ustimer_get_duration(us0);
- rt_printf("ac_e2prom_write:(offset=%d,ret=%d,us=%d)\r\n",offset,ret,us);
- if(ret != 0)
- {
-
- break;
- }
-
- offset += length;
- }
-
- offset = 0;
- memset(buffer,0,sizeof(buffer));
- while(offset < E2PROM_TEST_SUM)
- {
- //读
- length = (E2PROM_TEST_SUM - offset) > E2PROM_TEST_SIZE ? E2PROM_TEST_SIZE : (E2PROM_TEST_SUM - offset);
- memset(buffer,0,E2PROM_TEST_SIZE);
- us0 = ustimer_get_origin();
- ret = ac_e2prom_read(addr,offset,(unsigned char *)buffer,length);
- us = ustimer_get_duration(us0);
- rt_printf("ac_e2prom_read:(offset=%d,ret=%d,us=%d)\r\n",offset,ret,us);
-
- if(ret != 0)
- {
-
- break;
- }
-
- //比较
- for(i=0;i<length/2;i++)
- {
- if(buffer[i] != (unsigned short)(offset + i + 0x5555))
- {
-
- break;
- }
- }
- if(i== length/2)
- {
-
- rt_printf("compare ok(offset=%d,i=%d)!\r\n",offset,i);
- }
- else
- {
- rt_printf("compare error(offset=%d,i=%d)!\r\n",offset,i);
- break;
- }
-
- offset += length;
-
- }
-
- if(offset == E2PROM_TEST_SUM)
- {
-
- rt_printf("ac_e2prom_test ok!\r\n\n");
- }
- else
- {
-
- rt_printf("ac_e2prom_test fail!\r\n\n");
- }
- }
- return 0;
- }
- #endif
- #endif
- /*------------------------------ 文件结束 -------------------------------------
- */
|