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