0:20
everyone welcome to controllers tech
0:24
this is another video in the sdm 32
0:27
register based programming series
0:29
and today we will see how to receive
0:31
data from an i2c device
0:34
to keep the things more practical i am
0:36
going to use the mpu 6050 accelerometer
0:41
so i would need to write and read data
0:44
and hence both the i2c write and read
0:47
conditions will be used
0:50
i have already made a video on how to
0:54
and i would suggest you to go through
0:58
this is important because i will not
1:00
cover the i2c configuration today
1:02
and instead i am going to use all the
1:05
functions that are already covered in
1:08
let's start by creating the project in
1:12
first create your project folder
1:15
give the name to the project and click
1:24
i am using stm32f446re controller
1:29
i will fast forward through the initial
1:31
setup i guess you guys are already
1:34
familiar with this part
1:40
include our basic library files first
1:42
the clock configuration
1:44
and the delay header files
1:48
everything i am including here has
1:50
already been covered in the previous
1:52
videos check out the stm32 register
1:56
based playlist for the videos
2:03
now that all the files have been added
2:06
let's include them and write the main
2:30
like i said in the beginning i am going
2:32
to use the i2c functions from the
2:36
these functions include i2c
2:40
start i2c write send the address
2:43
to stop and to write the multiple bytes
3:02
i am going to copy all these functions
3:04
and this time i will create a new
3:06
library for i2c itself
3:09
to do that i am creating a source file
3:12
i2c.c and paste those functions here
3:35
here we also need to create a header
3:37
file where those functions can be
3:40
so that we can use them freely in other
3:44
i am going to name the header file as
3:54
here we only need to define the
3:56
functions so only copy the function's
4:10
it's not able to recognize the integer
4:19
our header file is ready now
4:25
we also need to include the device
4:27
header file in the i2c dot c
4:29
but i will just include a cc config.h
4:32
as it already have all other necessary
4:40
now include the i2c library that we just
4:43
created in our main file
4:55
in addition to all the functions that we
4:58
we need to create a new one to read the
5:06
i am calling it i2c read and it will
5:10
parameters and they are the address of
5:14
the buffer to store the data into and
5:16
the size of the data that you want to
5:25
before proceeding any further let's take
5:27
a look at the data sheet
5:36
here we have the transfer sequence for
5:47
here you can see in the receiver mode
5:50
after each byte is received
5:52
the acknowledgement bit is set and the
5:54
rxne bit also gets set
5:58
this rxne receive buffer not empty bit
6:01
basically indicates that there is some
6:03
data in the data register
6:05
and it gets cleared after we read that
6:09
receiving data using i2c in stm32 is
6:12
same as in any other microcontroller
6:14
but the things gets a little complicated
6:17
when we want to end the reception
6:19
i will try to keep it as simple as
6:24
let's start with this third point first
6:28
if we want to receive a single byte then
6:30
we must send the non-acknowledgement
6:32
before the address flag is cleared
6:34
and a stop must be sent after the ev6
6:39
this might be a bit complex to
6:42
so let's see the sequence diagram
6:45
when we want to receive data we send the
6:49
and then the address of the device and
6:51
then comes the ev6 event
6:54
which basically means that the address
6:56
flag is set and to clear the flag
6:58
we must make a read to status register 1
7:00
followed by status register 2.
7:05
as according to this line we must send a
7:08
non-acknowledgement before clearing the
7:11
and a stop after clearing the address
7:20
let's try to write the program using
7:27
i have summarized the steps here
7:30
for receiving one byte of data first
7:33
send the slave address and wait for the
7:37
then we will send the
7:38
non-acknowledgement bit clear the
7:41
and send the stop condition and then
7:44
wait for the rxne bit to indicate that
7:47
there is some data in the data register
7:51
and finally read that data
7:55
i am creating a variable to keep track
7:57
of the remaining bytes
8:06
here is the code for single byte
8:20
first send the address and wait for the
8:25
then clear the acknowledgement bit which
8:27
is bit 10 in control register 1.
8:30
then clear the address flag by
8:32
performing a read in status registers 1
8:36
and then send the stop condition
8:48
now wait for the rxne bit to set which
8:51
is bit 6 in status register 1
8:54
and finally save the data into the
8:59
this is how we receive a single byte
9:04
now let's see how to receive multiple
9:13
as you can see here in order to receive
9:17
we need to send a non-acknowledgement
9:19
after the second last byte of the data
9:29
which should be followed by a stop bit
9:43
so here is the big code for that
9:46
let's go through it here i have already
9:50
mentioned what steps are being followed
9:54
let's take a closer look at them
10:02
as usual first we are going to send the
10:05
and then wait for the address flag to
10:08
clear the address flag by reading the
10:12
and status register 2. now if the
10:15
remaining bytes are greater than 2
10:18
we will just perform the usual
10:23
that is wait for the rxne bit to set
10:26
save the data into the buffer and set
10:29
the acknowledgement bit to acknowledge
10:43
now we will receive the second last byte
10:47
but instead of setting the
10:48
acknowledgement bit we will clear it
10:55
this is according to the information
10:57
provided in the reference manual
11:01
and just after that set the stop bit to
11:08
and finally receive the last data byte
11:13
this is basically all for receiving the
11:16
data from any i2c device
11:19
i am going to do one little addition to
11:21
the i2c start function
11:29
i am enabling the acknowledgement bit
11:31
and to do so we need to write a one
11:33
in the tenth position of the control
11:46
as you can see here before reading the
11:49
data from the data register
11:51
we always check the rxne bit
11:58
this is bit 6 in the status register 1
12:01
and as mentioned here if this bit is set
12:03
it means the data register is not empty
12:07
so we basically wait for this bit to
12:10
read the data these are all the i2c
12:19
add this i2c receive in the header file
12:22
so that we can use it in our main file
12:25
like i said in the beginning i am using
12:28
mpu 6050 accelerometer
12:31
and in order to initialize the device we
12:34
need to write some data to the device
12:37
so let's create a function to write the
12:43
this function will take three parameters
12:46
and they are the address of the device
12:48
the register that you want to write the
12:49
data into and the data itself
12:53
writing the data into i2c device is
12:57
start the i2c send the address of the
13:03
send the register where you want to
13:07
send the data that you want to write
13:10
and finally stop the i2c
13:14
now let's create another function to
13:16
read the data from the device
13:18
this function will take four parameters
13:21
and they are the address of the device
13:23
the register where we want to read the
13:25
data from the buffer where you want to
13:28
and the size of the data to be received
13:31
in order to read the data from any i2c
13:35
we have to follow the same procedure
13:38
start the i2c send the address of the
13:43
send the address of the register where
13:45
we want to read the data from
13:48
start the i2c again this will trigger
13:51
the repeated start condition
13:53
and call the i2c read function
13:57
note here that we need to send the read
13:59
address which is just the regular
14:07
i have already covered how to interface
14:09
mpu 6050 accelerometer
14:12
and i am going to use the functions from
14:16
here are all the defines needed for this
14:27
this is the function to initialize the
14:30
and here instead of using the harley2c
14:33
i am using the mpu read to read the who
14:38
and then highlight 2c write are replaced
14:41
with mpu write functions
14:46
this is the function to read the
14:48
accelerometer data from the device
14:51
here also i am using mpu read to read
14:54
the six bytes of data from the x out
14:58
this data will be stored in the rx data
15:06
i have already covered these functions
15:08
before i will leave the link to the
15:10
video in the description
15:22
here we read the accelerations in
15:26
and then we convert them to g values
15:30
let's write the main function now
15:33
configure the system clocks first
15:36
i am initializing the timer so that i
15:41
and now call the i2c configuration
15:46
next we need to initialize the device
15:52
now in the while loop we will read the
15:57
and this process will keep going on
16:05
let's build the code now
16:13
seems like we have three warnings
16:17
remove this volatile keyword
16:20
one more warning left
16:34
so all the warnings are gone now
16:37
go to option my controller is running at
16:43
go to debug and select st link debugger
17:00
add the accelerations to the watch
17:16
let's run it now you can see the
17:19
accelerations on the right
17:37
as i change the orientation the values
17:40
are changing in the respective
17:41
axis this is a good proof that
17:44
everything is working
17:58
this is it for this video in the next
18:02
i will start with the basic interrupts
18:06
you can download the code from the link
18:10
you can support us by donating or by
18:12
joining the membership
18:15
the links are in the description of this
18:19
keep watching and have a nice day ahead