找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 10812|回复: 14
收起左侧

小白菜的EEPROM学习之路

  [复制链接]
ID:70650 发表于 2014-12-20 18:49 | 显示全部楼层 |阅读模式
零:接上回http://www.51hei.com/bbs/dpj-29235-1.html
上回书说到了标准IIC的编写,函数参数是指针和字节数,并非是以IIC地址和寄存器地址作参数,何故?小白菜考虑着,要想真正的适应大部分IIC器件的IIC操作而不必写两个功能相同的函数,用指针和字节数作参数是最好的选择。大虾们可能觉得这是为了统一而统一,这点必须承认。在参数传递效率上,确实比直接传递数据要低,但是小白菜接触到的IIC器件,没有一个是需要时时写入的(这里的时时是指MCU空闲下来就读取或写入IIC器件数据)。用的最多的是EEPROM、还有xxx7290(键盘数码管扫描芯片)、铁电存储器,测温芯片。这些器件没有一个是需要实时操作的,也就是说小白菜接触的IIC器件对实时性要求不高。于是,小白菜可以忽略参数传递效率的问题。当然“为了统一而统一”这个目的是去不掉的。
一:为了那“可爱”的目的。
还是2011年,小白菜空闲时,觉得以前用的AT24Cxx系列EEPROM的驱动不能相互兼容,你用24C02和用24C64,就得换驱动,从工程中去掉原来,然后添加上新的,相当的麻烦。于是小白菜便想,都是同一系列的产器,为什么不能用同一个驱动?
于是,小白菜得到了他的目的:
1编写一个能适应AT24Cxx全系列的驱动函数,对外只有两个函数,写EEPROM函数和读EEPROM函数;
2移植时(包括更换不同容量的芯片)只需要改变很少的宏定义选项就能完成。
二:发现共性(操作过程的比较与抽象)
1为了实现这两个目的,小白菜开始看手册,并写记录下AT24Cxx系列EEPROM的一些参数,见表1和表2。




表1:AT24Cxx比较
型号
容量(字节)
最大级联数
页字节数
地址字节数
写入时间
AT24C01
128 = 0x0080
8
8
2

  
5ms
  
(最大)
AT24C02
256 = 0x0100
8
8
2
AT24C04
512 = 0x0200
4
16
2
AT24C08
1024 = 0x0400
2
16
2
AT24C16
2048 = 0x0800
1
16
2
AT24C32
4096 = 0x1000
8
32
3
AT24C64
8192 = 0x2000
8
32
3
AT24C128
16384 = 0x4000
8
64
3
AT24C256
32768 = 0x8000
8
64
3


表2:AT24Cxx的IIC操作地址比较(二进制)
  
A2、A1、A0指的是芯片引脚,a14—a0指的是字节地址
型号
1个字节
  
MSB----LSB
2个字节
  
MSB----LSB
3字节
  
MSB----LSB
AT24C01
1     0     1    0
  
A2   A1   A0    R/W
0   a6   a5   a4
  
a3  a2   a1   a0
不发送
AT24C02
1     0     1    0
  
A2   A1   A0    R/W
a7  a6   a5   a4
  
a3  a2   a1   a0
不发送
AT24C04
1     0     1    0
  
A2   A1   a8   R/W
a7  a6   a5   a4
  
a3  a2   a1   a0
不发送
AT24C08
1     0     1    0
  
A2   a9    a8    R/W
a7  a6   a5   a4
  
a3  a2   a1   a0
不发送
AT24C16
1     0     1    0
  
a10  a9    a8    R/W
a7  a6   a5   a4
  
a3  a2   a1   a0
不发送
AT24C32
1     0     1    0
  
A2   A1   A0    R/W
0    0    0    0
  
a11  a10   a9   a8
a7  a6   a5   a4
  
a3  a2   a1   a0
AT24C64
1     0     1    0
  
A2   A1   A0    R/W
0    0     0     a12
  
a11  a10   a9   a8
a7  a6   a5   a4
  
a3  a2   a1   a0
AT24C128
1     0     1    0
  
A2   A1   A0    R/W
0    0    a13    a12
  
a11  a10   a9   a8
a7  a6   a5   a4
  
a3  a2   a1   a0
AT24C256
1     0     1    0
  
A2   A1   A0    R/W
0    a14   a13   a12
  
a11  a10   a9   a8
a7  a6   a5   a4
  
a3  a2   a1   a0
由表1和表2,小白菜开始想,不同容量的需要进行地址处理和页处理。小白菜还设想,在应用中,不大可能不同容量的EEPROM一起使用;有可能访问的数量大于芯片容量,所以要有溢出检测……小白菜想了很多,并整理了一个大体的思路。
读写函数 → 先要进行参数检查 → 进行溢出检测 → 地址处理 → 读写数据( →  写数据时写入等待) → 返回操作状态。
三 代码编写
小白菜用上面的流程,开始了代码的编写。写代码时,地址处理部分需要使用条件编译来实现不同芯片的操作;写入等待函数需要有超时机制……写啊写,写啊写,小白菜终于写出来了。列位看官,请继续向下看。
四 使用说明
4.1 移植修改  移植修改在H文件中的“移植修改”部分。这里有5处需要修改。
//----------------------------------------------------------------------------//
// 编号:1
// 名称:
// 功能:单片机寄存器头文件,例如reg51.h
//----------------------------------------------------------------------------//
#include "ATT703x.H"
4.1.1  请您把使用的单片机的头文件包含进来。大虾们用过MCU 多了,知道不同的MCU,其寄存器定义是不一样滴,不是所有的51 单片机都用Reg51.H 或Reg52.H 头文件。
//--------------------------------------------------------------------------//
// 编号 :2
// 名称 :AT24Cxx
// 功能 :选择您所使用的EEPROM芯片型号。只能启用一条宏。
//      :不支持一条总线上挂不同的EEPROM,支持同类型的多个EEPROM挂在总线上。
//--------------------------------------------------------------------------//
//  #defineAT24C01         // 使用AT24C01,则启用本句并屏蔽其它语句。
//  #defineAT24C02         // 使用AT24C02,则启用本句并屏蔽其它语句。
    #defineAT24C04         // 使用AT24C04,则启用本句并屏蔽其它语句。
//  #defineAT24C08         // 使用AT24C08,则启用本句并屏蔽其它语句。
//  #defineAT24C16         // 使用AT24C16,则启用本句并屏蔽其它语句。
//  #defineAT24C32         // 使用AT24C32,则启用本句并屏蔽其它语句。
//  #defineAT24C64         // 使用AT24C64,则启用本句并屏蔽其它语句。
//  #defineAT24C128        //使用AT24C128,则启用本句并屏蔽其它语句。
//  #defineAT24C256        //使用AT24C256,则启用本句并屏蔽其它语句。
4.1.2 这里启用您所用的芯片。不支持不同容量的芯片挂接在同一总线上。
//--------------------------------------------------------------------------//
// 编号 :3
// 名称 :AT24CXX_WP_ENABLE
// 功能 :启用AT24Cxx的写保护功能。为1时启用写保护。为0时不使用写保护。
//      :当WP引脚接地时,请禁用写保护功能。否则会浪费系统资源。
//--------------------------------------------------------------------------//
#define  AT24CXX_WP_ENABLE   (0)
//--------------------------------------------------------------------------//
// 编号 :4
// 名称 :AT24Cxx_WP
// 功能 :写保护引脚所用的口线。启用写保护时,才需要设置本参数
//--------------------------------------------------------------------------//
#if (1 == AT24CXX_WP_ENABLE)
    sbit   AT24Cxx_WP = P1^2;
#endif
4.1.3 这里是关于WP的操作,您可能并不使用写保护并把WP接地。如果AT24CXX_WP_ENABLE为0,即不使用写保护时,写入允许和禁止函数不编译。如果您为了减少改动,也可以把这两个函数体进行条件编译,而只留下一个“空函数”。
//--------------------------------------------------------------------------//
// 编号 :5
// 名称 :AT24Cxx_Delay_1ms()
// 功能 :精确的1毫秒延时函数。这里请使用您系统中的微秒延时函数。
//      :例如,您的延时函数是Delay_1us(),那么您可以使用下句
//      :#defineMK_Delay_1us()  Delay_1us()
//      :来实现延时。
//--------------------------------------------------------------------------//
#include "Delay.H"      // 您系统所用延时函数声明所在的头文件。
#define AT24Cxx_Delay_1ms()   Delay_MS(1)
4.1.4 这里的软件1ms延时函数用于写入等待。延时必须在1ms左右。
4.2 函数说明  
4.2.1 从AT24Cxx中读取数据函数
//----------------------------------------------------------------------------//
//                    从AT24Cxx中读取多字节数据函数(对外接口)
//函数名称:AT24Cxx_Read_Str
//函数功能:从Addr指定的地址开始读取AT24Cxx,一共读取Num个字节,数据读出后存
//         放在PDat数组中。
//入口参数:
//         A2A1A0:对应芯片A2 A1 A0引脚,低3位有效(高位被忽略).
//         Addr:对24Cxx进行读操作的起始地址。
//        *PDat:数据读取后存放的首地址
//         Num :要读取的字节数
//出口参数:0 = 成功,1 = 失败。
//重要说明:1.读取的第一个字节放在PDat[0]中,第二个放在PDat[1]中,以此类推。
//       :2.若EEPROM剩余空间不足,函数报错。
//----------------------------------------------------------------------------//
extern uint8 AT24Cxx_Read_Str(uint8 A2A1A0, uint16 Addr, uint8*PDat, uint16 Num)
第一个参数A2A1A0的低三位分别对应A2、A1、A0,并且不能对该参数进行检查,所以一定要设置正确。
应用示例:
    芯片的A2、A1、A0接地,并且从0x10地址开始读取,读取的字节数50,数据读取后存放在unsigned char Buf[100]数组中。
