SWM341_i2c.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /******************************************************************************************************************************************
  2. * 文件名称: SWM341_i2c.c
  3. * 功能说明: SWM341单片机的I2C串行接口功能驱动库
  4. * 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1
  5. * 注意事项:
  6. * 版本日期: V1.0.0 2016年1月30日
  7. * 升级记录:
  8. *
  9. *
  10. *******************************************************************************************************************************************
  11. * @attention
  12. *
  13. * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIES AT PROVIDING CUSTOMERS WITH CODING INFORMATION
  14. * REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIEE. AS A RESULT, SYNWIT SHALL NOT BE HELD LIABLE
  15. * FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIES ARISING FROM THE CONTENT
  16. * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONN-
  17. * -ECTION WITH THEIR PRODUCTS.
  18. *
  19. * COPYRIGHT 2012 Synwit Technology
  20. *******************************************************************************************************************************************/
  21. #include "SWM341.h"
  22. #include "SWM341_i2c.h"
  23. /******************************************************************************************************************************************
  24. * 函数名称: I2C_Init()
  25. * 功能说明: I2C初始化
  26. * 输 入: I2C_TypeDef * I2Cx 指定要被设置的I2C,有效值包括I2C0、I2C1
  27. * I2C_InitStructure * initStruct 包含I2C相关设定值的结构体
  28. * 输 出: 无
  29. * 注意事项: 无
  30. ******************************************************************************************************************************************/
  31. void I2C_Init(I2C_TypeDef * I2Cx, I2C_InitStructure * initStruct)
  32. {
  33. switch((uint32_t)I2Cx)
  34. {
  35. case ((uint32_t)I2C0):
  36. SYS->CLKEN0 |= (0x01 << SYS_CLKEN0_I2C0_Pos);
  37. break;
  38. case((uint32_t)I2C1):
  39. SYS->CLKEN0 |= (0x01 << SYS_CLKEN0_I2C1_Pos);
  40. break;
  41. }
  42. I2C_Close(I2Cx); //一些关键寄存器只能在I2C关闭时设置
  43. if(initStruct->Master == 1)
  44. {
  45. I2Cx->CR |= (1 << I2C_CR_MASTER_Pos);
  46. I2Cx->CLK = (((SystemCoreClock/2)/1000000/3*2 - 1) << I2C_CLK_SCLL_Pos) |
  47. (((SystemCoreClock/2)/1000000/3*1 - 1) << I2C_CLK_SCLH_Pos) |
  48. ((1000000 / initStruct->MstClk - 1) << I2C_CLK_DIV_Pos);
  49. I2Cx->IF = 0xFFFFFFFF;
  50. I2Cx->IE = (initStruct->TXEmptyIEn << I2C_IE_TXE_Pos) |
  51. (initStruct->RXNotEmptyIEn << I2C_IE_RXNE_Pos);
  52. switch((uint32_t)I2Cx)
  53. {
  54. case ((uint32_t)I2C0):
  55. if(initStruct->TXEmptyIEn | initStruct->RXNotEmptyIEn)
  56. {
  57. NVIC_EnableIRQ(I2C0_IRQn);
  58. }
  59. else
  60. {
  61. NVIC_DisableIRQ(I2C0_IRQn);
  62. }
  63. break;
  64. case ((uint32_t)I2C1):
  65. if(initStruct->TXEmptyIEn | initStruct->RXNotEmptyIEn)
  66. {
  67. NVIC_EnableIRQ(I2C1_IRQn);
  68. }
  69. else
  70. {
  71. NVIC_DisableIRQ(I2C1_IRQn);
  72. }
  73. break;
  74. }
  75. }
  76. else
  77. {
  78. I2Cx->CR &= ~(1 << I2C_CR_MASTER_Pos);
  79. I2Cx->SCR &= ~I2C_SCR_ADDR10_Msk;
  80. I2Cx->SCR |= (initStruct->Addr10b << I2C_SCR_ADDR10_Pos);
  81. if(initStruct->Addr10b)
  82. I2Cx->SADDR = (initStruct->SlvAddr << I2C_SADDR_ADDR10_Pos) |
  83. (initStruct->SlvAddrMsk << I2C_SADDR_MASK10_Pos);
  84. else
  85. I2Cx->SADDR = (initStruct->SlvAddr << I2C_SADDR_ADDR7_Pos) |
  86. (initStruct->SlvAddrMsk << I2C_SADDR_MASK7_Pos);
  87. I2Cx->IF = 0xFFFFFFFF;
  88. I2Cx->IE = (initStruct->TXEmptyIEn << I2C_IE_TXE_Pos) |
  89. (initStruct->RXNotEmptyIEn << I2C_IE_RXNE_Pos) |
  90. (initStruct->SlvSTADetIEn << I2C_IE_RXSTA_Pos) |
  91. (initStruct->SlvSTODetIEn << I2C_IE_RXSTO_Pos);
  92. switch((uint32_t)I2Cx)
  93. {
  94. case ((uint32_t)I2C0):
  95. if(initStruct->SlvSTADetIEn | initStruct->SlvSTODetIEn | initStruct->TXEmptyIEn | initStruct->RXNotEmptyIEn)
  96. {
  97. NVIC_EnableIRQ(I2C0_IRQn);
  98. }
  99. else
  100. {
  101. NVIC_DisableIRQ(I2C0_IRQn);
  102. }
  103. break;
  104. case ((uint32_t)I2C1):
  105. if(initStruct->SlvSTADetIEn | initStruct->SlvSTODetIEn | initStruct->TXEmptyIEn | initStruct->RXNotEmptyIEn)
  106. {
  107. NVIC_EnableIRQ(I2C1_IRQn);
  108. }
  109. else
  110. {
  111. NVIC_DisableIRQ(I2C1_IRQn);
  112. }
  113. break;
  114. }
  115. }
  116. }
  117. /******************************************************************************************************************************************
  118. * 函数名称: I2C_Open()
  119. * 功能说明: I2C打开,允许收发
  120. * 输 入: I2C_TypeDef * I2Cx 指定要被设置的I2C,有效值包括I2C0、I2C1
  121. * 输 出: 无
  122. * 注意事项: 无
  123. ******************************************************************************************************************************************/
  124. void I2C_Open(I2C_TypeDef * I2Cx)
  125. {
  126. I2Cx->CR |= (0x01 << I2C_CR_EN_Pos);
  127. }
  128. /******************************************************************************************************************************************
  129. * 函数名称: I2C_Close()
  130. * 功能说明: I2C关闭,禁止收发
  131. * 输 入: I2C_TypeDef * I2Cx 指定要被设置的I2C,有效值包括I2C0、I2C1
  132. * 输 出: 无
  133. * 注意事项: 无
  134. ******************************************************************************************************************************************/
  135. void I2C_Close(I2C_TypeDef * I2Cx)
  136. {
  137. I2Cx->CR &= ~(0x01 << I2C_CR_EN_Pos);
  138. }
  139. /******************************************************************************************************************************************
  140. * 函数名称: I2C_Start()
  141. * 功能说明: 产生起始信号并发送设备地址
  142. * 输 入: I2C_TypeDef * I2Cx 指定要被设置的I2C,有效值包括I2C0、I2C1
  143. * uint8_t addr 设备地址
  144. * uint8_t wait 是否等待发送完成,1 等待发送完成 0 不等待,立即返回
  145. * 输 出: uint8_t 1 接收到ACK 0 接收到NACK
  146. * 注意事项: 若选择不等待,立即返回,则返回值无意义;后续可通过 I2C_StartDone() 查询是否完成,完成后调用 I2C_IsAck() 查询接收到ACK还是NACK
  147. ******************************************************************************************************************************************/
  148. uint8_t I2C_Start(I2C_TypeDef * I2Cx, uint8_t addr, uint8_t wait)
  149. {
  150. I2Cx->TXDATA = addr;
  151. I2Cx->MCR = (1 << I2C_MCR_STA_Pos) |
  152. (1 << I2C_MCR_WR_Pos); //发送起始位和从机地址
  153. if(wait == 0)
  154. return 0;
  155. while(I2Cx->MCR & I2C_MCR_WR_Msk) __NOP(); //等待发送完成
  156. return (I2Cx->TR & I2C_TR_RXACK_Msk) ? 0 : 1;
  157. }
  158. uint8_t I2C_StartDone(I2C_TypeDef * I2Cx)
  159. {
  160. return (I2Cx->MCR & I2C_MCR_WR_Msk) ? 0 : 1;
  161. }
  162. uint8_t I2C_IsAck(I2C_TypeDef * I2Cx)
  163. {
  164. return (I2Cx->TR & I2C_TR_RXACK_Msk) ? 0 : 1;
  165. }
  166. /******************************************************************************************************************************************
  167. * 函数名称: I2C_Stop()
  168. * 功能说明: 产生停止信号
  169. * 输 入: I2C_TypeDef * I2Cx 指定要被设置的I2C,有效值包括I2C0、I2C1
  170. * uint8_t wait 是否等待发送完成,1 等待发送完成 0 不等待,立即返回
  171. * 输 出: 无
  172. * 注意事项: 若选择不等待,立即返回;后续可通过 I2C_StopDone() 查询是否完成
  173. ******************************************************************************************************************************************/
  174. void I2C_Stop(I2C_TypeDef * I2Cx, uint8_t wait)
  175. {
  176. I2Cx->MCR = (1 << I2C_MCR_STO_Pos);
  177. if(wait == 0)
  178. return;
  179. while(I2Cx->MCR & I2C_MCR_STO_Msk) __NOP(); //等待发送完成
  180. }
  181. uint8_t I2C_StopDone(I2C_TypeDef * I2Cx)
  182. {
  183. return (I2Cx->MCR & I2C_MCR_STO_Msk) ? 0 : 1;
  184. }
  185. /******************************************************************************************************************************************
  186. * 函数名称: I2C_Write()
  187. * 功能说明: 写入一个数据
  188. * 输 入: I2C_TypeDef * I2Cx 指定要被设置的I2C,有效值包括I2C0、I2C1
  189. * uint8_t data 要写的数据
  190. * uint8_t wait 是否等待发送完成,1 等待发送完成 0 不等待,立即返回
  191. * 输 出: uint8_t 1 接收到ACK 0 接收到NACK
  192. * 注意事项: 若选择不等待,立即返回,则返回值无意义;后续可通过 I2C_WriteDone() 查询是否完成,完成后调用 I2C_IsAck() 查询接收到ACK还是NACK
  193. ******************************************************************************************************************************************/
  194. uint8_t I2C_Write(I2C_TypeDef * I2Cx, uint8_t data, uint8_t wait)
  195. {
  196. I2Cx->TXDATA = data;
  197. I2Cx->MCR = (1 << I2C_MCR_WR_Pos);
  198. if(wait == 0)
  199. return 0;
  200. while(I2Cx->MCR & I2C_MCR_WR_Msk) __NOP(); //等待发送完成
  201. return (I2Cx->TR & I2C_TR_RXACK_Msk) ? 0 : 1;
  202. }
  203. uint8_t I2C_WriteDone(I2C_TypeDef * I2Cx)
  204. {
  205. return (I2Cx->MCR & I2C_MCR_WR_Msk) ? 0 : 1;
  206. }
  207. /******************************************************************************************************************************************
  208. * 函数名称: I2C_Read()
  209. * 功能说明: 读取一个数据
  210. * 输 入: I2C_TypeDef * I2Cx 指定要被设置的I2C,有效值包括I2C0、I2C1
  211. * uint8_t ack 1 发送ACK 0 发送NACK
  212. * uint8_t wait 是否等待发送完成,1 等待发送完成 0 不等待,立即返回
  213. * 输 出: uint8_t 读取到的数据
  214. * 注意事项: 若选择不等待,立即返回,则返回值无意义;后续可通过 I2C_ReadDone() 查询是否完成,完成后通过 I2Cx->RXDATA 获取读取到的数据
  215. ******************************************************************************************************************************************/
  216. uint8_t I2C_Read(I2C_TypeDef * I2Cx, uint8_t ack, uint8_t wait)
  217. {
  218. I2Cx->TR = ((ack ? 0 : 1) << I2C_TR_TXACK_Pos);
  219. I2Cx->MCR = (1 << I2C_MCR_RD_Pos);
  220. if(wait == 0)
  221. return 0;
  222. while(I2Cx->MCR & I2C_MCR_RD_Msk) __NOP(); //等待接收完成
  223. return I2Cx->RXDATA;
  224. }
  225. uint8_t I2C_ReadDone(I2C_TypeDef * I2Cx)
  226. {
  227. return (I2Cx->MCR & I2C_MCR_RD_Msk) ? 0 : 1;
  228. }
  229. /******************************************************************************************************************************************
  230. * 函数名称: I2C_INTEn()
  231. * 功能说明: 中断使能
  232. * 输 入: I2C_TypeDef * I2Cx 指定要被设置的I2C,有效值包括I2C0、I2C1
  233. * uint32_t it interrupt type,有效值I2C_IT_TX_EMPTY、I2C_IT_RX_NOT_EMPTY、I2C_IT_RX_OVF、I2C_IT_TX_DONE、I2C_IT_RX_DONE、
  234. * I2C_IT_SLV_DET_STA、I2C_IT_SLV_DET_STP、I2C_IT_ARB_LOST、I2C_IT_SCL_LOW_TO 及其“或”
  235. * 输 出: 无
  236. * 注意事项: 无
  237. ******************************************************************************************************************************************/
  238. void I2C_INTEn(I2C_TypeDef * I2Cx, uint32_t it)
  239. {
  240. I2Cx->IE |= it;
  241. }
  242. /******************************************************************************************************************************************
  243. * 函数名称: I2C_INTDis()
  244. * 功能说明: 中断禁止
  245. * 输 入: I2C_TypeDef * I2Cx 指定要被设置的I2C,有效值包括I2C0、I2C1
  246. * uint32_t it interrupt type,有效值I2C_IT_TX_EMPTY、I2C_IT_RX_NOT_EMPTY、I2C_IT_RX_OVF、I2C_IT_TX_DONE、I2C_IT_RX_DONE、
  247. * I2C_IT_SLV_DET_STA、I2C_IT_SLV_DET_STP、I2C_IT_ARB_LOST、I2C_IT_SCL_LOW_TO 及其“或”
  248. * 输 出: 无
  249. * 注意事项: 无
  250. ******************************************************************************************************************************************/
  251. void I2C_INTDis(I2C_TypeDef * I2Cx, uint32_t it)
  252. {
  253. I2Cx->IE &= ~it;
  254. }
  255. /******************************************************************************************************************************************
  256. * 函数名称: I2C_INTClr()
  257. * 功能说明: 中断标志清除
  258. * 输 入: I2C_TypeDef * I2Cx 指定要被设置的I2C,有效值包括I2C0、I2C1
  259. * uint32_t it interrupt type,有效值I2C_IT_TX_EMPTY、I2C_IT_RX_NOT_EMPTY、I2C_IT_RX_OVF、I2C_IT_TX_DONE、I2C_IT_RX_DONE、
  260. * I2C_IT_SLV_DET_STA、I2C_IT_SLV_DET_STP、I2C_IT_ARB_LOST、I2C_IT_SCL_LOW_TO 及其“或”
  261. * 输 出: 无
  262. * 注意事项: 无
  263. ******************************************************************************************************************************************/
  264. void I2C_INTClr(I2C_TypeDef * I2Cx, uint32_t it)
  265. {
  266. I2Cx->IF = it;
  267. }
  268. /******************************************************************************************************************************************
  269. * 函数名称: I2C_INTStat()
  270. * 功能说明: 中断状态查询
  271. * 输 入: I2C_TypeDef * I2Cx 指定要被设置的I2C,有效值包括I2C0、I2C1
  272. * uint32_t it interrupt type,有效值I2C_IT_TX_EMPTY、I2C_IT_RX_NOT_EMPTY、I2C_IT_RX_OVF、I2C_IT_TX_DONE、I2C_IT_RX_DONE、
  273. * I2C_IT_SLV_DET_STA、I2C_IT_SLV_DET_STP、I2C_IT_ARB_LOST、I2C_IT_SCL_LOW_TO 及其“或”
  274. * 输 出: uint32_t 1 中断发生 0 中断未发生
  275. * 注意事项: 无
  276. ******************************************************************************************************************************************/
  277. uint32_t I2C_INTStat(I2C_TypeDef * I2Cx, uint32_t it)
  278. {
  279. return (I2Cx->IF & it) ? 1 : 0;
  280. }