1 /******************************************************************************************************************************************
2 * 文件名称: SWM320_i2c.c
3 * 功能说明: SWM320单片机的I2C串行接口功能驱动库
4 * 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1
5 * 注意事项:
6 * 版本日期: V1.1.0      2017年10月25日
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 "SWM320.h"
22 #include "SWM320_i2c.h"
23 
24 /******************************************************************************************************************************************
25 * 函数名称: I2C_Init()
26 * 功能说明: I2C初始化
27 * 输    入: I2C_TypeDef * I2Cx        指定要被设置的I2C,有效值包括I2C0、I2C1
28 *           I2C_InitStructure * initStruct  包含I2C相关设定值的结构体
29 * 输    出: 无
30 * 注意事项: 模块只能工作于主机模式
31 ******************************************************************************************************************************************/
I2C_Init(I2C_TypeDef * I2Cx,I2C_InitStructure * initStruct)32 void I2C_Init(I2C_TypeDef * I2Cx, I2C_InitStructure * initStruct)
33 {
34     switch((uint32_t)I2Cx)
35     {
36     case ((uint32_t)I2C0):
37         SYS->CLKEN |= (0x01 << SYS_CLKEN_I2C0_Pos);
38         break;
39 
40     case ((uint32_t)I2C1):
41         SYS->CLKEN |= (0x01 << SYS_CLKEN_I2C1_Pos);
42         break;
43     }
44 
45     I2C_Close(I2Cx);    //一些关键寄存器只能在I2C关闭时设置
46 
47     if(initStruct->Master == 1)
48     {
49         I2Cx->CLKDIV = SystemCoreClock/5/initStruct->MstClk;
50 
51         I2Cx->MSTCMD = (I2Cx->MSTCMD & (~I2C_MSTCMD_IF_Msk)) | (1 << I2C_MSTCMD_IF_Pos);    //使能中断之前先清除中断标志
52         I2Cx->CTRL &= ~I2C_CTRL_MSTIE_Msk;
53         I2Cx->CTRL |= (initStruct->MstIEn << I2C_CTRL_MSTIE_Pos);
54 
55         switch((uint32_t)I2Cx)
56         {
57         case ((uint32_t)I2C0):
58             if(initStruct->MstIEn)
59             {
60                 NVIC_EnableIRQ(I2C0_IRQn);
61             }
62             else
63             {
64                 NVIC_DisableIRQ(I2C0_IRQn);
65             }
66             break;
67 
68         case ((uint32_t)I2C1):
69             if(initStruct->MstIEn)
70             {
71                 NVIC_EnableIRQ(I2C1_IRQn);
72             }
73             else
74             {
75                 NVIC_DisableIRQ(I2C1_IRQn);
76             }
77             break;
78         }
79     }
80     else
81     {
82         I2Cx->SLVCR |=  (1 << I2C_SLVCR_SLAVE_Pos);
83 
84         I2Cx->SLVCR &= ~(I2C_SLVCR_ADDR7b_Msk | I2C_SLVCR_ADDR_Msk);
85         I2Cx->SLVCR |= (1 << I2C_SLVCR_ACK_Pos) |
86                        (initStruct->Addr7b << I2C_SLVCR_ADDR7b_Pos) |
87                        (initStruct->SlvAddr << I2C_SLVCR_ADDR_Pos);
88 
89         I2Cx->SLVIF = I2C_SLVIF_RXEND_Msk | I2C_SLVIF_TXEND_Msk | I2C_SLVIF_STADET_Msk | I2C_SLVIF_STODET_Msk;  //清中断标志
90         I2Cx->SLVCR &= ~(I2C_SLVCR_IM_RXEND_Msk | I2C_SLVCR_IM_TXEND_Msk | I2C_SLVCR_IM_STADET_Msk | I2C_SLVCR_IM_STODET_Msk |
91                          I2C_SLVCR_IM_RDREQ_Msk | I2C_SLVCR_IM_WRREQ_Msk);
92         I2Cx->SLVCR |= ((initStruct->SlvRxEndIEn  ? 0 : 1) << I2C_SLVCR_IM_RXEND_Pos)  |
93                        ((initStruct->SlvTxEndIEn  ? 0 : 1) << I2C_SLVCR_IM_TXEND_Pos)  |
94                        ((initStruct->SlvSTADetIEn ? 0 : 1) << I2C_SLVCR_IM_STADET_Pos) |
95                        ((initStruct->SlvSTODetIEn ? 0 : 1) << I2C_SLVCR_IM_STODET_Pos) |
96                        ((initStruct->SlvRdReqIEn  ? 0 : 1) << I2C_SLVCR_IM_RDREQ_Pos)  |
97                        ((initStruct->SlvWrReqIEn  ? 0 : 1) << I2C_SLVCR_IM_WRREQ_Pos);
98 
99         switch((uint32_t)I2Cx)
100         {
101         case ((uint32_t)I2C0):
102             if(initStruct->SlvRxEndIEn | initStruct->SlvTxEndIEn | initStruct->SlvSTADetIEn |
103                initStruct->SlvSTODetIEn | initStruct->SlvRdReqIEn | initStruct->SlvWrReqIEn)
104             {
105                 NVIC_EnableIRQ(I2C0_IRQn);
106             }
107             else
108             {
109                 NVIC_DisableIRQ(I2C0_IRQn);
110             }
111             break;
112 
113         case ((uint32_t)I2C1):
114             if(initStruct->SlvRxEndIEn | initStruct->SlvTxEndIEn | initStruct->SlvSTADetIEn |
115                initStruct->SlvSTODetIEn | initStruct->SlvRdReqIEn | initStruct->SlvWrReqIEn)
116             {
117                 NVIC_EnableIRQ(I2C1_IRQn);
118             }
119             else
120             {
121                 NVIC_DisableIRQ(I2C1_IRQn);
122             }
123             break;
124         }
125     }
126 }
127 
128 /******************************************************************************************************************************************
129 * 函数名称: I2C_Open()
130 * 功能说明: I2C打开,允许收发
131 * 输    入: I2C_TypeDef * I2Cx        指定要被设置的I2C,有效值包括I2C0、I2C1
132 * 输    出: 无
133 * 注意事项: 无
134 ******************************************************************************************************************************************/
I2C_Open(I2C_TypeDef * I2Cx)135 void I2C_Open(I2C_TypeDef * I2Cx)
136 {
137     I2Cx->CTRL |= (0x01 << I2C_CTRL_EN_Pos);
138 }
139 
140 /******************************************************************************************************************************************
141 * 函数名称: I2C_Close()
142 * 功能说明: I2C关闭,禁止收发
143 * 输    入: I2C_TypeDef * I2Cx        指定要被设置的I2C,有效值包括I2C0、I2C1
144 * 输    出: 无
145 * 注意事项: 无
146 ******************************************************************************************************************************************/
I2C_Close(I2C_TypeDef * I2Cx)147 void I2C_Close(I2C_TypeDef * I2Cx)
148 {
149     I2Cx->CTRL &= ~I2C_CTRL_EN_Msk;
150 }
151 
152 /******************************************************************************************************************************************
153 * 函数名称: I2C_Start()
154 * 功能说明: 产生起始信号并发送设备地址
155 * 输    入: I2C_TypeDef * I2Cx        指定要被设置的I2C,有效值包括I2C0、I2C1
156 *           uint8_t addr            设备地址
157 * 输    出: uint8_t                   1 接收到ACK   0 接收到NACK
158 * 注意事项: 无
159 ******************************************************************************************************************************************/
I2C_Start(I2C_TypeDef * I2Cx,uint8_t addr)160 uint8_t I2C_Start(I2C_TypeDef * I2Cx, uint8_t addr)
161 {
162     I2Cx->MSTDAT = addr;
163     I2Cx->MSTCMD = (1 << I2C_MSTCMD_STA_Pos) |
164                    (1 << I2C_MSTCMD_WR_Pos);                //发送起始位和从机地址
165     while(I2Cx->MSTCMD & I2C_MSTCMD_TIP_Msk) __NOP();       //等待发送完成
166 
167     return (I2Cx->MSTCMD & I2C_MSTCMD_RXACK_Msk) ? 0 : 1;
168 }
169 
170 /******************************************************************************************************************************************
171 * 函数名称: I2C_Stop()
172 * 功能说明: 产生停止信号
173 * 输    入: I2C_TypeDef * I2Cx        指定要被设置的I2C,有效值包括I2C0、I2C1
174 * 输    出: 无
175 * 注意事项: 无
176 ******************************************************************************************************************************************/
I2C_Stop(I2C_TypeDef * I2Cx)177 void I2C_Stop(I2C_TypeDef * I2Cx)
178 {
179     I2Cx->MSTCMD = (1 << I2C_MSTCMD_STO_Pos);
180     while(I2Cx->MSTCMD & I2C_MSTCMD_TIP_Msk) __NOP();       //等待发送完成
181 }
182 
183 /******************************************************************************************************************************************
184 * 函数名称: I2C_Write()
185 * 功能说明: 写入一个数据
186 * 输    入: I2C_TypeDef * I2Cx        指定要被设置的I2C,有效值包括I2C0、I2C1
187 *           uint8_t data            要写的数据
188 * 输    出: uint8_t                   1 接收到ACK   0 接收到NACK
189 * 注意事项: 无
190 ******************************************************************************************************************************************/
I2C_Write(I2C_TypeDef * I2Cx,uint8_t data)191 uint8_t I2C_Write(I2C_TypeDef * I2Cx, uint8_t data)
192 {
193     I2Cx->MSTDAT = data;
194     I2Cx->MSTCMD = (1 << I2C_MSTCMD_WR_Pos);
195     while(I2Cx->MSTCMD & I2C_MSTCMD_TIP_Msk) __NOP();       //等待发送完成
196 
197     return (I2Cx->MSTCMD & I2C_MSTCMD_RXACK_Msk) ? 0 : 1;
198 }
199 
200 /******************************************************************************************************************************************
201 * 函数名称: I2C_Read()
202 * 功能说明: 读取一个数据
203 * 输    入: I2C_TypeDef * I2Cx        指定要被设置的I2C,有效值包括I2C0、I2C1
204 *           uint8_t ack             1 发送ACK   0 发送NACK
205 * 输    出: uint8_t                   读取到的数据
206 * 注意事项: 无
207 ******************************************************************************************************************************************/
I2C_Read(I2C_TypeDef * I2Cx,uint8_t ack)208 uint8_t I2C_Read(I2C_TypeDef * I2Cx, uint8_t ack)
209 {
210     I2Cx->MSTCMD = (1 << I2C_MSTCMD_RD_Pos) |
211                    ((ack ? 0 : 1) << I2C_MSTCMD_ACK_Pos);
212     while(I2Cx->MSTCMD & I2C_MSTCMD_TIP_Msk) __NOP();       //等待接收完成
213 
214     return I2Cx->MSTDAT;
215 }
216