I2C.c
上传用户:sdaoma
上传日期:2013-08-07
资源大小:3838k
文件大小:12k
源码类别:

GPS编程

开发平台:

C/C++

  1. /****************************************Copyright (c)**************************************************
  2. **                               广州周立功单片机发展有限公司
  3. **                                     研    究    所
  4. **                                        产品一部 
  5. **
  6. **                                 http://www.zlgmcu.com
  7. **
  8. **--------------文件信息--------------------------------------------------------------------------------
  9. **文   件   名: I2c.c
  10. **创   建   人: 陈明计
  11. **最后修改日期: 2003年7月21日
  12. **描        述: μCOS-II下LPC210x的I2c主模式底层驱动 
  13. **              
  14. **--------------历史版本信息----------------------------------------------------------------------------
  15. ** 创建人: 陈明计
  16. ** 版  本: v1.0
  17. ** 日 期: 2003年7月8日
  18. ** 描 述: 原始版本
  19. **
  20. **------------------------------------------------------------------------------------------------------
  21. ** 修改人: 陈明计
  22. ** 版  本: v1.1
  23. ** 日 期: 2003年7月21日
  24. ** 描 述: 根据正式文档更改寄存器名
  25. **
  26. **--------------当前版本修订------------------------------------------------------------------------------
  27. ** 修改人: 
  28. ** 日 期: 
  29. ** 描 述: 
  30. **
  31. **------------------------------------------------------------------------------------------------------
  32. ********************************************************************************************************/
  33. #define IN_I2C
  34. #include "config.h"
  35. static uint8 *I2cBuf;
  36. static OS_EVENT *I2cSem;
  37. static OS_EVENT *I2cMbox;
  38. static int16 I2cNbyte;
  39. static uint8 I2cAddr;
  40. #define I2C_WRITE_END       1           /* 写完成   */
  41. #define I2C_READ_END        2           /* 读完成   */
  42. #define I2C_NOT_GET_BUS     4           /* 丢失仲裁 */
  43. #define I2C_ACK_ERR         8           /* 接收ACK错误 */
  44. /*********************************************************************************************************
  45. ** 函数名称: I2cInit
  46. ** 功能描述: 初始化I2c(主模式)
  47. ** 输 入: FI2c:I2c总线频率
  48. **
  49. ** 输 出:TRUE  :成功
  50. **        FALSE:失败
  51. ** 全局变量: I2cSem,I2cMbox
  52. ** 调用模块: OSSemCreate
  53. **
  54. ** 作 者: 陈明计
  55. ** 日 期: 2003年7月8日
  56. **-------------------------------------------------------------------------------------------------------
  57. ** 修改人: 陈明计
  58. ** 日 期: 2003年7月10日
  59. **-------------------------------------------------------------------------------------------------------
  60. ** 修改人: 陈明计
  61. ** 日 期: 2003年7月21日
  62. **------------------------------------------------------------------------------------------------------
  63. ********************************************************************************************************/
  64.         uint8 I2cInit(uint32 FI2c)
  65. {
  66.     VICIntEnClr = 1 << 9;                           /* 禁止能I2c中断 */
  67.     if (FI2c <= 400000)
  68.     {
  69.         PINSEL0 = (PINSEL0 & 0xffffff0f) | 0x50;    /* 选择管脚为I2c */
  70.         I2CONCLR = 0x6C;                            /* 清除控制寄存器 */
  71.         I2SCLH = (Fpclk / FI2c + 1) / 2;            /* 设置高电平时间 */
  72.         I2SCLL = (Fpclk / FI2c) / 2;                /* 设置低电平时间 */
  73.         I2cSem = OSSemCreate(1);                    /* 信号量用于互斥操作总线 */
  74.         I2cMbox = OSMboxCreate(NULL);               /* 消息邮箱用于中断向任务传递操作结果 */
  75.         if (I2cMbox == NULL)
  76.         {
  77.             return FALSE;
  78.         }
  79.         if (I2cSem != NULL)
  80.         {
  81.             return TRUE;
  82.         }
  83.     }
  84.     return FALSE;
  85. }
  86. /*********************************************************************************************************
  87. ** 函数名称: __I2cWrite
  88. ** 功能描述: 读I2C,但不发送STOP信号 
  89. ** 输 入: Addr:从机地址
  90. **        Data:将要写的数据
  91. **        写的数据数目
  92. ** 输 出:发送的数据字节数
  93. **
  94. ** 全局变量: I2cAddr,I2cNbyte,I2cBuf
  95. ** 调用模块: OSMboxPend
  96. **
  97. ** 作 者: 陈明计
  98. ** 日 期: 2003年7月8日
  99. **-------------------------------------------------------------------------------------------------------
  100. ** 修改人: 陈明计
  101. ** 日 期: 2003年7月21日
  102. **------------------------------------------------------------------------------------------------------
  103. ********************************************************************************************************/
  104.         uint8 __I2cWrite(uint8 Addr, uint8 *Data, int16 NByte)
  105. {
  106.     uint8 err;
  107.     unsigned int Rt;
  108.     I2cAddr = Addr & 0xfe;                              /* 存储发送地址 */
  109.     I2cNbyte = NByte;                                   /* 存储写字节数 */
  110.     I2cBuf = Data;                                      /* 存储写的数据的指针 */
  111.     I2CONSET = 0x24;                                    /* 设置为主机,并启动总线 */
  112.     
  113.     Rt = (unsigned int) OSMboxPend(I2cMbox, 0, &err);   /* 等待操作结束 */
  114.     return Rt;
  115. }
  116. /*********************************************************************************************************
  117. ** 函数名称: I2cWrite
  118. ** 功能描述: 向I2C从器件写数据
  119. ** 输 入: Addr:从机地址
  120. **        Data:指向将要写的数据的指针
  121. **        NByte:写的数据数目
  122. ** 输 出:发送的数据字节数
  123. **
  124. ** 全局变量: I2cSem,I2cNbyte
  125. ** 调用模块: OSSemPend,__I2cWrite,OSSemPost
  126. **
  127. ** 作 者: 陈明计
  128. ** 日 期: 2003年7月8日
  129. **-------------------------------------------------------------------------------------------------------
  130. ** 修改人: 陈明计
  131. ** 日 期: 2003年7月10日
  132. **-------------------------------------------------------------------------------------------------------
  133. ** 修改人: 陈明计
  134. ** 日 期: 2003年7月21日
  135. **------------------------------------------------------------------------------------------------------
  136. ********************************************************************************************************/
  137.         uint16 I2cWrite(uint8 Addr, uint8 *Data, int16 NByte)
  138. {
  139.     uint8 err;
  140.     
  141.     OSSemPend(I2cSem, 0, &err);
  142.     
  143.     I2CONCLR = 0x6C;
  144.     I2CONSET = 0x40;                            /* 使能I2c */
  145.     VICIntEnable = 1 << 9;                      /* 使能I2c中断 */
  146.     if (__I2cWrite(Addr, Data, NByte) == I2C_WRITE_END)
  147.     {
  148.         I2CONSET = 1 << 4;                      /* 发送停止信号 */
  149.         I2CONCLR = 0x28;                        /* 清除标志 */
  150.     }
  151.     VICIntEnClr = 1 << 9;                       /* 禁止能I2c中断 */
  152.     OSSemPost(I2cSem);
  153.     return (NByte - I2cNbyte);
  154. }
  155. /*********************************************************************************************************
  156. ** 函数名称: I2cRead
  157. ** 功能描述: 从I2c从器件读数据
  158. ** 输 入: Addr:从机地址
  159. **        Ret:指向返回数据存储位置的指针
  160. **        Eaddr:扩展地址存储位置
  161. **        EaddrNByte:扩展地址字节数,0为无
  162. **        ReadNbyte:将要读取的字节数目
  163. ** 输 出:已读取的字节数
  164. **
  165. ** 全局变量: I2cSem,I2cAddr,I2cNbyte,I2cBuf
  166. ** 调用模块: OSSemPend,__I2cWrite,OSMboxPend,OSSemPost
  167. **
  168. ** 作 者: 陈明计
  169. ** 日 期: 2003年7月8日
  170. **-------------------------------------------------------------------------------------------------------
  171. ** 修改人: 陈明计
  172. ** 日 期: 2003年7月21日
  173. **------------------------------------------------------------------------------------------------------
  174. ********************************************************************************************************/
  175.         int16 I2cRead(uint8 Addr, uint8 *Ret, uint8 *Eaddr, int16 EaddrNByte, int16 ReadNbyte)
  176. {
  177.     uint8 err;
  178.     
  179.     OSSemPend(I2cSem, 0, &err);
  180.     I2CONCLR = 0x6C;
  181.     I2CONSET = 0x40;                            /* 使能I2c */
  182.     VICIntEnable = 1 << 9;                      /* 使能I2c中断 */
  183.     if (EaddrNByte > 0)
  184.     {
  185.         if (__I2cWrite(Addr, Eaddr, EaddrNByte) != I2C_WRITE_END)
  186.         {
  187.             return -1;
  188.         }
  189.     }
  190.     I2cAddr = Addr | 0x01;                      /* 存储发送地址 */
  191.     I2cNbyte = ReadNbyte;                       /* 存储读字节数 */
  192.     I2cBuf = Ret;                               /* 存储读到的数据 */
  193.     I2CONCLR = 0x28;
  194.     I2CONSET = 0x24;                            /* 设置为主机,并启动总线 */
  195.     VICIntEnable = 1 << 9;                      /* 使能I2c中断 */
  196.     OSMboxPend(I2cMbox, 0, &err);               /* 等待操作结束 */
  197.     VICIntEnClr = 1 << 9;                       /* 禁止能I2c中断 */
  198.     OSSemPost(I2cSem);
  199.     return (ReadNbyte - I2cNbyte);
  200. }
  201. /*********************************************************************************************************
  202. ** 函数名称: I2c_Exception
  203. ** 功能描述: I2c中断服务程序
  204. ** 输 入: 无
  205. **
  206. ** 输 出: 无
  207. **         
  208. ** 全局变量: I2cAddr,I2cBuf,I2cNbyte,I2cMbox
  209. ** 调用模块: OSMboxPost
  210. **
  211. ** 作 者: 陈明计
  212. ** 日 期: 2003年7月8日
  213. **-------------------------------------------------------------------------------------------------------
  214. ** 修改人: 陈明计
  215. ** 日 期: 2003年7月21日
  216. **------------------------------------------------------------------------------------------------------
  217. ********************************************************************************************************/
  218.         void I2c_Exception(void)
  219. {
  220.     OS_ENTER_CRITICAL();
  221.     switch(I2STAT & 0xf8)
  222.     {
  223.         case  0x08:                     /* 已发送起始条件,与0x18相同处理 */
  224. //            break;
  225.         case  0x10:                     /* 已发送重复起始条件 */
  226.             I2DAT = I2cAddr;            /* 发送地址 */
  227.             I2CONCLR = 0x28;            /* 清除标志 */
  228.             break;
  229.         case  0x18:                     /* 已发送SLA+W,并已接收应答 */
  230.             I2DAT = *I2cBuf++;
  231.             I2cNbyte--;
  232.             I2CONCLR = 0x28;            /* 清除标志 */
  233.             break;
  234.         case  0x28:                     /* 已发送I2C数据,并接收到应答 */
  235.             if (I2cNbyte > 0)
  236.             {
  237.                 I2DAT = *I2cBuf++;
  238.                 I2cNbyte--;
  239.                 I2CONCLR = 0x28;        /* 清除标志 */
  240.             }
  241.             else
  242.             {
  243.                 OSMboxPost(I2cMbox, (void *)I2C_WRITE_END);
  244.                 VICIntEnClr = 1 << 9;   /* 禁止能I2c中断 */
  245.             }
  246.             break;
  247.         case  0x20:                     /* 已发送SLA+W;已接收非ACK, 与0x48处理相同 */
  248. //            break;                    
  249.         case  0x30:                     /* 已发送I2DAT中的数据字节;已接收非ACK, 与0x48处理相同 */
  250. //            break;
  251.         case  0x48:                     /* 已发送SLA+R;已接收非ACK */
  252.             I2CONSET = 1 << 4;          /* 发送停止信号 */
  253.             OSMboxPost(I2cMbox, (void *)I2C_ACK_ERR);
  254.             I2CONCLR = 0x28;            /* 清除标志 */
  255.             break;
  256.         case  0x38:                     /* 在SLA+R/W或数据字节中丢失仲裁 */
  257.             OSMboxPost(I2cMbox, (void *)I2C_NOT_GET_BUS);
  258.             I2CONCLR = 0x28;            /* 清除标志 */
  259.             break;
  260.         case  0x40:                     /* 已发送SLA+R;已接收ACK */
  261.             if (I2cNbyte <= 1)
  262.             {
  263.                 I2CONCLR = 1 << 2;      /* 下次发送非应答信号 */
  264.             }
  265.             else
  266.             {
  267.                 I2CONSET= 1 << 2;       /* 下次发送应答信号 */
  268.             }
  269.             I2CONCLR = 0x28;            /* 清除标志 */
  270.             break;
  271.         case  0x50:                     /* 已接收数据字节;已发送ACK */
  272.             *I2cBuf++ = I2DAT;          /* 接收数据 */
  273.             I2cNbyte--;
  274.             if (I2cNbyte <= 1)
  275.             {
  276.                 I2CONCLR = 1 << 2;      /* 下次发送非应答信号 */
  277.             }
  278.             I2CONCLR = 0x28;            /* 清除标志 */
  279.             break;
  280.         case  0x58:                     /* 已接收数据字节;已返发送ACK */
  281.             *I2cBuf = I2DAT;            /* 接收数据 */
  282.             I2cNbyte--;
  283.             I2CONSET= 1 << 4;           /* 结束总线 */
  284.             OSMboxPost(I2cMbox, (void *)I2C_READ_END);
  285.             I2CONCLR = 0x28;            /* 清除标志 */
  286.             break;
  287.         default:
  288.             I2CONCLR = 0x28;            /* 清除标志 */
  289.             break;
  290.     }
  291.     VICVectAddr = 0;                    /* 通知中断控制器中断结束 */
  292.     OS_EXIT_CRITICAL();
  293. }
  294. /*********************************************************************************************************
  295. **                            End Of File
  296. ********************************************************************************************************/