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