add i2c module

This commit is contained in:
devsaurus 2017-01-16 21:33:30 +01:00
parent 4fcb1404b6
commit 381726f103
9 changed files with 830 additions and 0 deletions

View File

@ -0,0 +1 @@
COMPONENT_ADD_INCLUDEDIRS:=include

View File

@ -0,0 +1,314 @@
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: i2c_sw_master.c
*
* Description: i2c master API
*
* Modification history:
* 2014/3/12, v1.0 create this file.
*******************************************************************************/
#include "driver/gpio.h"
#include "driver/i2c_sw_master.h"
static uint8_t m_nLastSDA;
static uint8_t m_nLastSCL;
static uint8_t pinSDA;
static uint8_t pinSCL;
/******************************************************************************
* FunctionName : i2c_sw_master_setDC
* Description : Internal used function -
* set i2c SDA and SCL bit value for half clk cycle
* Parameters : uint8_t SDA
* uint8_t SCL
* Returns : NONE
*******************************************************************************/
static void i2c_sw_master_setDC(uint8_t SDA, uint8_t SCL)
{
uint8_t sclLevel;
SDA &= 0x01;
SCL &= 0x01;
m_nLastSDA = SDA;
m_nLastSCL = SCL;
gpio_set_level(pinSDA, SDA);
gpio_set_level(pinSCL, SCL);
if(1 == SCL) {
do {
sclLevel = gpio_get_level(pinSCL);
} while(sclLevel == 0);
}
}
/******************************************************************************
* FunctionName : i2c_sw_master_getDC
* Description : Internal used function -
* get i2c SDA bit value
* Parameters : NONE
* Returns : uint8_t - SDA bit value
*******************************************************************************/
static uint8_t i2c_sw_master_getDC(void)
{
return gpio_get_level(pinSDA);
}
/******************************************************************************
* FunctionName : i2c_sw_master_init
* Description : initilize I2C bus to enable i2c operations
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void i2c_sw_master_init(void)
{
uint8_t i;
i2c_sw_master_setDC(1, 0);
i2c_sw_master_wait(5);
// when SCL = 0, toggle SDA to clear up
i2c_sw_master_setDC(0, 0);
i2c_sw_master_wait(5);
i2c_sw_master_setDC(1, 0);
i2c_sw_master_wait(5);
// set data_cnt to max value
for (i = 0; i < 28; i++) {
i2c_sw_master_setDC(1, 0);
i2c_sw_master_wait(5); // sda 1, scl 0
i2c_sw_master_setDC(1, 1);
i2c_sw_master_wait(5); // sda 1, scl 1
}
// reset all
i2c_sw_master_stop();
return;
}
uint8_t i2c_sw_master_get_pinSDA()
{
return pinSDA;
}
uint8_t i2c_sw_master_get_pinSCL()
{
return pinSCL;
}
/******************************************************************************
* FunctionName : i2c_sw_master_gpio_init
* Description : config SDA and SCL gpio to open-drain output mode,
* mux and gpio num defined in i2c_sw_master.h
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void i2c_sw_master_gpio_init(uint8 sda, uint8 scl)
{
pinSDA = sda;
pinSCL = scl;
gpio_config_t cfg;
cfg.pin_bit_mask = 1 << sda | 1 << scl;
cfg.mode = GPIO_MODE_INPUT_OUTPUT_OD;
cfg.pull_up_en = GPIO_PULLUP_ENABLE;
cfg.pull_down_en = GPIO_PULLDOWN_DISABLE;
cfg.intr_type = GPIO_INTR_DISABLE;
if (ESP_OK != gpio_config(&cfg))
return;
gpio_set_level(scl, 1);
gpio_set_level(sda, 1);
i2c_sw_master_init();
}
/******************************************************************************
* FunctionName : i2c_sw_master_start
* Description : set i2c to send state
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void i2c_sw_master_start(void)
{
i2c_sw_master_setDC(1, m_nLastSCL);
i2c_sw_master_wait(5);
i2c_sw_master_setDC(1, 1);
i2c_sw_master_wait(5); // sda 1, scl 1
i2c_sw_master_setDC(0, 1);
i2c_sw_master_wait(5); // sda 0, scl 1
}
/******************************************************************************
* FunctionName : i2c_sw_master_stop
* Description : set i2c to stop sending state
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void i2c_sw_master_stop(void)
{
i2c_sw_master_wait(5);
i2c_sw_master_setDC(0, m_nLastSCL);
i2c_sw_master_wait(5); // sda 0
i2c_sw_master_setDC(0, 1);
i2c_sw_master_wait(5); // sda 0, scl 1
i2c_sw_master_setDC(1, 1);
i2c_sw_master_wait(5); // sda 1, scl 1
}
/******************************************************************************
* FunctionName : i2c_sw_master_setAck
* Description : set ack to i2c bus as level value
* Parameters : uint8_t level - 0 or 1
* Returns : NONE
*******************************************************************************/
void i2c_sw_master_setAck(uint8_t level)
{
i2c_sw_master_setDC(m_nLastSDA, 0);
i2c_sw_master_wait(5);
i2c_sw_master_setDC(level, 0);
i2c_sw_master_wait(5); // sda level, scl 0
i2c_sw_master_setDC(level, 1);
i2c_sw_master_wait(8); // sda level, scl 1
i2c_sw_master_setDC(level, 0);
i2c_sw_master_wait(5); // sda level, scl 0
i2c_sw_master_setDC(1, 0);
i2c_sw_master_wait(5);
}
/******************************************************************************
* FunctionName : i2c_sw_master_getAck
* Description : confirm if peer send ack
* Parameters : NONE
* Returns : uint8_t - ack value, 0 or 1
*******************************************************************************/
uint8_t i2c_sw_master_getAck(void)
{
uint8_t retVal;
i2c_sw_master_setDC(m_nLastSDA, 0);
i2c_sw_master_wait(5);
i2c_sw_master_setDC(1, 0);
i2c_sw_master_wait(5);
i2c_sw_master_setDC(1, 1);
i2c_sw_master_wait(5);
retVal = i2c_sw_master_getDC();
i2c_sw_master_wait(5);
i2c_sw_master_setDC(1, 0);
i2c_sw_master_wait(5);
return retVal;
}
/******************************************************************************
* FunctionName : i2c_sw_master_checkAck
* Description : get dev response
* Parameters : NONE
* Returns : true : get ack ; false : get nack
*******************************************************************************/
bool i2c_sw_master_checkAck(void)
{
if (i2c_sw_master_getAck()) {
return false;
} else {
return true;
}
}
/******************************************************************************
* FunctionName : i2c_sw_master_send_ack
* Description : response ack
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void i2c_sw_master_send_ack(void)
{
i2c_sw_master_setAck(0x0);
}
/******************************************************************************
* FunctionName : i2c_sw_master_send_nack
* Description : response nack
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void i2c_sw_master_send_nack(void)
{
i2c_sw_master_setAck(0x1);
}
/******************************************************************************
* FunctionName : i2c_sw_master_readByte
* Description : read Byte from i2c bus
* Parameters : NONE
* Returns : uint8_t - readed value
*******************************************************************************/
uint8_t i2c_sw_master_readByte(void)
{
uint8_t retVal = 0;
uint8_t k, i;
i2c_sw_master_wait(5);
i2c_sw_master_setDC(m_nLastSDA, 0);
i2c_sw_master_wait(5); // sda 1, scl 0
for (i = 0; i < 8; i++) {
i2c_sw_master_wait(5);
i2c_sw_master_setDC(1, 0);
i2c_sw_master_wait(5); // sda 1, scl 0
i2c_sw_master_setDC(1, 1);
i2c_sw_master_wait(5); // sda 1, scl 1
k = i2c_sw_master_getDC();
i2c_sw_master_wait(5);
if (i == 7) {
i2c_sw_master_wait(3);
}
k <<= (7 - i);
retVal |= k;
}
i2c_sw_master_setDC(1, 0);
i2c_sw_master_wait(5); // sda 1, scl 0
return retVal;
}
/******************************************************************************
* FunctionName : i2c_sw_master_writeByte
* Description : write wrdata value(one byte) into i2c
* Parameters : uint8_t wrdata - write value
* Returns : NONE
*******************************************************************************/
void i2c_sw_master_writeByte(uint8_t wrdata)
{
uint8_t dat;
int8_t i;
i2c_sw_master_wait(5);
i2c_sw_master_setDC(m_nLastSDA, 0);
i2c_sw_master_wait(5);
for (i = 7; i >= 0; i--) {
dat = wrdata >> i;
i2c_sw_master_setDC(dat, 0);
i2c_sw_master_wait(5);
i2c_sw_master_setDC(dat, 1);
i2c_sw_master_wait(5);
if (i == 0) {
i2c_sw_master_wait(3);
}
i2c_sw_master_setDC(dat, 0);
i2c_sw_master_wait(5);
}
}

