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 
25 /******************************************************************************************************************************************
26 * 函数名称: I2C_Init()
27 * 功能说明: I2C初始化
28 * 输    入: I2C_TypeDef * I2Cx        指定要被设置的I2C,有效值包括I2C0、I2C1
29 *           I2C_InitStructure * initStruct  包含I2C相关设定值的结构体
30 * 输    出: 无
31 * 注意事项: 无
32 ******************************************************************************************************************************************/
I2C_Init(I2C_TypeDef * I2Cx,I2C_InitStructure * initStruct)33 void I2C_Init(I2C_TypeDef * I2Cx, I2C_InitStructure * initStruct)
34 {
35     switch((uint32_t)I2Cx)
36     {
37     case ((uint32_t)I2C0):
38         SYS->CLKEN0 |= (0x01 << SYS_CLKEN0_I2C0_Pos);
39         break;
40 
41     case((uint32_t)I2C1):
42         SYS->CLKEN0 |= (0x01 << SYS_CLKEN0_I2C1_Pos);
43         break;
44     }
45 
46     I2C_Close(I2Cx);    //一些关键寄存器只能在I2C关闭时设置
47 
48     if(initStruct->Master == 1)
49     {
50         I2Cx->CR |= (1 << I2C_CR_MASTER_Pos);
51 
52         I2Cx->CLK = (((SystemCoreClock/2)/1000000/3*2 - 1) << I2C_CLK_SCLL_Pos) |
53                     (((SystemCoreClock/2)/1000000/3*1 - 1) << I2C_CLK_SCLH_Pos) |
54                     ((1000000 / initStruct->MstClk - 1)    << I2C_CLK_DIV_Pos);
55 
56         I2Cx->IF = 0xFFFFFFFF;
57         I2Cx->IE = (initStruct->TXEmptyIEn << I2C_IE_TXE_Pos) |
58                    (initStruct->RXNotEmptyIEn << I2C_IE_RXNE_Pos);
59 
60         switch((uint32_t)I2Cx)
61         {
62         case ((uint32_t)I2C0):
63             if(initStruct->TXEmptyIEn | initStruct->RXNotEmptyIEn)
64             {
65                 NVIC_EnableIRQ(I2C0_IRQn);
66             }
67             else
68             {
69                 NVIC_DisableIRQ(I2C0_IRQn);
70             }
71             break;
72 
73         case ((uint32_t)I2C1):
74             if(initStruct->TXEmptyIEn | initStruct->RXNotEmptyIEn)
75             {
76                 NVIC_EnableIRQ(I2C1_IRQn);
77             }
78             else
79             {
80                 NVIC_DisableIRQ(I2C1_IRQn);
81             }
82             break;
83         }
84     }
85     else
86     {
87         I2Cx->CR &= ~(1 << I2C_CR_MASTER_Pos);
88 
89         I2Cx->SCR &= ~I2C_SCR_ADDR10_Msk;
90         I2Cx->SCR |= (initStruct->Addr10b << I2C_SCR_ADDR10_Pos);
91 
92         if(initStruct->Addr10b)
93             I2Cx->SADDR = (initStruct->SlvAddr    << I2C_SADDR_ADDR10_Pos) |
94                           (initStruct->SlvAddrMsk << I2C_SADDR_MASK10_Pos);
95         else
96             I2Cx->SADDR = (initStruct->SlvAddr    << I2C_SADDR_ADDR7_Pos) |
97                           (initStruct->SlvAddrMsk << I2C_SADDR_MASK7_Pos);
98 
99         I2Cx->IF = 0xFFFFFFFF;
100         I2Cx->IE = (initStruct->TXEmptyIEn    << I2C_IE_TXE_Pos) |
101                    (initStruct->RXNotEmptyIEn << I2C_IE_RXNE_Pos) |
102                    (initStruct->SlvSTADetIEn  << I2C_IE_RXSTA_Pos) |
103                    (initStruct->SlvSTODetIEn  << I2C_IE_RXSTO_Pos);
104 
105         switch((uint32_t)I2Cx)
106         {
107         case ((uint32_t)I2C0):
108             if(initStruct->SlvSTADetIEn | initStruct->SlvSTODetIEn | initStruct->TXEmptyIEn | initStruct->RXNotEmptyIEn)
109             {
110                 NVIC_EnableIRQ(I2C0_IRQn);
111             }
112             else
113             {
114                 NVIC_DisableIRQ(I2C0_IRQn);
115             }
116             break;
117 
118         case ((uint32_t)I2C1):
119             if(initStruct->SlvSTADetIEn | initStruct->SlvSTODetIEn | initStruct->TXEmptyIEn | initStruct->RXNotEmptyIEn)
120             {
121                 NVIC_EnableIRQ(I2C1_IRQn);
122             }
123             else
124             {
125                 NVIC_DisableIRQ(I2C1_IRQn);
126             }
127             break;
128         }
129     }
130 }
131 
132 /******************************************************************************************************************************************
133 * 函数名称: I2C_Open()
134 * 功能说明: I2C打开,允许收发
135 * 输    入: I2C_TypeDef * I2Cx        指定要被设置的I2C,有效值包括I2C0、I2C1
136 * 输    出: 无
137 * 注意事项: 无
138 ******************************************************************************************************************************************/
I2C_Open(I2C_TypeDef * I2Cx)139 void I2C_Open(I2C_TypeDef * I2Cx)
140 {
141     I2Cx->CR |= (0x01 << I2C_CR_EN_Pos);
142 }
143 
144 /******************************************************************************************************************************************
145 * 函数名称: I2C_Close()
146 * 功能说明: I2C关闭,禁止收发
147 * 输    入: I2C_TypeDef * I2Cx        指定要被设置的I2C,有效值包括I2C0、I2C1
148 * 输    出: 无
149 * 注意事项: 无
150 ******************************************************************************************************************************************/
I2C_Close(I2C_TypeDef * I2Cx)151 void I2C_Close(I2C_TypeDef * I2Cx)
152 {
153     I2Cx->CR &= ~(0x01 << I2C_CR_EN_Pos);
154 }
155 
156 /******************************************************************************************************************************************
157 * 函数名称: I2C_Start()
158 * 功能说明: 产生起始信号并发送设备地址
159 * 输    入: I2C_TypeDef * I2Cx        指定要被设置的I2C,有效值包括I2C0、I2C1
160 *           uint8_t addr            设备地址
161 *           uint8_t wait            是否等待发送完成,1 等待发送完成   0 不等待,立即返回
162 * 输    出: uint8_t                   1 接收到ACK   0 接收到NACK
163 * 注意事项: 若选择不等待,立即返回,则返回值无意义;后续可通过 I2C_StartDone() 查询是否完成,完成后调用 I2C_IsAck() 查询接收到ACK还是NACK
164 ******************************************************************************************************************************************/
I2C_Start(I2C_TypeDef * I2Cx,uint8_t addr,uint8_t wait)165 uint8_t I2C_Start(I2C_TypeDef * I2Cx, uint8_t addr, uint8_t wait)
166 {
167     I2Cx->TXDATA = addr;
168     I2Cx->MCR = (1 << I2C_MCR_STA_Pos) |
169                 (1 << I2C_MCR_WR_Pos);              //发送起始位和从机地址
170 
171     if(wait == 0)
172         return 0;
173 
174     while(I2Cx->MCR & I2C_MCR_WR_Msk) __NOP();      //等待发送完成
175 
176     return (I2Cx->TR & I2C_TR_RXACK_Msk) ? 0 : 1;
177 }
178 
I2C_StartDone(I2C_TypeDef * I2Cx)179 uint8_t I2C_StartDone(I2C_TypeDef * I2Cx)
180 {
181     return (I2Cx->MCR & I2C_MCR_WR_Msk) ? 0 : 1;
182 }
183 
I2C_IsAck(I2C_TypeDef * I2Cx)184 uint8_t I2C_IsAck(I2C_TypeDef * I2Cx)
185 {
186     return (I2Cx->TR & I2C_TR_RXACK_Msk) ? 0 : 1;
187 }
188 
189 /******************************************************************************************************************************************
190 * 函数名称: I2C_Stop()
191 * 功能说明: 产生停止信号
192 * 输    入: I2C_TypeDef * I2Cx        指定要被设置的I2C,有效值包括I2C0、I2C1
193 *           uint8_t wait            是否等待发送完成,1 等待发送完成   0 不等待,立即返回
194 * 输    出: 无
195 * 注意事项: 若选择不等待,立即返回;后续可通过 I2C_StopDone() 查询是否完成
196 ******************************************************************************************************************************************/
I2C_Stop(I2C_TypeDef * I2Cx,uint8_t wait)197 void I2C_Stop(I2C_TypeDef * I2Cx, uint8_t wait)
198 {
199     I2Cx->MCR = (1 << I2C_MCR_STO_Pos);
200 
201     if(wait == 0)
202         return;
203 
204     while(I2Cx->MCR & I2C_MCR_STO_Msk) __NOP();     //等待发送完成
205 }
206 
I2C_StopDone(I2C_TypeDef * I2Cx)207 uint8_t I2C_StopDone(I2C_TypeDef * I2Cx)
208 {
209     return (I2Cx->MCR & I2C_MCR_STO_Msk) ? 0 : 1;
210 }
211 
212 /******************************************************************************************************************************************
213 * 函数名称: I2C_Write()
214 * 功能说明: 写入一个数据
215 * 输    入: I2C_TypeDef * I2Cx        指定要被设置的I2C,有效值包括I2C0、I2C1
216 *           uint8_t data            要写的数据
217 *           uint8_t wait            是否等待发送完成,1 等待发送完成   0 不等待,立即返回
218 * 输    出: uint8_t                   1 接收到ACK   0 接收到NACK
219 * 注意事项: 若选择不等待,立即返回,则返回值无意义;后续可通过 I2C_WriteDone() 查询是否完成,完成后调用 I2C_IsAck() 查询接收到ACK还是NACK
220 ******************************************************************************************************************************************/
I2C_Write(I2C_TypeDef * I2Cx,uint8_t data,uint8_t wait)221 uint8_t I2C_Write(I2C_TypeDef * I2Cx, uint8_t data, uint8_t wait)
222 {
223     I2Cx->TXDATA = data;
224     I2Cx->MCR = (1 << I2C_MCR_WR_Pos);
225 
226     if(wait == 0)
227         return 0;
228 
229     while(I2Cx->MCR & I2C_MCR_WR_Msk) __NOP();      //等待发送完成
230 
231     return (I2Cx->TR & I2C_TR_RXACK_Msk) ? 0 : 1;
232 }
233 
I2C_WriteDone(I2C_TypeDef * I2Cx)234 uint8_t I2C_WriteDone(I2C_TypeDef * I2Cx)
235 {
236     return (I2Cx->MCR & I2C_MCR_WR_Msk) ? 0 : 1;
237 }
238 
239 /******************************************************************************************************************************************
240 * 函数名称: I2C_Read()
241 * 功能说明: 读取一个数据
242 * 输    入: I2C_TypeDef * I2Cx        指定要被设置的I2C,有效值包括I2C0、I2C1
243 *           uint8_t ack             1 发送ACK   0 发送NACK
244 *           uint8_t wait            是否等待发送完成,1 等待发送完成   0 不等待,立即返回
245 * 输    出: uint8_t                   读取到的数据
246 * 注意事项: 若选择不等待,立即返回,则返回值无意义;后续可通过 I2C_ReadDone() 查询是否完成,完成后通过 I2Cx->RXDATA 获取读取到的数据
247 ******************************************************************************************************************************************/
I2C_Read(I2C_TypeDef * I2Cx,uint8_t ack,uint8_t wait)248 uint8_t I2C_Read(I2C_TypeDef * I2Cx, uint8_t ack, uint8_t wait)
249 {
250     I2Cx->TR = ((ack ? 0 : 1) << I2C_TR_TXACK_Pos);
251 
252     I2Cx->MCR = (1 << I2C_MCR_RD_Pos);
253 
254     if(wait == 0)
255         return 0;
256 
257     while(I2Cx->MCR & I2C_MCR_RD_Msk) __NOP();      //等待接收完成
258 
259     return I2Cx->RXDATA;
260 }
261 
I2C_ReadDone(I2C_TypeDef * I2Cx)262 uint8_t I2C_ReadDone(I2C_TypeDef * I2Cx)
263 {
264     return (I2Cx->MCR & I2C_MCR_RD_Msk) ? 0 : 1;
265 }
266 
267 /******************************************************************************************************************************************
268 * 函数名称: I2C_INTEn()
269 * 功能说明: 中断使能
270 * 输    入: I2C_TypeDef * I2Cx        指定要被设置的I2C,有效值包括I2C0、I2C1
271 *           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、
272 *                                   I2C_IT_SLV_DET_STA、I2C_IT_SLV_DET_STP、I2C_IT_ARB_LOST、I2C_IT_SCL_LOW_TO 及其“或”
273 * 输    出: 无
274 * 注意事项: 无
275 ******************************************************************************************************************************************/
I2C_INTEn(I2C_TypeDef * I2Cx,uint32_t it)276 void I2C_INTEn(I2C_TypeDef * I2Cx, uint32_t it)
277 {
278     I2Cx->IE |= it;
279 }
280 
281 /******************************************************************************************************************************************
282 * 函数名称: I2C_INTDis()
283 * 功能说明: 中断禁止
284 * 输    入: I2C_TypeDef * I2Cx        指定要被设置的I2C,有效值包括I2C0、I2C1
285 *           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、
286 *                                   I2C_IT_SLV_DET_STA、I2C_IT_SLV_DET_STP、I2C_IT_ARB_LOST、I2C_IT_SCL_LOW_TO 及其“或”
287 * 输    出: 无
288 * 注意事项: 无
289 ******************************************************************************************************************************************/
I2C_INTDis(I2C_TypeDef * I2Cx,uint32_t it)290 void I2C_INTDis(I2C_TypeDef * I2Cx, uint32_t it)
291 {
292     I2Cx->IE &= ~it;
293 }
294 
295 /******************************************************************************************************************************************
296 * 函数名称: I2C_INTClr()
297 * 功能说明: 中断标志清除
298 * 输    入: I2C_TypeDef * I2Cx        指定要被设置的I2C,有效值包括I2C0、I2C1
299 *           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、
300 *                                   I2C_IT_SLV_DET_STA、I2C_IT_SLV_DET_STP、I2C_IT_ARB_LOST、I2C_IT_SCL_LOW_TO 及其“或”
301 * 输    出: 无
302 * 注意事项: 无
303 ******************************************************************************************************************************************/
I2C_INTClr(I2C_TypeDef * I2Cx,uint32_t it)304 void I2C_INTClr(I2C_TypeDef * I2Cx, uint32_t it)
305 {
306     I2Cx->IF = it;
307 }
308 
309 /******************************************************************************************************************************************
310 * 函数名称: I2C_INTStat()
311 * 功能说明: 中断状态查询
312 * 输    入: I2C_TypeDef * I2Cx        指定要被设置的I2C,有效值包括I2C0、I2C1
313 *           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、
314 *                                   I2C_IT_SLV_DET_STA、I2C_IT_SLV_DET_STP、I2C_IT_ARB_LOST、I2C_IT_SCL_LOW_TO 及其“或”
315 * 输    出: uint32_t              1 中断发生    0 中断未发生
316 * 注意事项: 无
317 ******************************************************************************************************************************************/
I2C_INTStat(I2C_TypeDef * I2Cx,uint32_t it)318 uint32_t I2C_INTStat(I2C_TypeDef * I2Cx, uint32_t it)
319 {
320     return (I2Cx->IF & it) ? 1 : 0;
321 }
322