微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > TI蓝牙设计交流 > 关于CC2640如何通过蓝牙发送数据

关于CC2640如何通过蓝牙发送数据

时间:10-02 整理:3721RD 点击:

各位TI大神好,我最近刚学习使用TI的CC2640,现在根据软件开发手册调通了SPI和UART的一些通信,现在想用蓝牙把从外部传感器读回来的数据传出去该怎么实现?萌新看不太懂文档,求大神指导~~

1、建议参考TI的sensortag例程,这个例程中将很多传感器的采集数据通过BLE发送到手机的APP端口

2、BLE发送数据可以通过:  广播,Notify, Indicate的方式

<1>广播的方式很简单,直接将采集的数据进行广播处理

1.可连接的非定向广播(Connectable Undirected Event Type)。这是一种用途最广的广播类型,包括广播数据和扫描响应数据,它表示当前设备可以接受其他任何设备的连接请求。

2.可连接的定向广播(Connectable Directed Event Type)。定向广播类型是为了尽可能快的建立连接。这种报文包含两个地址:广播者的地址和发起者的地址。发起者收到发给自己的定向广播报文之后,可以立即发送连接请求作为回应。

定向广播类型有特殊的时序要求。完整的广播事件必须每3.75ms重复一次。这一要求使得扫描设备只需扫描3.75ms便可以收到定向广播设备的消息。

当然,如此快的发送会让报文充斥着广播信道,进而导致该区域内的其他设备无法进行广播。因此,定向广播不可以持续1.28s以上的时间。如果主机没有主动要求停止,或者连接没有建立,控制器都会自动停止广播。一旦到了1.28s,主机便只能使用间隔长得多的可连接非定向广播让其他设备来连接。

当使用定向广播时,设备不能被主动扫描。此外,定向广播报文的净荷中也不能带有其他附加数据。该净荷只能包含两个必须的地址。

3.不可连接的非定向广播(Non-connectable Undirected Event Type)。仅仅发送广播数据。

4.可扫描的非定向广播(Scannable Undirected Event Type)。这种广播不能用于发起连接,但允许其他设备扫描该广播设备。这意味着该设备可以被发现,既可以发送广播数据,也可以响应扫描发送扫描回应数据,但不能建立连接。这是一种适用于广播数据的广播形式,动态数据可以包含于广播数据之中,而静态数据可以包含于扫描响应数据之中。

注意:所谓的定向和非定向针对的是广播的对象,如果是针对特定的对象进行广播(在广播包PDU中会包含目标对象的MAC)就是定向广播,反之就是非定向。可连接和不可连接是指是否接受连接请求,如果是不可连接的广播类型,它将不回应连接请求。可扫描广播类型是指回应扫描请求。

<2>Notify:

在BLE建立Notification连接后,从机向主机发送的数据包,不需要主机确认收到,适合大量数据快速发送。
从机 Notification发送方式有两种,用户根据自身要求选择:
(1)调用GATT_Notification( uint16 connHandle, attHandleValueNoti_t *pNoti, uint8 authenticated );直接
发送
(2)调用GATTServApp_ProcessCharCfg函数,这个函数内部最终会导致master那边调用一个read请求,回调
到simpleProfile_ReadAttrCB()。用这个函数,只有master向Peripheral的Notification允许位写1,才能使能从
机,从而调用GATT_Notification向主机发送Notification。
<3>Notify和Indicate的区别

BLE introduction: Notify or Indicate

This is going to be a short article. I have been getting questions regarding the differences between Notify and Indicate. The short answer is that they both basically do the same thing, except Indicate requires acknowledgement, while Notify does not. For the longer answer, please read the rest of my post.

By default, you cannot push data to your remote client whenever your Bluetooth low energy (BLE) device has new data to publish. If you read my previous post, you will know that you need to enable the proper permission and include a "Client Characteristic Configuration Descriptor" (CCCD) for that to happen. Not forgetting, your remote client must subscribe to the attribute via the CCCD to receive the pushed data. 

Typically, people push data when they want their remote client to asynchronously receive updates whenever their BLE device has new data. While you can perform a periodic polling, the method wouldn't be very energy efficient and you will not get the quickest update (this depends on your polling rate). Also your BLE device might get updates in an aperiodic fashion, so periodic polling is an utter waste of energy. Furthermore, polling requires two-way communication and Notify is one way, so you will save on radio airtime which would lead to further energy reduction. However, because Notify is unacknowledged, it is unreliable since you will not know whether your remote client has received the data.

To rectify that, let me introduce the Indicate feature. It is almost the same as Notify, except it supports acknowledgment. Your remote client will have to send an acknowledgement if it has received the data. However, such reliability comes at the expense of speed since your BLE device will wait for the acknowledgement until it has timed out.

Conclusion

To quickly sum things up.