View File

@ -0,0 +1,26 @@
#ifndef __I2C_SW_MASTER_H__
#define __I2C_SW_MASTER_H__
#include "rom/ets_sys.h"
#define I2C_NUM_MAX 1
void i2c_sw_master_gpio_init(uint8 sda, uint8 scl);
void i2c_sw_master_init(void);
#define i2c_sw_master_wait ets_delay_us
void i2c_sw_master_stop(void);
void i2c_sw_master_start(void);
void i2c_sw_master_setAck(uint8_t level);
uint8_t i2c_sw_master_getAck(void);
uint8_t i2c_sw_master_readByte(void);
void i2c_sw_master_writeByte(uint8_t wrdata);
bool i2c_sw_master_checkAck(void);
void i2c_sw_master_send_ack(void);
void i2c_sw_master_send_nack(void);
uint8_t i2c_sw_master_get_pinSDA();
uint8_t i2c_sw_master_get_pinSCL();
#endif

View File

@ -79,6 +79,12 @@ config LUA_MODULE_GPIO
help
Includes the GPIO module (recommended).
config LUA_MODULE_I2C
bool "I2C module"
default "y"
help
Includes the I2C module (recommended).
config LUA_MODULE_NET
bool "Net module"
default "y"

161
components/modules/i2c.c Normal file
View File

