SWM341_spi.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. /******************************************************************************************************************************************
  2. * 文件名称: SWM341_spi.c
  3. * 功能说明: SWM341单片机的SPI功能驱动库
  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 AIMS AT PROVIDING CUSTOMERS WITH CODING INFORMATION
  14. * REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, SYNWIT SHALL NOT BE HELD LIABLE
  15. * FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS 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_spi.h"
  23. /******************************************************************************************************************************************
  24. * 函数名称: SPI_Init()
  25. * 功能说明: SPI同步串行接口初始化,包括帧长度设定、时序设定、速度设定、中断设定、FIFO触发设定
  26. * 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1
  27. * SPI_InitStructure * initStruct 包含SPI相关设定值的结构体
  28. * 输 出: 无
  29. * 注意事项: 无
  30. ******************************************************************************************************************************************/
  31. void SPI_Init(SPI_TypeDef * SPIx, SPI_InitStructure * initStruct)
  32. {
  33. uint32_t fast = 0, no_sync = 0;
  34. switch((uint32_t)SPIx)
  35. {
  36. case ((uint32_t)SPI0):
  37. SYS->CLKEN0 |= (0x01 << SYS_CLKEN0_SPI0_Pos);
  38. break;
  39. case ((uint32_t)SPI1):
  40. SYS->CLKEN0 |= (0x01 << SYS_CLKEN0_SPI1_Pos);
  41. break;
  42. }
  43. SPI_Close(SPIx); //一些关键寄存器只能在SPI关闭时设置
  44. if(initStruct->clkDiv == SPI_CLKDIV_2)
  45. {
  46. fast = 1;
  47. no_sync = 1;
  48. }
  49. else if(initStruct->clkDiv == SPI_CLKDIV_4)
  50. {
  51. no_sync = 1;
  52. }
  53. SPIx->CTRL &= ~(SPI_CTRL_FFS_Msk | SPI_CTRL_CPHA_Msk | SPI_CTRL_CPOL_Msk | SPI_CTRL_SIZE_Msk | SPI_CTRL_MSTR_Msk | SPI_CTRL_FAST_Msk | SPI_CTRL_NSYNC_Msk |
  54. SPI_CTRL_CLKDIV_Msk | SPI_CTRL_SSN_H_Msk | SPI_CTRL_RFTHR_Msk | SPI_CTRL_TFTHR_Msk);
  55. SPIx->CTRL |= (initStruct->FrameFormat << SPI_CTRL_FFS_Pos) |
  56. (initStruct->SampleEdge << SPI_CTRL_CPHA_Pos) |
  57. (initStruct->IdleLevel << SPI_CTRL_CPOL_Pos) |
  58. ((initStruct->WordSize-1) << SPI_CTRL_SIZE_Pos) |
  59. (initStruct->Master << SPI_CTRL_MSTR_Pos) |
  60. (fast << SPI_CTRL_FAST_Pos) |
  61. (no_sync << SPI_CTRL_NSYNC_Pos) |
  62. ((initStruct->clkDiv & 7) << SPI_CTRL_CLKDIV_Pos) |
  63. (0 << SPI_CTRL_SSN_H_Pos) |
  64. ((initStruct->RXThreshold > 0 ? initStruct->RXThreshold-1 : 0) << SPI_CTRL_RFTHR_Pos) |
  65. (initStruct->TXThreshold << SPI_CTRL_TFTHR_Pos) |
  66. (1 << SPI_CTRL_RFCLR_Pos) |
  67. (1 << SPI_CTRL_TFCLR_Pos);
  68. SPIx->CTRL &= ~(SPI_CTRL_RFCLR_Msk | SPI_CTRL_TFCLR_Msk);
  69. SPIx->IF = 0x37F; //清除中断标志
  70. SPIx->IE = 0x000;
  71. SPIx->IE |= (initStruct->RXThresholdIEn << SPI_IE_RFTHR_Pos) |
  72. (initStruct->TXThresholdIEn << SPI_IE_TFTHR_Pos) |
  73. (initStruct->TXCompleteIEn << SPI_IE_FTC_Pos);
  74. switch((uint32_t)SPIx)
  75. {
  76. case ((uint32_t)SPI0):
  77. if(initStruct->RXThresholdIEn | initStruct->TXThresholdIEn | initStruct->TXCompleteIEn)
  78. {
  79. NVIC_EnableIRQ(SPI0_IRQn);
  80. }
  81. else
  82. {
  83. NVIC_DisableIRQ(SPI0_IRQn);
  84. }
  85. break;
  86. case ((uint32_t)SPI1):
  87. if(initStruct->RXThresholdIEn | initStruct->TXThresholdIEn | initStruct->TXCompleteIEn)
  88. {
  89. NVIC_EnableIRQ(SPI1_IRQn);
  90. }
  91. else
  92. {
  93. NVIC_DisableIRQ(SPI1_IRQn);
  94. }
  95. break;
  96. }
  97. }
  98. /******************************************************************************************************************************************
  99. * 函数名称: SPI_Open()
  100. * 功能说明: SPI打开,允许收发
  101. * 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1
  102. * 输 出: 无
  103. * 注意事项: 无
  104. ******************************************************************************************************************************************/
  105. void SPI_Open(SPI_TypeDef * SPIx)
  106. {
  107. SPIx->CTRL |= (0x01 << SPI_CTRL_EN_Pos);
  108. }
  109. /******************************************************************************************************************************************
  110. * 函数名称: SPI_Close()
  111. * 功能说明: SPI关闭,禁止收发
  112. * 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1
  113. * 输 出: 无
  114. * 注意事项: 无
  115. ******************************************************************************************************************************************/
  116. void SPI_Close(SPI_TypeDef * SPIx)
  117. {
  118. SPIx->CTRL &= ~SPI_CTRL_EN_Msk;
  119. }
  120. /******************************************************************************************************************************************
  121. * 函数名称: SPI_Read()
  122. * 功能说明: 读取一个数据
  123. * 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1
  124. * 输 出: uint32_t 读取到的数据
  125. * 注意事项: 无
  126. ******************************************************************************************************************************************/
  127. uint32_t SPI_Read(SPI_TypeDef * SPIx)
  128. {
  129. return SPIx->DATA;
  130. }
  131. /******************************************************************************************************************************************
  132. * 函数名称: SPI_Write()
  133. * 功能说明: 写入一个数据
  134. * 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1
  135. * uint32_t 要写入的数据
  136. * 输 出: 无
  137. * 注意事项: 无
  138. ******************************************************************************************************************************************/
  139. void SPI_Write(SPI_TypeDef * SPIx, uint32_t data)
  140. {
  141. SPIx->DATA = data;
  142. }
  143. /******************************************************************************************************************************************
  144. * 函数名称: SPI_WriteWithWait()
  145. * 功能说明: 写入一个数据并等待数据完全发送出去
  146. * 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1、SPI1
  147. * uint32_t 要写入的数据
  148. * 输 出: 无
  149. * 注意事项: 无
  150. ******************************************************************************************************************************************/
  151. void SPI_WriteWithWait(SPI_TypeDef * SPIx, uint32_t data)
  152. {
  153. SPIx->STAT |= (1 << SPI_STAT_WTC_Pos);
  154. SPIx->DATA = data;
  155. while((SPIx->STAT & SPI_STAT_WTC_Msk) == 0);
  156. }
  157. /******************************************************************************************************************************************
  158. * 函数名称: SPI_ReadWrite()
  159. * 功能说明: 发送一个数据,并返回发送过程中接收到的
  160. * 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1
  161. * uint32_t data 要发送的数据
  162. * 输 出: uint32_t 接收到的数据
  163. * 注意事项: 对于同一个SPI模块,此函数不应与SPI_Write()混着用,因为SPI_Write()不清除SPI_STAT_RFNE状态
  164. ******************************************************************************************************************************************/
  165. uint32_t SPI_ReadWrite(SPI_TypeDef * SPIx, uint32_t data)
  166. {
  167. SPIx->DATA = data;
  168. while(!(SPIx->STAT & SPI_STAT_RFNE_Msk));
  169. return SPIx->DATA;
  170. }
  171. /******************************************************************************************************************************************
  172. * 函数名称: SPI_IsRXEmpty()
  173. * 功能说明: 接收FIFO是否空,如果不空则可以继续SPI_Read()
  174. * 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1
  175. * 输 出: uint32_t 1 接收FIFO空 0 接收FIFO非空
  176. * 注意事项: 无
  177. ******************************************************************************************************************************************/
  178. uint32_t SPI_IsRXEmpty(SPI_TypeDef * SPIx)
  179. {
  180. return (SPIx->STAT & SPI_STAT_RFNE_Msk) ? 0 : 1;
  181. }
  182. /******************************************************************************************************************************************
  183. * 函数名称: SPI_IsTXFull()
  184. * 功能说明: 发送FIFO是否满,如果不满则可以继续SPI_Write()
  185. * 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1
  186. * 输 出: uint32_t 1 发送FIFO满 0 发送FIFO不满
  187. * 注意事项: 无
  188. ******************************************************************************************************************************************/
  189. uint32_t SPI_IsTXFull(SPI_TypeDef * SPIx)
  190. {
  191. return (SPIx->STAT & SPI_STAT_TFNF_Msk) ? 0 : 1;
  192. }
  193. /******************************************************************************************************************************************
  194. * 函数名称: SPI_IsTXEmpty()
  195. * 功能说明: 发送FIFO是否空
  196. * 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1
  197. * 输 出: uint32_t 1 发送FIFO空 0 发送FIFO非空
  198. * 注意事项: 无
  199. ******************************************************************************************************************************************/
  200. uint32_t SPI_IsTXEmpty(SPI_TypeDef * SPIx)
  201. {
  202. return (SPIx->STAT & SPI_STAT_TFE_Msk) ? 1 : 0;
  203. }
  204. /******************************************************************************************************************************************
  205. * 函数名称: SPI_INTEn()
  206. * 功能说明: 中断使能
  207. * 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1
  208. * uint32_t it interrupt type,有效值SPI_IT_RX_OVF、SPI_IT_RX_FULL、SPI_IT_RX_HFULL、SPI_IT_TX_EMPTY、SPI_IT_TX_HFULL、
  209. * SPI_IT_RX_THRES、SPI_IT_TX_THRES、SPI_IT_TX_DONE、SPI_IT_CS_FALL、SPI_IT_CS_RISE 及其“或”
  210. * 输 出: 无
  211. * 注意事项: 无
  212. ******************************************************************************************************************************************/
  213. void SPI_INTEn(SPI_TypeDef * SPIx, uint32_t it)
  214. {
  215. SPIx->IE |= it;
  216. }
  217. /******************************************************************************************************************************************
  218. * 函数名称: SPI_INTDis()
  219. * 功能说明: 中断禁止
  220. * 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1
  221. * uint32_t it interrupt type,有效值SPI_IT_RX_OVF、SPI_IT_RX_FULL、SPI_IT_RX_HFULL、SPI_IT_TX_EMPTY、SPI_IT_TX_HFULL、
  222. * SPI_IT_RX_THRES、SPI_IT_TX_THRES、SPI_IT_TX_DONE、SPI_IT_CS_FALL、SPI_IT_CS_RISE 及其“或”
  223. * 输 出: 无
  224. * 注意事项: 无
  225. ******************************************************************************************************************************************/
  226. void SPI_INTDis(SPI_TypeDef * SPIx, uint32_t it)
  227. {
  228. SPIx->IE &= ~it;
  229. }
  230. /******************************************************************************************************************************************
  231. * 函数名称: SPI_INTClr()
  232. * 功能说明: 中断标志清除
  233. * 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1
  234. * uint32_t it interrupt type,有效值SPI_IT_RX_OVF、SPI_IT_RX_FULL、SPI_IT_RX_HFULL、SPI_IT_TX_EMPTY、SPI_IT_TX_HFULL、
  235. * SPI_IT_RX_THRES、SPI_IT_TX_THRES、SPI_IT_TX_DONE、SPI_IT_CS_FALL、SPI_IT_CS_RISE 及其“或”
  236. * 输 出: 无
  237. * 注意事项: 无
  238. ******************************************************************************************************************************************/
  239. void SPI_INTClr(SPI_TypeDef * SPIx, uint32_t it)
  240. {
  241. SPIx->IF = it;
  242. }
  243. /******************************************************************************************************************************************
  244. * 函数名称: SPI_INTStat()
  245. * 功能说明: 中断状态查询
  246. * 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1
  247. * uint32_t it interrupt type,有效值SPI_IT_RX_OVF、SPI_IT_RX_FULL、SPI_IT_RX_HFULL、SPI_IT_TX_EMPTY、SPI_IT_TX_HFULL、
  248. * SPI_IT_RX_THRES、SPI_IT_TX_THRES、SPI_IT_TX_DONE、SPI_IT_CS_FALL、SPI_IT_CS_RISE 及其“或”
  249. * 输 出: uint32_t 1 中断发生 0 中断未发生
  250. * 注意事项: 无
  251. ******************************************************************************************************************************************/
  252. uint32_t SPI_INTStat(SPI_TypeDef * SPIx, uint32_t it)
  253. {
  254. return (SPIx->IF & it) ? 1 : 0;
  255. }
  256. /******************************************************************************************************************************************
  257. * 函数名称: I2S_Init()
  258. * 功能说明: I2S音频串行接口初始化,包括帧格式、数据长度、时钟频率、中断设定、FIFO触发设定
  259. * 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1
  260. * I2S_InitStructure * initStruct 包含I2S相关设定值的结构体
  261. * 输 出: 无
  262. * 注意事项: 无
  263. ******************************************************************************************************************************************/
  264. void I2S_Init(SPI_TypeDef * SPIx, I2S_InitStructure * initStruct)
  265. {
  266. switch((uint32_t)SPIx)
  267. {
  268. case ((uint32_t)SPI0):
  269. SYS->CLKEN0 |= (0x01 << SYS_CLKEN0_SPI0_Pos);
  270. break;
  271. case ((uint32_t)SPI1):
  272. SYS->CLKEN0 |= (0x01 << SYS_CLKEN0_SPI1_Pos);
  273. break;
  274. }
  275. I2S_Close(SPIx); //一些关键寄存器只能在SPI关闭时设置
  276. SPIx->CTRL &= ~(SPI_CTRL_FFS_Msk | SPI_CTRL_RFTHR_Msk | SPI_CTRL_TFTHR_Msk);
  277. SPIx->CTRL |= (SPI_FORMAT_I2S << SPI_CTRL_FFS_Pos) |
  278. ((initStruct->RXThreshold > 0 ? initStruct->RXThreshold-1 : 0) << SPI_CTRL_RFTHR_Pos) |
  279. (initStruct->TXThreshold << SPI_CTRL_TFTHR_Pos) |
  280. (1 << SPI_CTRL_RFCLR_Pos) |
  281. (1 << SPI_CTRL_TFCLR_Pos);
  282. SPIx->CTRL &= ~(SPI_CTRL_RFCLR_Msk | SPI_CTRL_TFCLR_Msk);
  283. SPIx->I2SCR &= ~(SPI_I2SCR_MSTR_Msk | SPI_I2SCR_DIEN_Msk | SPI_I2SCR_DOEN_Msk | SPI_I2SCR_FFMT_Msk | SPI_I2SCR_DLEN_Msk | SPI_I2SCR_CHLEN_Msk | SPI_I2SCR_PCMSYNW_Msk);
  284. SPIx->I2SCR |= ((initStruct->Mode & 0x04 ? 1 : 0) << SPI_I2SCR_MSTR_Pos) |
  285. ((initStruct->Mode & 0x02 ? 1 : 0) << SPI_I2SCR_DOEN_Pos) |
  286. ((initStruct->Mode & 0x01 ? 1 : 0) << SPI_I2SCR_DIEN_Pos) |
  287. ((initStruct->FrameFormat & 0x03) << SPI_I2SCR_FFMT_Pos) |
  288. (initStruct->DataLen << SPI_I2SCR_DLEN_Pos) |
  289. (initStruct->ChannelLen << SPI_I2SCR_CHLEN_Pos) |
  290. ((initStruct->FrameFormat & 0x04 ? 1 : 0) << SPI_I2SCR_PCMSYNW_Pos);
  291. SPIx->I2SPR &= ~SPI_I2SPR_SCLKDIV_Msk;
  292. SPIx->I2SPR |= (SystemCoreClock / initStruct->ClkFreq / 2 - 1) << SPI_I2SPR_SCLKDIV_Pos;
  293. SPIx->IF = 0x37F; //清除中断标志
  294. SPIx->IE = 0x000;
  295. SPIx->IE |= (initStruct->RXThresholdIEn << SPI_IE_RFTHR_Pos) |
  296. (initStruct->TXThresholdIEn << SPI_IE_TFTHR_Pos) |
  297. (initStruct->TXCompleteIEn << SPI_IE_FTC_Pos);
  298. switch((uint32_t)SPIx)
  299. {
  300. case ((uint32_t)SPI0):
  301. if(initStruct->RXThresholdIEn | initStruct->TXThresholdIEn | initStruct->TXCompleteIEn)
  302. {
  303. NVIC_EnableIRQ(SPI0_IRQn);
  304. }
  305. else
  306. {
  307. NVIC_DisableIRQ(SPI0_IRQn);
  308. }
  309. break;
  310. case ((uint32_t)SPI1):
  311. if(initStruct->RXThresholdIEn | initStruct->TXThresholdIEn | initStruct->TXCompleteIEn)
  312. {
  313. NVIC_EnableIRQ(SPI1_IRQn);
  314. }
  315. else
  316. {
  317. NVIC_DisableIRQ(SPI1_IRQn);
  318. }
  319. break;
  320. }
  321. }
  322. /******************************************************************************************************************************************
  323. * 函数名称: I2S_Open()
  324. * 功能说明: I2S打开,允许收发
  325. * 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1
  326. * 输 出: 无
  327. * 注意事项: 无
  328. ******************************************************************************************************************************************/
  329. void I2S_Open(SPI_TypeDef * SPIx)
  330. {
  331. SPIx->CTRL |= (0x01 << SPI_CTRL_EN_Pos); //使能SPI才能使用TX Complete中断
  332. SPIx->I2SCR |= (0x01 << SPI_I2SCR_EN_Pos);
  333. }
  334. /******************************************************************************************************************************************
  335. * 函数名称: I2S_Close()
  336. * 功能说明: I2S关闭,禁止收发
  337. * 输 入: SPI_TypeDef * SPIx 指定要被设置的SPI,有效值包括SPI0、SPI1
  338. * 输 出: 无
  339. * 注意事项: 无
  340. ******************************************************************************************************************************************/
  341. void I2S_Close(SPI_TypeDef * SPIx)
  342. {
  343. SPIx->CTRL &= ~SPI_CTRL_EN_Msk;
  344. SPIx->I2SCR &= ~SPI_I2SCR_EN_Msk;
  345. }