解析:由于A2、A1、A0接地,所以第一个参数为0,函数调用是
AT24Cxx_Read_Str(0, 0x10,  Buf,  50)
Buf中存放的EEPROM中(0x10 + i)单元的内容,
4.2.2 向AT24Cxx中写入数据函数
//-------------------------------------------------------------------------------//
//                    向AT24Cxx写入多字节数据函数(对外接口)
//函数名称:AT24Cxx_Write_Str
//函数功能:向AT24Cxx中写入多字节。写入的起始地址由Addr确定,数据存放的首
//         地址在PDat中存放,写入的字节数是Num(16位无符号数)。
//入口参数:
//         A2A1A0:对应芯片A2 A1 A0引脚,低3位有效(高位被忽略).
//         Addr:对24Cxx进行写操作的起始地址。
//        *PDat:发送的数据存放的首地址
//         Num :发送的字节数
//出口参数:0 = 成功,1 = 失败。
//重要说明:1.先发送PDat[0],再发送PDat[1],以此类推。
//       :2.若EEPROM剩余空间不足,函数报错。
//       :3.若启用了写保护功能,必须先使写保护失效,否则无法进行写入。
//-------------------------------------------------------------------------------//
extern uint8 AT24Cxx_Write_Str(uint8 A2A1A0, uint16 Addr, uint8*PDat, uint16 Num)
第一个参数A2A1A0的说明见4.2.1。
若启用了写保护功能,在调用本函数必须调用写入允许函数,否则函数写入出错。
应用示例:
    芯片的A2、A1、A0接地,并且从0x10地址开始写入,写入的字节数50,写入数据存放在unsigned char Buf[100]数组中。Buf写入EEPROM中(0x10 + i)单元。
解析:A2、A1、A0接地,所以第一个参数为0,函数调用是
AT24Cxx_ Write _Str(0, 0x10,  Buf,  50)
4.2.3  AT24Cxx定义允许禁止函数
extern voidAT24Cxx_Write_Enable(void);     // 允许写入。
extern voidAT24Cxx_Write_Disable(void);    // 禁止写入。
这两个函数是写入允许和禁止函数,实际是操作WP引脚。您也可以改为宏定义,这里小白菜就不弄啦。这两个函数受AT24CXX_WP_ENABLE的控制。AT24CXX_WP_ENABLE为1时,即打开写保护,当写入时,必须先调用AT24Cxx_Write_Enable()函数,以使能写入。
这对函数应成对的调用哦(就像进入和退出临界区函数一样),要不然写保护有没有意义了。
五 最后的有用的话
这套驱动,小白菜只测试过AT24C64和AT24C04,其他并没有测试过。所以要慎用哦。欢迎各位童鞋进行拍砖!要是有Bug,小白菜也非常希望大家能给小白菜说一声哦~
非常感谢~
AT24Cxx.rar (194.63 KB, 下载次数: 81)
回复

使用道具 举报