@ -0,0 +1,161 @@
// Module for interfacing with the I2C interface
#include "module.h"
#include "lauxlib.h"
#include "platform.h"
// Lua: i2c.setup( id, sda, scl, speed )
static int i2c_setup( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
unsigned sda = luaL_checkinteger( L, 2 );
unsigned scl = luaL_checkinteger( L, 3 );
MOD_CHECK_ID( i2c, id );
MOD_CHECK_ID( gpio, sda );
MOD_CHECK_ID( gpio, scl );
int32_t speed = ( int32_t )luaL_checkinteger( L, 4 );
luaL_argcheck( L, speed > 0, 4, "wrong arg range" );
if (!platform_i2c_setup( id, sda, scl, (uint32_t)speed ))
luaL_error( L, "setup failed" );
return 0;
}
// Lua: i2c.start( id )
static int i2c_start( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( i2c, id );
if (!platform_i2c_send_start( id ))
luaL_error( L, "command failed");
return 0;
}
// Lua: i2c.stop( id )
static int i2c_stop( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( i2c, id );
if (!platform_i2c_send_stop( id ))
luaL_error( L, "command failed" );
return 0;
}
// Lua: status = i2c.address( id, address, direction )
static int i2c_address( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
int address = luaL_checkinteger( L, 2 );
int direction = luaL_checkinteger( L, 3 );
MOD_CHECK_ID( i2c, id );
luaL_argcheck( L, address >= 0 && address <= 127, 2, "wrong arg range" );
int ret = platform_i2c_send_address( id, (uint16_t)address, direction, 1 );
lua_pushboolean( L, ret > 0 );
return 1;
}
// Lua: wrote = i2c.write( id, data1, [data2], ..., [datan] )
// data can be either a string, a table or an 8-bit number
static int i2c_write( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
const char *pdata;
size_t datalen, i;
int numdata;
uint32_t wrote = 0;
unsigned argn;
MOD_CHECK_ID( i2c, id );
if( lua_gettop( L ) < 2 )
return luaL_error( L, "wrong arg type" );
for( argn = 2; argn <= lua_gettop( L ); argn ++ )
{
// lua_isnumber() would silently convert a string of digits to an integer
// whereas here strings are handled separately.
if( lua_type( L, argn ) == LUA_TNUMBER )
{
numdata = ( int )luaL_checkinteger( L, argn );
if( numdata < 0 || numdata > 255 )
return luaL_error( L, "wrong arg range" );
if( platform_i2c_send_byte( id, numdata, 1 ) != 1 )
break;
wrote ++;
}
else if( lua_istable( L, argn ) )
{
datalen = lua_objlen( L, argn );
for( i = 0; i < datalen; i ++ )
{
lua_rawgeti( L, argn, i + 1 );
numdata = ( int )luaL_checkinteger( L, -1 );
lua_pop( L, 1 );
if( numdata < 0 || numdata > 255 )
return luaL_error( L, "wrong arg range" );
if( platform_i2c_send_byte( id, numdata, 1 ) == 0 )
break;
}
wrote += i;
if( i < datalen )
break;
}
else
{
pdata = luaL_checklstring( L, argn, &datalen );
for( i = 0; i < datalen; i ++ )
if( platform_i2c_send_byte( id, pdata[ i ], 1 ) == 0 )
break;
wrote += i;
if( i < datalen )
break;
}
}
lua_pushinteger( L, wrote );
return 1;
}
// Lua: read = i2c.read( id, size )
static int i2c_read( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
uint32_t size = ( uint32_t )luaL_checkinteger( L, 2 ), i;
luaL_Buffer b;
int data;
MOD_CHECK_ID( i2c, id );
if( size == 0 )
return 0;
luaL_buffinit( L, &b );
for( i = 0; i < size; i ++ )
if( ( data = platform_i2c_recv_byte( id, i < size - 1 ) ) == -1 )
break;
else
luaL_addchar( &b, ( char )data );
luaL_pushresult( &b );
return 1;
}
static const LUA_REG_TYPE i2c_map[] = {
{ LSTRKEY( "setup" ), LFUNCVAL( i2c_setup ) },
{ LSTRKEY( "start" ), LFUNCVAL( i2c_start ) },
{ LSTRKEY( "stop" ), LFUNCVAL( i2c_stop ) },
{ LSTRKEY( "address" ), LFUNCVAL( i2c_address ) },
{ LSTRKEY( "write" ), LFUNCVAL( i2c_write ) },
{ LSTRKEY( "read" ), LFUNCVAL( i2c_read ) },
{ LSTRKEY( "FAST" ), LNUMVAL( PLATFORM_I2C_SPEED_FAST ) },
{ LSTRKEY( "SLOW" ), LNUMVAL( PLATFORM_I2C_SPEED_SLOW ) },
{ LSTRKEY( "TRANSMITTER" ), LNUMVAL( PLATFORM_I2C_DIRECTION_TRANSMITTER ) },
{ LSTRKEY( "RECEIVER" ), LNUMVAL( PLATFORM_I2C_DIRECTION_RECEIVER ) },
{LNILKEY, LNILVAL}
};
NODEMCU_MODULE(I2C, "i2c", i2c_map, NULL);

