http://www.ethernut.de/nutwiki/index.php?title=I2C_Bus_API&feed=atom&action=historyI2C Bus API - Revision history2024-03-29T07:51:59ZRevision history for this page on the wikiMediaWiki 1.26.2http://www.ethernut.de/nutwiki/index.php?title=I2C_Bus_API&diff=124&oldid=prevHarald: 1 revision imported2016-10-27T16:02:56Z<p>1 revision imported</p>
<table class='diff diff-contentalign-left'>
<tr style='vertical-align: top;' lang='en'>
<td colspan='1' style="background-color: white; color:black; text-align: center;">← Older revision</td>
<td colspan='1' style="background-color: white; color:black; text-align: center;">Revision as of 16:02, 27 October 2016</td>
</tr><tr><td colspan='2' style='text-align: center;' lang='en'><div class="mw-diff-empty">(No difference)</div>
</td></tr></table>Haraldhttp://www.ethernut.de/nutwiki/index.php?title=I2C_Bus_API&diff=123&oldid=prevHarald: Slave Configuration2012-12-03T19:07:46Z<p>Slave Configuration</p>
<p><b>New page</b></p><div>== Introduction ==<br />
<br />
Starting with Nut/OS 5.0.6 a new API has been implemented for I2C support. The problem with the [[Legacy I2C API|previous API]] was, that only one type of I2C interface could be used by an application. For example, there was no chance to mix bit banging drivers with I2C hardware based drivers in a single application.<br />
<br />
The new API presented here is not very well tested and at the time of this writing it has been implemented for the AT91 only and tested on Ethernut 5 only. And, there's only one device driver available, which makes use of this API and supports the PCF8563 RTC chip.<br />
<br />
== Application Usage ==<br />
<br />
=== I2C Device Registration ===<br />
<br />
As usual, an application that wants to make use of a specific device driver needs to register it first. The following call is used for I2C slave devices:<br />
<br />
NutRegisterI2cSlave(&lt;slave_driver&gt;, &lt;bus_driver&gt;);<br />
<br />
Beside doing all the required interface initialization, this call attaches the given slave to the specified bus.<br />
<br />
Right now only one slave and one bus driver is available. The bus driver is referenced by the structure variable ''i2cBus0At91''.<br />
<br />
The slave driver is a bit more complicated, because it is typically embedded into another device, in our case in the RTC (realtime clock) driver used to keep track of the current [[Time and Date|date and time]]. This RTC driver is referenced by the structure variable ''rtcI2cPcf85xx'', which contains a reference to the I2C slave driver in the ''dcb'' member of this structure. Thus, the call to register the slave driver and attach it to a given bus is<br />
<br />
NutRegisterI2cSlave(rtcI2cPcf85xx.dcb, &i2cBus0At91);<br />
<br />
Note, that this call registers the I2C part only. It is still required to register the RTC driver itself, so Nut/OS knows where to get the current date and time information from. This is done by calling<br />
<br />
NutRegisterRtc(&rtcI2cPcf85xx);<br />
<br />
This is the same call that is used by older drivers using the legacy I2C API.<br />
<br />
=== I2C Bus Probing ===<br />
<br />
This is a new feature, which hadn't been available in the legacy API. The related API call is<br />
<br />
NutI2cBusScan(&lt;bus_driver&gt;, &lt;start_sla&gt;, &lt;end_sla&gt;);<br />
<br />
It scans the bus for a given range of slave addresses and, if a device is found, returns the discovered address. If none was found, it returns I2C_SLA_NONE instead.<br />
<br />
The following routine can be used to scan the entire bus.<br />
<br />
<source lang="c"><br />
void ScanBus(NUTI2C_BUS *bus)<br />
{<br />
int sla = 0;<br />
<br />
puts("Scanning I2C bus");<br />
for (;;) {<br />
sla = NutI2cBusScan(bus, sla, 127);<br />
if (sla == I2C_SLA_NONE) {<br />
break;<br />
}<br />
printf("%3d (0x%02x) detected\n", sla, sla);<br />
sla++;<br />
}<br />
}<br />
</source><br />
<br />
To scan the first I2C bus connected to an AT91 CPU, you could call<br />
<br />
ScanBus(&i2cBus0At91);<br />
<br />
=== Bus Configuration ===<br />
<br />
There are currently two configurable items, bus clock rate and bus access timeout.<br />
<br />
While the first is set with<br />
<br />
NutI2cBusRate(&lt;bus_driver&gt;, &lt;frequency&gt;);<br />
<br />
the latter is set with<br />
<br />
NutI2cBusTimeout(&lt;bus_driver&gt;, &lt;milliseconds&gt;);<br />
<br />
Setting the bus clock rate is quite obvious, the clock frequency is specified in Hertz. By default the rate is set to 100kHz, which is specified in the original I2C specification and should work with the majority of I2C chips. When passing a frequency of zero, then the clock is reset to the mentioned default.<br />
<br />
To set the rate to 400kHz, call<br />
<br />
NutI2cBusRate(&i2cBus0At91, 400000);<br />
<br />
The bus driver may be used concurrently by any number of threads, but of course only one thread can access the bus at a time. The timeout is used when a thread tries to access the bus, which is currently in use by another thread. If access isn't granted within the specified number of milliseconds, then the related function will return an error.<br />
<br />
NutI2cBusTimeout(&i2cBus0At91, 1);<br />
<br />
sets the timeout to one millisecond, which is the minimum. As you may already know, the value of zero is used by Nut/OS to disable timeout monitoring.<br />
<br />
Both function return the previously set value. If you simply want to query the current setting, you can pass a special value, ''I2C_CURRENT_RATE'' for the clock and ''I2C_CURRENT_TIMEOUT'' as the timeout value.<br />
<br />
For example, the following code fragment will set the rate to 400kHz and then print out the currently set value.<br />
<br />
<source lang="c"><br />
if (NutI2cBusRate(&i2cBus0At91, 400000) == I2C_CURRENT_RATE) {<br />
puts("Error");<br />
}<br />
printf("%ld bps\n", NutI2cBusRate(&i2cBus0At91, I2C_CURRENT_RATE));<br />
</source><br />
<br />
Also note, that NutI2cBusRate() returns ''I2C_CURRENT_RATE'' instead of the previously set value if the requested clock rate is beyond the capabilities of the hardware. In this case the clock rate will not change. In contrast, NutI2cBusTimeout() will accept all values and therefore always return the previously set timeout.<br />
<br />
=== Slave Configuration ===<br />
<br />
Two configurable items are related to a single I2C slave, the slave address and the response timeout.<br />
<br />
Usually there is no need to change the slave address, but some chips do have a configurable address, which may differ from the default address that is hard coded in the driver.<br />
<br />
NutI2cSlaveAddress(&lt;slave_driver&gt;, &lt;slave_address&gt;);<br />
<br />
To avoid any confusion, this will set the address in the driver, used to access the hardware chip. While the chips actual address is typically set via specific pins, possibly connected to jumpers.<br />
<br />
The second item, the response timeout can be changed by calling<br />
<br />
NutI2cSlaveTimeout(&lt;slave_driver&gt;, &lt;milliseconds&gt;);<br />
<br />
If the chip will not respond within the given time, the related function will return an error.</div>Harald