ID:70650 发表于 2014-12-20 18:49 | 显示全部楼层
主程序文件:
  1. /*
  2. ********************************************************************************
  3. *                                    
  4. *                             
  5. *
  6. *     地址:
  7. *                  (c) Copyright 2012,   All Rights Reserved
  8. *                                
  9. * 开发环境  : Keil3
  10. * 文件名    : BusIIC.C
  11. * 程序员    : 3htech
  12. * 开发时间  : 2011
  13. * 描述      : IIC总线抽象。使用51单片机IO口线来模拟IIC总线。
  14. * 生存条件  : 类型重定义,微秒级精确延时函数Delay1US(),Delay2US(),Delay5US();
  15. *-------------------------------------------------------------------------------
  16. * 修 改    :
  17. * 日 期    :
  18. * 描  述    :
  19. *-------------------------------------------------------------------------------
  20. ********************************************************************************
  21. */
  22. //------------------------------    程序开关    ------------------------------//
  23. //----------------------------------------------------------------------------//
  24. // 开关名 :IIC_IO_ENABLE
  25. //  功能  :使能H文件中的SDA和SCL信号线。使其仅在本文件中可见。
  26. //----------------------------------------------------------------------------//
  27. #define IIC_IO_ENABLE



  28. //------------------------------ 系统头文件包含 ------------------------------//
  29. // 无

  30. //----------------------------- 自定义头文件包含 -----------------------------//
  31. #include"BusIIC.H"



  32. //------------------------------  全局变量定义  ------------------------------//

  33. //----------------------------------------------------------------------------//
  34. //变量名称:IICBuf
  35. //变量功能:仅用于IIC_MCU_Send_SDA_Byte()和IIC_MCU_Rcv_SDA_Byte()函数中。
  36. //        :用来辅助IIC发送和接收过程。(仅限本文件使用)。IICBuf可位寻址。
  37. //作用域  :仅限本文件、对外完全不可见
  38. //重要说明:无
  39. //----------------------------------------------------------------------------//
  40. static uint8 bdata IICBuf;

  41. sbit IICBufBit7 = IICBuf^7;    // IICBuf的第7位,用于IIC发送
  42. sbit IICBufBit0 = IICBuf^0;    // IICBuf的第0位,用于IIC接收



  43. //-------------------------------   宏定义   ---------------------------------//
  44. //----------------------------------------------------------------------------//
  45. //宏名    :IIC_ACK、IIC_N_ACK
  46. //功能    :IIC应答信号类型。
  47. //重要说明:仅用于IIC_MCU_Rcv_ACK()和IICMCUSendACK()函数的相关操作。
  48. //----------------------------------------------------------------------------//
  49. #define IIC_ACK    0    //应答信号   
  50. #define IIC_N_ACK  1    //非应答信号或无应答



  51. ////////////////////////////////////////////////////////////////////////////////
  52. //                            本文件专用函数定义                              //
  53. ////////////////////////////////////////////////////////////////////////////////

  54. ////////////////////////////////////////////////////////////////////////////////
  55. //                            本文件专用函数定义                              //
  56. ////////////////////////////////////////////////////////////////////////////////


  57. //----------------------------------------------------------------------------//
  58. //                             微秒级延时函数函数(仅限本文件使用)
  59. //函数名称:IIC_Delay_nUS()
  60. //函数功能:启动IIC总线,即发送IIC起始条件。
  61. //入口参数:无
  62. //出口参数:无
  63. //重要说明:无
  64. //----------------------------------------------------------------------------//
  65. #define IIC_Delay_2US()   IIC_Delay_1US();IIC_Delay_1US()
  66. #define IIC_Delay_5US()   IIC_Delay_2US();IIC_Delay_2US();IIC_Delay_1US()


  67. //----------------------------------------------------------------------------//
  68. //                             IIC总线起动函数(仅限本文件使用)
  69. //函数名称:IIC_Start  
  70. //函数功能:启动IIC总线,即发送IIC起始条件。
  71. //入口参数:无
  72. //出口参数:无
  73. //重要说明:无
  74. //----------------------------------------------------------------------------//
  75. static void IIC_Start(void)
  76. {
  77.     SDA = 1;            // 发送起始条件的数据信号
  78.     IIC_Delay_1US();    // 延时1us

  79.     SCL = 1;            // 起始条件建立时间大于4.7us
  80.     IIC_Delay_5US();    // 延时5us
  81.       
  82.     SDA = 0;            // 发送起始信号,起始条件锁定时间大于4.7us
  83.     IIC_Delay_5US();    // 延时5us

  84.     SCL = 0;            // 钳住I2C总线,准备发送或接收数据
  85.     IIC_Delay_5US();
  86. }
  87. //-------------------------------------------------------------------------------//
  88. //                      IIC总线结束函数(仅限本文件使用)
  89. //函数名称:IIC_Stop  
  90. //函数功能:结束I2C总线,即发送I2C结束条件。
  91. //入口参数:无
  92. //出口参数:无
  93. //重要说明:无
  94. //-------------------------------------------------------------------------------//
  95. static void IIC_Stop(void)
  96. {
  97.     SDA = 0;            // 发送结束条件的数据信号
  98.     IIC_Delay_1US();    // 延时1us

  99.     SCL = 1;            // 结束条件建立时间大于4us
  100.     IIC_Delay_5US();    // 延时5us

  101.     SDA = 1;            // 发送I2C总线结束信号,时间大于4us
  102.     IIC_Delay_5US();    // 延时5us
  103. }

  104. //-------------------------------------------------------------------------------//
  105. //                     MCU发送一字节数据到SDA函数(仅限本文件使用)
  106. //函数名称:IIC_MCU_Send_SDA_Byte
  107. //函数功能:单片机发送1字节数据到SDA上。   
  108. //入口参数:DataValue,要发送的一字节数据
  109. //出口参数:无
  110. //重要说明:本函数与ACK信号无任何关联。
  111. //          使用本函数后应立即调用MCU接收ACK信号函数IICMCURcvACK()以判断传输是否成功。
  112. //-------------------------------------------------------------------------------//
  113. static void IIC_MCU_Send_SDA_Byte(uint8 DataValue)
  114. {
  115.     uint8 i = 0;

  116.     // 把要发送的数据送入IIC数据缓冲区IICBuf中。(该变量定义在文件开头)
  117.     IICBuf = DataValue;

  118.     // 开始发送数据,数据从高位开始发送
  119.     for(i = 0; i < 8; i++)
  120.     {
  121.         // 时钟线拉低,总时间大于4.7us
  122.         SCL = 0;

  123.         // 高位数据放到总线上
  124.         SDA = IICBufBit7;

  125.         // 时钟低电平时间大于4.7us  
  126.         IIC_Delay_5US();

  127.         // 数据保持时间大于4us。(即时钟线高电平宽度大于4us)
  128.         SCL = 1;   
  129.         IIC_Delay_5US();

  130.         // IICBuf左移一位,为发送下一位做准备
  131.         IICBuf <<= 1;
  132.     }

  133.     // 钳住I2C总线,准备接收ACK信号
  134.     SCL = 0;
  135.     IIC_Delay_5US();
  136. }


  137. //-------------------------------------------------------------------------------//
  138. //                 MCU从SDA上接收一字节数据函数(仅限本文件使用)
  139. //函数名称:IIC_MCU_Rcv_SDA_Byte
  140. //函数功能:单片机从SDA线上接收1字节数据。
  141. //入口参数:无
  142. //出口参数:接收到的一字节数据。
  143. //重要说明:本函数与ACK信号无任何关联。
  144. //          使用本函数后应立即调用MCU发送ACK信号函数IICMCUSendACK()来进行应答或非应答。
  145. //-------------------------------------------------------------------------------//
  146. static uint8 IIC_MCU_Rcv_SDA_Byte(void)
  147. {
  148.     uint8  i = 0;

  149.     // 此时IICBuf用作接收缓冲器,所以先清0
  150.     IICBuf = 0;

  151.     // 置数据线为输入方式
  152.     SDA = 1;      


  153.     // 开始接收数据
  154.     for(i = 0; i < 8; i++)
  155.     {
  156.         // 时钟为低,使器件输出数据到SDA线上           
  157.         SCL = 0;
  158.         IIC_Delay_5US();    // 时钟低电平周期大于4.7us

  159.         // 时钟为高,使数据线上数据有效。
  160.         SCL = 1;
  161.         IIC_Delay_5US();    // 时钟高电平周期大于4.7us

  162.         // 接收数据         
  163.         IICBuf <<= 1;       // 先左移一位
  164.         IICBufBit0 = SDA;   // 读取SDA并放入IICBuf的最低位中
  165.     }

  166.     // 钳住I2C总线,准备发送应答或非应答信号
  167.     SCL = 0;
  168.     IIC_Delay_5US();

  169.     // 返回接收到的数据
  170.     return(IICBuf);
  171. }


  172. //-------------------------------------------------------------------------------//
  173. //                     MCU发送ACK信号函数(仅限本文件使用)
  174. //函数名称:IIC_MCU_Send_ACK
  175. //函数功能:主控器进行应答信号(可以是应答或非应答信号)
  176. //入口参数:应答信号类型,仅以宏 IIC_ACK表示ACK应答信号,IIC_N_ACK表示非应答信号。
  177. //出口参数:无
  178. //重要说明:在调用完IIC_MCU_Rcv_SDA_Byte()函数后,应立即调用本函数进行应答或非应应答。
  179. //        :这里不检查参数的合法性。为保证参数不出错,请您一定只使用宏
  180. //        :IIC_ACK 和 IIC_N_ACK 来做参数。
  181. //-------------------------------------------------------------------------------//
  182. static void IIC_MCU_Send_ACK(bit ACK_Tpye)
  183. {
  184.     // 在SDA建立数据之前,SCL是低电平,因为本函数只能跟在IICMCURcvSDAByte()函数之后。
  185.     if(IIC_N_ACK == ACK_Tpye)
  186.     {
  187.         SDA = 1;    // 发出非应答信号
  188.     }
  189.     else
  190.     {
  191.         SDA = 0;    // 发出应答信号
  192.     }

  193.     // 时钟低电平时间大于4.7us
  194.     IIC_Delay_5US();

  195.     // 时钟高电平周期大于4us
  196.     SCL=1;
  197.     IIC_Delay_5US();

  198.     // 清时钟线,钳住IIC总线以便继续接收或停止
  199.     SCL=0;   
  200.     IIC_Delay_2US();   
  201. }


  202. //-------------------------------------------------------------------------------//
  203. //                      MCU接收ACK信号函数(仅限本文件使用)
  204. //函数名称:IIC_MCU_Rcv_ACK  
  205. //函数功能:MCU接收IIC从器件发送的ACK信号.
  206. //入口参数:无
  207. //出口参数:IIC_N_ACK = 表示未收到ACK应答信号,说明传输未成功。
  208. //          IIC_ACK   = 表示收到ACK应答信号,说明传输成功。
  209. //重要说明:此函数应在使用完字节发送函数IIC_MCU_Send_SDA_Byte后立即使用以判断传输是否成功。
  210. //-------------------------------------------------------------------------------//
  211. static uint8 IIC_MCU_Rcv_ACK(void)
  212. {
  213.     bit ACK_Type = 0;  // 作用:暂时存储ACK信号

  214.     // 释放数据线,准备接收应答
  215.     SDA = 1;

  216.     IIC_Delay_5US();

  217.     // 应答信号宽度大于4us
  218.     SCL = 1;   
  219.     IIC_Delay_5US();      

  220.     // 检查是否收到了应答信号
  221.     if(1 == SDA)      
  222.     {
  223.         ACK_Type = IIC_N_ACK;   // 未收到应答信号,ACKtmp赋值为非应答标志IIC_N_ACK
  224.     }
  225.     else                 
  226.     {
  227.         ACK_Type = IIC_ACK;     // 收到应答信号,ACKtmp赋值为应答标志IIC_ACK
  228.     }

  229.     // 钳住I2C总线,准备发送新数据或停止发送
  230.     SCL = 0;
  231.     IIC_Delay_5US();

  232.     // 返回接收到的ACK信号类型。
  233.     return ACK_Type;
  234. }


  235. ////////////////////////////////////////////////////////////////////////////////
  236. //                          本文件专用函数定义结束                            //
  237. ////////////////////////////////////////////////////////////////////////////////







  238. ////////////////////////////////////////////////////////////////////////////////
  239. //                             对外服务函数定义                               //
  240. ////////////////////////////////////////////////////////////////////////////////



  241. //----------------------------------------------------------------------------//
  242. //                    MCU向IIC器件发送多字节数据函数(对外提供服务)
  243. //函数名称:IIC_MCU_Send_Str
  244. //函数功能:MCU向IIC从器件发送多字节数据。本函数是写IIC从器件的抽象函数。
  245. //入口参数:
  246. //          *PAddr:    IIC地址以及子地址。PAddr[0]中存放IIC地址,后面的存放子地址。
  247. //          AddrNum :  IIC以及子地址的字节数。不可为0.
  248. //
  249. //          *PDataAddr:第2批发送的数据的首地址。这部分是发送的数据。
  250. //          DataNum :  第2批要发送的字节数(最大为65536个字节)。为0时不发送这一部分。
  251. //出口参数:0 = 操作成功,1 = 操作出错。
  252. //重要说明:这是一个从启动IIC总线到发送数据再到最后结束总线为止的完整的发送过程。
  253. //          数据发送的顺序是先发送PAddr[0],最后发送PAddr[AddrNum - 1],然后发送
  254. //          PDataAddr[0],最后发送PDataAddr[DataNum - 1]。
  255. //          一般地,PAddr用于发送器件IIC地址和子地址,PDataAddr用于发送数据。
  256. //          本函数对有无子地址的IIC器件都适用。
  257. //----------------------------------------------------------------------------//
  258. extern uint8 IIC_MCU_Send_Str(uint8 *PAddr, uint8 AddrNum, uint8 *PDataAddr, uint16 DataNum)
  259. {
  260.     uint8 ErrFlg;       // 0 = 传输正确。1 = 传输出错。

  261.     // 初始化局部变量。
  262.     ErrFlg = 0;

  263.     // 参数检查
  264.     if(0 == AddrNum)
  265.     {
  266.         ErrFlg = 1;
  267.     }

  268.     //启动总线
  269.     if(0 == ErrFlg)
  270.     {
  271.         IIC_Start();
  272.     }

  273.     // 开始发送IIC地址(以及子地址)数据
  274.     for( ; AddrNum > 0;  AddrNum--)
  275.     {
  276.         if(1 == ErrFlg)               // 如果传输过程中出错,则立即终止传输。
  277.         {
  278.             break;
  279.         }

  280.         IIC_MCU_Send_SDA_Byte(*PAddr);      // 发送数据

  281.         if(IIC_N_ACK == IIC_MCU_Rcv_ACK())
  282.         {
  283.             ErrFlg = 1;               // 未收到从器件的应答信号,说明传输出错。
  284.         }

  285.         PAddr++;                            // 为发送下一个数据作准备
  286.     }

  287.     // 开始发送数据
  288.     for( ; DataNum > 0;  DataNum--)
  289.     {
  290.         if(1 == ErrFlg)               // 如果传输过程中出错,则立即终止传输。
  291.         {
  292.             break;
  293.         }
  294.       
  295.         IIC_MCU_Send_SDA_Byte(*PDataAddr);  // 发送数据

  296.         if(IIC_N_ACK == IIC_MCU_Rcv_ACK())  // 未收到从器件的应答信号,说明传输出错。
  297.         {
  298.             ErrFlg = 1;
  299.         }

  300.         PDataAddr++;                        // 为发送下一个数据作准备
  301.     }

  302.     // 结束总线。不论传输是否出错,都要关闭总线。
  303.     IIC_Stop();

  304.     // 返回出错信息。
  305.     return ErrFlg;
  306. }


  307. //----------------------------------------------------------------------------//
  308. //                  MCU从有子地址的IIC器件中接收多字节函数(对外接口)
  309. //函数名称:IICMCURcvStr
  310. //函数功能:本函数用于有子地址的IIC器件的读操作。
  311. //入口参数:
  312. //          *PAddr:    IIC地址以及子地址。PAddr[0]中存放IIC地址,后面的存放子地址。
  313. //          AddrNum :  IIC以及子地址的字节数。为0时出错.
  314. //
  315. //        *PDataAddr:存放所接收数据的首地址
  316. //         DataNum :  要接收的字节数。合法值1-65535。为0时出错。
  317. //
  318. //出口参数:0 = 操作成功,1 = 操作出错。
  319. //重要说明:
  320. //有子地址的IIC器件的读操作是:
  321. //  MCU先启动总线,然后发送器件的IIC地址和需要操作的子地址
  322. //(这一部分就是*PAddr),之后重新启动总线,再次发送器件的IIC地址且最低位置1以表明是读
  323. // 操作,等待应答后便开始接收数据(这一部分是*PDataAddr),最后关闭总线。
  324. //----------------------------------------------------------------------------//
  325. extern uint8 IIC_MCU_Rcv_Str(uint8 *PAddr, uint8 AddrNum,  uint8 *PDataAddr, uint16 DataNum)
  326. {
  327.     uint8 IICAddr;     
  328.     uint8 ErrFlg;           // 0 = 传输正确。1 = 传输出错。

  329.     // 初始化局部变量。
  330.     ErrFlg   = 0;
  331.     IICAddr  = PAddr[0];    // IIC地址放在PAddr[0]中。

  332.     // 参数检查
  333.     if((0 == AddrNum) || (0 == DataNum))
  334.     {
  335.         ErrFlg = 1;         // 参数出错。
  336.     }

  337.     //启动总线
  338.     if(0 == ErrFlg)
  339.     {
  340.         IIC_Start();
  341.     }

  342.     // 开始发送IIC地址和子地址。
  343.     for(  ; AddrNum > 0; AddrNum--)
  344.     {
  345.         if(1 == ErrFlg)               // 如果传输过程中出错,则立即终止传输。
  346.         {
  347.             break;
  348.         }

  349.         IIC_MCU_Send_SDA_Byte(*PAddr);      // 发送数据
  350.    
  351.         if(IIC_N_ACK == IIC_MCU_Rcv_ACK())  // 检测是否收到从器件的应答信号
  352.         {
  353.             ErrFlg = 1;               // 未收到从器件的应答信号,传输出错。
  354.         }

  355.         PAddr++;                            // 为发送下一个数据作准备
  356.     }

  357.     //重新启动总线。
  358.     if(0 == ErrFlg)
  359.     {
  360.         IIC_Start();

  361.     // 开始发送IIC地址,此时bit[0]要为1以表明是要读。
  362.         IIC_MCU_Send_SDA_Byte(IICAddr | 0x01);

  363.         if(IIC_N_ACK == IIC_MCU_Rcv_ACK())  // 检测是否收到从器件的应答信号
  364.         {
  365.             ErrFlg = 1;               // 未收到从器件的应答信号,传输出错。
  366.         }
  367.     }

  368.     // 接收数据。
  369.     if(0 == ErrFlg)
  370.     {
  371.         // MCU接收IIC器件发送前(DataNum-1个数据)的数据
  372.         for(  ;  DataNum > 1; DataNum--)
  373.         {

  374.             *PDataAddr = IIC_MCU_Rcv_SDA_Byte();// 接收数据

  375.             IIC_MCU_Send_ACK(IIC_ACK);          // 发送ACK应答信号

  376.             PDataAddr++;                        // 为接收下一个数据作准备
  377.         }

  378.         // 接收最后一字节数据
  379.         *PDataAddr = IIC_MCU_Rcv_SDA_Byte();

  380.         IIC_MCU_Send_ACK(IIC_N_ACK);            // 发送非应答信号
  381.     }

  382.     // 结束总线。不论传输是否出错,都要关闭总线。
  383.     IIC_Stop();

  384.     // 返回出错信息。
  385.     return ErrFlg;
  386. }

  387. //----------------------------------------------------------------------------//
  388. //                  MCU从IIC总线接收多字节函数(对外接口) (未测试)
  389. //函数名称:IIC_MCU_Rcv_NoReg_Str
  390. //函数功能:本函数用于无子地址的IIC器件的读操作。
  391. //入口参数:
  392. //         IICAddr:IIC地址。
  393. //        *PRcvDat:存放所接收数据的首地址
  394. //         RcvNum :要接收的字节数。不可为0.
  395. //出口参数:0 = 操作成功,1 = 操作出错。
  396. //重要说明:

  397. //无子地址的IIC器件的读操作是:
  398. //  MCU先启动总线,然后发送器件的IIC地址且最低位置1以表明是读操作(这一部分是IICAddr),
  399. //  等待应答后便开始接收数据(这一部分是*PRcvDat),最后关闭总线。
  400. //----------------------------------------------------------------------------//
  401. /*extern uint8 IIC_MCU_Rcv_NoReg_Str(uint8 IICAddr, uint8 *PRcvDat, uint16 RcvNum)
  402. {
  403.     uint8 ErrFlg;           // 0 = 传输正确。1 = 传输出错。

  404.     // 初始化局部变量。
  405.     ErrFlg   = 0;

  406.     // 若需要接收的数据量为0,则直接返回。您不应该使RcvNum为0.
  407.     if(0 == RcvNum)
  408.     {
  409.         ErrFlg =  1;
  410.     }

  411.     // 启动总线。
  412.     if(0 == ErrFlg)
  413.     {
  414.         IIC_Start();
  415.     }

  416.     // 开始IIC地址。
  417.     if(0 == ErrFlg)
  418.     {
  419.         IIC_MCU_Send_SDA_Byte(IICAddr|0x01);

  420.         if(IIC_N_ACK == IIC_MCU_Rcv_ACK())  // 检测是否收到从器件的应答信号
  421.         {
  422.             ErrFlg = 1;                       // 未收到从器件的应答信号,说明传输出错,返回IIC出错信息。
  423.         }
  424.     }

  425.     // 接收前(RcvNum-1)个字节数据
  426.     if(0 == ErrFlg)
  427.     {
  428.         for(  ; RcvNum > 1; RcvNum--)
  429.         {
  430.             *PRcvDat = IIC_MCU_Rcv_SDA_Byte();  // 接收数据

  431.             IIC_MCU_Send_ACK(IIC_ACK);          // 发送ACK应答信号

  432.             PRcvDat++;                          // 指针加1,为接收下一个数据作准备
  433.         }

  434.         // 接收最后一字节数据
  435.         *PRcvDat = IIC_MCU_Rcv_SDA_Byte();

  436.         IIC_MCU_Send_ACK(IIC_N_ACK);    // 发送非应答信号
  437.     }

  438.     // 结束总线
  439.     IIC_Stop();           

  440.     // 返回出错信息。
  441.     return ErrFlg;
  442. }*/
  443. ////////////////////////////////////////////////////////////////////////////////
  444. //                           对外服务函数定义结束                             //
  445. ////////////////////////////////////////////////////////////////////////////////