View File

@ -34,6 +34,13 @@ enum
int platform_init (void);
// *****************************************************************************
// GPIO subsection
int platform_gpio_exists( unsigned gpio );
int platform_gpio_output_exists( unsigned gpio );
// *****************************************************************************
// UART subsection
@ -80,6 +87,33 @@ uint8_t platform_sigma_delta_set_prescale( uint8_t channel, uint8_t prescale );
uint8_t platform_sigma_delta_set_duty( uint8_t channel, int8_t duty );
// *****************************************************************************
// I2C platform interface
// I2C speed
enum
{
PLATFORM_I2C_SPEED_SLOW = 100000,
PLATFORM_I2C_SPEED_FAST = 400000
};
// I2C direction
enum
{
PLATFORM_I2C_DIRECTION_TRANSMITTER,
PLATFORM_I2C_DIRECTION_RECEIVER
};
int platform_i2c_exists( unsigned id );
int platform_i2c_setup( unsigned id, uint8_t sda, uint8_t scl, uint32_t speed );
int platform_i2c_send_start( unsigned id );
int platform_i2c_send_stop( unsigned id );
int platform_i2c_send_address( unsigned id, uint16_t address, int direction, int ack_check_en );
int platform_i2c_send_byte( unsigned id, uint8_t data, int ack_check_en );
// ack_val: 1 = send ACK, 0 = send NACK
int platform_i2c_recv_byte( unsigned id, int ack_val );
// Internal flash erase/write functions
uint32_t platform_flash_get_sector_of_address( uint32_t addr );

View File

