PKE8720DF-C13-F10开发板I2C功能简介
PKE8720DF-C13-F10 中 I2C 的设计旨在低功耗或电池供电产品中的传感器应用。提供了一个 I2C port,用于获取或控制外部传感器数据。
I2C总线支持两种速度模式:标准模式下 100 k/s,快速模式下 400 k/s;支持 Master / Slave I2C 操作;支持7位和10位寻址;深度为16的发送和接收 buffer ;支持 Tx / Rx DMA;提供多主机能力,包括总线仲裁方案。
下图是 Master / Slave 和 Transmitter / Receiver 的关系图。
Figure 1. Master/Slave and Transmitter/Receiver relationships
PKE8720DF-C13-F10开发板详细信息、引脚对应以及Arduino IDE配置方法可以参考之前的文章:使用PKE8720DF-C13-F10实现Arduino example——Button_deer_vickey的博客-CSDN博客
Arduino IDE——I2C数据收发
1)所需材料
- 2 × PKE8720DF-C13-F10开发板
- 2 x USB转type-C数据线
- 2 × 杜邦线
2)电路连接
- Master board 的 SCL (PB25) 连接到 Slave board 的 SCL (PB25)
- Master board 的 SDA (PB26) 连接到 Slave board 的 SDA (PB26)
3)代码解析
代码通过macro I2C_MASTER_DEVICE 区分 master 和 slave 的角色,从LOG_UART可以看到输出。完整的源代码文件 I2C_DUPLEX.ino 可以在下面的链接下载:https://download.csdn.net/download/deer_vickey/88148518?spm=1001.2014.3001.5503
include files
I2C功能的接口定义在下面的头文件中,相关函数可以在ambd_arduino源代码中查询,源代码可以从github下载:GitHub - ambiot/ambd_arduino: AmebaD Arduino third-party package SDK
#include "PinNames.h"
#include "basic_types.h"
#include "diag.h"
#include "i2c_api.h"
#include "pinmap.h"
definitions and global variables
- I2C_MASTER_DEVICE 用来区分 master 和 slave,进行 define 的话表示 master,没有 define 则表示 slave
- I2C_BUS_CLK 是 I2C 总线的时钟,标准模式下它的值是100k/s
- i2c_data_master_tx[] 存放 master 发送的数据
- i2c_data_slave_tx[] 存放 slave 发送的数据
- i2c_data_master_rx[] 和 i2c_data_master_rx[] 分别存放 master / slave 接收的数据
#define I2C_MASTER_DEVICE
//I2C1_SEL S0
#define I2C_MTR_SDA PA_26
#define I2C_MTR_SCL PA_25
//I2C0_SEL S0
#define I2C_SLV_SDA PA_26
#define I2C_SLV_SCL PA_25
#define I2C_SLAVE_ADDR0 0x23
#define I2C_BUS_CLK 100000 //hz
#define I2C_DATA_LENGTH 10
uint8_t i2c_data_master_tx[I2C_DATA_LENGTH];
uint8_t i2c_data_slave_rx[I2C_DATA_LENGTH];
uint8_t i2c_data_slave_tx[I2C_DATA_LENGTH];
uint8_t i2c_data_master_rx[I2C_DATA_LENGTH];
setup()
- 首先对Master、Slave需要传送的数据分别进行赋值操作,调用 trans_data_init() 函数:
- i2c_data_master_tx[] :01 02 03 04 05 06 07 08 09 0a
- i2c_data_slave_tx[] :0a 09 08 07 06 05 04 03 02 01
- i2c_data_master_rx[] 和 i2c_data_master_rx[] 都初始化为0
void trans_data_init(void)
{
int index = 0;
for(index = 0; index < I2C_DATA_LENGTH; index++)
{
i2c_data_master_tx[index] = index + 1;
}
for(index = 0; index < I2C_DATA_LENGTH; index++)
{
i2c_data_slave_tx[index] = I2C_DATA_LENGTH - index;
}
_memset(&i2c_data_slave_rx[0], 0x00, I2C_DATA_LENGTH);
_memset(&i2c_data_master_rx[0], 0x00, I2C_DATA_LENGTH);
}
- Master:初始化成功之后调用 i2c_write() 把 i2c_data_master_tx[] buffer中的数据发送给 I2C Slave;再通过 i2c_read() 函数把 Slave 发送的数据读取到 i2c_data_master_rx[] buffer中。比较 Master 读到的数据和 Slave 发送的数据是否相同。
int index = 0;
i2c_init(&i2c_master, I2C_MTR_SDA , I2C_MTR_SCL);
i2c_frequency(&i2c_master, I2C_BUS_CLK);
// Master write - Slave read
printf("\r\nMaster write(i2c_data_master_tx)>>>\n");
for(index = 0; index < I2C_DATA_LENGTH; index += 2)
{
printf(" %02x \t %02x\n",i2c_data_master_tx[index],i2c_data_master_tx[index+1]);
}
i2c_write(&i2c_master, I2C_SLAVE_ADDR0, (const char *)&i2c_data_master_tx[0],
I2C_DATA_LENGTH, 1);
// Master read - Slave write
printf("Master read(i2c_data_master_rx)>>>\n");
i2c_read(&i2c_master, I2C_SLAVE_ADDR0, (char *)&i2c_data_master_rx[0], I2C_DATA_LENGTH, 1);
i2c_master_rx_check();
- Slave:初始化成功之后调用 i2c_slave_read() 函数把 Master 发送的数据读取到 i2c_data_slave_rx[] buffer中;再通过 i2c_slave_write() 把 i2c_data_slave_tx[] buffer中的数据发送给 I2C Master。比较 Slave 读到的数据和 Master 发送的数据是否相同。
int index = 0;
i2c_init(&i2c_slave, I2C_SLV_SDA, I2C_SLV_SCL);
i2c_frequency(&i2c_slave, I2C_BUS_CLK);
i2c_slave_address(&i2c_slave, 0, I2C_SLAVE_ADDR0, 0xFF);
i2c_slave_mode(&i2c_slave, 1);
// Master write - Slave read
printf("\r\nSlave read(i2c_data_slave_rx)>>>\n");
i2c_slave_read(&i2c_slave, (char *)&i2c_data_slave_rx[0], I2C_DATA_LENGTH);
i2c_slave_rx_check();
// Master read - Slave write
printf("Slave write(i2c_data_slave_tx)>>>\n");
for(index = 0; index < I2C_DATA_LENGTH; index += 2)
{
printf(" %02x \t %02x\n",i2c_data_slave_tx[index], i2c_data_slave_tx[index+1]);
}
i2c_slave_set_for_rd_req(&i2c_slave, 1);
i2c_slave_write(&i2c_slave, (const char *)&i2c_data_slave_tx[0], I2C_DATA_LENGTH);
4)烧录image
- Master:“Tools” --> “Port” 中选择 Master 的 COM 口,打开 I2C_MASTER_DEVICE,点击 “Sketch” --> “Upload” 把 image 烧录到板子中
- Slave:“Tools” --> “Port” 中选择 Slave 的 COM 口,关闭 I2C_MASTER_DEVICE,点击 “Sketch” --> “Upload” 把 image 烧录到板子中
5)实验结果
使用 TeraTerm 查看 LOG_UART 的 output。打开两个 TeraTerm 窗口,在 Serial 中分别选择 Master 和 Slave 对应的 COM 口;把 “Setup” --> “Serial port” 中的 speed 设置成115200。
先按下 Slave 的 Reset 键,再按下 Master 的 Reset 键,可以看到下图的serial output。左侧的 COM31 是Master,右侧的 COM34 是 Slave。
- 红色框内显示的是 Master write - Slave read
- 蓝色框内显示的是 Master read - Slave write
可以看到接收端的 data 和发送端的 data 完全相同,结果符合预期。如果您的实验结果与本文不符,则需要在每条线上都外接一个上拉电阻(典型值为 4.7 kΩ),默认情况下将其保持为高电平。