复制代码
回复

使用道具 举报

ID:70650 发表于 2014-12-20 18:51 | 显示全部楼层
BusIIC.H文件:
  1. /*
  2. ********************************************************************************
  3. *                                    
  4. *                             
  5. *
  6. *     地址:
  7. *                  (c) Copyright 2012,   All Rights Reserved
  8. *                                
  9. * 开发环境  : Keil3
  10. * 文件名    : BusIIC.H
  11. * 程序员    : 3htech
  12. * 开发时间  : 2011
  13. * 描述      : IIC总线抽象。使用51单片机IO口线来模拟IIC总线。
  14. * 生存条件  : 类型重定义,微秒级精确延时函数Delay1US(),Delay2US(),Delay5US();
  15. *-------------------------------------------------------------------------------
  16. * 修 改    :
  17. * 日 期    :
  18. * 描  述    :
  19. *-------------------------------------------------------------------------------
  20. ********************************************************************************
  21. */

  22. //------------------------------    文件开关    ------------------------------//
  23. // 防止文件包含时多次编本文件,与本文件结尾处的endif对应。
  24. #ifndef         _BUSIIC_H_
  25.     #define     _BUSIIC_H_
  26. //----------------------------------------------------------------------------//



  27. //------------------------------ 系统头文件包含 ------------------------------//
  28. #include<intrins.h>            // 为了使用_nop_()函数

  29. //----------------------------- 自定义头文件包含 -----------------------------//
  30. #include"TypeRedefine.H"



  31. ////////////////////////////////////////////////////////////////////////////////
  32. //                                移植修改(3处)                               //
  33. ////////////////////////////////////////////////////////////////////////////////
  34. //----------------------------------------------------------------------------//
  35. // 编号 :1
  36. // 名称 :
  37. // 功能 :单片机寄存器头文件,例如reg51.h
  38. //----------------------------------------------------------------------------//
  39. #include "ATT703x.H"

  40. //----------------------------------------------------------------------------//
  41. // 编号 :2
  42. // 名称 :SDA, SCL
  43. // 功能 :模拟I2C数据传送位
  44. //----------------------------------------------------------------------------//
  45. #if defined(IIC_IO_ENABLE)

  46.     sbit SDA = P0^0;    // 模拟I2C数据传送位。
  47.     sbit SCL = P2^6;    // 模拟I2C时钟控制位。

  48. #endif

  49. //----------------------------------------------------------------------------//
  50. // 编号 :3
  51. // 名称 :IIC_Delay_1US()
  52. // 功能 :精确的1微秒延时函数。请根据您所用的单片机来正确设置。
  53. //      :如果您的系统中有精确的微妙级延时函数,那么您可以直接使用。
  54. //      :例如,您的延时函数是Delay_1us(),那么您可以使用下句
  55. //      :#define IIC_Delay_1us()  Delay_1us()
  56. //      :来实现延时。
  57. //----------------------------------------------------------------------------//
  58. #define IIC_Delay_500ns() _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  59. #define IIC_Delay_1US()   IIC_Delay_500ns();IIC_Delay_500ns();

  60. ////////////////////////////////////////////////////////////////////////////////
  61. //                               移植修改结束                                 //
  62. ////////////////////////////////////////////////////////////////////////////////



  63. //------------------------------  全局变量声明  ------------------------------//
  64. // NULL


  65. //-------------------------------   宏定义   ---------------------------------//




  66. ////////////////////////////////////////////////////////////////////////////////
  67. //                                 函数声明                                   //
  68. ////////////////////////////////////////////////////////////////////////////////
  69. extern uint8 IIC_MCU_Send_Str(uint8 *PAddr, uint8 AddrNum, uint8 *PDataAddr, uint16 DataNum);

  70. extern uint8 IIC_MCU_Rcv_Str(uint8 *PAddr, uint8 AddrNum,  uint8 *PDataAddr, uint16 DataNum);


  71. //extern uint8 IIC_MCU_Rcv_NoReg_Str(uint8 IICAddr, uint8 *PRcvDat, uint16 RcvNum);



  72. ////////////////////////////////////////////////////////////////////////////////
  73. //                               函数声明结束                                 //
  74. ////////////////////////////////////////////////////////////////////////////////

  75. //------------------------------    文件开关    ------------------------------//
  76. // 防止文件包含时多次编本文件,与本文件开头处的 #ifndef 对应。
  77. #endif
  78. //----------------------------------------------------------------------------//