@ -8,6 +8,14 @@ int platform_init (void)
return PLATFORM_OK;
}
// *****************************************************************************
// GPIO subsection
int platform_gpio_exists( unsigned gpio ) { return GPIO_IS_VALID_GPIO(gpio); }
int platform_gpio_output_exists( unsigned gpio ) { return GPIO_IS_VALID_OUTPUT_GPIO(gpio); }
// ****************************************************************************
// UART
@ -138,3 +146,149 @@ uint8_t IRAM_ATTR platform_sigma_delta_set_duty( uint8_t channel, int8_t duty )
{
return ESP_OK == sigmadelta_set_duty( channel, duty ) ? 1 : 0;
}
// *****************************************************************************
// I2C platform interface
#if 0
// platform functions for the IDF I2C driver
// they're currently deactivated because of https://github.com/espressif/esp-idf/issues/241
// long-term goal is to use these instead of the SW driver in the #else branch
#include "driver/i2c.h"
int platform_i2c_setup( unsigned id, uint8_t sda, uint8_t scl, uint32_t speed ) {
i2c_config_t conf;
conf.mode = I2C_MODE_MASTER;
conf.sda_io_num = sda;
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
conf.scl_io_num = scl;
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
conf.master.clk_speed = speed;
if (ESP_OK != i2c_param_config( id, &conf ))
return 0;
if (ESP_OK != i2c_driver_install( id, conf.mode, 0, 0, 0 ))
return 0;
return 1;
}
int platform_i2c_send_start( unsigned id ) {
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start( cmd );
esp_err_t ret = i2c_master_cmd_begin( id, cmd, 1000 / portTICK_RATE_MS );
i2c_cmd_link_delete( cmd );
return ret == ESP_OK ? 1 : 0;
}
int platform_i2c_send_stop( unsigned id ) {
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_stop( cmd );
esp_err_t ret = i2c_master_cmd_begin( id, cmd, 1000 / portTICK_RATE_MS );
i2c_cmd_link_delete( cmd );
return ret == ESP_OK ? 1 : 0;
}
int platform_i2c_send_address( unsigned id, uint16_t address, int direction, int ack_check_en ) {
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
direction = ( direction == PLATFORM_I2C_DIRECTION_TRANSMITTER ) ? 0 : 1;
i2c_master_write_byte( cmd, (uint8_t) ((address << 1) | direction ), ack_check_en );
esp_err_t ret = i2c_master_cmd_begin( id, cmd, 1000 / portTICK_RATE_MS );
i2c_cmd_link_delete( cmd );
// we return ack (1=acked).
if (ret == ESP_FAIL)
return 0;
else if (ret == ESP_OK)
return 1;
else
return -1;
}
int platform_i2c_send_byte( unsigned id, uint8_t data, int ack_check_en ) {
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_write_byte( cmd, data, ack_check_en );
esp_err_t ret = i2c_master_cmd_begin( id, cmd, 1000 / portTICK_RATE_MS );
i2c_cmd_link_delete( cmd );
// we return ack (1=acked).
if (ret == ESP_FAIL)
return 0;
else if (ret == ESP_OK)
return 1;
else
return -1;
}
int platform_i2c_recv_byte( unsigned id, int ack_val ){
uint8_t data;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_read_byte( cmd, &data, ack_val > 0 ? 0 : 1 );
esp_err_t ret = i2c_master_cmd_begin( id, cmd, 1000 / portTICK_RATE_MS );
i2c_cmd_link_delete( cmd );
return ret == ESP_OK ? data : -1;
}
#else
// platform functions for SW-based I2C driver
// they work around the issue with the IDF driver
// remove when functions for the IDF driver can be used instead
#include "driver/i2c_sw_master.h"
int platform_i2c_setup( unsigned id, uint8_t sda, uint8_t scl, uint32_t speed ){
if (!platform_gpio_output_exists(sda) || !platform_gpio_output_exists(scl))
return 0;
if (speed != PLATFORM_I2C_SPEED_SLOW)
return 0;
i2c_sw_master_gpio_init(sda, scl);
return 1;
}
int platform_i2c_send_start( unsigned id ){
i2c_sw_master_start();
return 1;
}
int platform_i2c_send_stop( unsigned id ){
i2c_sw_master_stop();
return 1;
}
int platform_i2c_send_address( unsigned id, uint16_t address, int direction, int ack_check_en ){
// Convert enum codes to R/w bit value.
// If TX == 0 and RX == 1, this test will be removed by the compiler
if ( ! ( PLATFORM_I2C_DIRECTION_TRANSMITTER == 0 &&
PLATFORM_I2C_DIRECTION_RECEIVER == 1 ) ) {
direction = ( direction == PLATFORM_I2C_DIRECTION_TRANSMITTER ) ? 0 : 1;
}
i2c_sw_master_writeByte( (uint8_t) ((address << 1) | direction ));
// Low-level returns nack (0=acked); we return ack (1=acked).
return ! i2c_sw_master_getAck();
}
int platform_i2c_send_byte( unsigned id, uint8_t data, int ack_check_en ){
i2c_sw_master_writeByte(data);
// Low-level returns nack (0=acked); we return ack (1=acked).
return ! i2c_sw_master_getAck();
}
int platform_i2c_recv_byte( unsigned id, int ack ){
uint8_t r = i2c_sw_master_readByte();
i2c_sw_master_setAck( !ack );
return r;
}
#endif
int platform_i2c_exists( unsigned id ) { return id < I2C_NUM_MAX; }