For most use cases, I would recommend you start with Notify until you find out in your test environment that data is dropping out, then you move into Indicate. In any case, Indicate might take up additional airtime, but it shouldn’t drastically affect your use case. If the communication speed of Indicate is bordering your requirement, then perhaps you should be looking at alternative wireless technologies because BLE is not meant for high-speed communication. 

看我个性签名档的博客地址,《CC2640之添加自定义服务》。

你可以根据TI的学院教程学习一下。

http://software-dl.ti.com/lprf/simplelink_academy/overview.html

你好,

CC2640 Sensortag是非常好的demo,可以直接拿来和IOS系统做连接。

但是并不是很好上手的工程,因为里面的东西太多了,还包含一些OAD的框架在里面。

首先还是在sensortag工程上看:

注意下面这个函数:

static void SensorTag_processAppMsg(stEvt_t *pMsg)
{
switch (pMsg->event)
{
case ST_STATE_CHANGE_EVT:
SensorTag_processStateChangeEvt((gaprole_States_t)pMsg->serviceID);
break;

case ST_CHAR_CHANGE_EVT:
SensorTag_processCharValueChangeEvt(pMsg->serviceID, pMsg->paramID);
break;

default:
// Do nothing.
break;
}
}

在ST_CHAR_CHANGE_EVT事件中:

定义了很多传感器的profile值修改后会被调用的API。

我们以温度传感器为例:

你可以看到两个东西你需要关注:

1.

void SensorTagTmp_processCharChangeEvt(uint8_t paramID)
{
uint8_t newValue;

switch (paramID)
{
case SENSOR_CONF:
if ((SensorTag_testResult() & SENSOR_TMP_TEST_BM) == 0)
{
sensorConfig = ST_CFG_ERROR;
}

if (sensorConfig != ST_CFG_ERROR)
{
IRTemp_getParameter(SENSOR_CONF, &newValue);

if (newValue == ST_CFG_SENSOR_DISABLE)
{
// Reset characteristics
initCharacteristicValue(SENSOR_DATA, 0, SENSOR_DATA_LEN);

// Deactivate task
Task_setPri(Task_handle(&sensorTask), -1);
}
else
{
Task_setPri(Task_handle(&sensorTask), SENSOR_TASK_PRIORITY);
}

sensorConfig = newValue;
}
else
{
// Make sure the previous characteristics value is restored
initCharacteristicValue(SENSOR_CONF, sensorConfig, sizeof(uint8_t));
}

// Make sure sensor is disabled
SensorTmp007_enable(false);
break;

case SENSOR_PERI:
IRTemp_getParameter(SENSOR_PERI, &newValue);
sensorPeriod = newValue * SENSOR_PERIOD_RESOLUTION;
break;

default:
// Should not get here
break;
}
}

在SENSOR_CONF这个switch case里面就有读取

if (sensorConfig != ST_CFG_ERROR)
{
IRTemp_getParameter(SENSOR_CONF, &newValue);

if (newValue == ST_CFG_SENSOR_DISABLE)
{
// Reset characteristics
initCharacteristicValue(SENSOR_DATA, 0, SENSOR_DATA_LEN);

// Deactivate task
Task_setPri(Task_handle(&sensorTask), -1);
}
else
{
Task_setPri(Task_handle(&sensorTask), SENSOR_TASK_PRIORITY);
}

sensorConfig = newValue;
}

CC2640读取手机端对该profile的修改。

2.

在sensortag_tmp.c

static void sensorTaskFxn(UArg a0, UArg a1)
{
typedef union
{
struct
{
uint16_t tempTarget, tempLocal;
} v;
uint16_t a[2];
} Data_t;

// Register task with BLE stack
ICall_registerApp(&sensorSelfEntity, &sensorSem);

// Deactivate task (active only when measurement is enabled)
Task_setPri(Task_handle(&sensorTask), -1);

// Task loop
while (true)
{
if (sensorConfig == ST_CFG_SENSOR_ENABLE)
{
Data_t data;

// Read data
SensorTmp007_enable(true);
DELAY_MS(TEMP_MEAS_DELAY);
SensorTmp007_read(&data.v.tempLocal, &data.v.tempTarget);
SensorTmp007_enable(false);

// Update GATT
IRTemp_setParameter(SENSOR_DATA, SENSOR_DATA_LEN, data.a);

// Next cycle
DELAY_MS(sensorPeriod - TEMP_MEAS_DELAY);
}
else
{
DELAY_MS(SENSOR_DEFAULT_PERIOD);
}
}
}

该函数里面读取温度传感器的值,然后更新到蓝牙profile.

// Update GATT
IRTemp_setParameter(SENSOR_DATA, SENSOR_DATA_LEN, data.a);

你好,

如果可以的话,请你尽量还是先拿simple_peripheral例程入手。

该例程比较简单,但是不包含任何传感器的数据采集,你可以拿char 4入手,因为该characteristic带notification功能,手机可以一直显示你CC2640传输的每串数据。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top