复制代码
回复

使用道具 举报

ID:70650 发表于 2014-12-20 18:52 | 显示全部楼层
ChipAT24Cxx.C文件:
  1. /*
  2. ********************************************************************************
  3. *                                    
  4. *                             
  5. *
  6. *     
  7. *                  (c) Copyright 2012,   All Rights Reserved
  8. *                                
  9. * 开发环境  : Keil4
  10. * 文件名    : ChipAT24Cxx.C
  11. * 程序员    : 3htech
  12. * 开发时间  : 20110907--20110907
  13. * 描述      : EEPROM芯片AT24Cxx驱动。   其他与AT24C比完全兼容的EEPROM芯片也可使用本驱动。
  14. *           :不支持不同容量的EEPROM混用,同容量的EEPROM可以一起使用。
  15. * 生存条件  : 类型重定义,还需要一个毫秒级精确延时函数Delay_MS();
  16. *-------------------------------------------------------------------------------
  17. * 修 改    :
  18. * 日 期    :
  19. * 描  述    :
  20. *-------------------------------------------------------------------------------
  21. ********************************************************************************
  22. */
  23. //------------------------------    程序开关    ------------------------------//
  24. // 无

  25. //------------------------------ 系统头文件包含 ------------------------------//
  26. // 无

  27. //----------------------------- 自定义头文件包含 -----------------------------//
  28. #include"ChipAT24Cxx.H"



  29. //------------------------------  全局变量定义  ------------------------------//
  30. // NULL

  31. //-------------------------------   宏定义   ---------------------------------//
  32. //----------------------------------------------------------------------------//
  33. //宏名    :IIC_ADDR_AT24CXX
  34. //功能    :AT24Cxx的IIC地址。仅限本文件使用。
  35. //重要说明:AT24Cxx的IIC地址只有高4位有效。
  36. //----------------------------------------------------------------------------//
  37. #define IIC_ADDR_AT24CXX  0xA0


  38. //----------------------------------------------------------------------------//
  39. //宏名    :AT24CXX_MAX_SIZE
  40. //功能    :AT24Cxx的容量,以字节数为单位。仅限本文件使用。
  41. //重要说明:该宏受.H文件中“移植修改”部分的控制。这里请不要改动。
  42. //----------------------------------------------------------------------------//
  43. #if   defined(AT24C01)
  44.     #define AT24CXX_MAX_SIZE  0x0080    // AT24C01含有1K/8即128个字节

  45. #elif defined(AT24C02)
  46.     #define AT24CXX_MAX_SIZE  0x0100    // AT24C02含有2K/8即256个字节

  47. #elif defined(AT24C04)
  48.     #define AT24CXX_MAX_SIZE  0x0200    // AT24C04含有4K/8即512个字节

  49. #elif defined(AT24C08)
  50.     #define AT24CXX_MAX_SIZE  0x0400    // AT24C08含有8K/8即1K个字节

  51. #elif defined(AT24C16)
  52.     #define AT24CXX_MAX_SIZE  0x0800    // AT24C16含有16K/8即2K个字节

  53. #elif defined(AT24C32)
  54.     #define AT24CXX_MAX_SIZE  0x1000    // AT24C32含有32K/8即4K个字节

  55. #elif defined(AT24C64)
  56.     #define AT24CXX_MAX_SIZE  0x2000    // AT24C64含有64K/8即8K个字节

  57. #elif defined(AT24C128)
  58.     #define AT24CXX_MAX_SIZE  0x4000    // AT24C128含有128K/8即16K个字节

  59. #elif defined(AT24C256)
  60.     #define AT24CXX_MAX_SIZE  0x8000    // AT24C256含有256K/8即32K个字节

  61. #endif



  62. //----------------------------------------------------------------------------//
  63. //宏名    :AT24CXX_PAGEBUF_SIZE
  64. //功能    :AT24Cxx页写缓冲器大小。仅限本文件使用。
  65. //重要说明:该宏受H中移植修改”部分的控制。这里请不要改动。
  66. //----------------------------------------------------------------------------//
  67. #if   defined(AT24C01)
  68.     #define AT24CXX_PAGEBUF_SIZE   8    // AT24C01页写缓冲器大小为8B

  69. #elif defined(AT24C02)
  70.     #define AT24CXX_PAGEBUF_SIZE   8    // AT24C02页写缓冲器大小为8B

  71. #elif defined(AT24C04)
  72.     #define AT24CXX_PAGEBUF_SIZE  16    // AT24C04页写缓冲器大小为16B

  73. #elif defined(AT24C08)
  74.     #define AT24CXX_PAGEBUF_SIZE  16    // AT24C08页写缓冲器大小为16B

  75. #elif defined(AT24C16)
  76.     #define AT24CXX_PAGEBUF_SIZE  16    // AT24C16页写缓冲器大小为16B

  77. #elif defined(AT24C32)
  78.     #define AT24CXX_PAGEBUF_SIZE  32    // AT24C32页写缓冲器大小为32B

  79. #elif defined(AT24C64)
  80.     #define AT24CXX_PAGEBUF_SIZE  32    // AT24C64页写缓冲器大小为32B

  81. #elif defined(AT24C128)
  82.     #define AT24CXX_PAGEBUF_SIZE  64    // AT24C128页写缓冲器大小为64B

  83. #elif defined(AT24C256)
  84.     #define AT24CXX_PAGEBUF_SIZE  64    // AT24C256页写缓冲器大小为64B

  85. #endif

  86. ////////////////////////////////////////////////////////////////////////////////
  87. //                            本文件专用函数定义                              //
  88. ////////////////////////////////////////////////////////////////////////////////

  89. //----------------------------------------------------------------------------//
  90. //                检测AT24Cxx内部页写(擦写)是否完成函数(仅限本文件使用)
  91. //函数名称:AT24Cxx_Finish_PageWrite
  92. //函数功能:检测AT24Cxx内部是否页写(擦写)完毕。一个页写的内部擦写时间小于10ms。
  93. //入口参数:无。
  94. //出口参数:0,擦写完毕;1,所用时间超过一页最大擦写时间,无应答(芯片或已损坏)。
  95. //重要说明:本函数只供写操作函数AT24CxxWrStr()调用。
  96. //          用于在页写后对AT24Cxx进行检测,以判断其内部是否擦写完毕。
  97. //----------------------------------------------------------------------------//
  98. static uint8 AT24Cxx_Finish_PageWrite(void)
  99. {
  100.     uint8 TimeFlow;         // 时间计数器
  101.     uint8 TmpAddr;
  102.     uint8 ErrFlg;           // 0 = 正确,1 = 出错。

  103.     // 初始化局部变量。
  104.     TmpAddr = IIC_ADDR_AT24CXX; // EEPROM的IIC地址。
  105.     ErrFlg  = 0;

  106.     // 一个页写的内部擦写时间小于10ms,这里检查20次延时已经到了20ms。若还没写完,
  107.     // 则说可能写入失败。
  108.     ErrFlg = 1;

  109.     for(TimeFlow = 0; TimeFlow < 20; TimeFlow++)
  110.     {
  111.                             // 向IIC总线只发送其IIC地址(一字节),并判断是否有回应
  112.         if(0 == IIC_MCU_Send_Str(&TmpAddr,1, &TmpAddr, 0))
  113.         {
  114.             ErrFlg = 0;     // 有回应说明擦写已经完成。
  115.             break;
  116.         }

  117.         AT24Cxx_Delay_1ms();    // 延时1ms
  118.     }

  119.     // 返回出错信息。0 = 擦写完成,1 = 失败。
  120.     return ErrFlg;
  121. }


  122. //----------------------------------------------------------------------------//
  123. //                      AT24Cxx溢出检测函数(仅限本文件使用)
  124. //函数名称:AT24Cxx_OverFlow_Check
  125. //函数功能:检测AT24Cxx是否会发生地址溢出(或翻转)。
  126. //          通过检测EEPROM从当前地址开始的剩余字节数(AT24CXX_MAX_SIZE-Addr)和
  127. //          数据字节数DatSize的大小,来判断是否会发生溢出。当(AT24CXX_MAX_SIZE-Addr)
  128. //          小于DatSize时,溢出、返回1;否则不溢出,返回0。
  129. //入口参数:Addr,AT24Cxx需要操作的起始字节地址。与A2 A1 A0无关。
  130. //          DatSize,需要操作数据的字节数
  131. //出口参数:1,会发生溢出;0,不会发生溢出。
  132. //重要说明:本函数只用于AT24Cxx发送和接收函数,用于在实际操作前进行溢出检测。
  133. //----------------------------------------------------------------------------//

  134. static uint8 AT24Cxx_OverFlow_Check(uint16 Addr, uint16 DatSize)
  135. {
  136.     uint8 ErrFlg;           // 0 = 正确,1 = 出错。

  137.     // 初始化局部变量。
  138.     ErrFlg  = 0;

  139.     // 当前地址已经大于了EEPROM的容量,会发生溢出。
  140.     if(Addr > AT24CXX_MAX_SIZE)
  141.     {
  142.         ErrFlg = 1;
  143.     }
  144.     // EEPROM剩余字节数比需要操作的字节数小,会发生溢出
  145.     else if((AT24CXX_MAX_SIZE - Addr) < DatSize)
  146.     {
  147.         ErrFlg = 1;
  148.     }

  149.     // 返回出错信息。
  150.     return ErrFlg;
  151. }

  152. //-------------------------------------------------------------------------------//
  153. //                      AT24Cxx地址整理函数(仅限本文件使用)
  154. //函数名称:AT24Cxx_Make_Addr
  155. //函数功能:把A2 A1 A0以及字节地址整理成发送格式,然后存放到PAddrBuf数组中。
  156. //          PAddrBuf数组需要3个字节的长度。
  157. //入口参数:
  158. //          A2A1A0:对应芯片A2 A1 A0引脚,低3位有效(高位被忽略)。
  159. //          Addr  :对24Cxx进行操作的起始地址。
  160. //          *PAddrBuf:处理后数据存放的地址。

  161. //出口参数:PAddrBuf数组中有效的字节数。即进行读写前发送的字节数。其中第1个字节是
  162. //          IIC地址和A2 A1 A0(或是a_n)的组合,第2个字节是字节地址,第3个字节(若是
  163. //          有的话)是字节地址。

  164. //重要说明:本函数不支持不同类型的IIC器件一起使用。
  165. //-------------------------------------------------------------------------------//
  166. static uint8 AT24Cxx_Make_Addr(uint8 A2A1A0, uint16 Addr, uint8 *PAddrBuf)
  167. {
  168.     uint8 AvailableLength = 0;

  169. #if   defined(AT24C01)      // 可级联8个器件,7位字节地址,2字节发送。

  170.     // PAddrBuf[0]中存放的是(二进制表示)1  0   1  0    A2  A1  A0  0。
  171.     // PAddrBuf[1]中存放的是(二进制表示)0  a6 a5  a4   a3  a2  a1 a0。

  172.     // 操作数分别是  1 0 1 0        A2  A1  A0  0
  173.     PAddrBuf[0] = IIC_ADDR_AT24CXX | ((A2A1A0 << 1) & 0x0E);
  174.     PAddrBuf[1] = (uint8)(Addr & 0x7F);

  175.     AvailableLength = 2;

  176. #elif defined(AT24C02)      // 可级联8个器件,8位字节地址,2字节发送。

  177.     // PAddrBuf[0]中存放的是(二进制表示)1  0  1  0    A2  A1  A0  0。
  178.     // PAddrBuf[1]中存放的是(二进制表示)a7 a6 a5 a4   a3  a2  a1 a0。

  179.     // 操作数分别是  1 0 1 0           A2  A1  A0  0
  180.     PAddrBuf[0] = IIC_ADDR_AT24CXX | ((A2A1A0 << 1) & 0x0E);
  181.     PAddrBuf[1] = (uint8)(Addr & 0xFF);

  182.     AvailableLength = 2;

  183. #elif defined(AT24C04)      // 可级联4个器件,9位字节地址,2字节发送。

  184.     // PAddrBuf[0]中存放的是(二进制表示)1   0  1   0   A1  A0  a8  0。
  185.     // PAddrBuf[1]中存放的是(二进制表示)a7 a6  a5  a4  a3  a2  a1  a0。

  186.     // 操作数分别是  1 0 1 0            A1 A0                        a8    0
  187.     PAddrBuf[0] = IIC_ADDR_AT24CXX | ((A2A1A0 << 2) & 0x0C) | (uint8)((Addr >> 7) & 0x02);
  188.     PAddrBuf[1] = (uint8)(Addr & 0xFF);

  189.     AvailableLength = 2;

  190. #elif defined(AT24C08)      // 可级联2个器件,10位字节地址,2字节发送。

  191.     // PAddrBuf[0]中存放的是(二进制表示)1   0   1  0   A0  a9  a8  0。
  192.     // PAddrBuf[1]中存放的是(二进制表示)a7 a6  a5  a4  a3  a2  a1 a0。

  193.     // 操作数分别是  1 0 1 0                A0                     a9   a8   0  
  194.     PAddrBuf[0] = IIC_ADDR_AT24CXX | ((A2A1A0 << 3) & 0x08) | (uint8)((Addr >> 7) & 0x06);
  195.     PAddrBuf[1] = (uint8)(Addr & 0xFF);

  196.     AvailableLength = 2;

  197. #elif defined(AT24C16)      // 不可级联,11位字节地址,2字节发送。

  198.     // PAddrBuf[0]中存放的是(二进制表示)1   0   1  0  a10  a9  a8  0。
  199.     // PAddrBuf[1]中存放的是(二进制表示)a7 a6  a5  a4  a3  a2  a1 a0。

  200.     // 操作数分别是  1 0 1 0              a10   a9   a8   0  
  201.     PAddrBuf[0] = IIC_ADDR_AT24Cxx | (uint8)((Addr >> 7) & 0x0E);
  202.     PAddrBuf[1] = (uint8)(Addr & 0xFF);

  203.     A2A1A0 = 0;    // 故意使用A2A1A0一次,以避免Keil的警告信息

  204.     AvailableLength = 2;

  205. #elif defined(AT24C32)      // 可级联8个器件,12位字节地址,3字节发送。

  206.     // PAddrBuf[0]中存放的是(二进制表示)1    0     1    0    A2   A1   A0   0。
  207.     // PAddrBuf[1]中存放的是(二进制表示)0    0     0    0   a11  a10   a9  a8。
  208.     // PAddrBuf[2]中存放的是(二进制表示)a7   a6   a5   a4    a3   a2   a1  a0。

  209.     // 操作数分别是  1 0 1 0        A2  A1  A0  0
  210.     PAddrBuf[0] = IIC_ADDR_AT24CXX | ((A2A1A0 << 1) & 0x0E);
  211.     PAddrBuf[1] = (uint8)((Addr >> 8) & 0x0F);
  212.     PAddrBuf[2] = (uint8)(Addr & 0xFF);

  213.     AvailableLength = 3;

  214. #elif defined(AT24C64)      // 可级联8个器件,13位字节地址,3字节发送。

  215.     // PAddrBuf[0]中存放的是(二进制表示)1    0     1    0    A2   A1   A0   0。
  216.     // PAddrBuf[1]中存放的是(二进制表示)0    0     0   a12  a11  a10   a9  a8。
  217.     // PAddrBuf[2]中存放的是(二进制表示)a7   a6   a5   a4    a3   a2   a1  a0。

  218.     // 操作数分别是  1 0 1 0        A2  A1  A0  0
  219.     PAddrBuf[0] = IIC_ADDR_AT24CXX | ((A2A1A0 << 1) & 0x0E);
  220.     PAddrBuf[1] = (uint8)((Addr >> 8) & 0x1F);
  221.     PAddrBuf[2] = (uint8)(Addr & 0xFF);

  222.     AvailableLength = 3;

  223. #elif defined(AT24C128)     // 可级联8个器件,14位字节地址,3字节发送。

  224.     // PAddrBuf[0]中存放的是(二进制表示)1    0     1    0      A2   A1   A0   0。
  225.     // PAddrBuf[1]中存放的是(二进制表示)0    0    a13  a12    a11  a10   a9  a8。
  226.     // PAddrBuf[2]中存放的是(二进制表示)a7   a6   a5   a4      a3   a2   a1  a0。

  227.     PAddrBuf[0] = IIC_ADDR_AT24CXX | ((A2A1A0 << 1) & 0x0E);
  228.     PAddrBuf[1] = (uint8)((Addr >> 8) & 0x3F);
  229.     PAddrBuf[2] = (uint8)(Addr & 0xFF);
  230.     A2A1A0 = 0;    // 故意使用A2A1A0一次,以避免Keil的警告信息

  231.     AvailableLength = 3;

  232. #elif defined(AT24C256) //可级联8个器件,15位字节地址,3字节发送。

  233.     // PAddrBuf[0]中存放的是(二进制表示)1    0     1    0      A2   A1   A0   0。
  234.     // PAddrBuf[1]中存放的是(二进制表示)0   a14   a13  a12    a11  a10   a9  a8。
  235.     // PAddrBuf[2]中存放的是(二进制表示)a7   a6   a5   a4      a3   a2   a1  a0。

  236.     // 操作数分别是  1 0 1 0        0  A1  A0  0
  237.     PAddrBuf[0] = IIC_ADDR_AT24CXX | ((A2A1A0 << 1) & 0x0E);
  238.     PAddrBuf[1] = (uint8)((Addr >> 8) & 0x7F);
  239.     PAddrBuf[2] = (uint8)(Addr & 0xFF);

  240.     AvailableLength = 3;

  241. #endif


  242.     //返回PAddrBuf数组中的有效字节数
  243.     return AvailableLength;
  244. }

  245. ////////////////////////////////////////////////////////////////////////////////
  246. //                          本文件专用函数定义结束                            //
  247. ////////////////////////////////////////////////////////////////////////////////







  248. ////////////////////////////////////////////////////////////////////////////////
  249. //                             对外服务函数定义                               //
  250. ////////////////////////////////////////////////////////////////////////////////
  251. //----------------------------------------------------------------------------//
  252. //                    允许写入和禁止写入函数(对外接口)
  253. //函数名称:
  254. //函数功能:允许写入和禁止写入。
  255. //入口参数:无
  256. //出口参数:无
  257. //重要说明:没有启用写保护功能时,本函数不会进行编译。
  258. //----------------------------------------------------------------------------//
  259. #if (1 == AT24CXX_WP_ENABLE)

  260. extern void AT24Cxx_Write_Enable(void)      // 允许写入。
  261. {
  262.     AT24Cxx_WP = 0;
  263. }

  264. extern void AT24Cxx_Write_Disable(void)     // 禁止写入。
  265. {
  266.     AT24Cxx_WP = 1;
  267. }

  268. #endif

  269. //----------------------------------------------------------------------------//
  270. //                    从AT24Cxx中读取多字节数据函数(对外接口)
  271. //函数名称:AT24Cxx_Read_Str
  272. //函数功能:从Addr指定的地址开始读取AT24Cxx,一共读取Num个字节,数据读出后存放在
  273. //          PDat数组中。
  274. //入口参数:
  275. //          A2A1A0:对应芯片A2 A1 A0引脚,低3位有效(高位被忽略).
  276. //          Addr:对24Cxx进行读操作的起始地址。
  277. //         *PDat:数据读取后存放的首地址
  278. //          Num :要读取的字节数
  279. //出口参数:0 = 成功,1 = 失败。
  280. //重要说明:1.读取的第一个字节放在PDat[0]中,第二个放在PDat[1]中,以此类推。
  281. //        :2.若EEPROM剩余空间不足,函数报错。
  282. //----------------------------------------------------------------------------//
  283. extern uint8 AT24Cxx_Read_Str(uint8 A2A1A0, uint16 Addr, uint8 *PDat, uint16 Num)
  284. {
  285.     uint8 ErrFlg;               // 0 = 正确,1 = 错误。
  286.     uint8 AddrBuf[3];           // 该数组用于接收AT24CxxDivideAddr()函数分解后的地址信息。
  287.     uint8 AddrLength;           // 该变量用于指示AddrBuf数组中有效的字节数。

  288.     // 局部变量初始化。
  289.     ErrFlg = 0;

  290.     // 忽略A2A1A0的高位。
  291.     A2A1A0 &= 0x07;

  292.     // 溢出检测
  293.     ErrFlg = AT24Cxx_OverFlow_Check(Addr, Num);

  294.     // 把地址整理成发送格式。并获取地址字节数。
  295.     AddrLength = AT24Cxx_Make_Addr(A2A1A0, Addr, AddrBuf);

  296.     // 读取数据。
  297.     if(0 == ErrFlg)
  298.     {
  299.         ErrFlg = IIC_MCU_Rcv_Str(AddrBuf, AddrLength, PDat, Num);
  300.     }

  301.     // 返回出错信息。
  302.     return ErrFlg;
  303. }


  304. //-------------------------------------------------------------------------------//
  305. //                    向AT24Cxx写入多字节数据函数(对外接口)
  306. //函数名称:AT24Cxx_Write_Str
  307. //函数功能:向AT24Cxx中写入多字节。写入的起始地址由Addr确定,数据存放的首地址在PDat中存
  308. //          放,写入的字节数是Num(16位无符号数)。
  309. //入口参数:
  310. //          A2A1A0:对应芯片A2 A1 A0引脚,低3位有效(高位被忽略).
  311. //          Addr:对24Cxx进行写操作的起始地址。
  312. //         *PDat:发送的数据存放的首地址
  313. //          Num :发送的字节数
  314. //出口参数:0 = 成功,1 = 失败。
  315. //重要说明:1.先发送PDat[0],再发送PDat[1],以此类推。
  316. //        :2.若EEPROM剩余空间不足,函数报错。
  317. //        :3.若启用了写保护功能,必须先使写保护失效,否则无法进行写入。
  318. //-------------------------------------------------------------------------------//
  319. extern uint8 AT24Cxx_Write_Str(uint8 A2A1A0, uint16 Addr, uint8 *PDat, uint16 Num)
  320. {
  321.     uint8 ErrFlg;           // 0 = 正确,1 = 错误。

  322.     uint8 AddrBuf[3];       // 该数组用于接收AT24CxxDivideAddr()函数分解后的地址信息。
  323.     uint8 AddrLength;       // 该变量用于指示AddrBuf数组中有效的字节数。
  324.     uint8 PageRemainSize;   // 该变量用于指示当前页剩余字节数据

  325.     // 局部变量初始化。
  326.     ErrFlg = 0;
  327.     PageRemainSize = 0;

  328.     // 忽略A2A1A0的高位。
  329.     A2A1A0 &= 0x07;

  330.     // 溢出检测
  331.     ErrFlg = AT24Cxx_OverFlow_Check(Addr, Num);

  332.     // 当前页剩余字节数赋给该PageRemainSize变量
  333.     PageRemainSize = AT24CXX_PAGEBUF_SIZE - Addr % AT24CXX_PAGEBUF_SIZE;

  334.     // 如果当前EEPROM写保护,则返回错误。
  335.     #if (1 == AT24CXX_WP_ENABLE)
  336.     if(  1== AT24Cxx_WP)
  337.     {
  338.         ErrFlg = 1;
  339.     }
  340.     #endif

  341.     // -------------写入的字节小于等于当前页的剩余字节------------------
  342.     if(Num <= PageRemainSize)
  343.     {
  344.         if(0 == ErrFlg)
  345.         {
  346.             // 把地址整理成发送格式。并获取地址字节数。
  347.             AddrLength = AT24Cxx_Make_Addr(A2A1A0, Addr, AddrBuf);

  348.             // 发送数据。一次写入所有字节,即Num个字节
  349.             ErrFlg |= IIC_MCU_Send_Str(AddrBuf, AddrLength, PDat, Num);

  350.             // 等待AT24Cxx擦写完毕
  351.             ErrFlg |= AT24Cxx_Finish_PageWrite();
  352.         }
  353.     }
  354.     // --------------写入的字节数大于当前页的剩余字节数-----------------
  355.     else
  356.     {
  357.         ////// 先写当前页 //////
  358.         if(0 == ErrFlg)
  359.         {
  360.             // 把地址整理成发送格式。并获取地址字节数。
  361.             AddrLength = AT24Cxx_Make_Addr(A2A1A0, Addr, AddrBuf);

  362.             // 写当前页剩余字节。
  363.             ErrFlg |= IIC_MCU_Send_Str(AddrBuf, AddrLength, PDat, PageRemainSize);

  364.             // 等待AT24Cxx擦写完毕
  365.             ErrFlg |= AT24Cxx_Finish_PageWrite();

  366.             // 改变相应的变量的值,为下次发送做准备
  367.             Addr += PageRemainSize;           // AT24Cxx写入地址增加
  368.             PDat += PageRemainSize;           // 存放数据的地址增加
  369.             Num  -= PageRemainSize;           // 需要写入的字节数减少
  370.         }// if(0 == ErrFlg)

  371.         ////// 写当前页完毕 //////

  372.         //////  写中间整页  //////
  373.         while(Num > AT24CXX_PAGEBUF_SIZE)   // 这里不可使用>=号,否则会死循环。
  374.         {
  375.             // 写入时出错,立即中止写入操作。
  376.             if(1 == ErrFlg)
  377.             {
  378.                 break;
  379.             }

  380.             // 把地址整理成发送格式。并获取地址字节数。
  381.             AddrLength = AT24Cxx_Make_Addr(A2A1A0, Addr, AddrBuf);

  382.             // 发送数据。整页写,即一次写AT24CXX_PAGEBUF_SIZE个字节。
  383.             ErrFlg |= IIC_MCU_Send_Str(AddrBuf, AddrLength, PDat, AT24CXX_PAGEBUF_SIZE);

  384.             // 等待AT24Cxx擦写完毕
  385.             ErrFlg |= AT24Cxx_Finish_PageWrite();

  386.             // 改变相应的变量的值,为下次发送做准备
  387.             Addr += AT24CXX_PAGEBUF_SIZE;       // AT24Cxx写入地址增加
  388.             PDat += AT24CXX_PAGEBUF_SIZE;       // 存放数据的地址增加
  389.             Num  -= AT24CXX_PAGEBUF_SIZE;       // 需要写入的字节数减少

  390.         }// while(Num > AT24CXX_PAGEBUF_SIZE)
  391.         //////写中间整页完毕//////

  392.         //////  写最后一页  //////
  393.         if(0 == ErrFlg)
  394.         {
  395.             // 把地址整理成发送格式。并获取地址字节数。
  396.             AddrLength = AT24Cxx_Make_Addr(A2A1A0, Addr, AddrBuf);

  397.             // 写当最后一页剩余字节。
  398.             ErrFlg |= IIC_MCU_Send_Str(AddrBuf, AddrLength, PDat, Num);

  399.             // 等待AT24Cxx擦写完毕
  400.             ErrFlg |= AT24Cxx_Finish_PageWrite();

  401.         }// if(0 == ErrFlg)

  402.         //////写最后一页完毕//////

  403.     }// if(Num <= PageRemainSize)


  404.     // 返回出错信息。
  405.     return ErrFlg;
  406. }

  407. ////////////////////////////////////////////////////////////////////////////////
  408. //                           对外服务函数定义结束                             //
  409. ////////////////////////////////////////////////////////////////////////////////



  410. //------------------------------    文件结束    ------------------------------//