133
docs/en/modules/i2c.md Normal file
View File

@ -0,0 +1,133 @@
# I²C Module
| Since | Origin / Contributor | Maintainer | Source |
| :----- | :-------------------- | :---------- | :------ |
| 2014-12-22 | [Zeroday](https://github.com/funshine) | [Zeroday](https://github.com/funshine) | [i2c.c](../../../app/modules/i2c.c)|
## i2c.address()
Setup I²C address and read/write mode for the next transfer.
#### Syntax
`i2c.address(id, device_addr, direction)`
#### Parameters
- `id` always 0
- `device_addr` device address
- `direction` `i2c.TRANSMITTER` for writing mode , `i2c. RECEIVER` for reading mode
#### Returns
`true` if ack received, `false` if no ack received.
#### See also
[i2c.read()](#i2cread)
## i2c.read()
Read data for variable number of bytes.
#### Syntax
`i2c.read(id, len)`
#### Parameters
- `id` always 0
- `len` number of data bytes
#### Returns
`string` of received data
#### Example
```lua
id = 0
sda = 1
scl = 2
-- initialize i2c, set pin1 as sda, set pin2 as scl
i2c.setup(id, sda, scl, i2c.SLOW)
-- user defined function: read from reg_addr content of dev_addr
function read_reg(dev_addr, reg_addr)
i2c.start(id)
i2c.address(id, dev_addr, i2c.TRANSMITTER)
i2c.write(id, reg_addr)
i2c.stop(id)
i2c.start(id)
i2c.address(id, dev_addr, i2c.RECEIVER)
c = i2c.read(id, 1)
i2c.stop(id)
return c
end
-- get content of register 0xAA of device 0x77
reg = read_reg(0x77, 0xAA)
print(string.byte(reg))
```
####See also
[i2c.write()](#i2cwrite)
## i2c.setup()
Initialize the I²C module.
#### Syntax
`i2c.setup(id, pinSDA, pinSCL, speed)`
####Parameters
- `id` always 0
- `pinSDA` 1~12, IO index
- `pinSCL` 1~12, IO index
- `speed` only `i2c.SLOW` supported
#### Returns
`speed` the selected speed
####See also
[i2c.read()](#i2cread)
## i2c.start()
Send an I²C start condition.
#### Syntax
`i2c.start(id)`
#### Parameters
`id` always 0
#### Returns
`nil`
####See also
[i2c.read()](#i2cread)
## i2c.stop()
Send an I²C stop condition.
#### Syntax
`i2c.stop(id)`
####Parameters
`id` always 0
#### Returns
`nil`
####See also
[i2c.read()](#i2cread)
## i2c.write()
Write data to I²C bus. Data items can be multiple numbers, strings or lua tables.
####Syntax
`i2c.write(id, data1[, data2[, ..., datan]])`
####Parameters
- `id` always 0
- `data` data can be numbers, string or lua table.
#### Returns
`number` number of bytes written
#### Example
```lua
i2c.write(0, "hello", "world")
```
#### See also
[i2c.read()](#i2cread)

View File

@ -33,6 +33,7 @@ pages:
- 'bit': 'en/modules/bit.md'
- 'bthci': 'en/modules/bthci.md'
- 'file': 'en/modules/file.md'
- 'i2c': 'en/modules/i2c.md'
- 'node': 'en/modules/node.md'
- 'sigma delta': 'en/modules/sigma-delta.md'
- 'struct': 'en/modules/struct.md'