本项目设计初衷是为了提醒自己出门不要忘记带东西——“身”、“手”、“钥”、“钱” (身份证,手机,钥匙,钱包)等。不过现在好像都在线支付了,钱包都不带了。笔者觉得后期可以改造成播报天气等,提醒带伞等等。
项目最初设计是使用安信可24G雷达传感器模块人体微动感应检测模组“Rd-03” 来做。由于手上刚好有一个"HC-SR501 红外感应电子模块传感器" 模块,所以这次先用这个试试。
红外感应模块:HC-SR501
语音合成播报模块:XFS5152
开发板:Ai-M61-32S
GPIO 全称 General Purpose Input Output(通用输入 / 输出),博流系列芯片的 GPIO 外设主要有以下功能。
普通输入输出带上下拉
复用功能带上下拉
模拟功能
外部中断(上升沿、下降沿、高电平、低电平)
硬件消抖
驱动能力控制
bl mcu sdk 的引脚配置方式分为两种。
GPIO 复用功能通过专门的 pinmux table ,用户只需要修改 table 中的相关引脚的功能,程序会自动配置这些引脚。pinmux table 位于 bsp/board/xxx_board 目录下 pinmux_config.h 文件。
通过标准的 GPIO 设备接口配置引脚,缺点是只能配置普通的输入输出和中断功能,复用功能建议还是使用 table 进行配置。
**绝对零 (0 开尔文/-273.5 *C) 以上的每个物体都会以红外辐射的形式发出热能。物体越热,它发出的辐射就越多。辐射对人眼是不可见的,PIR传感器专门设计用于检测这种辐射水平。
PIR 传感器由两个主要部分组成,可以看到的热释电传感器是圆形的,中间有一个矩形晶体。
一种称为菲涅尔透镜的特殊透镜,可将红外信号聚焦到热释电传感器上。
热释电传感器热释电传感器由一个窗口和两个由涂层硅制成的矩形槽组成,它允许红外线通过并阻挡任何其他辐射。传感器的设计使得一个可以抵消另一个,这样传感器就可以抵消环境辐射并检测辐射模式的变化。
当没有检测到运动时,产生的输出信号为零,因为传感器正在检测背景辐射。但是,当传感器的任何一半截获运动时,都会导致传感器两部分之间的电压电平发生变化,这就是检测运动的方式。
菲涅耳透镜由一系列刻在塑料上的同心凹槽组成。这些轮廓充当单独的折射表面,在焦点处聚集平行光线。因此,菲涅耳透镜能够像传统光学透镜一样聚焦光线。
实际上,为了增加 PIR 传感器的范围和视野,透镜被分成几个面部分,每个部分都是一个单独的菲涅尔透镜。
HC-SR501 模块具有三个引脚。模块丝印被菲涅耳透镜遮挡,请参考下面给出的引脚排列。施加 5V – 12V 电源和接地,传感器输出在检测到运动时变为高电平,在空闲时变为低电平(未检测到运动)。
有两种触发模式决定传感器在检测到运动时如何反应。
单触发模式:持续运动将导致单触发。
多重触发模式:不断的运动会引起一系列的触发。
L - 在此设置中,传感器将处于单触发模式,在此模式下,当检测到运动时输出变高。并在延时电位器设定的一定时间内保持高电平。任何其他类型的检测都会被阻止,直到输出变低。
H - 选择这些设置将设置多重触发模式。在这种模式下,当检测到运动时输出变高,高电平周期由设置的电位器决定。但与单触发模式不同的是,进一步检测不会被阻止并且可以连续触发,当未检测到移动时,引脚变为低电平。
PIR 传感器背面有一个电位器,用于调节灵敏度。在电位器的帮助下,可以调整设备的灵敏度。顺时针旋转电位器会增加灵敏度,逆时针旋转电位器会降低灵敏度。
传感器背面的另一个锅设置输出将保持高电平的时间以及在检测到运动后顺时针转动锅会增加延迟,逆时针转动锅会减少延迟。
该模块带有一个 3.3V 稳压器,因此它可以由 4.5V 至 12V 电源供电。虽然 5V 是常用的。
该模块带有一个保护二极管,用于保护二极管免受反向电压和电流的影响。
HC-SR501 PIR 传感器模块故障排除
PIR 传感器无法正常工作可能有多种原因。需要通过一些测试来找出问题的根本原因。
传感器的工作电压为 4.8V 至 20V,因此无法使用 3.3V 为传感器供电。
在某些情况下会看到镜头顶部积聚了灰尘,因此 PIR 传感器可能会停止工作。
如果上述方法均无效,请尝试旋转电位器。如果将电位计的灵敏度设置为最低,那么这可能是传感器不工作的原因。
在测试了所有方法后,如果传感器不工作,那么您可以确定您手中的传感器有故障。
部分代码
#include "bflb\_mtimer.h"
#include "board.h"
#include "bflb\_gpio.h"
#include "locale.h"
#define DBG\_TAG "MAIN"
#include "log.h"
struct bflb\_device\_s \*gpio;
int main(void)
{
board\_init();
gpio = bflb\_device\_get\_by\_name("gpio");
bflb\_gpio\_init(gpio, GPIO\_PIN\_13, GPIO\_INPUT | GPIO\_PULLDOWN | GPIO\_SMT\_EN | GPIO\_DRV\_0);
bflb\_gpio\_init(gpio, GPIO\_PIN\_12, GPIO\_OUTPUT | GPIO\_PULLUP | GPIO\_SMT\_EN | GPIO\_DRV\_0);
while (1) {
bool isH = bflb\_gpio\_read(gpio, GPIO\_PIN\_13);
if(isH){
bflb\_gpio\_set(gpio, GPIO\_PIN\_12);
}else{
bflb\_gpio\_reset(gpio, GPIO\_PIN\_12);
}
LOG\_F("是否有人=%d\\r\\n", isH);
bflb\_mtimer\_delay\_ms(500);
}
}
Step1: 构建项目并实现 Ai-M61-32S 与 人体红外感应模块 HC-SR501 连接,并获取状态值。
默认灯光是关闭的:
检测有人经过时,红灯亮起。
TTS 语音模块:XFS5152CE 语音合成模块
TTS 是 Text To Speech 的缩写,即“从文本到语音”,是人机对话的一部分,让机器能够说话。
语音播报功能的实现方式* TTS 语音模块,比如 XFS5152、SYN6288 等
其中 TTS 语音模块使用起来最方便灵活,OTP 语音芯片最简单。
由于项目使用的是 XFS5152CE,所以简单介绍一下科大讯飞的 XFS5152CE 语音合成模块。
性能描述
1 采用 XFS5152CE 语音合成芯片,支持任意中文文本、英文文本合成及中英混读。
2 支持文本控制标记设置,使用便捷,同时提升了文本处理的正确率。
3具有文本智能分析处理功能,对常见的数字、号码、时间、日期、度量衡符号等能正确的识别和处理。
4.具有很强的多音字和中文姓氏处理能力。
5.支持内置多款播音人声可供选择。
6.支持 10 级语速调节。
7.支持 10 级音调调节。
8.支持 10 级音量调节。
9.支持 GB2312、GBK、BIG5 和 UNICODE 四种编码方式。
10.每次合成的文本量多达 4K 字节。
11.集成 80 种常用提示音效,适用于不同场合的信息提示、铃声、警报
等功能。
12.支持多种控制命令,如合成文本、停止合成、状态查询等。
13.板载扬声器。
14.支持三种连接方式:杜邦线接口、鳄鱼夹接口、PH2.0 防呆接口。
15.通信方式:IIC 通信。
16.12C 地址:0x50[新版本 0x30]。
由于协议使用的是 I2C,为了方便使用封装 I2C 功能。
Wire.h
#pragma once
#include "bflb\_gpio.h"
#include "bl616\_gpio.h"
#include "bl616\_glb.h"
#include "bl616\_glb\_gpio.h"
#include "../../drivers/lhal/include/hardware/i2c\_reg.h"
#include "bflb\_i2c.h"
#define lowByte(w) ((uint8\_t) ((w) & 0xff))
#define highByte(w) ((uint8\_t) ((w) >> 8))
bool getWireTimeoutFlag();
bool clearWireTimeoutFlag();
void setWireTimeout(int timeout, bool reset\_on\_timeout);
void onRequest(void (\*callback)());
void onReceive(void (\*callback)(int));
void setClock(int clockFrequency);
int readI2c();
int available();
int write\_len(uint8\_t \*str, int len);
int write\_str(uint8\_t \*str);
int write\_char(unsigned
char value);
void endTransmission\_stop(bool stop);
void endTransmission();
void beginTransmission(unsigned char addr);
int requestFrom\_stop(unsigned char addr, int quantity, bool stop);
int requestFrom(unsigned char addr, int quantity);
void end();
void begin\_addr(unsigned char addr);
void begin();
其中
#define lowByte(w) ((uint8_t) ((w) & 0xff))
#define highByte(w) ((uint8_t) ((w) >> 8))
这是 Arduino 中的方法,主要是获取高位和低位数据
Wire.c
#include "Wire.h"
#define PUT_UINT32_LE(field, value) \
do { \
(field)[0] = (uint8_t)((value) >> 0); \
(field)[1] = (uint8_t)((value) >> 8); \
(field)[2] = (uint8_t)((value) >> 16); \
(field)[3] = (uint8_t)((value) >> 24); \
} while (0)
struct bflb_device_s *i2c0;
uint8_t rbuf[128];
int available_count;
int indexi2c;
int wire_timeout;
bool wire_timeout_flag;
void board_i2c_pinmux_init(void)
{
GLB_GPIO_Type pinlist[] = {
GLB_GPIO_PIN_30,
GLB_GPIO_PIN_31
};
GLB_GPIO_Func_Init(GPIO_FUN_I2C0, pinlist, 2);
}
bool bflb_i2c_isend(struct bflb_device_s *dev)
{
uint32_t regval;
uint32_t reg_base;
reg_base = dev->reg_base;
regval = getreg32(reg_base + I2C_INT_STS_OFFSET);
if (regval & I2C_END_INT) {
return true;
}
return false;
}
bool bflb_i2c_isnak(struct bflb_device_s *dev)
{
uint32_t regval;
uint32_t reg_base;
reg_base = dev->reg_base;
regval = getreg32(reg_base + I2C_INT_STS_OFFSET);
if (regval & I2C_NAK_INT) {
return true;
}
return false;
}
bool bflb_i2c_isbusy(struct bflb_device_s *dev)
{
uint32_t regval;
uint32_t reg_base;
reg_base = dev->reg_base;
regval = getreg32(reg_base + I2C_BUS_BUSY_OFFSET);
if (regval & I2C_STS_I2C_BUS_BUSY) {
return true;
}
return false;
}
void bflb_i2c_enable(struct bflb_device_s *dev)
{
uint32_t regval;
uint32_t reg_base;
reg_base = dev->reg_base;
regval = getreg32(reg_base + I2C_CONFIG_OFFSET);
regval |= I2C_CR_I2C_M_EN;
putreg32(regval, reg_base + I2C_CONFIG_OFFSET);
}
bool bflb_i2c_isenable(struct bflb_device_s *dev)
{
uint32_t regval;
uint32_t reg_base;
reg_base = dev->reg_base;
regval = getreg32(reg_base + I2C_CONFIG_OFFSET);
if (regval & I2C_CR_I2C_M_EN) {
return true;
}
return false;
}
void bflb_i2c_disable(struct bflb_device_s *dev)
{
uint32_t regval;
uint32_t reg_base;
reg_base = dev->reg_base;
regval = getreg32(reg_base + I2C_CONFIG_OFFSET);
regval &= ~I2C_CR_I2C_M_EN;
putreg32(regval, reg_base + I2C_CONFIG_OFFSET);
regval = getreg32(reg_base + I2C_FIFO_CONFIG_0_OFFSET);
regval |= I2C_TX_FIFO_CLR;
regval |= I2C_RX_FIFO_CLR;
putreg32(regval, reg_base + I2C_FIFO_CONFIG_0_OFFSET);
regval = getreg32(reg_base + I2C_INT_STS_OFFSET);
regval |= I2C_CR_I2C_END_CLR;
regval |= I2C_CR_I2C_NAK_CLR;
regval |= I2C_CR_I2C_ARB_CLR;
putreg32(regval, reg_base + I2C_INT_STS_OFFSET);
}
void bflb_i2c_addr_config(struct bflb_device_s *dev, uint16_t slaveaddr, uint16_t subaddr, uint8_t subaddr_size, bool is_addr_10bit)
{
uint32_t regval;
uint32_t reg_base;
reg_base = dev->reg_base;
regval = getreg32(reg_base + I2C_CONFIG_OFFSET);
if (subaddr_size > 0) {
regval |= I2C_CR_I2C_SUB_ADDR_EN;
regval &= ~I2C_CR_I2C_SUB_ADDR_BC_MASK;
regval |= ((subaddr_size - 1) << I2C_CR_I2C_SUB_ADDR_BC_SHIFT);
} else {
regval &= ~I2C_CR_I2C_SUB_ADDR_EN;
}
regval &= ~I2C_CR_I2C_SLV_ADDR_MASK;
regval |= (slaveaddr << I2C_CR_I2C_SLV_ADDR_SHIFT);
#if !defined(BL602) && !defined(BL702)
if (is_addr_10bit) {
regval |= I2C_CR_I2C_10B_ADDR_EN;
} else {
regval &= ~I2C_CR_I2C_10B_ADDR_EN;
}
#endif
putreg32(subaddr, reg_base + I2C_SUB_ADDR_OFFSET);
putreg32(regval, reg_base + I2C_CONFIG_OFFSET);
}
void bflb_i2c_set_datalen(struct bflb_device_s *dev, uint16_t data_len)
{
uint32_t regval;
uint32_t reg_base;
reg_base = dev->reg_base;
regval = getreg32(reg_base + I2C_CONFIG_OFFSET);
regval &= ~I2C_CR_I2C_PKT_LEN_MASK;
regval |= ((data_len - 1) << I2C_CR_I2C_PKT_LEN_SHIFT) & I2C_CR_I2C_PKT_LEN_MASK;
putreg32(regval, reg_base + I2C_CONFIG_OFFSET);
}
void bflb_i2c_set_dir(struct bflb_device_s *dev, bool is_in)
{
uint32_t regval;
uint32_t reg_base;
reg_base = dev->reg_base;
regval = getreg32(reg_base + I2C_CONFIG_OFFSET);
if (is_in) {
regval |= I2C_CR_I2C_PKT_DIR;
} else {
regval &= ~I2C_CR_I2C_PKT_DIR;
}
putreg32(regval, reg_base + I2C_CONFIG_OFFSET);
}
int bflb_i2c_write_bytes(struct bflb_device_s *dev, uint8_t *data, uint32_t len, uint32_t timeout)
{
uint32_t reg_base;
uint32_t temp = 0;
uint8_t *tmp_buf;
uint64_t start_time;
reg_base = dev->reg_base;
tmp_buf = data;
while (len >= 4) {
for (uint8_t i = 0; i < 4; i++) {
temp += (tmp_buf[i] << ((i % 4) * 8));
}
tmp_buf += 4;
len -= 4;
start_time = bflb_mtimer_get_time_ms();
while ((getreg32(reg_base + I2C_FIFO_CONFIG_1_OFFSET) & I2C_TX_FIFO_CNT_MASK) == 0) {
if ((bflb_mtimer_get_time_ms() - start_time) > timeout) {
return -ETIMEDOUT;
}
}
putreg32(temp, reg_base + I2C_FIFO_WDATA_OFFSET);
if (!bflb_i2c_isenable(dev)) {
bflb_i2c_enable(dev);
}
temp = 0;
}
if (len > 0) {
for (uint8_t i = 0; i < len; i++) {
temp += (tmp_buf[i] << ((i % 4) * 8));
}
start_time = bflb_mtimer_get_time_ms();
while ((getreg32(reg_base + I2C_FIFO_CONFIG_1_OFFSET) & I2C_TX_FIFO_CNT_MASK) == 0) {
if ((bflb_mtimer_get_time_ms() - start_time) > timeout) {
return -ETIMEDOUT;
}
}
putreg32(temp, reg_base + I2C_FIFO_WDATA_OFFSET);
if (!bflb_i2c_isenable(dev)) {
bflb_i2c_enable(dev);
}
}
start_time = bflb_mtimer_get_time_ms();
while (bflb_i2c_isbusy(dev) || !bflb_i2c_isend(dev) || bflb_i2c_isnak(dev)) {
if ((bflb_mtimer_get_time_ms() - start_time) > timeout) {
return -ETIMEDOUT;
}
}
bflb_i2c_disable(dev);
return 0;
}
int bflb_i2c_read_bytes(struct bflb_device_s *dev, uint8_t *data, uint32_t len, uint32_t timeout)
{
uint32_t reg_base;
uint32_t temp = 0;
uint8_t *tmp_buf;
uint64_t start_time;
reg_base = dev->reg_base;
tmp_buf = data;
bflb_i2c_enable(dev);
while (len >= 4) {
start_time = bflb_mtimer_get_time_ms();
while ((getreg32(reg_base + I2C_FIFO_CONFIG_1_OFFSET) & I2C_RX_FIFO_CNT_MASK) == 0) {
if ((bflb_mtimer_get_time_ms() - start_time) > timeout) {
return -ETIMEDOUT;
}
}
temp = getreg32(reg_base + I2C_FIFO_RDATA_OFFSET);
PUT_UINT32_LE(tmp_buf, temp);
tmp_buf += 4;
len -= 4;
}
if (len > 0) {
start_time = bflb_mtimer_get_time_ms();
while ((getreg32(reg_base + I2C_FIFO_CONFIG_1_OFFSET) & I2C_RX_FIFO_CNT_MASK) == 0) {
if ((bflb_mtimer_get_time_ms() - start_time) > timeout) {
return -ETIMEDOUT;
}
}
temp = getreg32(reg_base + I2C_FIFO_RDATA_OFFSET);
for (uint8_t i = 0; i < len; i++) {
tmp_buf[i] = (temp >> (i * 8)) & 0xff;
}
}
start_time = bflb_mtimer_get_time_ms();
while (bflb_i2c_isbusy(dev) || !bflb_i2c_isend(dev)) {
if ((bflb_mtimer_get_time_ms() - start_time) > timeout) {
return -ETIMEDOUT;
}
}
bflb_i2c_disable(dev);
return 0;
}
void begin_addr(unsigned char addr) {
wire_timeout = 100;
wire_timeout_flag = false;
board_i2c_pinmux_init();
i2c0 = bflb_device_get_by_name("i2c0");
bflb_i2c_init(i2c0, 50000);
}
void begin() {
wire_timeout = 100;
wire_timeout_flag = false;
board_i2c_pinmux_init();
i2c0 = bflb_device_get_by_name("i2c0");
bflb_i2c_init(i2c0, 50000);
}
void end() {
bflb_i2c_deinit(i2c0);
}
int requestFrom_stop(unsigned char addr, int quantity, bool stop) {
indexi2c = 0;
bflb_i2c_disable(i2c0);
bflb_i2c_enable(i2c0);
bflb_i2c_addr_config(i2c0, addr, 0, 0, false);
bflb_i2c_set_datalen(i2c0,quantity);
bflb_i2c_set_dir(i2c0, 1);
bflb_i2c_read_bytes(i2c0, rbuf,quantity,wire_timeout);
available_count = quantity;
if(true == stop){
bflb_i2c_disable(i2c0);
}
return 0;
}
int requestFrom(unsigned char addr, int quantity) {
indexi2c = 0;
bflb_i2c_disable(i2c0);
bflb_i2c_enable(i2c0);
bflb_i2c_addr_config(i2c0, addr, 0, 0, false);
bflb_i2c_set_datalen(i2c0,quantity);
bflb_i2c_set_dir(i2c0, 1);
bflb_i2c_read_bytes(i2c0, rbuf,quantity,wire_timeout);
available_count = quantity;
return 0;
}
void beginTransmission(unsigned char addr) {
bflb_i2c_addr_config(i2c0, addr, 0, 0, false);
bflb_i2c_set_dir(i2c0, 0);
}
void endTransmission_stop(bool stop) {
bflb_i2c_disable(i2c0);
}
void endTransmission() {
bflb_i2c_disable(i2c0);
}
int write_char(unsigned char value) {
bflb_i2c_set_datalen(i2c0, 1);
bflb_i2c_write_bytes(i2c0, &value, 1,wire_timeout);
return 0;
}
int write_str(uint8_t *str) {
bflb_i2c_set_datalen(i2c0, strlen((const char*)str));
bflb_i2c_write_bytes(i2c0, str, strlen((const char*)str),wire_timeout);
return 0;
}
int write_len(uint8_t *str, int len) {
bflb_i2c_set_datalen(i2c0, len);
int ret = bflb_i2c_write_bytes(i2c0, str, len,wire_timeout);
return ret;
}
int available() {
return available_count;
}
int readI2c() {
unsigned char ret;
if(available_count){
available_count--;
ret = rbuf[indexi2c];
indexi2c++;
return ret;
}
return 0;
}
void setClock(int clockFrequency) {
bflb_i2c_deinit(i2c0);
bflb_i2c_init(i2c0, clockFrequency);
}
void onReceive(void (*callback)(int)) {
}
void onRequest(void (*callback)()) {
}
void setWireTimeout(int timeout, bool reset_on_timeout) {
wire_timeout = timeout;
wire_timeout_flag = true;
}
bool clearWireTimeoutFlag() {
wire_timeout_flag = false;
return true;
}
bool getWireTimeoutFlag() {
return wire_timeout_flag;
}
这里修改了 I2C 引脚
GLB_GPIO_Type pinlist[] = {
GLB_GPIO_PIN_30,
GLB_GPIO_PIN_31
};
默认是 GLB_GPIO_PIN_14、GLB_GPIO_PIN_15.然后封装.
XFS5152CE 模块功能代码
XFS.h
#ifndef __XFS_H
#define __XFS_H
#include
#include
#include
#include
#include
#include
#include //Added for uint_t
#include
#include "bflb_mtimer.h"
struct XFS_Protocol_TypeDef
{
uint8_t DataHead;
uint8_t Length_HH;
uint8_t Length_LL;
uint8_t Commond;
uint8_t EncodingFormat;
const char* Text;
};
typedef enum
{
CMD_StartSynthesis = 0x01,
CMD_StopSynthesis = 0x02,
CMD_PauseSynthesis = 0x03,
CMD_RecoverySynthesis = 0x04,
CMD_CheckChipStatus = 0x21,
CMD_PowerSavingMode = 0x88,
CMD_NormalMode = 0xFF
} CMD_Type;
void StartSynthesis(const char* str);
bool IIC_WriteByte(uint8_t data);
void IIC_WriteByteSize(uint8_t* buff, uint32_t size);
void SendCommond(CMD_Type cmd);
void StopSynthesis();
void PauseSynthesis();
void RecoverySynthesis();
typedef enum
{
GB2312 = 0x00,
GBK = 0x01,
BIG5 = 0x02,
UNICODE = 0x03
} EncodingFormat_Type;
void SetEncodingFormat(EncodingFormat_Type encodingFormat);
typedef enum
{
ChipStatus_InitSuccessful = 0x4A,
ChipStatus_CorrectCommand = 0x41,
ChipStatus_ErrorCommand = 0x45,
ChipStatus_Busy = 0x4E,
ChipStatus_Idle = 0x4F
} ChipStatus_Type;
typedef enum
{
Style_Single,
Style_Continue
} Style_Type;
void SetStyle(Style_Type style);
typedef enum
{
Language_Auto,
Language_Chinese,
Language_English
} Language_Type;
void SetLanguage(Language_Type language);
typedef enum
{
Articulation_Auto,
Articulation_Letter,
Articulation_Word
} Articulation_Type;
void SetArticulation(Articulation_Type articulation);
typedef enum
{
Spell_Disable,
Spell_Enable
} Spell_Type;
void SetSpell(Spell_Type spell);
typedef enum
{
Reader_XiaoYan = 3,
Reader_XuJiu = 51,
Reader_XuDuo = 52,
Reader_XiaoPing = 53,
Reader_DonaldDuck = 54,
Reader_XuXiaoBao = 55
} Reader_Type;
void SetReader(Reader_Type reader);
typedef enum
{
NumberHandle_Auto,
NumberHandle_Number,
NumberHandle_Value
} NumberHandle_Type;
void SetNumberHandle(NumberHandle_Type numberHandle);
typedef enum
{
ZeroPronunciation_Zero,
ZeroPronunciation_O
} ZeroPronunciation_Type;
void SetZeroPronunciation(ZeroPronunciation_Type zeroPronunciation);
typedef enum
{
NamePronunciation_Auto,
NamePronunciation_Constraint
} NamePronunciation_Type;
void SetNamePronunciation(NamePronunciation_Type namePronunciation);
void SetSpeed(int speed);
void
SetIntonation(int intonation);
void SetVolume(int volume);
typedef enum
{
PromptTone_Disable,
PromptTone_Enable
} PromptTone_Type;
void SetPromptTone(PromptTone_Type promptTone);
typedef enum
{
OnePronunciation_Yao,
OnePronunciation_Yi
} OnePronunciation_Type;
void SetOnePronunciation(OnePronunciation_Type onePronunciation);
typedef enum
{
Rhythm_Diasble,
Rhythm_Enable
} Rhythm_Type;
void SetRhythm(Rhythm_Type rhythm);
void SetRestoreDefault();
void XFS5152CE(uint8_t encodingFormat);
void Begin(uint8_t addr);
uint8_t GetChipStatus();
void TextCtrl(char c, int d);
#endif
XFS.c
#include "XFS.h"
#include
#define DBG_TAG "MAIN"
#include "log.h"
#define XFS_DataHead (uint8_t)0xFD
uint8_t I2C_Addr;
uint8_t ChipStatus;
struct XFS_Protocol_TypeDef DataPack;
size_t foo( const char* restrict src, uint8_t* restrict dst, size_t dst_maxlen )
{
size_t idx = 0;
for( ; src[idx] && dst_maxlen; ++idx )
{
if( idx%8 == 0 )
*dst = 0;
if( src[idx] != '0' )
*dst |= 1<7-idx%8);
if( idx%8 == 7 )
++dst, --dst_maxlen;
}
return (idx+7)/8;
}
void XFS5152CE(uint8_t encodingFormat)
{
DataPack.DataHead = XFS_DataHead;
DataPack.Length_HH = 0x00;
DataPack.Length_LL = 0x00;
DataPack.Commond = 0x00;
DataPack.EncodingFormat = encodingFormat;
ChipStatus = 0x00;
}
void Begin(uint8_t addr)
{
I2C_Addr = addr;
XFS5152CE(GB2312);
begin();
}
uint8_t GetChipStatus()
{
uint8_t AskState[4] = {0xFD,0x00,0x01,0x21};
beginTransmission(I2C_Addr);
write_len(AskState,4);
endTransmission();
bflb_mtimer_delay_ms(100);
requestFrom(I2C_Addr, 1);
while (available())
{
ChipStatus = readI2c();
}
LOG_F("ChipStatus=%x\r\n", ChipStatus);
return ChipStatus;
}
bool IIC_WriteByte(uint8_t data)
{
beginTransmission(I2C_Addr);
write_char(data);
endTransmission();
bflb_mtimer_delay_ms(10);
return true;
}
void IIC_WriteBytes(uint8_t* buff, uint32_t size)
{
for (uint32_t i = 0; i < size; i++)
{
IIC_WriteByte(buff[i]);
}
}
void StartSynthesis(const char* str)
{
uint16_t size = strlen(str) + 2;
DataPack.Length_HH = highByte(size);
DataPack.Length_LL = lowByte(size);
DataPack.Commond = CMD_StartSynthesis;
DataPack.Text = str;
uint8_t dst[(strlen(DataPack.Text)-1+7)/8];
size_t len = foo(DataPack.Text, dst, sizeof(dst)/sizeof(*dst) );
IIC_WriteBytes((uint8_t*)&DataPack,5);
IIC_WriteBytes(DataPack.Text, strlen(str));
}
void SendCommond(CMD_Type cmd)
{
DataPack.Length_HH = 0x00;
DataPack.Length_LL = 0x01;
DataPack.Commond = cmd;
beginTransmission(I2C_Addr);
write_len((uint8_t*)&DataPack, 4);
endTransmission();
}
void StopSynthesis()
{
SendCommond(CMD_StopSynthesis);
}
void PauseSynthesis()
{
SendCommond(CMD_PauseSynthesis);
}
void RecoverySynthesis()
{
SendCommond(CMD_RecoverySynthesis);
}
void TextCtrl(char c, int d)
{
char str[10];
if (d != -1)
sprintf(str, "[%c%d]", c, d);
else
sprintf(str, "[%c]", c);
StartSynthesis(str);
}
void SetEncodingFormat(EncodingFormat_Type encodingFormat)
{
DataPack.EncodingFormat = encodingFormat;
}
void SetStyle(Style_Type style)
{
TextCtrl('f', style);
while(GetChipStatus() != ChipStatus_Idle)
{
bflb_mtimer_delay_ms(30);
}
}
void SetLanguage(Language_Type language)
{
TextCtrl('g', language);
while(GetChipStatus() != ChipStatus_Idle)
{
bflb_mtimer_delay_ms(30);
}
}
void SetArticulation(Articulation_Type articulation)
{
TextCtrl('h', articulation);
while(GetChipStatus() != ChipStatus_Idle)
{
bflb_mtimer_delay_ms(30);
}
}
void SetSpell(Spell_Type spell)
{
TextCtrl('i', spell);
while(GetChipStatus() != ChipStatus_Idle)
{
bflb_mtimer_delay_ms(30);
}
}
void SetReader(Reader_Type reader)
{
TextCtrl('m', reader);
while(GetChipStatus() != ChipStatus_Idle)
{
bflb_mtimer_delay_ms(30);
}
}
void SetNumberHandle(NumberHandle_Type numberHandle)
{
TextCtrl('n', numberHandle);
while(GetChipStatus() != ChipStatus_Idle)
{
bflb_mtimer_delay_ms(30);
}
}
void SetZeroPronunciation(ZeroPronunciation_Type zeroPronunciation)
{
TextCtrl('o', zeroPronunciation);
while(GetChipStatus() != ChipStatus_Idle)
{
bflb_mtimer_delay_ms(30);
}