forked from romanjoe/stm32camera
-
Notifications
You must be signed in to change notification settings - Fork 0
/
i2c_routine.c
152 lines (132 loc) · 5.07 KB
/
i2c_routine.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
#include "stm32f4xx_i2c.h"
void delay_ms(uint32_t volatile delay_time_ms)
{
uint32_t delay_time = 0;
delay_time = (SystemCoreClock / 10000) * delay_time_ms;
for (; delay_time != 0; delay_time--);
}
/**
*
* @param I2Cx - I2C peripheral module number
* @param I2C_Addr - I2C SLAVE address in network
* @param addr - slave register address
* @param buf - pointer to receiver buffer
* @param num - number of bytes to receive
* @return buffer -
*
* @bug Function now works not actually write. input buffer, pointer on which must be used (*buf) do not used.
* Instead of this, function is used with *buf == 0, and returns 1 byte via uint8_t buffer
*
* Need to be optimized!!!!!
*/
uint8_t I2C_Read(I2C_TypeDef *I2Cx, uint8_t I2C_Addr, uint8_t addr, uint8_t *buf, uint16_t num)
{
uint8_t buffer;
if(num == 0)
return 1;
// check is the line is busy
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
// enable acknowledgement
I2C_AcknowledgeConfig(I2Cx, ENABLE);
// generate start condition
I2C_GenerateSTART(I2Cx, ENABLE);
// check if MASTER mode for STM32 is selected
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
// send SLAVE I2C address to SLAVE with TRANSMITION MODE SELECT bit
I2C_Send7bitAddress(I2Cx, I2C_Addr, I2C_Direction_Transmitter);
// check if TRANSMITTER MODE SELECTED for STM32
while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
// transmit SLAVE's register address to read byte
I2C_SendData(I2Cx, addr);
while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// check if the address byte transmitted - THIS IS THE END of TRANSMITION
// generate start event for receiving
I2C_GenerateSTART(I2Cx, ENABLE);
// check if MASTER mode for STM32 is selected
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
// send self address to slave with RECEPTION MODE SELECT bit
I2C_Send7bitAddress(I2Cx, I2C_Addr, I2C_Direction_Receiver);
// check if RECEIVER MODE SELECTED for STM32
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
while (num)
{ // while number of bytes to receive (num) != 0
if(num == 1)
{
// disable acknowledgement
I2C_AcknowledgeConfig(I2Cx, DISABLE);
// and generate end of communication
I2C_GenerateSTOP(I2Cx, ENABLE);
}
// check if the next byte is received
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); /* EV7 */
/* white to reception Buffer
* and increment the index of the buffer in case of
* multibytes reception operation
* decrement the read bytes counter
*/
buffer = I2C_ReceiveData(I2Cx);
// buf++; //
//
num--; //
}
I2C_AcknowledgeConfig(I2Cx, ENABLE); // enable acknowledge for next transmition session
return buffer; // return reception buffer
}
/**
* @brief Function implements transmission of one byte via I2C
*
* @param I2Cx - I2C peripheral module number
* @param I2C_Addr - I2C SLAVE address in network
* @param addr - slave register address
* @param value - byte to transmit
* @return 0
*/
uint8_t I2C_WriteOneByte(I2C_TypeDef *I2Cx, uint8_t I2C_Addr, uint8_t addr, uint8_t value)
{
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
// I2C_AcknowledgeConfig(I2Cx, ENABLE);
// generate start condition by master
I2C_GenerateSTART(I2Cx, ENABLE);
// check if MASTER MODE selected for STM32
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
// send SLAVE I2C address to SLAVE with TRANSMITION MODE SELECT bit
I2C_Send7bitAddress(I2Cx, I2C_Addr, I2C_Direction_Transmitter);
// check if TRANSMITTER MODE SELECTED for STM32
while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
// send register to write address in slave device
I2C_SendData(I2Cx, addr);
// check if register to write address transmitted
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// send dedicated byte to slave, addressed register
I2C_SendData(I2Cx, value);
// check if register to write address transmitted
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// generate STOP event
I2C_GenerateSTOP(I2Cx, ENABLE);
return 0;
}
/**
* @brief Function implements transmission of multiple bytes via I2C
*
* @param I2Cx - I2C peripheral module number
* @param I2C_Addr - I2C SLAVE address in network
* @param addr - slave register address
* @param buf - transmission buffer
* @param num - number of bytes to transmit
* @return 0
*/
uint8_t I2C_Write(I2C_TypeDef *I2Cx, uint8_t I2C_Addr, uint8_t addr, uint8_t *buf, uint16_t num)
{
uint8_t err = 0;
while(num--)
{
if(I2C_WriteOneByte(I2Cx, I2C_Addr, addr++, *buf++))
{
err++;
}
}
if(err)
return 1;
else
return 0;
}