-
Notifications
You must be signed in to change notification settings - Fork 0
/
softI2c.c
541 lines (472 loc) · 14.1 KB
/
softI2c.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
/*
* @Author: chilkings
* @Date: 2022-01-25 11:28:31
* @LastEditTime: 2022-01-26 22:38:55
* @Description: 模拟IIC源文件
* @mail:[email protected]
*/
#include "softI2c.h"
#include "delay.h"
/*定义用于初始化IO口的结构体*/
//GPIO_InitTypeDef SDAPinInit = {0}; //SDA OUT
//GPIO_InitTypeDef SCLPinInit = {0}; //SCL OUT
//GPIO_InitTypeDef SDAPinInput = {0}; //SDA IN
/**
* @description: 模拟IIC IO口初始化
* @param {SFIIC_HandleTypeDef*} *hsfi2c 储存IIC IO口结构体的指针
* @return None
* @note 建议在cubemx中直接配置好IO口为推挽输出,拉高
*/
void softI2cInit(SFIIC_HandleTypeDef *hsfi2c)
{
GPIO_TypeDef *SDA = hsfi2c->SDAPort;
uint32_t SDAP = hsfi2c->SDAPin;
GPIO_TypeDef *SCL = hsfi2c->SCLPort;
uint32_t SCLP = hsfi2c->SCLPin;
hsfi2c->Master_Receive = SFIIC_Master_Receive;
hsfi2c->Master_Transmit = SFIIC_Master_Transmit;
hsfi2c->Mem_Read = SFIIC_Mem_Read;
hsfi2c->Mem_Write = SFIIC_Mem_Write;
if (SDA == GPIOA || SCL == GPIOA)
__HAL_RCC_GPIOA_CLK_ENABLE();
else if (SDA == GPIOB || SCL == GPIOB)
__HAL_RCC_GPIOB_CLK_ENABLE();
else if (SDA == GPIOC || SCL == GPIOC)
__HAL_RCC_GPIOC_CLK_ENABLE();
else if (SDA == GPIOD || SCL == GPIOD)
__HAL_RCC_GPIOD_CLK_ENABLE();
else if (SDA == GPIOE || SCL == GPIOE)
__HAL_RCC_GPIOE_CLK_ENABLE();
// HAL_GPIO_WritePin(SDA, SDAP, GPIO_PIN_RESET);
// HAL_GPIO_WritePin(SCL, SCLP, GPIO_PIN_RESET);
hsfi2c->SDAPinInit.Pin = SDAP;
hsfi2c->SDAPinInit.Mode = GPIO_MODE_OUTPUT_PP;
hsfi2c->SDAPinInit.Pull = GPIO_NOPULL;
hsfi2c->SDAPinInit.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(SDA, &(hsfi2c->SDAPinInit));
HAL_GPIO_WritePin(SDA, SDAP, GPIO_PIN_SET);
hsfi2c->SCLPinInit.Pin = SCLP;
hsfi2c->SCLPinInit.Mode = GPIO_MODE_OUTPUT_PP;
hsfi2c->SCLPinInit.Pull = GPIO_NOPULL;
hsfi2c->SCLPinInit.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(SCL, &(hsfi2c->SCLPinInit));
HAL_GPIO_WritePin(SCL, SCLP, GPIO_PIN_SET);
}
/**
* @description: 微妙级延时函数,可以自定义
*/
void softI2cDelay()
{
// for (int i = 0; i < delayCount; i++)
// ;
delay_us(1);
}
/**
* @description: 测试IO口工作是否正常
* @param {SFIIC_HandleTypeDef} *hsfi2c
* @return None
*/
void testOutput(SFIIC_HandleTypeDef *hsfi2c)
{
GPIO_TypeDef *SDA = hsfi2c->SDAPort;
uint32_t SDAP = hsfi2c->SDAPin;
GPIO_TypeDef *SCL = hsfi2c->SCLPort;
uint32_t SCLP = hsfi2c->SCLPin;
SCL->BSRR = SCLP;
SDA->BSRR = SDAP;
HAL_Delay(1000);
SDA->BSRR = (uint32_t)SDAP << 16U;
SCL->BSRR = (uint32_t)SCLP << 16U;
HAL_Delay(1000);
}
/**
* @description: 修改SDA IO口输入输出方向
* @param {SFIIC_HandleTypeDef} *hsfi2c
* @param {int} selection selection 0输入 1输出
* @return None
*/
void changeSDAState(SFIIC_HandleTypeDef *hsfi2c, int selection)
{
GPIO_TypeDef *SDA = hsfi2c->SDAPort;
uint32_t SDAP = hsfi2c->SDAPin;
GPIO_TypeDef *SCL = hsfi2c->SCLPort;
uint32_t SCLP = hsfi2c->SCLPin;
if (selection == 0)
{
hsfi2c->SDAPinInit.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(SDA, &(hsfi2c->SDAPinInit));
}
else if (selection == 1)
{
SCL->BSRR = (uint32_t)SCLP << 16U ;
hsfi2c->SDAPinInit.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(SDA, &(hsfi2c->SDAPinInit));
SDA->BSRR = (uint32_t)SDAP << 16U ;
SCL->BSRR = (uint32_t)SCLP << 16U ;
}
for(int i=0;i<5;i++)
{
softI2cDelay();
}
}
/**
* @description: 复位IIC
* @param None
* @return None
*/
void resetIO(SFIIC_HandleTypeDef *hsfi2c)
{
GPIO_TypeDef *SDA = hsfi2c->SDAPort;
uint32_t SDAP = hsfi2c->SDAPin;
GPIO_TypeDef *SCL = hsfi2c->SCLPort;
uint32_t SCLP = hsfi2c->SCLPin;
changeSDAState(hsfi2c, 1); //sda输出
SCL->BSRR = SCLP; //scl拉高
SDA->BSRR = SDAP; //sda拉高
}
/**
* @description: 产生启动信号
* @param {SFIIC_HandleTypeDef} *hsfi2c
* @return {*}
*/
void startCondition(SFIIC_HandleTypeDef *hsfi2c)
{
GPIO_TypeDef *SDA = hsfi2c->SDAPort;
uint32_t SDAP = hsfi2c->SDAPin;
GPIO_TypeDef *SCL = hsfi2c->SCLPort;
uint32_t SCLP = hsfi2c->SCLPin;
SDA->BSRR = (uint32_t)SDAP << 16U ;
softI2cDelay();
SCL->BSRR = (uint32_t)SCLP << 16U ;
}
/**
* @description: 产生停止信号
* @param {SFIIC_HandleTypeDef} *hsfi2c
* @return {*}
*/
void stopCondition(SFIIC_HandleTypeDef *hsfi2c)
{
GPIO_TypeDef *SDA = hsfi2c->SDAPort;
uint32_t SDAP = hsfi2c->SDAPin;
GPIO_TypeDef *SCL = hsfi2c->SCLPort;
uint32_t SCLP = hsfi2c->SCLPin;
changeSDAState(hsfi2c, 1);
SCL->BSRR = SCLP; //拉高scl
softI2cDelay();
SDA->BSRR = SDAP; //拉高sda
softI2cDelay();
}
/**
* @description: 发送ack信号
* @param {SFIIC_HandleTypeDef} *hsfi2c
* @param {int} select 1发送ack 0发送nack
* @return {*}
*/
void sendACK(SFIIC_HandleTypeDef *hsfi2c, int select)
{
GPIO_TypeDef *SDA = hsfi2c->SDAPort;
uint32_t SDAP = hsfi2c->SDAPin;
GPIO_TypeDef *SCL = hsfi2c->SCLPort;
uint32_t SCLP = hsfi2c->SCLPin;
changeSDAState(hsfi2c, 1);
if (select == 1)
SDA->BSRR = (uint32_t)SDAP << 16U;
else
SDA->BSRR = SDAP;
softI2cDelay();
SCL->BSRR = SCLP;
softI2cDelay();
SCL->BSRR = (uint32_t)SCLP << 16U;
}
/**
* @description: 重复启动信号
* @param {SFIIC_HandleTypeDef} *hsfi2c
* @return {*}
*/
void repeatedStartCondition(SFIIC_HandleTypeDef *hsfi2c)
{
GPIO_TypeDef *SDA = hsfi2c->SDAPort;
uint32_t SDAP = hsfi2c->SDAPin;
GPIO_TypeDef *SCL = hsfi2c->SCLPort;
uint32_t SCLP = hsfi2c->SCLPin;
changeSDAState(hsfi2c, 1);
SDA->BSRR = SDAP;
softI2cDelay();
SCL->BSRR = SCLP;
softI2cDelay();
SDA->BSRR = (uint32_t)SDAP << 16U;
}
/**
* @description: 等待ACK信号
* @param {uint32_t} timeOut 超时时间
* @return {*}
*/
SFIIC_StatusTypeDef waitACK(SFIIC_HandleTypeDef *hsfi2c, uint32_t timeOut)
{
GPIO_TypeDef *SDA = hsfi2c->SDAPort;
uint32_t SDAP = hsfi2c->SDAPin;
GPIO_TypeDef *SCL = hsfi2c->SCLPort;
uint32_t SCLP = hsfi2c->SCLPin;
changeSDAState(hsfi2c, 0);
int ACK = 0;
SCL->BSRR = SCLP;
softI2cDelay();
if (!(HAL_GPIO_ReadPin(SDA, SDAP)))
{
ACK = 1;
changeSDAState(hsfi2c, 1);
}
SCL->BSRR = (uint32_t)SCLP << 16U;
changeSDAState(hsfi2c, 1);
return ACK == 1 ? SFIIC_OK : SFIIC_ERROR;
}
/**
* @description: 写入器件地址
* @param {SFIIC_HandleTypeDef} *hsfi2c
* @param {uint8_t} address
* @param {bool} selection 1写操作 0读操作
* @param {int32_t} timeOut
* @return {*}
*/
SFIIC_StatusTypeDef writeReadBitSet(SFIIC_HandleTypeDef *hsfi2c, uint8_t address, int selection, int32_t timeOut)
{
GPIO_TypeDef *SDA = hsfi2c->SDAPort;
uint32_t SDAP = hsfi2c->SDAPin;
GPIO_TypeDef *SCL = hsfi2c->SCLPort;
uint32_t SCLP = hsfi2c->SCLPin;
int successfullACK = 0;
int writeAddress = 0;
if (selection)
writeAddress = address & 0xFE; //读地址
else
writeAddress = address | 0x01; //写地址
startCondition(hsfi2c);
for (int i = 7; i >= 0; i--)
{
if ((writeAddress >> i) & 0x01)
SDA->BSRR = SDAP;
else
SDA->BSRR = (uint32_t)SDAP << 16U;
softI2cDelay();
SCL->BSRR = SCLP;
softI2cDelay();
SCL->BSRR = (uint32_t)SCLP << 16U;
}
if (waitACK(hsfi2c, timeOut) == SFIIC_OK)
successfullACK = 1;
if(selection == 1)
changeSDAState(hsfi2c,1);
return successfullACK == 1 ? SFIIC_OK : SFIIC_ERROR;
}
/**
* @description: 写入一个字节
* @param {SFIIC_HandleTypeDef} *hsfi2c
* @param {uint8_t} value 写入值
* @param {int32_t} timeOut
* @return {*}
*/
SFIIC_StatusTypeDef writeBytes(SFIIC_HandleTypeDef *hsfi2c, uint8_t value, int32_t timeOut)
{
GPIO_TypeDef *SDA = hsfi2c->SDAPort;
uint32_t SDAP = hsfi2c->SDAPin;
GPIO_TypeDef *SCL = hsfi2c->SCLPort;
uint32_t SCLP = hsfi2c->SCLPin;
int successfullACK = 0;
SCL->BSRR = (uint32_t)(SCLP << 16U);
for (int i = 7; i >= 0; i--)
{
if ((value >> i) & 0x01)
SDA->BSRR = SDAP;
else
SDA->BSRR = (uint32_t)(SDAP << 16U);
softI2cDelay();
SCL->BSRR = SCLP;
softI2cDelay();
SCL->BSRR = (uint32_t)(SCLP << 16U);
}
if (waitACK(hsfi2c, timeOut) == SFIIC_OK)
successfullACK = 1;
//changeSDAState(1);
return successfullACK == 1 ? SFIIC_OK : SFIIC_ERROR;
}
/**
* @description: 读入一个字节
* @param {SFIIC_HandleTypeDef} *hsfi2c
* @return {*} 返回读入的值
*/
uint8_t readBytes(SFIIC_HandleTypeDef *hsfi2c)
{
GPIO_TypeDef *SDA = hsfi2c->SDAPort;
uint32_t SDAP = hsfi2c->SDAPin;
GPIO_TypeDef *SCL = hsfi2c->SCLPort;
uint32_t SCLP = hsfi2c->SCLPin;
changeSDAState(hsfi2c, 0);
uint8_t data = 0;
uint8_t counter = 0;
while (1)
{
SCL->BSRR = SCLP;
softI2cDelay();
data |= HAL_GPIO_ReadPin(SDA, SDAP);
counter++;
SCL->BSRR = (uint32_t)SCLP << 16U;
softI2cDelay();
if (counter == 8)
return data;
data = data << 1;
}
}
/**
* @description: 向iic器件的寄存器写入数据
* @param {SFIIC_HandleTypeDef} *hsfi2c
* @param {uint16_t} DevAddress 器件地址
* @param {uint16_t} MemAddress 寄存器地址
* @param {uint16_t} MemAddSize 寄存器大小 1一个字节 2两个字节 TODO:实现两个字节
* @param {uint8_t} *pData 写入数据地址指针
* @param {uint16_t} Size 写入数据大小
* @param {uint32_t} Timeout 超时时间 TODO:待实现
* @return {*}
*/
SFIIC_StatusTypeDef SFIIC_Mem_Write(SFIIC_HandleTypeDef *hsfi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
if (!(writeReadBitSet(hsfi2c, DevAddress, 1, Timeout) == SFIIC_OK)) //写入器件地址
{
resetIO(hsfi2c);
return SFIIC_BUSY;
}
if (MemAddSize == 1) //写入寄存器地址 地址长度为8位
{
if (!(writeBytes(hsfi2c, MemAddress, Timeout) == SFIIC_OK)) //写入寄存器地址
{
resetIO(hsfi2c);
return SFIIC_ERROR;
}
}
else //写入寄存器地址 地址长度为16位 TODO:待实现
{
if (!(writeBytes(hsfi2c, MemAddress, Timeout) == SFIIC_OK)) //写入寄存器地址
{
resetIO(hsfi2c);
return SFIIC_ERROR;
}
}
for (int i = 0; i < Size; i++) //写入要发送的数据
{
if (!(writeBytes(hsfi2c, pData[i], Timeout) == SFIIC_OK))
{
resetIO(hsfi2c);
return SFIIC_ERROR;
}
}
stopCondition(hsfi2c); //发送停止信号
return SFIIC_OK;
}
/**
* @description: 向IIC器件寄存器读出数据
* @param {SFIIC_HandleTypeDef} *hsfi2c
* @param {uint16_t} DevAddress 器件地址
* @param {uint16_t} MemAddress 寄存器地址
* @param {uint16_t} MemAddSize 寄存器大小 1一个字节 2两个字节 TODO:实现两个字节
* @param {uint8_t} *pData 存放读出数据地址指针
* @param {uint16_t} Size 读出数据大小
* @param {uint32_t} Timeout 超时时间 TODO:待实现
* @return {*}
*/
SFIIC_StatusTypeDef SFIIC_Mem_Read(SFIIC_HandleTypeDef *hsfi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
if (!(writeReadBitSet(hsfi2c, DevAddress, 1, Timeout) == SFIIC_OK))
{
resetIO(hsfi2c);
return SFIIC_BUSY;
}
if (MemAddSize == 1) //写入寄存器地址 地址长度为8位
{
if (!(writeBytes(hsfi2c, MemAddress, Timeout) == SFIIC_OK)) //写入寄存器地址
{
resetIO(hsfi2c);
return SFIIC_ERROR;
}
}
else //写入寄存器地址 地址长度为16位 TODO:待实现
{
if (!(writeBytes(hsfi2c, MemAddress, Timeout) == SFIIC_OK)) //写入寄存器地址
{
resetIO(hsfi2c);
return SFIIC_ERROR;
}
}
repeatedStartCondition(hsfi2c);
if (!(writeReadBitSet(hsfi2c, DevAddress, 0, Timeout) == SFIIC_OK))
{
resetIO(hsfi2c);
return SFIIC_ERROR;
}
for (int i = 0; i < Size; i++)
{
pData[i] = readBytes(hsfi2c);
if (i != Size - 1)
{
sendACK(hsfi2c, 1);
changeSDAState(hsfi2c, 0);
}
}
sendACK(hsfi2c, 0);
stopCondition(hsfi2c);
return SFIIC_OK;
}
/**
* @description: 向IIC器件发送数据
* @param {SFIIC_HandleTypeDef} *hsfi2c
* @param {uint16_t} DevAddress 器件地址
* @param {uint8_t} *pData 发送数据指针
* @param {uint16_t} Size 发送数据大小
* @param {uint32_t} Timeout 超时时间 Todo:待实现
* @return {*}
*/
SFIIC_StatusTypeDef SFIIC_Master_Transmit(SFIIC_HandleTypeDef *hsfi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
if (!(writeReadBitSet(hsfi2c, DevAddress, 1, Timeout) == SFIIC_OK))
{
resetIO(hsfi2c);
return SFIIC_BUSY;
}
for (int i = 0; i < Size; i++) //写入要发送的数据
{
if (!(writeBytes(hsfi2c, pData[i], Timeout) == SFIIC_OK))
{
resetIO(hsfi2c);
return SFIIC_ERROR;
}
}
stopCondition(hsfi2c); //发送停止信号
return SFIIC_OK;
}
/**
* @description: 向IIC器件读入数据
* @param {SFIIC_HandleTypeDef} *hsfi2c
* @param {uint16_t} DevAddress 器件地址
* @param {uint8_t} *pData 存放读入数据指针
* @param {uint16_t} Size 读入数据大小
* @param {uint32_t} Timeout 超时时间 Todo:待实现
* @return {*}
*/
SFIIC_StatusTypeDef SFIIC_Master_Receive(SFIIC_HandleTypeDef *hsfi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
if (!(writeReadBitSet(hsfi2c, DevAddress, 0, Timeout) == SFIIC_OK))
{
resetIO(hsfi2c);
return SFIIC_BUSY;
}
for (int i = 0; i < Size; i++)
{
pData[i] = readBytes(hsfi2c);
if (i != Size - 1)
{
sendACK(hsfi2c, 1);
changeSDAState(hsfi2c, 0);
}
}
sendACK(hsfi2c, 0);
stopCondition(hsfi2c);
return SFIIC_OK;
}