i2c.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /******************************************************************************
  2. 版权所有:
  3. 文件名称: i2c.c
  4. 文件版本: 01.01
  5. 创建作者: sunxi
  6. 创建日期: 2008-08-01
  7. 功能说明: i2c驱动程序。目前总线频率391KHZ.
  8. 其它说明:
  9. 修改记录:
  10. */
  11. /*------------------------------- 头文件 --------------------------------------
  12. */
  13. #include "bspconfig.h"
  14. #include "ustimer.h"
  15. #include "i2c.h"
  16. /*------------------------------- 宏定义 --------------------------------------
  17. */
  18. #define I2C_PM_REG MCF_PMM_PPMCR1
  19. #define I2C_PM_INDEX 4
  20. /*------------------------------ 全局变量 -------------------------------------
  21. */
  22. //总线占用状态
  23. int gh_i2c = 0;
  24. /*------------------------------ 外部函数 -------------------------------------
  25. */
  26. /******************************************************************************
  27. 函数名称: i2c_init
  28. 函数版本: 01.01
  29. 创建作者: sunxi
  30. 创建日期: 2008-06-26
  31. 函数说明: i2c初始化。
  32. 参数说明: 无
  33. 返回值: 成功返回0.
  34. 修改记录:
  35. */
  36. int i2c_init(void)
  37. {
  38. #if 0
  39. unsigned char temp;
  40. //允许I2C模块时钟
  41. I2C_PM_REG = I2C_PM_INDEX;
  42. //管脚配置,假设从默认值开始设置
  43. MCF_PAD_PAR_SSI0H |= 0
  44. | MCF_PAD_PAR_SSI0H_PAR_TXD_SCL2
  45. | MCF_PAD_PAR_SSI0H_PAR_RXD_SDA2;
  46. //I2C模块输入时钟125M,将频率设为接近400KHZ(391khz)(分频比320,值0x34).
  47. MCF_I2FDR = MCF_I2C_I2FDR_IC(0x34);
  48. //允许模块,mcf54418必须打开中断。
  49. MCF_I2CR = 0 | MCF_I2C_I2CR_IEN | MCF_I2C_I2CR_IIEN;
  50. //如果总线忙bit设置,发送一个stop信号到slave模块。
  51. if( MCF_I2SR & MCF_I2C_I2SR_IBB)
  52. {
  53. MCF_I2CR = 0; /* clear control register */
  54. MCF_I2CR = MCF_I2C_I2CR_IEN /* enable module */
  55. | MCF_I2C_I2CR_MSTA; /* send a START condition */
  56. temp = MCF_I2DR; /* dummy read */
  57. MCF_I2SR = 0; /* clear status register */
  58. MCF_I2CR = 0; /* clear control register */
  59. MCF_I2CR = MCF_I2C_I2CR_IEN; /* enable the module again */
  60. }
  61. #endif
  62. return 0;
  63. }
  64. /******************************************************************************
  65. 函数名称: i2c_open
  66. 函数版本: 01.01
  67. 创建作者: sunxi
  68. 创建日期: 2008-08-19
  69. 函数说明: 打开一个I2C设备,所有的I2C设备互斥,一次只能打开一个.
  70. 注意:此函数在资源竞争问题上,有一定的系统要求,如果要求不满足,用户应
  71. 自己处理资源竞争问题.这个要求为:系统中每个任务(一个中断服务程序也算
  72. 一个任务)都具有唯一优先级.目前UT800S的系统满足这个条件.
  73. 参数说明:
  74. i2c_id: 指定需要打开I2C设备的标识符(以I2C_ID_开头)。
  75. 返回值:
  76. >=0 : 打开设备的句柄
  77. <0 : 打开失败。
  78. 修改记录:
  79. */
  80. int i2c_open(int i2c_id)
  81. {
  82. if(i2c_id != I2C_ID_RTC && i2c_id != I2C_ID_E2PROM)
  83. {
  84. return -1;
  85. }
  86. //如果QSPI总线空闲,占有它。
  87. if(gh_i2c == 0)
  88. {
  89. gh_i2c = i2c_id;
  90. }
  91. else
  92. {
  93. return -1;
  94. }
  95. //解决资源竞争问题,如果两个值不相等,说明在竞争中失败,退出。
  96. if(gh_i2c != i2c_id)
  97. {
  98. return -2;
  99. }
  100. return i2c_id;
  101. }
  102. /******************************************************************************
  103. 函数名称: i2c_close
  104. 函数版本: 01.01
  105. 创建作者: sunxi
  106. 创建日期: 2008-08-21
  107. 函数说明: 关闭一个I2C设备。
  108. 参数说明:
  109. h_i2c:关闭设备的句柄。
  110. 返回值: 成功返回0.
  111. 修改记录:
  112. */
  113. int i2c_close(int h_i2c)
  114. {
  115. if(h_i2c != gh_i2c)
  116. {
  117. return -1;
  118. }
  119. gh_i2c = 0;
  120. return 0;
  121. }
  122. /******************************************************************************
  123. 函数名称: i2c_wait_completion
  124. 函数版本: 01.01
  125. 创建作者: sunxi
  126. 创建日期: 2008-08-07
  127. 函数说明: 等待i2c传输一个字节完成,带0.1秒超时。
  128. 参数说明: 无
  129. 返回值: 成功返回0.
  130. 修改记录:
  131. */
  132. int i2c_wait_completion(void)
  133. {
  134. uint32_t us0,us;
  135. //等待中断发生
  136. us0 = ustimer_get_origin();
  137. while(1)
  138. {
  139. // 得到超时值
  140. us = ustimer_get_duration(us0);
  141. // 检查条件
  142. //if((MCF_I2SR & MCF_I2C_I2SR_IIF))
  143. {
  144. break;
  145. }
  146. //超时设定为1秒
  147. if(us > 1*USTIMER_SEC)
  148. {
  149. //重新初始化I2C模块,否则模块可能再也不能正常工作。
  150. MCF_I2CR = 0;
  151. i2c_init();
  152. return -1;
  153. }
  154. }
  155. //MCF_I2SR &= ~MCF_I2C_I2SR_IIF;
  156. return 0;
  157. }
  158. /******************************************************************************
  159. 函数名称: i2c_wait_bus_idle
  160. 函数版本: 01.01
  161. 创建作者: sunxi
  162. 创建日期: 2008-08-07
  163. 函数说明: 等待i2c总线空闲,带0.1秒超时。
  164. 参数说明: 无
  165. 返回值: 成功返回0.
  166. 修改记录:
  167. */
  168. int i2c_wait_bus_idle(void)
  169. {
  170. uint32_t us0,us;
  171. //清除arbitration位(IAL),增强程序健壮性。
  172. // MCF_I2SR &= ~MCF_I2C_I2SR_IAL;
  173. //等待总线空闲
  174. us0 = ustimer_get_origin();
  175. while(1)
  176. {
  177. // 得到超时值
  178. us = ustimer_get_duration(us0);
  179. // 检查条件
  180. // if((MCF_I2SR & MCF_I2C_I2SR_IBB) == 0)
  181. {
  182. break;
  183. }
  184. //超时设定为1秒
  185. if(us > 1*USTIMER_SEC)
  186. {
  187. //重新初始化I2C模块,否则模块可能再也不能正常工作。
  188. MCF_I2CR = 0;
  189. i2c_init();
  190. return -1;
  191. }
  192. }
  193. return 0;
  194. }
  195. /*------------------------------ 内部函数 -------------------------------------
  196. */
  197. /*------------------------------ 测试函数 -------------------------------------
  198. */