复制代码
回复

使用道具 举报

ID:70650 发表于 2014-12-20 18:52 | 显示全部楼层
ChipAT24Cxx.H文件:
  1. /*
  2. ********************************************************************************
  3. *                                    
  4. *                             
  5. *
  6. *     
  7. *                  (c) Copyright 2012,   All Rights Reserved
  8. *                                
  9. * 开发环境  : Keil4
  10. * 文件名    : ChipAT24Cxx.H
  11. * 程序员    : 3htech
  12. * 开发时间  : 20110907--20110907
  13. * 描述      : EEPROM芯片AT24Cxx驱动。   其他与AT24C比完全兼容的EEPROM芯片也可使用本驱动。
  14. *           :不支持不同容量的EEPROM混用,同容量的EEPROM可以一起使用。
  15. * 生存条件  : 类型重定义,还需要一个毫秒级精确延时函数Delay_MS();
  16. *-------------------------------------------------------------------------------
  17. * 修 改    :
  18. * 日 期    :
  19. * 描  述    :
  20. *-------------------------------------------------------------------------------
  21. ********************************************************************************
  22. */
  23. //------------------------------    文件开关    ------------------------------//
  24. // 防止文件包含时多次编本文件,与本文件结尾处的endif对应。
  25. #ifndef         _ChIPAT24CXX_H_
  26.     #define     _ChIPAT24CXX_H_
  27. //----------------------------------------------------------------------------//



  28. //------------------------------ 系统头文件包含 ------------------------------//
  29. // 无

  30. //----------------------------- 自定义头文件包含 -----------------------------//
  31. #include"BusIIC_ATT703x.H"
  32. #include"TypeRedefine.H"

  33. ////////////////////////////////////////////////////////////////////////////////
  34. //                              移植修改(5处)                                 //
  35. ////////////////////////////////////////////////////////////////////////////////
  36. //----------------------------------------------------------------------------//
  37. // 编号 :1
  38. // 名称 :
  39. // 功能 :单片机寄存器头文件,例如reg51.h
  40. //----------------------------------------------------------------------------//
  41. #include "ATT703x.H"

  42. //----------------------------------------------------------------------------//
  43. // 编号 :2
  44. // 名称 :AT24Cxx
  45. // 功能 :选择您所使用的EEPROM芯片型号。只能启用一条宏。
  46. //      :不支持一条总线上挂不同的EEPROM,支持同类型的多个EEPROM挂在总线上。
  47. //----------------------------------------------------------------------------//
  48. //  #define AT24C01         // 使用AT24C01,则启用本句并屏蔽其它语句。
  49. //  #define AT24C02         // 使用AT24C02,则启用本句并屏蔽其它语句。
  50.     #define AT24C04         // 使用AT24C04,则启用本句并屏蔽其它语句。
  51. //  #define AT24C08         // 使用AT24C08,则启用本句并屏蔽其它语句。
  52. //  #define AT24C16         // 使用AT24C16,则启用本句并屏蔽其它语句。
  53. //  #define AT24C32         // 使用AT24C32,则启用本句并屏蔽其它语句。
  54. //  #define AT24C64         // 使用AT24C64,则启用本句并屏蔽其它语句。
  55. //  #define AT24C128        //使用AT24C128,则启用本句并屏蔽其它语句。
  56. //  #define AT24C256        //使用AT24C256,则启用本句并屏蔽其它语句。


  57. //----------------------------------------------------------------------------//
  58. // 编号 :3
  59. // 名称 :AT24CXX_WP_ENABLE
  60. // 功能 :启用AT24Cxx的写保护功能。为1时启用写保护。为0时不使用写保护。
  61. //      :当WP引脚接地时,请禁用写保护功能。否则会浪费系统资源。
  62. //----------------------------------------------------------------------------//
  63. #define   AT24CXX_WP_ENABLE   (0)


  64. //----------------------------------------------------------------------------//
  65. // 编号 :4
  66. // 名称 :AT24Cxx_WP
  67. // 功能 :写保护引脚所用的口线。启用写保护时,才需要设置本参数
  68. //----------------------------------------------------------------------------//
  69. #if (1 == AT24CXX_WP_ENABLE)
  70.     sbit   AT24Cxx_WP = P1^2;
  71. #endif

  72. //----------------------------------------------------------------------------//
  73. // 编号 :5
  74. // 名称 :AT24Cxx_Delay_1ms()
  75. // 功能 :精确的1毫秒延时函数。这里请使用您系统中的微秒延时函数。
  76. //      :例如,您的延时函数是Delay_1us(),那么您可以使用下句
  77. //      :#define AT24Cxx_Delay_1us()  Delay_1us()
  78. //      :来实现延时。
  79. //----------------------------------------------------------------------------//
  80. #include "Delay.H"      // 您系统所用延时函数声明所在的头文件。
  81. #define AT24Cxx_Delay_1ms()   Delay_MS(1)
  82. ////////////////////////////////////////////////////////////////////////////////
  83. //                               移植修改结束                                 //
  84. ////////////////////////////////////////////////////////////////////////////////



  85. //------------------------------  全局变量声明  ------------------------------//

  86. //----------------------------------------------------------------------------//
  87. //变量名称:
  88. //变量功能:
  89. //作用域  :全局变量、仅限本文件、对外完全不可见;(对外完全可见)
  90. //重要说明:无
  91. //----------------------------------------------------------------------------//




  92. //-------------------------------   宏定义   ---------------------------------//
  93. //----------------------------------------------------------------------------//
  94. //宏名    :
  95. //功能    :
  96. //重要说明:无
  97. //----------------------------------------------------------------------------//






  98. ////////////////////////////////////////////////////////////////////////////////
  99. //                                 函数声明                                   //
  100. ////////////////////////////////////////////////////////////////////////////////

  101. #if (1 == AT24CXX_WP_ENABLE)

  102. extern void AT24Cxx_Write_Enable(void);     // 允许写入。
  103. extern void AT24Cxx_Write_Disable(void);    // 禁止写入。

  104. #endif


  105. extern uint8 AT24Cxx_Read_Str (uint8 A2A1A0, uint16 Addr, uint8 *PDat, uint16 Num);
  106. extern uint8 AT24Cxx_Write_Str(uint8 A2A1A0, uint16 Addr, uint8 *PDat, uint16 Num);

  107. ////////////////////////////////////////////////////////////////////////////////
  108. //                               函数声明结束                                 //
  109. ////////////////////////////////////////////////////////////////////////////////

  110. //------------------------------    文件开关    ------------------------------//
  111. // 防止文件包含时多次编本文件,与本文件开头处的 #ifndef 对应。
  112. #endif
  113. //----------------------------------------------------------------------------//

  114. //------------------------------    文件结束    ------------------------------//
