-
Notifications
You must be signed in to change notification settings - Fork 0
/
i2c.c
147 lines (114 loc) · 3.7 KB
/
i2c.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
//
// COMP-GENG 421 - Tom Lupfer
//
// I2C module
//
#include "main.h"
#include "i2c.h"
#define I2C_DUTYCYCLE LL_I2C_DUTYCYCLE_2
#define I2C_REQUEST_READ 0x01
#define I2C_REQUEST_WRITE 0x00
#define I2C_SPEEDCLOCK 400000
void I2cInit(void)
{
LL_RCC_ClocksTypeDef RccClocks;
// Enable the GPIOB port clock
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB);
// Configure SCL Pin as alt fcn, high speed, open drain, pull-up
LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_8, LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetAFPin_8_15(GPIOB, LL_GPIO_PIN_8, LL_GPIO_AF_4);
LL_GPIO_SetPinSpeed(GPIOB, LL_GPIO_PIN_8, LL_GPIO_SPEED_FREQ_HIGH);
LL_GPIO_SetPinOutputType(GPIOB, LL_GPIO_PIN_8, LL_GPIO_OUTPUT_OPENDRAIN);
LL_GPIO_SetPinPull(GPIOB, LL_GPIO_PIN_8, LL_GPIO_PULL_UP);
// Configure SDA Pin as alt fcn, high speed, open drain, pull-up
LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_9, LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetAFPin_8_15(GPIOB, LL_GPIO_PIN_9, LL_GPIO_AF_4);
LL_GPIO_SetPinSpeed(GPIOB, LL_GPIO_PIN_9, LL_GPIO_SPEED_FREQ_HIGH);
LL_GPIO_SetPinOutputType(GPIOB, LL_GPIO_PIN_9, LL_GPIO_OUTPUT_OPENDRAIN);
LL_GPIO_SetPinPull(GPIOB, LL_GPIO_PIN_9, LL_GPIO_PULL_UP);
// Enable the clock for I2C1
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
// Configure SCL
LL_I2C_Disable(I2C1);
LL_RCC_GetSystemClocksFreq(&RccClocks);
LL_I2C_ConfigSpeed(I2C1, RccClocks.PCLK1_Frequency, I2C_SPEEDCLOCK, I2C_DUTYCYCLE);
LL_I2C_Enable(I2C1);
}
void I2cWrite(UInt8 DevAddr, UInt8 RegAddr, int NumBytes, UInt8 * DataBuf)
{
// Prepare acknowledge for master data reception
LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_ACK);
// Generate start condition
LL_I2C_GenerateStartCondition(I2C1);
// Wait for SB flag to be set
while(!LL_I2C_IsActiveFlag_SB(I2C1))
;
// Write device address for a write
LL_I2C_TransmitData8(I2C1, DevAddr | I2C_REQUEST_WRITE);
// Wait for ADDR flag to be set, then clear it
while(!LL_I2C_IsActiveFlag_ADDR(I2C1))
;
LL_I2C_ClearFlag_ADDR(I2C1);
// Write register address, wait for completion
LL_I2C_TransmitData8(I2C1, RegAddr);
while(!LL_I2C_IsActiveFlag_TXE(I2C1))
;
// Write data buffer
while(NumBytes > 0)
{
// Write data byte, wait for completion
LL_I2C_TransmitData8(I2C1, *DataBuf++);
while(!LL_I2C_IsActiveFlag_TXE(I2C1))
;
NumBytes--;
}
// Generate stop condition
LL_I2C_GenerateStopCondition(I2C1);
}
void I2cRead(UInt8 DevAddr, UInt8 RegAddr, int NumBytes, UInt8 * DataBuf)
{
// Prepare ACK for master to receive data
LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_ACK);
// Generate start condition
LL_I2C_GenerateStartCondition(I2C1);
// Wait for SB flag to be set
while(!LL_I2C_IsActiveFlag_SB(I2C1))
;
// Write device address for a write
LL_I2C_TransmitData8(I2C1, DevAddr | I2C_REQUEST_WRITE);
// Wait for ADDR flag to be set, then clear it
while(!LL_I2C_IsActiveFlag_ADDR(I2C1))
;
LL_I2C_ClearFlag_ADDR(I2C1);
// Write register address, wait for completion
LL_I2C_TransmitData8(I2C1, RegAddr);
while(!LL_I2C_IsActiveFlag_TXE(I2C1))
;
// Generate repeated start condition
LL_I2C_GenerateStartCondition(I2C1);
// Wait for SB flag to be set
while(!LL_I2C_IsActiveFlag_SB(I2C1))
;
// Write device address for a read
LL_I2C_TransmitData8(I2C1, DevAddr | I2C_REQUEST_READ);
// Wait for ADDR flag to be set, then clear it
while(!LL_I2C_IsActiveFlag_ADDR(I2C1))
;
LL_I2C_ClearFlag_ADDR(I2C1);
// Read data into buffer
while(NumBytes > 0)
{
if (NumBytes == 1)
{
// Prepare NACK for master to receive last data byte
LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_NACK);
}
// Wait for read data, then read
while(!LL_I2C_IsActiveFlag_RXNE(I2C1))
;
*DataBuf++ = LL_I2C_ReceiveData8(I2C1);
NumBytes--;
}
// Generate stop condition
LL_I2C_GenerateStopCondition(I2C1);
}