0:09
hello and welcome to controllers Tech
0:12
this is the fifth tutorial in the AVR
0:15
series using the explained mini
0:16
development board from microchip and
0:19
today we will start working with i2c the
0:23
circuit the i2c is a very popular
0:26
communication standard developed by
0:28
Phillips and it is used by many devices
0:31
to transfer the data using only two
0:34
wires we will understand the
0:36
communication protocol in a while let's
0:38
see the data sheet of the at tin 817
0:42
controller first it supports the 2y
0:45
communication interface and fully
0:47
compatible with the Philips i2c
0:50
interface it supports the standard mode
0:53
the fast mode and the fast mode plus it
0:57
can operate as a host or client
1:00
ently it has the hardware support for
1:03
the client address match and can
1:05
recognize a 7-bit host
1:07
address the two lines are needed for
1:09
communication using the i2c S is the
1:13
clock line and SDA is the data
1:16
line here you can see the communication
1:20
protocol a start condition is generated
1:22
on the bus when the data line is pulled
1:25
low while the clock is still high
1:28
similarly a stop condition is generated
1:31
when the data like is pulled High while
1:33
the clock is high our entire frame is
1:36
transferred between these start and stop
1:40
conditions after generating the start we
1:43
send the seven bit slave address
1:45
followed by the read or right bit this
1:48
bit must be zero if the master wants to
1:50
perform the right and it should be one
1:52
if the master wants to perform the read
1:55
operation if the address matches with
1:57
the address of any of the devices on the
1:59
B bu the respective device sends an
2:02
acknowledgement signal on receiving the
2:05
acknowledgement the master starts
2:07
transmitting data after receiving each
2:10
data bite the slave sends an
2:13
acknowledgement signal after all the
2:16
data bytes have been transmitted the
2:18
master sends a stop condition in the
2:21
first few tutorials we will be using the
2:24
MCU in the master mode or the host mode
2:28
here you can see the steps for the host
2:32
initialization basically we need to set
2:34
the board rate for the clock frequency
2:36
and then enable the twi host in the
2:40
register we will see it in the
2:43
registers here we have the formula to
2:46
calculate the value for the board
2:48
register there are different formulas
2:51
available but we will use this one let's
2:54
check the pin out to see the available
2:57
pins here you can see the PIN pa1 is the
3:00
data pin and pa2 is the clock pin for
3:04
i2c we will use these pins to connect to
3:09
device now before we proceed any further
3:12
with the date sheet let's start the IDE
3:16
project I have switched to MPL labx ID
3:20
as it is supported in Macos but I will
3:22
keep uploading the microchip Studio
3:26
website the process might be different
3:30
but the code Remains the Same I have
3:33
connected the development board to the
3:35
computer let's create a new project now
3:39
the device is at tiny 817 and the board
3:42
has a built-in debugger tool let's
3:45
choose the AVR compiler and click next
3:49
give the name to the project and click
3:54
finish we need to manually add the main
3:56
file to the project so right click on
3:59
the source files and add the main
4:05
file here is the project from the
4:08
previous video we will copy the clock
4:11
initialization section from
4:17
it let's paste it in our main file and
4:21
call the clock initialization in the Min
4:28
function we will create separate Library
4:31
files for the i2c so that we can use it
4:33
for other projects as well let's start
4:36
with a new source file and call it i2c
4:39
master. C here we will first include the
4:43
Avo header file so that it has access to
4:46
all the registers now write a function
4:51
i2c let's check the registers in the
4:56
sheet we will leave the control a
4:58
register to its default state so the SD
5:01
setup time is for clock Cycles there is
5:04
no SD hold time and the interface is
5:07
operating in standard mode or the fast
5:09
mode the debug control register is also
5:13
unmodified so the interface will also
5:15
halt when we halt the
5:17
debugger the host control a register is
5:20
generally used to enable different
5:22
interrupts for read write
5:25
Etc we are not working with interrupts
5:28
for now so let leave them
5:30
disabled the inactive bus timeout is
5:34
disabled the smart mode can be used to
5:37
send the auto acknowledgement to the
5:39
slave after reading the data
5:42
register we will keep it disabled also
5:45
and manually send the aoac
5:48
responses the Bit Zero of this register
5:50
enables the interface so we will only
5:53
write a one to this bit so let's write
5:56
the value one to the host control
6:00
next is the host control register B the
6:04
flush bit clears the internal state of
6:06
the bus and changes its state to idle we
6:10
disabled the acknowledge action bit
6:12
decides whether the master will send an
6:14
act response or an neck
6:16
response when the smart mode is enabled
6:20
whether to send an act response or an
6:21
neck response is decided by this
6:24
acknowledge action bit since we are not
6:27
using Smart Mode we need to send the
6:30
response manually using the command
6:32
bits while I was testing the project the
6:35
bus wasn't running when the i2c was
6:38
initialized with this bit kept to zero
6:41
so let's enable this bit for now and we
6:44
will modify it before reading some data
6:47
slave next are the command
6:50
bits these bits decide the response of
6:54
host the host can issue a repeated start
6:57
condition or an acknowledge injection
6:59
after reading the data from the slave or
7:02
the stop condition we will control it in
7:05
between the writing and reading
7:06
operation so let's keep it at zero for
7:09
now so we only need to set bit two in
7:12
the host control register b instead of
7:15
writing the numbers I am going to write
7:18
the name of the bits so it will be
7:20
easier for you to understand it we need
7:23
to write a one to the bit two of the
7:24
control register B which is equivalent
7:27
to setting a neck response to the
7:34
bit next is the status register which
7:37
will play an important role throughout
7:41
project the read interrupt flag is set
7:44
whenever the host finishes reading a
7:45
bite from the data register the right
7:48
interrupt flag is set whenever the host
7:51
finishes transmitting an address or a
7:53
data bite the received acknowledge bit
7:56
holds the most recent acknowledgement
7:58
status from the slave so it helps us
8:01
decide whether the slave sent an A or
8:04
response other bits are dedicated to
8:06
different errors which arise during the
8:09
transaction the first two bits hold the
8:16
bus next is the board
8:19
register the value in this register will
8:22
decide the frequency of the i2c
8:24
clock as I mentioned in the beginning we
8:27
will use this formula to calculate the
8:31
register the peripheral clock is at 5
8:34
mahz and we will keep the i2c clock
8:39
khz the value of TR can be found in the
8:42
electrical characteristics of the
8:48
controller here you can see for the
8:50
clock frequency up to 100 khz the value
8:56
nond let's set all the values in the
9:00
formula now the value for the board
9:03
register comes around
9:06
17.5 I will set it to 18 as we can't set
9:10
the decimal value in a 8bit
9:12
register the next register is for the
9:15
address and then we have the data
9:18
register that is all the registers we
9:22
host now one last thing we need to do is
9:25
set the pins in the i2c mode this can be
9:29
achieved in the port multiplexer
9:32
register here the controlb register can
9:35
be used to set the respective pins in
9:39
interface to do so we will write a one
9:42
to the fourth bit of this
9:46
register all right that completes our
9:51
initialization now let's write another
9:53
function to send the data via the
9:56
i2c the parameters of this function will
9:58
be the S bit slave address the pointer
10:02
to the data to be sent and the size of
10:04
the data let's take a look at how the
10:07
communication protocol actually
10:11
looks the master sends a start condition
10:15
followed by the slave
10:17
address the slave address consists of
10:19
the seven bit address plus the read or
10:21
write bit which decides whether the
10:24
master wants to perform a read or write
10:26
operation writing a one to this position
10:28
means means the master wants to read the
10:30
data and writing a zero means the master
10:33
wants to write the data after receiving
10:36
the address the slave sends an
10:38
acknowledgement signal and then the
10:40
master starts transmitting data bytes
10:44
after each datab byy the slave sends an
10:46
acknowledgement signal and once all the
10:49
data has been transferred the master
10:51
sends the stock condition the at tiny do
10:55
not have the means to control the start
10:58
separately when we send the address the
11:00
start bit is generated
11:03
automatically so we will first Define a
11:05
new 8bit address which is made by
11:08
Shifting the seven bit address to the
11:10
left and then adding a zero to the least
11:12
significant position this indicates that
11:15
the master wants to write the data now
11:19
load the right address to the address
11:21
register and wait for the right
11:23
interrupt flag to set the setting of
11:26
this flag indicates that the address
11:28
transmission has has been
11:29
finished now the slave will send an
11:32
acknowledgement after receiving the
11:37
address the fourth bit of the status
11:40
register will be zero if the slave has
11:42
sent an act response and it will be set
11:45
to one if there was an act response from
11:47
slave so we will only proceed if there
11:50
was an acknowledgement from the
11:52
slave here we will check if the RX
11:55
acknowledge bit in the status register
11:57
is reset or not not if it is the master
12:01
will start transmitting the data let's
12:05
define an index variable which will keep
12:07
track of how many bytes have been
12:09
sent now we will only write the data if
12:12
the slave acknowledges the received data
12:15
and if the value of the index variable
12:17
is less than the data
12:19
size to transmit the data we will copy
12:22
the data to the data register and
12:26
variable then wait for the writer
12:28
interrupt flag to set which indicates
12:31
that the data has been
12:33
transmitted this Loop will run till all
12:35
the data bytes have been
12:38
transmitted if the slave does not
12:40
acknowledge the address we need to stop
12:43
transaction to do so the master will
12:46
send a stop condition by modifying the
12:48
command bits in the control register
12:55
B let's change the function type so that
12:58
we can return different errors in case
13:00
there is some issue while
13:02
transmitting when all the data bytes
13:05
have been transferred the value of the
13:07
index variable will be equal to the size
13:10
parameter and when this happens the
13:13
master will again send the stop
13:15
condition and return
13:17
success this is enough for writing the
13:19
data let's build the code once to check
13:30
all right let's include the i2c master
13:33
header file this file is not present in
13:36
the project so we will create it
13:45
now here we will just Define those two
13:48
functions so that we can call them in
14:00
we will not be using any slave device
14:03
today we will simply check if the master
14:06
is able to transmit the data or not so
14:10
let's comment out the parts where the
14:11
master waits for the acknowledgement
14:26
device now the master will send the data
14:29
irrespective of whether the slave is
14:31
ready to accept it or not basically the
14:34
master will send the address and wait
14:36
for the address to be transmitted then
14:38
it will send the data and wait for each
14:41
data bite to transmit once all the bytes
14:44
have been transferred it will send the
14:47
stop condition the pins pa1 and pa2 are
14:53
pins I have Simply Connected a logic
14:56
analyzer to these pins and we will see
14:58
the i2c frame in the logic software in
15:02
the main function include the i2c master
15:05
header file so that we can call the i2c
15:08
functions now in the main function call
15:11
the i2c initialization and give some
15:13
delay so that the bus initializes
15:16
completely let's define an array that we
15:19
need to transmit via the
15:21
i2c now in the while loop we will call
15:24
the i2c right function let's give a
15:27
random device address 15 hex the data is
15:30
defined above and the size is 11 bytes
15:34
this function will be called everyone
15:39
second all right the code builds fine so
15:43
let's test it let me start the logic
15:46
software so that we could see the i2c
15:54
it the data line is connected to channel
15:57
one and the clock is connected to
15:59
Channel Zero let's Flash the code to the
16:25
board here you can see the transmission
16:28
is happening every 1
16:30
second let's check the frame at first we
16:34
have the start bit The Green Dot it is
16:38
followed by the slave address 15 hex
16:40
with the right request there is a knack
16:43
response as there is no slave connected
16:45
on the bus to acknowledge it even after
16:49
receiving The Knack response the master
16:51
continues to transmit the data you can
16:54
see each bite of the data is followed by
16:56
the Knack response after the master
16:59
sends the entire data hello world it
17:02
sends a stop condition the orange dot so
17:06
the i2c code works and we were able to
17:08
transmit the data as the i2c master in
17:12
the next tutorial we will connect an
17:14
actual slave device and send the data to
17:16
it then we will write the function to
17:19
receive data as the master and try to
17:21
read data from some sensor or memory
17:24
device this is it for the video I hope
17:28
you understood how to initialize the i2c
17:31
and write the function to send data to
17:33
the slave you can download the code from
17:36
the link in the description leave
17:38
comments in case of any doubt keep
17:41
watching and have a nice day ahead