复制代码
回复

使用道具 举报

ID:70650 发表于 2014-12-20 18:53 | 显示全部楼层
TypeRedefine.H文件:
  1. /*
  2. ********************************************************************************
  3. *                                    
  4. *                             
  5. *
  6. *     地址:
  7. *                  (c) Copyright 2012,   All Rights Reserved
  8. *                                
  9. * 开发环境  : Keil4
  10. * 文件名    : TypeRedefine.H
  11. * 程序员    : 3htech
  12. * 开发时间  : 2012-06-04
  13. * 描述      : 类型重新定义。
  14. * 生存条件  : 自由存在。
  15. *-------------------------------------------------------------------------------
  16. * 修 改    :
  17. * 日 期    :
  18. * 描  述    :
  19. *-------------------------------------------------------------------------------
  20. ********************************************************************************
  21. */


  22. //------------------------------    文件开关    ------------------------------//
  23. // 防止文件包含时多次编本文件,与本文件结尾处的endif对应。
  24. #ifndef     _TYPEREDEFINE_H_
  25.     #define _TYPEREDEFINE_H_
  26. //----------------------------------------------------------------------------//




  27. //------------------------------ 系统头文件包含 ------------------------------//
  28. #include<stdio.H>       // 为了使用NULL的定义。

  29. //----------------------------- 自定义头文件包含 -----------------------------//
  30. //无
  31. //--------------------------------  类型声明  --------------------------------//
  32. //----------------------------------------------------------------------------//
  33. //类型名称:
  34. //类型功能:
  35. //成员详解:
  36. //重要说明:
  37. //----------------------------------------------------------------------------//


  38. //------------------------------  全局变量定义  ------------------------------//
  39. //无


  40. //--------------------------------------------------------------//
  41. //                     类型重新定义
  42. //名称:类型重新定义
  43. //功能:
  44. //      51系列单片机应用下的类型重新定义。
  45. //      使用的是8位单片机,因此char是8位,int为16位,long为32位
  46. //--------------------------------------------------------------//

  47. typedef  bit  bdata   uint1;    //  无符号1 位整型变量需要加前缀u1

  48. typedef unsigned char uint8;    // 无符号8 位整型,前缀u8
  49. typedef   signed char  int8;    // 有符号8 位整型,前缀i8

  50. typedef unsigned int  uint16;   // 无符号16位整型,前缀u16
  51. typedef   signed int   int16;   // 有符号16位整型,前缀i16

  52. typedef unsigned long uint32;   // 无符号32位整型,前缀u32
  53. typedef   signed long  int32;   // 有符号32位整型,前缀i32

  54. typedef  float         flt32;   // 单精度浮点数(32位长度),前缀f32



  55. //-------------------------------   宏定义   ---------------------------------//
  56. //----------------------------------------------------------------------------//
  57. //宏名    :TURE, FALSE
  58. //功能    :错误标志或操作完成标志。
  59. //重要说明:无
  60. //----------------------------------------------------------------------------//
  61. #ifndef TRUE
  62.     #define TRUE  0
  63. #endif

  64. #ifndef FALSE
  65.     #define FALSE 1
  66. #endif
  67. //------------------------------    文件开关    ------------------------------//
  68. // 防止文件包含时多次编本文件,与本文件开头处的 #ifndef 对应。
  69. #endif
  70. //----------------------------------------------------------------------------//


  71. //------------------------------    文件结束    ------------------------------//
复制代码
回复

使用道具 举报

ID:11942 发表于 2015-1-7 13:57 | 显示全部楼层
学习学习
回复

使用道具 举报

ID:96187 发表于 2015-11-18 09:32 | 显示全部楼层
拜读了,受益匪浅
回复

使用道具 举报

ID:79544 发表于 2016-9-8 20:04 | 显示全部楼层
感觉好乱啊,怎么没头绪
回复

使用道具 举报

ID:235719 发表于 2018-12-14 09:05 | 显示全部楼层
写得规范啊
回复

使用道具 举报

ID:235719 发表于 2018-12-14 09:33 | 显示全部楼层
十分规范,就是有些地方可以优化精简,毕竟如果51用代码占太多空间了。
回复

使用道具 举报

ID:147215 发表于 2020-5-14 09:46 | 显示全部楼层
谢谢分享!,,,,
回复

使用道具 举报

ID:704585 发表于 2020-6-3 14:08 | 显示全部楼层
感谢楼主分享
回复

使用道具 举报

ID:684771 发表于 2020-6-3 16:43 | 显示全部楼层
感谢分享
回复

使用道具 举报

ID:128463 发表于 2020-6-5 08:40 | 显示全部楼层

感谢楼主分享!!
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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