Board 层 API 是涂鸦抽象各芯片硬件外设,封装的一层标准接口。您可以调用这些 API 来使用相应外设,快速实现产品功能,也可以根据需要直接调用原厂外设接口。
Board 层功能模块列表如下:
名称 | API 文件 | 功能说明 |
---|---|---|
PIN | ty_pin.h | GPIO 外设相关函数的使用说明 |
PWM | ty_pwm.h | PWM 外设相关函数的使用说明 |
ADC | ty_adc.h | ADC 外设相关函数的使用说明 |
I2C | ty_i2c.h | I2C 外设相关函数的使用说明 |
FLASH | ty_flash.h | Flash 外设相关函数的使用说明 |
API Demo 获取:tuya_ble_board_api_demo
一. PIN
1.1 文件说明
API 文件
PIN 相关 API 位于 ty_pin.h
文件中,芯片平台关联的驱动代码位于 ty_pin_xxxx.c
文件中。
tuya_ble_sdk_demo
└── board
├── include
| └── ty_pin.h
├── xxxx /* xxxx 为芯片平台,如 TLSR825x */
| └── ty_board_xxxx /* xxxx 为芯片平台,如 ty_board_tlsr825x */
| └── ty_pin_xxxx.c /* xxxx 为芯片平台,如 ty_pin_tlsr825x.c */
└── board.h
Demo 文件
tuya_board_api_demo 的 PIN Demo 文件结构如下:
tuya_ble_sdk_demo
├── app /* API 应用示例 */
| ├── include
| | └── ty_board_demo
| | | ├── demo_config.h /* demo 配置文件 */
| | | └── ty_pin_demo.h /* pin 模块示例代码 */
| | ├── tuya_ble_board_api_demo.h /* board api 示例程序入口 */
| | └── tuya_ble_sdk_demo.h /* tuya_ble_sdk 应用入口 */
| └── src
| ├── ty_board_demo
| | └── ty_pin_demo.c /* pin 模块示例代码 */
| ├── tuya_ble_board_api_demo.c /* board api 示例程序入口 */
| └── tuya_ble_sdk_demo.c /* tuya_ble_sdk 应用入口 */
└── board /* 部分 API 修改示例 */
修改 demo_config.h
文件即可切换到 PIN 模块示例程序:
#define BOARD_API_DEMO BOARD_API_PIN
1.2 API 列表
函数名称 | 功能描述 |
---|---|
ty_pin_init | 初始化引脚模式 |
ty_pin_set | 设置引脚的电平 |
ty_pin_get | 读取引脚的电平 |
ty_pin_control | 引脚相关控制 |
ty_pin_uninit | 关闭引脚模块 |
1.3 API 说明
ty_pin_init
函数名 | ty_pin_init |
---|---|
函数原型 | uint32_t ty_pin_init(uint8_t pin, ty_pin_mode_t mode); |
功能概述 | 初始化引脚模式 |
参数 | pin [in]:引脚编号 mode [in]:引脚模式,由 ty_pin_mode_t 类型定义 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_pin_set
函数名 | ty_pin_set |
---|---|
函数原型 | uint32_t ty_pin_set(uint8_t pin, ty_pin_level_t level); |
功能概述 | 设置引脚的电平 |
参数 | pin [in]:引脚编号 level [in]:引脚电平,由 ty_pin_level_t 类型定义 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_pin_get
函数名 | ty_pin_get |
---|---|
函数原型 | uint32_t ty_pin_get(uint8_t pin, ty_pin_level_t* p_level); |
功能概述 | 读取引脚的电平 |
参数 | pin [in]:引脚编号 p_level [out]:引脚电平,由 ty_pin_level_t 类型定义 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_pin_control
函数名 | ty_pin_control |
---|---|
函数原型 | uint32_t ty_pin_control(uint8_t pin, uint8_t cmd, void* arg); |
功能概述 | 控制引脚 |
参数 | pin [in]:引脚编号 cmd [in]:控制命令 arg [in]:命令参数 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_pin_uninit
函数名 | ty_pin_uninit |
---|---|
函数原型 | uint32_t ty_pin_uninit(uint8_t pin, ty_pin_mode_t mode); |
功能概述 | 设置引脚的电平 |
参数 | pin [in]:引脚编号 mode [in]:引脚模式 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值改 |
1.4 数据结构
ty_pin_mode_t
/* ! 与 SDK 中不一致是因为此处省略了部分代码 */
typedef enum {
//PU -> pull up
//PD -> pull dowm
//FL -> floating
//PP -> push pull
//OD -> open drain
//hiz -> high-impedance level
/* 输入 */
TY_PIN_MODE_IN_PU, /* 上拉输入 */
TY_PIN_MODE_IN_PD, /* 下拉输入 */
TY_PIN_MODE_IN_FL, /* 浮空输入 */
/* 外部中断 */
TY_PIN_MODE_IN_IRQ_RISE, /* 上升沿触发 */
TY_PIN_MODE_IN_IRQ_FALL, /* 下降沿触发 */
TY_PIN_MODE_IN_IRQ_RISE_FALL, /* 双边沿触发 */
TY_PIN_MODE_IN_IRQ_LOW, /* 低电平触发 */
TY_PIN_MODE_IN_IRQ_HIGH, /* 高电平触发 */
/* 推挽输出 */
TY_PIN_MODE_OUT_PP_LOW, /* 初期低电平 */
TY_PIN_MODE_OUT_PP_HIGH, /* 初期高电平 */
/* 推挽输出,带上拉 */
TY_PIN_MODE_OUT_PP_PU_LOW, /* 初期低电平 */
TY_PIN_MODE_OUT_PP_PU_HIGH, /* 初期高电平 */
/* 推挽输出,带下拉 */
TY_PIN_MODE_OUT_PP_PD_LOW, /* 初期低电平 */
TY_PIN_MODE_OUT_PP_PD_HIGH, /* 初期高电平 */
/* 开漏输出 */
TY_PIN_MODE_OUT_OD_LOW, /* 初期低电平 */
TY_PIN_MODE_OUT_OD_HIZ, /* 初期高阻态 */
/* 开漏输出,带上拉 */
TY_PIN_MODE_OUT_OD_PU_LOW, /* 初期低电平 */
TY_PIN_MODE_OUT_OD_PU_HIGH, /* 初期高电平 */
} ty_pin_mode_t;
ty_pin_level_t
typedef enum {
TY_PIN_LOW = 0, /* 低电平 */
TY_PIN_HIGH /* 高电平 */
} ty_pin_level_t;
1.5 API 示例
以 TLSR825x 平台为例,可参考以下代码补充 PIN 模块的 API 函数,或者直接在应用代码中调用芯片原厂提供的 API 来实现相关功能。
ty_pin.h
/* ! pin的类型默认为uint8_t,需要根据芯片平台进行修改 */
uint32_t ty_pin_init(uint16_t pin, ty_pin_mode_t mode);
uint32_t ty_pin_set(uint16_t pin, ty_pin_level_t level);
uint32_t ty_pin_get(uint16_t pin, ty_pin_level_t* p_level);
ty_pin_tlsr825x.c
uint32_t ty_pin_init(uint16_t pin, ty_pin_mode_t mode)
{
gpio_set_func(pin, AS_GPIO);
if ((mode & TY_PIN_INOUT_MASK) <= TY_PIN_IN_IRQ) {
gpio_set_input_en(pin, 1);
gpio_set_output_en(pin, 0);
} else {
gpio_set_input_en(pin, 0);
gpio_set_output_en(pin, 1);
}
switch (mode) {
case TY_PIN_MODE_IN_PU:
gpio_setup_up_down_resistor(pin, PM_PIN_PULLUP_10K);
break;
case TY_PIN_MODE_IN_PD:
gpio_setup_up_down_resistor(pin, PM_PIN_PULLDOWN_100K);
break;
case TY_PIN_MODE_IN_FL:
gpio_setup_up_down_resistor(pin, PM_PIN_UP_DOWN_FLOAT);
break;
case TY_PIN_MODE_OUT_PP_LOW:
gpio_write(pin, 0);
break;
case TY_PIN_MODE_OUT_PP_HIGH:
gpio_write(pin, 1);
break;
default:
break;
}
#if(GPIO_WAKEUP_MODULE_POLARITY == 1)
cpu_set_gpio_wakeup (WAKEUP_MODULE_GPIO, Level_High, 1);
GPIO_WAKEUP_MODULE_LOW;
#else
cpu_set_gpio_wakeup (WAKEUP_MODULE_GPIO, Level_Low, 1);
GPIO_WAKEUP_MODULE_HIGH;
#endif
return 0;
}
uint32_t ty_pin_set(uint16_t pin, ty_pin_level_t level)
{
gpio_write(pin, level);
return 0;
}
uint32_t ty_pin_get(uint16_t pin, ty_pin_level_t* p_level)
{
*p_level = gpio_read(pin);
return 0;
}
1.6 应用示例
功能概述
按键按下 (Low),LED 点亮 (High);按键释放 (High),LED 熄灭 (Low)。
代码示例
以 TLSR825x 平台为例:
#include "ty_pin_demo.h"
#include "ty_pin.h"
#include "tuya_ble_log.h"
#include "tuya_ble_port.h"
/***********************************************************
************************micro define************************
***********************************************************/
#define KEY_PIN GPIO_PA0
#define LED_PIN GPIO_PD7
#define KEY_SCAN_TIME_MS 10
/***********************************************************
***********************variable define**********************
***********************************************************/
static tuya_ble_timer_t sg_pin_timer;
/***********************************************************
***********************function define**********************
***********************************************************/
/**
* @brief pin timer callback
* @param none
* @return none
*/
void __pin_timer_cb(void)
{
ty_pin_level_t pin_level = 0;
ty_pin_get(KEY_PIN, &pin_level);
ty_pin_set(LED_PIN, !pin_level);
}
/**
* @brief ty_pin api demo init
* @param none
* @return none
*/
void ty_pin_demo_init(void)
{
uint32_t res;
/* key pin init */
res = ty_pin_init(KEY_PIN, TY_PIN_MODE_IN_PU);
if (res) {
TUYA_APP_LOG_ERROR("ty_pin_init KEY_PIN failed, error code: %d", res);
return;
}
/* led pin init */
res = ty_pin_init(LED_PIN, TY_PIN_MODE_OUT_PP_LOW);
if (res) {
TUYA_APP_LOG_ERROR("ty_pin_init KEY_PIN failed, error code: %d", res);
return;
}
/* timer init */
tuya_ble_timer_create(&sg_pin_timer, KEY_SCAN_TIME_MS, TUYA_BLE_TIMER_REPEATED, (tuya_ble_timer_handler_t)__pin_timer_cb);
tuya_ble_timer_start(sg_pin_timer);
}
二. PWM
2.1 文件说明
API 文件
PWM 相关 API 位于 ty_pwm.h
文件中,芯片平台关联的驱动代码位于 ty_pwm_xxxx.c
文件中。
tuya_ble_sdk_demo
└── board
├── include
| └── ty_pwm.h
├── xxxx /* xxxx 为芯片平台,如 TLSR825x */
| └── ty_board_xxxx /* xxxx 为芯片平台,如 ty_board_tlsr825x */
| └── ty_pwm_xxxx.c /* xxxx 为芯片平台,如 ty_pwm_tlsr825x.c */
└── board.h
Demo 文件
tuya_board_api_demo 的 PWM Demo 文件结构如下:
tuya_ble_sdk_demo
├── app /* API 应用示例 */
| ├── include
| | └── ty_board_demo
| | | ├── demo_config.h /* demo 配置文件 */
| | | └── ty_pwm_demo.h /* pwm 模块示例代码 */
| | ├── tuya_ble_board_api_demo.h /* board api 示例程序入口 */
| | └── tuya_ble_sdk_demo.h /* tuya_ble_sdk 应用入口 */
| └── src
| ├── ty_board_demo
| | └── ty_pwm_demo.c /* pwm 模块示例代码 */
| ├── tuya_ble_board_api_demo.c /* board api 示例程序入口 */
| └── tuya_ble_sdk_demo.c /* tuya_ble_sdk 应用入口 */
└── board /* 部分 API 修改示例 */
修改 demo_config.h
文件即可切换到 PWM 模块示例程序:
#define BOARD_API_DEMO BOARD_API_PWM
2.2 API 列表
函数名称 | 功能描述 |
---|---|
ty_pwm_init | 初始化 PWM 模块 |
ty_pwm_start | 启动 PWM 输出 |
ty_pwm_stop | 停止 PWM 输出 |
ty_pwm_control | 控制 PWM 模块 |
ty_pwm_uninit | 关闭 PWM 模块 |
2.3 API 说明
ty_pwm_init
函数名 | ty_pwm_init |
---|---|
函数原型 | uint32_t ty_pwm_init(ty_pwm_t* p_pwm); |
功能概述 | 初始化 PWM 模块 |
参数 | p_pwm [in]:pwm 参数,由 ty_pwm_t 类型定义 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_pwm_start
函数名 | ty_pwm_start |
---|---|
函数原型 | uint32_t ty_pwm_start(ty_pwm_t* p_pwm); |
功能概述 | 启动 PWM 输出 |
参数 | p_pwm [in]:pwm 参数,由 ty_pwm_t 类型定义 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_pwm_stop
函数名 | ty_pwm_stop |
---|---|
函数原型 | uint32_t ty_pwm_stop(ty_pwm_t* p_pwm); |
功能概述 | 停止 PWM 输出 |
参数 | p_pwm [in]:pwm 参数,由 ty_pwm_t 类型定义 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_pwm_control
函数名 | ty_pwm_control |
---|---|
函数原型 | uint32_t ty_pwm_control(ty_pwm_t* p_pwm, uint8_t cmd, void* arg); |
功能概述 | 控制 PWM 模块 |
参数 | p_pwm [inout]:pwm 参数,由 ty_pwm_t 类型定义 cmd [in]:控制命令,由 ty_pwm_cmd_t 类型定义 arg [in]:命令参数,取决于控制命令 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_pwm_uninit
函数名 | ty_pwm_uninit |
---|---|
函数原型 | uint32_t ty_pwm_uninit(ty_pwm_t* p_pwm); |
功能概述 | 关闭 PWM 模块 |
参数 | p_pwm [in]:pwm 参数,由 ty_pwm_t 类型定义 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
2.4 数据结构
ty_pwm_t
typedef struct {
GPIO_PinTypeDef pin; /* 引脚编号 */
pwm_id id; /* PWM ID */
uint8_t polarity; /* 极性 */
uint32_t freq; /* 周期 */
uint8_t duty; /* 占空比 */
} ty_pwm_t;
ty_pwm_cmd_t
typedef enum {
TY_PWM_CMD_SET_POLARITY = 0, /* 极性 */
TY_PWM_CMD_SET_FREQ, /* 周期 */
TY_PWM_CMD_SET_DUTY, /* 占空比 */
} ty_pwm_cmd_t;
ty_pwm_set_polarity_t
typedef struct {
uint8_t polarity; /* 极性(0-H, 1-L) */
} ty_pwm_set_polarity_t;
ty_pwm_set_freq_t
typedef struct {
uint32_t freq; /* 周期(us) */
} ty_pwm_set_freq_t;
ty_pwm_set_duty_t
typedef struct {
uint8_t duty; /* 占空比(%) */
} ty_pwm_set_duty_t;
2.5 API 示例
以 TLSR825x 平台为例,可参考以下代码补充 PWM 模块的 API 函数,或者直接在应用代码中调用芯片原厂提供的 API 来实现相关功能。
ty_pwm.h
/* 根据TLSR825x的pwm通道和引脚对应关系,修改参数id为func */
typedef struct {
GPIO_PinTypeDef pin; /* 引脚编号 */
GPIO_FuncTypeDef func; /* 引脚功能 */
uint8_t polarity; /* 极性 */
uint32_t freq; /* 周期 */
uint8_t duty; /* 占空比 */
} ty_pwm_t;
ty_pwm_tlsr825x.c
/****************************************************
PWM0 : PA2. PC1. PC2. PD5.
PWM1 : PA3. PC3.
PWM2 : PA4. PC4.
PWM3 : PB0. PD2.
PWM4 : PB1. PB4.
PWM5 : PB2. PB5.
PWM0_N : PA0. PB3. PC4. PD5.
PWM1_N : PC1. PD3.
PWM2_N : PD4.
PWM3_N : PC5.
PWM4_N : PC0. PC6.
PWM5_N : PC7.
****************************************************/
uint32_t ty_pwm_init(ty_pwm_t* p_pwm)
{
if (p_pwm == NULL) {
return 1;
}
if (p_pwm->duty < 0 || p_pwm->duty > 100) {
return 2;
}
if (p_pwm->func < AS_PWM0 || p_pwm->func > AS_PWM5_N) {
return 3;
}
pwm_set_clk(CLOCK_SYS_CLOCK_HZ, CLOCK_SYS_CLOCK_HZ);
gpio_set_func(p_pwm->pin, p_pwm->func);
pwm_id id = (p_pwm->func < AS_PWM0_N) ? (p_pwm->func - AS_PWM0) : (p_pwm->func - AS_PWM0_N);
pwm_set_mode(id, PWM_NORMAL_MODE);
pwm_polo_enable(id, p_pwm->polarity);
pwm_set_cycle_and_duty(id, (uint16_t)(p_pwm->freq * CLOCK_SYS_CLOCK_1US),
(uint16_t)(p_pwm->freq * CLOCK_SYS_CLOCK_1US * p_pwm->duty / 100));
return 0;
}
uint32_t ty_pwm_start(ty_pwm_t* p_pwm)
{
if (p_pwm == NULL) {
return 1;
}
if (p_pwm->duty < 0 || p_pwm->duty > 100) {
return 2;
}
if (p_pwm->func < AS_PWM0 || p_pwm->func > AS_PWM5_N) {
return 3;
}
pwm_id id = (p_pwm->func < AS_PWM0_N) ? (p_pwm->func - AS_PWM0) : (p_pwm->func - AS_PWM0_N);
pwm_start(id);
return 0;
}
uint32_t ty_pwm_stop(ty_pwm_t* p_pwm)
{
if (p_pwm == NULL) {
return 1;
}
if (p_pwm->func < AS_PWM0 || p_pwm->func > AS_PWM5_N) {
return 3;
}
pwm_id id = (p_pwm->func < AS_PWM0_N) ? (p_pwm->func - AS_PWM0) : (p_pwm->func - AS_PWM0_N);
pwm_stop(id);
return 0;
}
uint32_t ty_pwm_control(ty_pwm_t* p_pwm, uint8_t cmd, void* arg)
{
if ((p_pwm == NULL) || (arg == NULL)) {
return 1;
}
if (p_pwm->func < AS_PWM0 || p_pwm->func > AS_PWM5_N) {
return 3;
}
pwm_id id = (p_pwm->func < AS_PWM0_N) ? (p_pwm->func - AS_PWM0) : (p_pwm->func - AS_PWM0_N);
switch(cmd) {
case TY_PWM_CMD_SET_POLARITY: {
ty_pwm_set_polarity_t* param = arg;
p_pwm->polarity = param->polarity;
pwm_polo_enable(id, p_pwm->polarity);
}
break;
case TY_PWM_CMD_SET_FREQ: {
ty_pwm_set_freq_t* param = arg;
p_pwm->freq = param->freq;
pwm_set_cycle_and_duty(id, (uint16_t)(p_pwm->freq * CLOCK_SYS_CLOCK_1US),
(uint16_t)(p_pwm->freq * CLOCK_SYS_CLOCK_1US * p_pwm->duty / 100));
}
break;
case TY_PWM_CMD_SET_DUTY: {
ty_pwm_set_duty_t* param = arg;
if (p_pwm->duty < 0 || p_pwm->duty > 100) {
return 2;
}
p_pwm->duty = param->duty;
pwm_set_cmp(id, (uint16_t)(p_pwm->freq * CLOCK_SYS_CLOCK_1US * p_pwm->duty / 100));
}
break;
default:
break;
}
return 0;
}
uint32_t ty_pwm_uninit(ty_pwm_t* p_pwm)
{
uint32_t res = ty_pwm_stop(p_pwm);
if (res) {
return res;
}
gpio_set_func(p_pwm->pin, AS_GPIO);
return 0;
}
2.6 应用示例
功能概述
初期输出周期 500us,占空比 50%,极性高电平的 PWM 波形;2s 后,更新占空比为 80%;再 2s 后,更新周期为 800us;再 2s 后,更新极性为低电平;再 2s 后,停止 PWM 输出并关闭 PWM 模块。
代码示例
以 TLSR825x 平台为例:
#include "ty_pwm_demo.h"
#include "ty_pwm.h"
#include "tuya_ble_log.h"
#include "tuya_ble_port.h"
/***********************************************************
************************micro define************************
***********************************************************/
#define PWM_PIN GPIO_PB5
#define PWM_FUNC AS_PWM5
#define PWM_POL 0
#define PWM_POL_UPDATE 1
#define PWM_FREQ 500
#define PWM_FREQ_UPDATE 800
#define PWM_DUTY 50
#define PWM_DUTY_UPDATE 80
#define PWM_UPDATE_TIME_MS 2000
/***********************************************************
***********************variable define**********************
***********************************************************/
static ty_pwm_t sg_pwm = {
.pin = PWM_PIN,
.func = PWM_FUNC,
.polarity = PWM_POL,
.freq = PWM_FREQ,
.duty = PWM_DUTY
};
static tuya_ble_timer_t sg_pwm_timer;
/***********************************************************
***********************function define**********************
***********************************************************/
/**
* @brief pwm timer callback
* @param[in] none
* @return none
*/
void __pwm_timer_cb(void)
{
static uint8_t s_step = 0;
switch (s_step) {
case 0: {
ty_pwm_set_duty_t new_duty = {
.duty = PWM_DUTY_UPDATE
};
ty_pwm_control(&sg_pwm, TY_PWM_CMD_SET_DUTY, &new_duty);
}
break;
case 1: {
ty_pwm_set_freq_t new_freq = {
.freq = PWM_FREQ_UPDATE
};
ty_pwm_control(&sg_pwm, TY_PWM_CMD_SET_FREQ, &new_freq);
}
break;
case 2: {
ty_pwm_set_polarity_t new_pol = {
.polarity = PWM_POL_UPDATE
};
ty_pwm_control(&sg_pwm, TY_PWM_CMD_SET_POLARITY, &new_pol);
}
break;
case 3: {
ty_pwm_stop(&sg_pwm);
ty_pwm_uninit(&sg_pwm);
}
break;
default:
break;
}
if (s_step <= 3) {
s_step++;
}
}
/**
* @brief ty_pwm api demo init
* @param none
* @return none
*/
void ty_pwm_demo_init(void)
{
uint32_t res;
res = ty_pwm_init(&sg_pwm);
if (res) {
TUYA_APP_LOG_ERROR("ty_pwm_init failed, error code: %d", res);
return;
}
res = ty_pwm_start(&sg_pwm);
if (res) {
TUYA_APP_LOG_ERROR("ty_pwm_start failed, error code: %d", res);
return;
}
tuya_ble_timer_create(&sg_pwm_timer, PWM_UPDATE_TIME_MS, TUYA_BLE_TIMER_REPEATED, (tuya_ble_timer_handler_t)__pwm_timer_cb);
tuya_ble_timer_start(sg_pwm_timer);
}
三. ADC
3.1 文件说明
API 文件
ADC 相关 API 位于 ty_adc.h
文件中,芯片平台关联的驱动代码位于 ty_adc_xxxx.c
文件中。
tuya_ble_sdk_demo
└── board
├── include
| └── ty_adc.h
├── xxxx /* xxxx 为芯片平台,如 TLSR825x */
| └── ty_board_xxxx /* xxxx 为芯片平台,如 ty_board_tlsr825x */
| └── ty_adc_xxxx.c /* xxxx 为芯片平台,如 ty_adc_tlsr825x.c */
└── board.h
Demo 文件
tuya_board_api_demo 的 ADC Demo 文件结构如下:
tuya_ble_sdk_demo
├── app /* API 应用示例 */
| ├── include
| | └── ty_board_demo
| | | ├── demo_config.h /* demo 配置文件 */
| | | └── ty_adc_demo.h /* adc 模块示例代码 */
| | ├── tuya_ble_board_api_demo.h /* board api 示例程序入口 */
| | └── tuya_ble_sdk_demo.h /* tuya_ble_sdk 应用入口 */
| └── src
| ├── ty_board_demo
| | └── ty_adc_demo.c /* adc 模块示例代码 */
| ├── tuya_ble_board_api_demo.c /* board api 示例程序入口 */
| └── tuya_ble_sdk_demo.c /* tuya_ble_sdk 应用入口 */
└── board /* 部分 API 修改示例 */
修改 demo_config.h
文件即可切换到 ADC 模块示例程序:
#define BOARD_API_DEMO BOARD_API_ADC
3.2 API 列表
函数名称 | 功能描述 |
---|---|
ty_adc_init | 初始化 ADC 模块 |
ty_adc_start | 启动 ADC 采样 |
ty_adc_stop | 停止 ADC 采样 |
ty_adc_control | 控制 ADC 模块 |
ty_adc_uninit | 关闭 ADC 模块 |
3.3 API 说明
ty_adc_init
函数名 | ty_adc_init |
---|---|
函数原型 | uint32_t ty_adc_init(ty_adc_t* p_adc); |
功能概述 | 初始化 ADC 模块 |
参数 | p_adc [in]:adc 参数,由 ty_adc_t 类型定义 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_adc_start
函数名 | ty_adc_start |
---|---|
函数原型 | uint32_t ty_adc_start(ty_adc_t* p_adc); |
功能概述 | 启动 ADC 采样 |
参数 | p_adc [inout]:adc 参数,由 ty_adc_t 类型定义 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_adc_stop
函数名 | ty_adc_stop |
---|---|
函数原型 | uint32_t ty_adc_stop(ty_adc_t* p_adc); |
功能概述 | 停止 ADC 采样 |
参数 | p_adc [in]:adc 参数,由 ty_adc_t 类型定义 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_adc_control
函数名 | ty_adc_control |
---|---|
函数原型 | uint32_t ty_adc_control(ty_adc_t* p_adc, uint8_t cmd, void* arg); |
功能概述 | 控制 ADC 模块 |
参数 | p_adc [in]:adc 参数,由 ty_adc_t 类型定义 cmd [in]:控制命令 arg [in]:命令参数 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_adc_uninit
函数名 | ty_adc_uninit |
---|---|
函数原型 | uint32_t ty_adc_uninit(ty_adc_t* p_adc); |
功能概述 | 关闭 ADC 模块 |
参数 | p_adc [in]:adc 参数,由 ty_adc_t 类型定义 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
3.4 数据结构
ty_adc_t
/* TLSR825x 平台 */
typedef struct {
GPIO_PinTypeDef pin; /* 引脚编号 */
ADC_InputPchTypeDef channel;/* ADC 通道 */
uint32_t value; /* ADC 采样结果 */
} ty_adc_t;
/* nRF52832 平台 */
typedef struct {
uint8_t channel; /* ADC 通道 */
int16_t value; /* ADC 采样结果 */
} ty_adc_t;
3.5 API 示例
以 TLSR825x 平台为例,可参考以下代码补充 ADC 模块的 API 函数,或者直接在应用代码中调用芯片原厂提供的 API 来实现相关功能。
ty_adc.h
/* ! 本示例中channel成员可删除 */
typedef struct {
GPIO_PinTypeDef pin; /* 引脚编号 */
uint32_t value; /* ADC 采样结果 */
} ty_adc_t;
ty_adc_tlsr825x.c
uint32_t ty_adc_init(ty_adc_t* p_adc)
{
adc_init();
adc_base_init(p_adc->pin);
adc_power_on_sar_adc(1);
}
uint32_t ty_adc_start(ty_adc_t* p_adc)
{
p_adc.value = adc_sample_and_get_result();
return 0;
}
3.6 应用示例
功能概述
采集 ADC 引脚的电压值,每秒读取 1 次。
代码示例
以 TLSR825x 平台为例:
#include "ty_adc_demo.h"
#include "ty_adc.h"
#include "tuya_ble_log.h"
#include "tuya_ble_port.h"
/***********************************************************
************************micro define************************
***********************************************************/
#define ADC_PIN GPIO_PB6
#define ADC_SAMPLE_TIME_MS 1000
/***********************************************************
***********************variable define**********************
***********************************************************/
static ty_adc_t sg_adc = {
.pin = ADC_PIN,
.value = 0
};
static tuya_ble_timer_t sg_adc_timer;
/***********************************************************
***********************function define**********************
***********************************************************/
/**
* @brief adc timer callback
* @param none
* @return none
*/
void __adc_timer_cb(void)
{
uint32_t res = ty_adc_start(&sg_adc);
if (res) {
TUYA_APP_LOG_ERROR("ty_adc_start failed, error code: %d", res);
} else {
TUYA_APP_LOG_INFO("adc_value is: %d mV", sg_adc.value);
}
}
/**
* @brief ty_adc api demo init
* @param none
* @return none
*/
void ty_adc_demo_init(void)
{
uint32_t res = ty_adc_init(&sg_adc);
if (res) {
TUYA_APP_LOG_ERROR("ty_adc_init failed, error code: %d", res);
return;
}
tuya_ble_timer_create(&sg_adc_timer, ADC_SAMPLE_TIME_MS, TUYA_BLE_TIMER_REPEATED, (tuya_ble_timer_handler_t)__adc_timer_cb);
tuya_ble_timer_start(sg_adc_timer);
}
四. I2C
4.1 文件说明
API 文件
I2C 相关 API 位于 ty_i2c.h
文件中,芯片平台关联的驱动代码位于 ty_i2c_xxxx.c
文件中。
tuya_ble_sdk_demo
└── board
├── include
| └── ty_i2c.h
├── xxxx /* xxxx 为芯片平台,如 TLSR825x */
| └── ty_board_xxxx /* xxxx 为芯片平台,如 ty_board_tlsr825x */
| └── ty_i2c_xxxx.c /* xxxx 为芯片平台,如 ty_i2c_tlsr825x.c */
└── board.h
Demo 文件
tuya_board_api_demo 的 I2C Demo 文件结构如下:
tuya_ble_sdk_demo
├── app /* API 应用示例 */
| ├── include
| | └── ty_board_demo
| | | ├── demo_config.h /* demo 配置文件 */
| | | └── ty_i2c_demo.h /* i2c 模块示例代码 */
| | ├── tuya_ble_board_api_demo.h /* board api 示例程序入口 */
| | └── tuya_ble_sdk_demo.h /* tuya_ble_sdk 应用入口 */
| └── src
| ├── ty_board_demo
| | └── ty_i2c_demo.c /* i2c 模块示例代码 */
| ├── tuya_ble_board_api_demo.c /* board api 示例程序入口 */
| └── tuya_ble_sdk_demo.c /* tuya_ble_sdk 应用入口 */
└── board /* 部分 API 修改示例 */
修改 demo_config.h
文件即可切换到 I2C 模块示例程序:
#define BOARD_API_DEMO BOARD_API_I2C
4.2 API 列表
函数名称 | 功能描述 |
---|---|
ty_i2c_init | 初始化 I2C 模块 |
ty_i2c_start | 硬件 I2C:启动 I2C 传输 |
ty_i2c_stop | 硬件 I2C:停止 I2C 传输 |
ty_i2c_control | 硬件I2C:控制 I2C 模块 |
ty_i2c_uninit | 硬件 I2C:关闭 I2C 模块 |
ty_i2c_send | 硬件 I2C:发送数据 |
i2c_send_bytes | 软件 I2C:发送多个字节数据 |
i2c_rcv_bytes | 软件 I2C:接收多个字节数据 |
i2c_soft_cfg | 软件 I2C:配置从机寄存器 |
i2c_soft_gpio_init | 软件 I2C:初始 I2C 引脚 |
i2c_start | 软件 I2C:发送起始信号 |
i2c_stop | 软件 I2C:发送停止信号 |
i2c_delay | 软件 I2C:微秒级延时 |
4.3 API 说明
ty_i2c_init
函数名 | ty_i2c_init |
---|---|
函数原型 | uint32_t ty_i2c_init(void); |
功能概述 | 初始化 I2C 模块 |
参数 | 无 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_i2c_start
函数名 | ty_i2c_start |
---|---|
函数原型 | uint32_t ty_i2c_start(void); |
功能概述 | 硬件 I2C:启动 I2C 传输 |
参数 | 无 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_i2c_stop
函数名 | ty_i2c_stop |
---|---|
函数原型 | uint32_t ty_i2c_stop(void); |
功能概述 | 硬件 I2C:停止 I2C 传输 |
参数 | 无 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_i2c_control
函数名 | ty_i2c_control |
---|---|
函数原型 | uint32_t ty_i2c_control(uint8_t cmd, void* arg); |
功能概述 | 硬件I2C:控制 I2C 模块 |
参数 | cmd [in]:控制命令 arg [in]:命令参数 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_i2c_uninit
函数名 | ty_i2c_uninit |
---|---|
函数原型 | uint32_t ty_i2c_uninit(void); |
功能概述 | 硬件 I2C:关闭 I2C 模块 |
参数 | 无 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_i2c_send
函数名 | ty_i2c_send |
---|---|
函数原型 | uint32_t ty_i2c_send(const uint8_t addr, const uint8_t* buf, uint32_t size); |
功能概述 | 硬件 I2C:发送数据 |
参数 | addr [in]:地址 buf [in]:发送数据 size [in]:数据大小 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
i2c_send_bytes
函数名 | i2c_send_bytes |
---|---|
函数原型 | void i2c_send_bytes(uint8_t adderss_cmd, uint8_t *buff, uint8_t len); |
功能概述 | 软件 I2C:发送多个字节数据 |
参数 | adderss_cmd [in]:“从机地址+读写命令”字节 buff [in]:发送数据 len [in]:数据长度 |
返回值 | 无 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
i2c_rcv_bytes
函数名 | i2c_rcv_bytes |
---|---|
函数原型 | void i2c_rcv_bytes(uint8_t adderss_cmd, uint8_t *buff, uint8_t len); |
功能概述 | 软件 I2C:接收多个字节数据 |
参数 | adderss_cmd [in]:“从机地址+读写命令”字节 buff [out]:接收数据 len [in]:数据长度 |
返回值 | 无 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
i2c_soft_cfg
函数名 | i2c_soft_cfg |
---|---|
函数原型 | void i2c_soft_cfg(uint8_t adderss_cmd, uint8_t reg_addr, uint8_t data); |
功能概述 | 软件 I2C:配置从机寄存器 |
参数 | adderss_cmd [in]:“从机地址+读写命令”字节 reg_addr [in]:寄存器地址 data [in]:寄存器值 |
返回值 | 无 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
i2c_soft_gpio_init
函数名 | i2c_soft_gpio_init |
---|---|
函数原型 | void i2c_soft_gpio_init(void); |
功能概述 | 软件 I2C:初始 I2C 引脚 |
参数 | 无 |
返回值 | 无 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
i2c_start
函数名 | i2c_start |
---|---|
函数原型 | void i2c_start(void); |
功能概述 | 软件 I2C:发送起始信号 |
参数 | 无 |
返回值 | 无 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
i2c_stop
函数名 | i2c_stop |
---|---|
函数原型 | void i2c_stop(void); |
功能概述 | 软件 I2C:发送停止信号 |
参数 | 无 |
返回值 | 无 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
i2c_delay
函数名 | i2c_delay |
---|---|
函数原型 | void i2c_delay(unsigned long tim_1us); |
功能概述 | 软件 I2C:微秒级延时 |
参数 | tim_1us[in]:微秒值 |
返回值 | 无 |
备注 | 无 |
4.4 数据结构
无。
4.5 API 示例
以 TLSR825x 平台为例,可参考以下代码补充 I2C 模块的 API 函数,或者直接在应用代码中调用芯片原厂提供的 API 来实现相关功能。
ty_i2c.h
/* !该宏用于区分使用软件I2C还是硬件I2C;本Demo已将软/硬件I2C接口函数专用化,因此该宏可忽略 */
#define USE_SOFT_I2C 0
/* !修改了addr的类型,增加了addr_len参数,增加了ty_i2c_rcv函数 */
uint32_t ty_i2c_send(const uint32_t addr, const uint8_t addr_len, const uint8_t* buf, uint32_t size);
uint32_t ty_i2c_rcv(const uint32_t addr, const uint8_t addr_len, uint8_t* buf, uint32_t size);
ty_i2c_tlsr825x.c
/* !I2C的引脚在这里配置,增加了SLAVE_ADDR_WRITE用于硬件I2C初始化 */
#define TLSR_I2C_GPIO_GROUP I2C_GPIO_GROUP_C0C1
#define I2C_PIN_SDA GPIO_PC0
#define I2C_PIN_SCL GPIO_PC1
#define SLAVE_ADDR_WRITE (0x44 << 1 | 0x00) // (0x68 << 1 | 0x00)
/* !修改了i2c_master_init的传入参数 */
uint32_t ty_i2c_init(void)
{
i2c_gpio_set(TLSR_I2C_GPIO_GROUP);
i2c_master_init(SLAVE_ADDR_WRITE, (unsigned char)(CLOCK_SYS_CLOCK_HZ/(4*200000)));
return 0;
}
/* !修改了发送函数的参数和内容,这里addr表示寄存器地址,addr_len表示地址所占字节个数 */
uint32_t ty_i2c_send(const uint32_t addr, const uint8_t addr_len, const uint8_t* buf, uint32_t size)
{
i2c_write_series(addr, addr_len, buf, size);
return 0;
}
/* !增加了接收函数,参数含义与发送函数相同 */
uint32_t ty_i2c_rcv(const uint32_t addr, const uint8_t addr_len, uint8_t* buf, uint32_t size)
{
i2c_read_series(addr, addr_len, buf, size);
return 0;
}
4.6 应用示例
功能概述
使用硬件 I2C 或 软件 I2C 驱动从机设备,定时采集传感器数据。
代码示例
以 TLSR825x 平台为例。
I2C_API_DEMO_SHT3X
- 温湿度传感器 SHT30-DIS 驱动示例
传感资料:
- 数据手册:Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf
- 示例代码:Sensirion_Humidity_Sensors_Software_SHT3x_Sample_Code.zip
注:SHT3x 的 16 位命令可以作为寄存器地址使用。
#include "ty_i2c_demo.h"
#include "ty_i2c.h"
#include "tuya_ble_log.h"
#include "tuya_ble_port.h"
/***********************************************************
************************micro define************************
***********************************************************/
/* Demo config */
#define I2C_API_DEMO_S 0x00 /* software I2C */
#define I2C_API_DEMO_H 0x01 /* hardware I2C */
#define I2C_API_DEMO_MODE I2C_API_DEMO_S
/* slave device config */
#define I2C_SLAVE_ADDR 0x44
#define I2C_DAQ_TIME_MS 1000 /* 1s / 1Hz */
/* register map */
#define SHT3X_CMD_MEAS_PERI_1_H 0x2130 /* measurement: periodic 1 mps, high repeatability */
#define SHT3X_CMD_FETCH_DATA 0xE000 /* readout measurements for periodic mode */
/* I2C command */
#define I2C_CMD_BIT_WRITE 0
#define I2C_CMD_BIT_READ 1
#define I2C_ADDR_CMD_W (I2C_SLAVE_ADDR << 1 | I2C_CMD_BIT_WRITE)
#define I2C_ADDR_CMD_R (I2C_SLAVE_ADDR << 1 | I2C_CMD_BIT_READ)
/***********************************************************
***********************variable define**********************
***********************************************************/
static tuya_ble_timer_t sg_daq_timer;
/***********************************************************
***********************function define**********************
***********************************************************/
/**
* @brief check checksum
* @param[in] data: data to be checked
* @param[in] len: data length
* @param[in] crc_val: crc value
* @return check result
*/
static uint8_t __check_crc_8(uint8_t* data, uint16_t len, uint8_t crc_val)
{
uint8_t i;
uint8_t crc = 0xFF;
while (len--) {
crc ^= *data;
for (i = 8; i > 0; --i) {
if (crc & 0x80) {
crc = (crc << 1) ^ 0x31;
} else {
crc = (crc << 1);
}
}
data++;
}
if (crc != crc_val){
return 0;
}
return 1;
}
/**
* @brief write command to SHT3x
* @param[in] cmd: command
* @param[in] stop: whether a stop signal needs to be sent
* @return none
*/
static void __i2c_write_cmd_sht3x(uint16_t cmd, bool stop)
{
#if (I2C_API_DEMO_MODE == I2C_API_DEMO_S)
uint8_t cmd_bytes[2];
cmd_bytes[0] = (uint8_t)(cmd >> 8);
cmd_bytes[1] = (uint8_t)(cmd & 0x00FF);
i2c_start();
i2c_send_bytes(I2C_ADDR_CMD_W, cmd_bytes, 2);
if (stop) {
i2c_stop();
}
#else
ty_i2c_send(cmd, 2, null, 0);
#endif
}
/**
* @brief read data from SHT3x
* @param[out] buf: data buffer
* @param[in] len: data length
* @return none
*/
static void __i2c_read_data_sht3x(uint8_t *buf, uint8_t len)
{
#if (I2C_API_DEMO_MODE == I2C_API_DEMO_S)
i2c_start();
i2c_rcv_bytes(I2C_ADDR_CMD_R, buf, len);
i2c_stop();
#else
ty_i2c_rcv(0, 0, buf, len);
#endif
}
/**
* @brief data acquisition timer handler
* @param none
* @return none
*/
static void __daq_timer_handler(void)
{
uint8_t buf[6];
/* send fetch command to SHT3x */
__i2c_write_cmd_sht3x(SHT3X_CMD_FETCH_DATA, 0);
/* read data from SHT3x */
__i2c_read_data_sht3x(buf, 6);
/* check CRC value */
if ((!__check_crc_8(buf, 2, buf[2])) ||
(!__check_crc_8(buf+3, 2, buf[5]))) {
TUYA_APP_LOG_ERROR("__sht3x_check_crc failed.");
return;
}
/* calculate temperature and humidity */
int32_t temp = ((int16_t)buf[0] << 8 | buf[1]) * 175 / 65535 - 45;
uint32_t humi = ((uint16_t)buf[3] << 8 | buf[4]) * 100 / 65535;
TUYA_APP_LOG_INFO("Temperature: %d, Humidity: %d", temp, humi);
}
/**
* @brief ty_i2c api demo init
* @param none
* @return none
*/
void ty_i2c_demo_init(void)
{
/* I2C init */
#if (I2C_API_DEMO_MODE == I2C_API_DEMO_S)
i2c_soft_gpio_init();
#else
ty_i2c_init();
#endif
/* SHT3x: start periodic measurement */
__i2c_write_cmd_sht3x(SHT3X_CMD_MEAS_PERI_1_H, 0);
/* creat and start DAQ timer */
tuya_ble_timer_create(&sg_daq_timer, I2C_DAQ_TIME_MS, TUYA_BLE_TIMER_REPEATED, (tuya_ble_timer_handler_t)__daq_timer_handler);
tuya_ble_timer_start(sg_daq_timer);
}
I2C_API_DEMO_MPU6050
- 运动传感器 MPU6050 驱动示例
传感资料:
- 产品规格书:MPU-6000 and MPU-6050 Product Specification Revision 3.4
- 寄存器手册:MPU-6000 and MPU-6050 Register Map and Descriptions Revision 4.2
#include "ty_i2c_demo.h"
#include "ty_i2c.h"
#include "tuya_ble_log.h"
#include "tuya_ble_port.h"
/***********************************************************
************************micro define************************
***********************************************************/
/* Demo config */
#define I2C_API_DEMO_S 0x00 /* software I2C */
#define I2C_API_DEMO_H 0x01 /* hardware I2C */
#define I2C_API_DEMO_MODE I2C_API_DEMO_S
/* slave device config */
#define I2C_SLAVE_ADDR 0x68
#define I2C_DAQ_TIME_MS 5 /* 5ms / 200Hz */
#define MPU6050_DEV_ID 0x68
/* register map */
#define MPU6050_RA_SMPRT_DIV 0x19
#define MPU6050_RA_CONFIG 0x1A
#define MPU6050_RA_GYRO_CONFIG 0x1B
#define MPU6050_RA_ACCEL_CONFIG 0x1C
#define MPU6050_RA_ACCEL_XOUT_H 0x3B
#define MPU6050_RA_PWR_MGMT_1 0x6B
#define MPU6050_RA_WHO_AM_I 0x75
/* I2C command */
#define I2C_CMD_BIT_WRITE 0
#define I2C_CMD_BIT_READ 1
#define I2C_ADDR_CMD_W (I2C_SLAVE_ADDR << 1 | I2C_CMD_BIT_WRITE)
#define I2C_ADDR_CMD_R (I2C_SLAVE_ADDR << 1 | I2C_CMD_BIT_READ)
/***********************************************************
***********************variable define**********************
***********************************************************/
static tuya_ble_timer_t sg_daq_timer;
/***********************************************************
***********************function define**********************
***********************************************************/
/**
* @brief write register of MPU6050
* @param[in] reg_addr: register address
* @param[in] reg_val: value to be written
* @return none
*/
static void __i2c_write_reg(uint8_t reg_addr, uint8_t reg_val)
{
#if (I2C_API_DEMO_MODE == I2C_API_DEMO_S)
i2c_soft_cfg(I2C_ADDR_CMD_W, reg_addr, reg_val);
#else
ty_i2c_send(reg_addr, 1, ®_val, 1);
#endif
}
/**
* @brief read register of MPU6050
* @param[in] reg_addr: register address
* @param[out] reg_val: register value
* @param[in] len: register length
* @return none
*/
static void __i2c_read_reg(uint8_t reg_addr, uint8_t *reg_val, uint8_t len)
{
#if (I2C_API_DEMO_MODE == I2C_API_DEMO_S)
i2c_start();
i2c_send_bytes(I2C_ADDR_CMD_W, ®_addr, 1);
i2c_start();
i2c_rcv_bytes(I2C_ADDR_CMD_R, reg_val, len);
i2c_stop();
#else
ty_i2c_rcv(reg_addr, 1, reg_val, len);
#endif
}
/**
* @brief data acquisition timer handler
* @param none
* @return none
*/
static void __daq_timer_handler(void)
{
uint8_t i;
uint8_t tmp_buf[14];
int16_t accel[3], gyro[3];
/* read data from MPU6050 */
__i2c_read_reg(MPU6050_RA_ACCEL_XOUT_H, tmp_buf, 14);
/* calculate acceleration (g) and angular velocity (dps) */
for (i = 0; i < 3; i++) {
accel[i] = ((int16_t)tmp_buf[i*2] << 8) | tmp_buf[i*2+1];
accel[i] /= 2048;
gyro[i] = ((int16_t)tmp_buf[i*2+8] << 8) | tmp_buf[i*2+9];
gyro[i] = gyro[i] * 10 / 164;
}
TUYA_APP_LOG_INFO("ax: %d, ay: %d, az: %d, gx: %d, gy: %d, gz: %d",
accel[0], accel[1], accel[2], gyro[0], gyro[1], gyro[2]);
}
/**
* @brief ty_i2c api demo init
* @param none
* @return none
*/
void ty_i2c_demo_init(void)
{
/* I2C init */
#if (I2C_API_DEMO_MODE == I2C_API_DEMO_S)
i2c_soft_gpio_init();
#else
ty_i2c_init();
#endif
/* reset MPU6050 and exit sleep mode */
__i2c_write_reg(MPU6050_RA_PWR_MGMT_1, 0x80);
i2c_delay(200*1000);
/* check communication */
uint8_t dev_id;
__i2c_read_reg(MPU6050_RA_WHO_AM_I, &dev_id, 1);
if (dev_id != MPU6050_DEV_ID) {
TUYA_APP_LOG_ERROR("MPU6050 is not found.");
return;
}
/* MPU6050 init */
__i2c_write_reg(MPU6050_RA_PWR_MGMT_1, 0x01); /* set clock source: PLL_XGYRO */
__i2c_write_reg(MPU6050_RA_GYRO_CONFIG, 0x03); /* set gyroscope's full-scale range: 2000dps */
__i2c_write_reg(MPU6050_RA_ACCEL_CONFIG, 0x03); /* set accelerometer's full-scale range: 16g */
__i2c_write_reg(MPU6050_RA_SMPRT_DIV, 0x04); /* set sample rate: 1kHz/(1+4) = 200Hz */
__i2c_write_reg(MPU6050_RA_CONFIG, 0x02); /* set DLPF */
/* creat and start DAQ timer */
tuya_ble_timer_create(&sg_daq_timer, I2C_DAQ_TIME_MS, TUYA_BLE_TIMER_REPEATED, (tuya_ble_timer_handler_t)__daq_timer_handler);
tuya_ble_timer_start(sg_daq_timer);
}
五. FLASH
5.1 文件说明
API 文件
Flash 相关 API 位于 ty_flash.h
文件中,芯片平台关联的驱动代码位于 ty_flash_xxxx.c
文件中。
tuya_ble_sdk_demo
└── board
├── include
| └── ty_flash.h
├── xxxx /* xxxx 为芯片平台,如 TLSR825x */
| └── ty_board_xxxx /* xxxx 为芯片平台,如 ty_board_tlsr825x */
| └── ty_flash_xxxx.c /* xxxx 为芯片平台,如 ty_flash_tlsr825x.c */
└── board.h
Demo 文件
tuya_board_api_demo 的 Flash Demo 文件结构如下:
tuya_ble_sdk_demo
├── app /* API 应用示例 */
| ├── include
| | └── ty_board_demo
| | | ├── demo_config.h /* demo 配置文件 */
| | | └── ty_flash_demo.h /* flash 模块示例代码 */
| | ├── tuya_ble_board_api_demo.h /* board api 示例程序入口 */
| | └── tuya_ble_sdk_demo.h /* tuya_ble_sdk 应用入口 */
| └── src
| ├── ty_board_demo
| | └── ty_flash_demo.c /* flash 模块示例代码 */
| ├── tuya_ble_board_api_demo.c /* board api 示例程序入口 */
| └── tuya_ble_sdk_demo.c /* tuya_ble_sdk 应用入口 */
└── board /* 部分 API 修改示例 */
修改 demo_config.h
文件即可切换到 Flash 模块示例程序:
#define BOARD_API_DEMO BOARD_API_FLASH
5.2 API 列表
函数名称 | 功能描述 |
---|---|
ty_flash_init | 初始化 Flash 模块 |
ty_flash_read | 读取 Flash |
ty_flash_write | 写入 Flash |
ty_flash_erase | 擦除 Flash |
5.3 API 说明
ty_flash_init
函数名 | ty_flash_init |
---|---|
函数原型 | uint32_t ty_flash_init(void); |
功能概述 | 初始化 Flash 模块 |
参数 | 无 |
返回值 | 0 :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_flash_read
函数名 | ty_flash_read |
---|---|
函数原型 | uint32_t ty_flash_read(uint32_t addr, uint8_t* buf, uint32_t size); |
功能概述 | 读取 Flash |
参数 | addr [in]:起始地址 buf [out]:Flash 数据 size [in]:数据大小 |
返回值 | TUYA_BLE_SUCCESS :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_flash_write
函数名 | ty_flash_write |
---|---|
函数原型 | uint32_t ty_flash_write(uint32_t addr, const uint8_t* buf, uint32_t size); |
功能概述 | 写入 Flash |
参数 | addr [in]:起始地址 buf [in]:Flash 数据 size [in]:数据大小 |
返回值 | TUYA_BLE_SUCCESS :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值 |
ty_flash_erase
函数名 | ty_flash_erase |
---|---|
函数原型 | uint32_t ty_flash_erase(uint32_t addr, uint32_t num); |
功能概述 | 擦除 Flash |
参数 | addr [in]:起始地址 num [in]:擦除单位的个数 |
返回值 | TUYA_BLE_SUCCESS :成功;其他:失败 |
备注 | 可根据芯片平台按需补充或修改函数内容、参数及返回值,不同芯片平台的擦除单位可能不同 |
5.4 数据结构
无。
5.5 API 示例
无。可直接使用 SDK 中的 API 函数。
5.6 应用示例
功能概述
上电后读取 Flash 并打印,如果已写入过数据,擦除 Flash 后将新数据写入 Flash,擦除和写入操作后读一次数据用来检查操作是否成功。
代码示例
以 TLSR825x 平台为例:(Flash 地址可查看 tuya_ble_sdk_demo\doc
目录下的 flash 分区表)
#include "ty_flash_demo.h"
#include "ty_flash.h"
#include "tuya_ble_log.h"
/***********************************************************
************************micro define************************
***********************************************************/
#define FLASH_ADDR_STA 0x034000
#define FLASH_BUF_SIZE 4
/***********************************************************
***********************function define**********************
***********************************************************/
/**
* @brief ty_flash api demo init
* @param none
* @return none
*/
void ty_flash_demo_init(void)
{
uint8_t i;
uint8_t flash_buf[FLASH_BUF_SIZE];
uint8_t flash_buf_tmp[FLASH_BUF_SIZE];
/* read flash */
ty_flash_read(FLASH_ADDR_STA, flash_buf, FLASH_BUF_SIZE);
for (i = 0; i < FLASH_BUF_SIZE; i++) {
TUYA_APP_LOG_INFO("The data in %x is %02x", FLASH_ADDR_STA + 8*i, flash_buf[i]);
}
/* erase flash and check it */
if (flash_buf[0] != 0xFF) {
ty_flash_erase(FLASH_ADDR_STA, 1);
ty_flash_read(FLASH_ADDR_STA, flash_buf_tmp, FLASH_BUF_SIZE);
for (i = 0; i < FLASH_BUF_SIZE; i++) {
TUYA_APP_LOG_INFO("The data in %x is %02x", FLASH_ADDR_STA + 8*i, flash_buf_tmp[i]);
}
}
/* write flash and check it */
for (i = 0; i < FLASH_BUF_SIZE; i++) {
flash_buf[i] += (i+1);
}
ty_flash_write(FLASH_ADDR_STA, flash_buf, FLASH_BUF_SIZE);
ty_flash_read(FLASH_ADDR_STA, flash_buf_tmp, FLASH_BUF_SIZE);
for (i = 0; i < FLASH_BUF_SIZE; i++) {
TUYA_APP_LOG_INFO("The data in %x is %02x", FLASH_ADDR_STA + 8*i, flash_buf_tmp[i]);
}
}
上一篇: 第 7 课:SDK API 说明
下一篇: 无