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