TI CC254x学习笔记整理
更新时间:2023-12-09 14:59:01 阅读量: 教育文库 文档下载
- tiktok推荐度:
- 相关推荐
Ti CC2540蓝牙模块学习笔记整理
接触CC2540几天,终于有了初步的理解,现将笔记整理如下,只是皮毛,如有错误,还请指正,还有好多没闹明白的地方,以后应该还会继续向里面更新~ 一、整体
1.TI的蓝牙平台支持2种协议栈/应用配置:单一设备配置、网络处理器配置 2.协议栈最顶层2个通用profile:
GAP 通用访问配置文件层 Generic Access Profile GATT 通用属性配置文件层 Generic Attribute Profile
3. GAP:处理设备的接入方式及接入过程:①设备发现 ②链路建立 ③链路终止 ④启动安全功能 ⑤设备配置(主要是连接参数配置)
GATT:完成服务器与客户端之间通信的相关子过程
4.BLE支持40个信道的跳频机制,其中3个通道用于Advertise,剩下的用于数据通信 5.OS抽象层:疑问 如何配置一个新的任务,任务的优先级,事件触发机制,消息的传递 6.主要用于实现的是2个代码文件:
OSAL_SimpleBLEPeripheral.c 任务回调函数数据的定义 和 任务初始化函数定义 作为OSAL的外部全局变量
SimpleBLEPeripheral.c BLE应用程序的实现代码,该源文件调用一系列的BLE API函数,完成复杂的蓝牙协议
通过 constpTaskEventHandleFntasksArr[] 数组来存储要调用的函数
simpleBLEPeripheral.h 一些常量的定义,和蓝牙应用程序任务初始化和任务回调函数声明。 7.LL层任务函数优先级 最高, 而应用程序函数的优先级最低
8.OSAL为每个任务分配了1个16位的Event,每一位代表一个事件,最高位代表SYS_EVENT_MSG,这个事件被OSAL系统保留
9.main()函数中最后进入的 void osal_run_system( void ),这个函数就是看相应任务有没有事件发生,有时间发生就跳转到相应的函数
10.任务间通信,一般通过 事件 和 消息 进行,每当任务间有消息传递,都会触发SYS_EVENT_MSG事件,并且每次处理完事件后,都要清空标志位。
osal_set_event() OSAL.h中 该函数会直接调度一个事件
osal_start_timerEx() OSAL_Timers.h中 需要掩饰触发的事件,调用这个函数
11.Heap Manager(堆栈管理),函数osal_mem_alloc,给函数分配需要的字节数,osal_mem_free()用来释放内存。
二、OSAL( 操作系统抽象层 Operate System Abstraction Layer ) 1.OSAL中的消息:
发送消息前,用osal_msg_allocate()函数分配内存空间,填充数据,调用osal_msg_send()将消息发送到指定的函数中去。然后置位该函数的SYS_EVENT_MSG,然后接收端使用osal_mem_receive()将消息接收过来,接收完成后,使用osal_mem_deallocate()函数来回收当前消息所占用的内存。OSAL推荐在任务中使用独立的消息接收函数来处理消息,例如: simpleBLEPeripheral_ProcessOSALMsg()函数。 2.GAP (通用访问配置文件层 Generic Access Profile )
连接过程:①设备发现 ②链路建立 ③链路终止 ④启动安全功能 ⑤设备配置(主要是连接参数配置) GAP层总是工作在以下角色中的1种:
Broadcaster 广播员,表明我在,但是你们只能看到我,不可以连接我 Observer 观察者,看看谁在,我只观察,不连接 Peripheral 外设,我存在,设想连我,我就连谁 Centeral 中心,看看谁在,工作在单层或多层的连接
3.连接过程: Peripheral向外广播->Centeral接收到向从机发送“Scan”命令->Peripheral以“ScanResp”命令回应->Centeral发送连接请求
4.Connect Interval 通信间隙 每个间隔1.25ms为基本单位,最小6单位7.5mS,最大3200单位4.0S。 5.Slave Latency 从机延时 表示Peripheral可以连续忽略的连接数,最大不能超过499个,最长不能超过32S。 6.Supervision Timeout 监管超时 2个成功连接事件之间的最大间隔。
7.Profile 一种规范 ; Service 一个服务 ; Characteristic 特征值 ; UUID 统一标识码(Service,Characteristic都需要),Centeral与Peripheral间的通信,均通过Characteristic实现 8.发送数据
主->从 Client调用GATT_WriteCharValue()函数发送;
从->主 Service调用GATT_Notification()函数实现。 9.接收数据
从<-主 从机接收后,会产生1个GATT_Profile_Callback调用; 三、BLE 四、低功耗部分 1.如何总是在PM1
osal_pwrmgr_device( PWRMGR_ALWAYS_ON ); 2.如何进入PM2
osal_pwrmgr_device( PWRMGR_BATTERY );在空闲的时候就会进入到PM2模式 3.如何进入PM3
存在连接就断开连接,存在广播就停掉广播,并确认自己创建的所有定时任务都已关闭,则系统应该就会进入PM3模式,只能进行外部中断唤醒 4.CC2540低功耗中引脚的设置问题
不用的引脚应该与外部不连接,并将引脚配置为通用上拉输入状态(除了P1.0,P1.1),并且这些脚不应该与VDD,GND直接相连。
*关于P1.0,P1.1,“User Guide”给出的解释是\capability\,字面意思是没有上下拉能力,可是我没理解,这个上下拉,是指什么。。。 五、常用的命令,功能,以及实现方法 1.切换电源模式
osal_pwrmgr_device( PWRMGR_ALWAYS_ON ); osal_pwrmgr_device( PWRMGR_BATTERY ); 2.Peripheral怎么主动断开与Centeral的连接
bStatus_tGAPRole_TerminateConnection(); 在文件peripheralBroadcaster.c文件中 3.怎么设置Peripheral的广播的超时时间
首先保证是限制类型的广播 即DEVDISC_MODE_LIMIT(永久广播是 DEVDISC_MODE_GENERAL ),在 simpleBLEPeripheral.c文件 static uint8 advertData[]数组中设置。
当模式处于Limit模式时,广播超时的设置可通过设置宏 TGAP_LIM_ADV_TIME_OUT,不设置的话,默认超时时间是180S。 4.如何打开与关闭广播
uint8 initial_advertising_enable = TRUE/FALSE TRUE:打开广播 FALSE:关闭广播
GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof(uint8), &initial_advertising_enable );
CC2541 BLE源码阅读知识积累之外设从机Peripheral工作模式 阅读的源代码:核心主要是位于BLE/project/SimpleBLEPeripheral部分
阅读的参考文档:TI_BLE_Software_Developer's_Guide.pdf,BLE_CC2540_DeepDive_Training_2011.pdf,TI_BLE_Sample_Applications_Guide.pdf,SIG的Core_V4.0.pdf
在BLE的源码架构中,感觉是好复杂,还好TI对协议栈不开源,不然就得累死。能力有限只能把整个架构从最简单的主从工作模式入手。
1.BLE中主从机建立连接,到配对和绑定的过程如下图。
正如上图所示,最简单一次蓝牙通信需要以上相关步骤,包括discovery device,connect,pairing,bond等4个主要部分。
2.BLE中的GAP和GATT
初始接触,感觉十分的抽象,到现在为止,GAP个人认为就是监控上图中的交互状态,比如从广播变成连接,到配对等。
GATT通俗理解为用于主从机之间的客户端和服务器端的数据交互,以Attribute Table来体现。 GAP Role Profile:在GAP剧本里所处的4个角色:广播Advertise,主机central,从机Peripheral,观察者Observer。
GATT Attribute:通用属性配置文件。
3.SimpleBLEPeripheral_Init函数解析。
无论是在主机还是从机,任何的蓝牙都将这部分内容作为自己的APPlication,在init中都会完成Bluetooth的GAP,GATT,SM等相关初始化。 void SimpleBLEPeripheral_Init( uint8 task_id ) {
simpleBLEPeripheral_TaskID = task_id;
// Setup the GAP Peripheral Role Profile //GAP外设剧本 {
#if defined( CC2540_MINIDK )
// For the CC2540DK-MINI keyfob, device doesn't start advertising until button is pressed uint8 initial_advertising_enable = FALSE; #else
// For other hardware platforms, device starts advertising upon initialization uint8 initial_advertising_enable = TRUE;//广播使能 #endif
// By setting this to zero, the device will go into the waiting state after // being discoverable for 30.72 second, and will not being advertising again // until the enabler is set back to TRUE uint16 gapRole_AdvertOffTime = 0;
uint8 enable_update_request = DEFAULT_ENABLE_UPDATE_REQUEST;//使能请求更新
uint16 desired_min_interval = DEFAULT_DESIRED_MIN_CONN_INTERVAL; //最小连接间隔0.1ms
} break;
case GAPROLE_WAITING_AFTER_TIMEOUT: {
#if (defined HAL_LCD) && (HAL_LCD == TRUE) HalLcdWriteString( \HAL_LCD_LINE_3 ); #endif // (defined HAL_LCD) && (HAL_LCD == TRUE) } break;
case GAPROLE_ERROR: {
#if (defined HAL_LCD) && (HAL_LCD == TRUE) HalLcdWriteString( \HAL_LCD_LINE_3 ); #endif // (defined HAL_LCD) && (HAL_LCD == TRUE) } break; default: {
#if (defined HAL_LCD) && (HAL_LCD == TRUE) HalLcdWriteString( \HAL_LCD_LINE_3 ); #endif // (defined HAL_LCD) && (HAL_LCD == TRUE) } break; }
可以看到GAP Role 作为外设从机时,各种状态的变化,而这些状态 变化都由GAP(不开源部分)调用回调函数,将当前状态参数传入,以使得不同的APP做出反应。体现了一种回调函数设计的便捷性。
5.GATT Server的相关设置函数。 // Initialize GATT attributes
GGS_AddService( GATT_ALL_SERVICES ); // GAP Service GATTServApp_AddService( GATT_ALL_SERVICES ); // GATT attributes DevInfo_AddService(); // Device Information Service
SimpleProfile_AddService( GATT_ALL_SERVICES ); // Simple GATT Profile
通常一个GATT中GAP server和GATT server是必须强制存在的(Mandatory)以及自己设计的profile server. 作为GATT的server和client,主要通过Attribute来进行交互,当client请求server读取数据时,通过如下注册的回调函数来进行访问。
// Register callback with SimpleGATTprofile
VOID SimpleProfile_RegisterAppCBs( &simpleBLEPeripheral_SimpleProfileCBs );//给应用注册回调函数 在回调函数中对时间做出处理。 蓝牙设计
1. 问:什么是蓝牙通信?
答:蓝牙通讯最初设计初衷是方便移动电话(手机)与配件之间进行低成本、低功耗无线通信连接,现在已经成为IEEE802.15标准,得到全球上万家厂商支持。
2. 问:如果从事蓝牙开发有没有前途?
答:严格地说,这不是一个技术问题,而是一个世界观问题。什么是前途?如果单纯是金钱,从事技术是不太可能暴富的(注意比尔.盖茨是个技术商人);如果想用你所能改善世界,这是可能的,毕竟蓝牙的主要用途是民用。附带说一句,考虑赚钱和改变世界是中国和西方人世界观的主要差别。
3. 问:蓝牙有什么优势?
答:首先是低功耗,以BLE 4.0为例,一节钮扣电池在静态工作状态可以支持一年;其次是低成本,TI公司的CC2540蓝牙SOC方案芯片出售价仅1美元,可以让人们低廉使用蓝牙技术;再次是开放性,2.4GHz的频段全球开放,没有政府监管;最后是适合时代潮流,现在是手机的时代,蓝牙技术本来就为它而生。
4. 问:蓝牙4.0协议和BLE是什么?
答:蓝牙4.0协议是2010年6月由SIG(Special Interest Group)发布的最新标准,它有2种模式:BLE(Bluetooth low energy)只能与4.0协议设备通信,适应节能且仅收发少量数据的设备(如家用电子);BR/EDR(Basic Rate / Enhanced Data Rate),向下兼容(能与3.0/2.1/2.0通信),适应收发数据较多的设备(如耳机)。
5. 问:目前支持蓝牙4.0的移动设备有哪些?
答:苹果公司的iPhone 4S、iPhone 5、miniPad和iPad 3;小米手机2;三星公司的Galaxy SIII和Note II;HTC ONE系列。
6. 问:如何开始蓝牙4.0的开发呢?
答:概括地讲至少以下三方面的准备吧。硬件方面,需要购买TI公司蓝牙迷你套件,包括蓝牙USB电子狗和KeyFob以及CC Debugger传真器;软件方面,安装IAR for 8051,TI公司BTool软件;技术知识,《CC2540/41 BLE Software Developer’s Guide 1.3》和《CC2540/41 User’s Guide》。
7. 问:刚开始接触蓝牙如何快速上手?
答:理论联系实践是比较好的学习方法,建议先学习《CC2540/41 BLE Software Developer’s Guide 1.3》,然后将SimpleBLEPerepheral工程导入IAR for 8051,结合电子狗和BTool,调试蓝牙通讯中的广播/连接/绑定/访问。光看书不动手,空虚;不看书光动手,浅薄。
8. 问:IAR调试CC2540时程序导入到了芯片的Flash中了吗?
答:确实。CC2540是SOC(System On Chip)芯片,它的内核就是8051,它需要从ROM中取指令,从RAM中取数据来运行。仿真时,CC Debugger会把程序导入芯片Flash中,再执行仿真。
9. 问:当IAR调试中出现警告“缺少断点,无法运行到main()”?
答:出现这个错误的原因是,IAR for 8051最多只能设置3个断点,如果设置过多,当程序下载后,将出现些调试警告。解决的方法很简单,去掉一些断点,再重新载入程序。
10. 问:为什么IAR调试时有很多变量无法查看它的值?
答:主要的原因是IAR编译器设置了优化功能,函数中的自动变量以及一些静态函数都被优化过了,所以没有生成对应的调试信息,无法查看和设置断点。解决的方法是关闭编译器的优化功能,右键点击工程的Options -> C/C++ Compiler -> Optimizations中的Level设置为None。
11. 问:蓝牙协议分层很多且比较复杂,该如何掌握呢?
答:蓝牙协议从应用层到物理层一共分了8层,看上去比较复杂且API函数很多。首先不必要知道每一层的具体实现,掌握与应用紧密关联GAP/GATT(或者GAP Role和GATT Profiles)层就可以满足大部分设计需要;每一层的软件都是通过OSAL来调用的,因此需要了解OSAL的基本原理:任务/事件/消息/定时器/动态分配内存;最后把蓝牙通讯过程理解,将有助于开发。
12. 问:OSAL是一个操作系统吗?
答:OSAL(Operating System Abstraction Layer)操作系统抽象层,它不是一个真正的操作系统(它没有Context Switch上下文切换功能),但它巧妙地组织各任务,支持任务优先级,任务之间可以通过事件和消息来通信,为任务提供软定时器和动态内存分配。要避免的陷阱是,应用任务的单个函数运行时间不能太长(如操作大批量数据的Flash写),否则它无法及时调度高优先级的LL(Link Layer)任务而导致蓝牙通信中断。
13. 问:蓝牙节点是如何组成微微网的呢?
答:蓝牙节点组网中,只能存在一个主节点(Central)和多个从节点(Peripheral),从节点是发出信号者,主节点是扫描且发起连接者。
14. 问:主节点和从节点通信的过程是怎样的呢?
答:当从节点发出广告信号(包括设备地址和设备名称之类的附加信息);主节点收到此广告信号后,向从节点发出扫描请求;当从节点回应扫描时,就完成了设备发现过程。
接着主节点向从节点发出连接请求(包括连接时隙、从节点待机次数、连接超时值),从节点
回应连接,就完成了建立连接。
为了安全起见,一些数据的访问需要认证,它的完成是这样的:一方(可以是主节点,也可以
是从节点)向另一方索要6位数字的密码,之后,两个节点彼此交换安全密钥用于加密和认证,此过程称为配对。
认证的过程比较繁琐,BLE协议支持两节点保存认证的安全密钥(一般是非易失性存储器中),
以便于两节点下次连接后快速认证,这就是绑定技术。
15. 问:蓝牙通信中两个节点如何交换数据?
答:这是蓝牙通信中最让初学者迷惑的地方。大部分通信,尤其是TCP/IP,交换数据的婚介是数据包,但蓝牙通信中,工程师找不到数据包访问方式,于是就产生疑问。其实蓝牙最底层也是基于无线数据包交换,只是通过层层封装,交付给工程师的API接口就变成了Client访问Server的方式。
16. 问:Client和Server节点是如何定义呢?
答:通俗地说吧,Server(服务器)就是数据中心,Client(客户端)就是访问数据者。特别说明,它与主/从设备是独立的概念:一个主设备既可以充当Server,又可以充当Client;从设备亦然。
17. 问:Server是如何提供数据呢?
答:Server首先将一个服务按“属性/句柄/数值/描述”这种格式予以组织,然后调用API函数
GATTServApp_RegisterService将服务数据进行注册。举个实例吧,设提供一个电池电量服务字节,它允许Client读取,数据为一个8比特无符号数(0~100%),它的组织如下:02 25 00 19 2A, 这5个数据(小端格式)分别是:0x02=只读属性,0x0025=句柄;0x2A19=服务UUID。
18. 问:不明白Server提供服务中的UUID?
答:UUID(Universal Unique Identifier)全球惟一标识符,本来是SIC组织分配给特定蓝牙服务的标识,如分配0x2A25为设备序列号的UUID,这样任意蓝牙设备都可以通过它得到另一个设备的序列号。
打个类比,它就像书名,如《现代操作系统》,所有人一看就知道它是计算机大师Andrew S. Tanenbaum写的书。
19. 问:什么是Server提供服务中的句柄呢?
答:句柄(Handle)就是服务数据在数据中心的地址,当所有的服务数据组织起来后,它总得有个先后顺序,某个服务的位置就是它的句柄。还是上面的类比,如果想去图书馆借阅《现代操作系统》,需要查明该书在哪一层楼,哪个房间,这就是该书的Hanle。
20. 问:为什么Server提供的服务中有描述?
答:有些服务是有描述(Descriptor)的,它是用于Client配置该服务的功能(通知或者显示)。像某人没有借到《现代操作系统》该书(可能是被别人借光了),他(她)可以打个电话给图书馆工作人员,请求一旦该书可以借阅了给他一个通知,这个过程相当于配置该书的Descriptor。
21. 问:服务的属性与描述有区别吗?
答:有区别,服务的属性是Server设置访问权限。就像图书馆的工作人员可以设置《现代操作系统》仅能在阅览室看不能外借(只读),或者即可以看也可以外借(读/写)。 22. 问:Client如何访问Server的服务呢?
答:大致分三类:读取服务的值,需要知道服务的UUID或者Handle;写服务的值,需要知道服务的Hanle;写服务描述符,需要知道该Descriptor的Hanle。
23. 问:如何知道一个服务的Handle?
答:根据服务的UUID调用API函数GATT_ReadUsingCharUUID
协议栈会返回该服务的Handle。特别注意的是,一个服务的Descriptor的Handle总是该服务的Handle+1,如电池电量服务的Handle是0x0025,那么它的Descriptor的Handle是0x0026。
24. 问:Server可以访问Client吗?
答:蓝牙通信中,Server不能直接访问(读/写)Client,但是可以通知(Notification)Client,通知的前提是Client通过写Descriptor使能通知功能。例如,某Server发现电池电量已经低于安全阀值,它可以调用GATT_Notification通知所有已连接的Client,但是Client接收后如果处理是它自己的事情。
25. 问:如果得知电池容量?
答:任何使用电池供电的设备都必须精确监控电池容量,否则设备可以突然断电而停止工作,它的基本原理是通过ADC(模数转换器)计算电池电压。以CC2540芯片用一钮扣电池为例,电池电压从2.0v~3.0v,即电量的0%~100%;CC2540有一10比特的ADC,量程范围为0~511,参考电压为1.25v,最大测量电压为3.75v,以上信息可以得知:(v/3)/ 1.25 * 511 = adc,则2.0v=273adc,3.0v=409adc,根据下图可以很容易得知ADC转换为电压的公式: Percentage / (X – 273) = 100 / 136 = 25 / 34,变换后为:
Percentage = (X - 273) * 25 / 34,为四舍五入提高计算精度则有: Percentage = [(X - 273) * 25 + 33] / 34。
26. 问:蓝牙发射信号功率调整会影响通信距离吗? 答:会,以TI公司的CC2540为例,它支持4种发射功率选择:4dBm、0dBm、-6dBm和-23dBm,按无线电功率定义:LdBm=10lg(Pwr/1mW),以上4种分贝值换算成瓦特为:2.51mW、1mW、0.251mW和0.005mW,有效通信距离分别为:30米、10米、7米和3米。 27. 问:如何知道两个蓝牙通信节点之间的距离? 答:要知道蓝牙通信节点(如手机和蓝牙设备)之间的距离,最容易实现的方法是通过读取接收RSSI(Received Signal Strength Indication)值来计算。无线通讯中功率与距离的关系如下: 其中A可以看作是信号传输1米远时接收信号的功率,n是传播因子(它受障碍,温度和湿度等影响),r是节点之间的距离。当确定了常数A与n的值后,距离r就可以根据PR(dBm)计算出来。 28. 问:如何获取蓝牙节点的接收RSSI值? 答:具体的设备接收RSSI值的方法不一样,以iPhone手机为例,iOS提供API函数获取RSSI值;TI公司的CC2540芯片的BLE协议栈中,首先将读取RSSI值回调函数挂载到gapRolesRssiRead_t类型的指针下,建立连接后,主设备调用GAPCentralRole_StartRssi(),从设备调用 GAPRole_SetParameter(GAPROLE_RSSI_READ_RATE, ……)。这样就可以定时读取接收的RSSI值了。 29. 问:如何开展读取RSSI值的实验? 答:读取RSSI值的实验可以这样搭建,主设备固定位置,向从设备发送信号,从设备LED光和Buzzer报警为通信成功,逐次移动从设备,而获取RSSI值随物理距离之间的关系。下图是笔者做实验的数据: Distance(m) RSSI(dBm) Loss(p) 1 -47 0 2 -59 0 3 -73 9 4 -80 11 5 -80 27 6 -79 2 7 -85 50 8 -88 32 9 -86 22 10 -87 49 实验器材为2块CC2540芯片,主芯片发射功率为4dBm(2.51mW),Loss是通信节点中失败次数。
30. 问:如何将接收RSSI实验数据得到距离计算公式呢?
答:最好的工具是EXCEL软件,以上表中的实验数据和EXCEL 2007为例。首先选中Distance和RSSI两行,点击“插入->散列图”,软件会自动生成如下图:
选取其中任意点,点右键,“添加趋势线->对数”,将会出现下图:
可见RSSI与距离的关系是比较符合指数函数,再点击“显示公式”
此时得到指数函数公式为:y = -49.53 – 17.7 ln (x),再把自然对数换成10常用对数,则有:y = -49.53 – 40.71 lg (x)。通过以上几步就轻松得到RSSI与距离之间的计算公式。
31问:针对RSSI采样值选用什么样的滤波算法?
答:RSSI采样值遵循以下特点:有个别的脉冲干扰引起极大值和极小值的出现,其他采样数据值沿平均值分布,比较适合的算法是:滑动防脉冲干扰平均滤波法。它的原理是,设有N个单位的队列,用新的采样值覆盖旧的采样值,去除队列中最大值和最小值后,再计算队列中采样数据的平均值。用C语言描述如下: static INT8S Filter(INT8S chVal) {
#define FIFO_NUM 10
INT8S chMinVal, chMaxVal, chTemp; INT16S nCnt, nSum;
static INT8S s_chIx = 0, s_chIsFull = FALSE; static INT8S s_achBuf[FIFO_NUM];
/* Save the NEW value, kick out the OLDest one */
s_achBuf[s_chIx] = chVal; if (++s_chIx >= FIFO_NUM) {
s_chIx = 0; /* Wrap to 1th unit */ s_chIsFull = TRUE; }
/* Number of sampled data less than N */ if (!s_chIsFull) {
nSum = 0;
for (nCnt = 0; nCnt < s_chIx; ++nCnt) {
nSum += s_achBuf[nCnt]; }
return (INT8S)(nSum / s_chIx); }
/* Get the SUM and Max. and Min. */ chMaxVal = chMinVal = nSum = 0; for (nCnt = 0; nCnt < FIFO_NUM; ++nCnt) {
chTemp = s_achBuf[nCnt];
nSum += chTemp;
if (chTemp > chMaxVal) {
chMaxVal = chTemp; }
else if (chTemp < chMinVal) {
chMinVal = chTemp; } }
/* Calculate the average */
nSum -= (chMaxVal + chMinVal); /* SUB Max. and Min. */ nSum /= (FIFO_NUM - 2); /* Get average */
return (INT8S)nSum; }
使用GATT_Notification 的示例
总体思路:
分为两部分:
1、此部为从机写特征值的回调函数,主要是主机会写入CFG 0x0001打开Notify使能。 static bStatus_t battWriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset ) {
bStatus_t status = SUCCESS;
uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]); switch ( uuid ) {
case GATT_CLIENT_CHAR_CFG_UUID:
status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY ); if ( status == SUCCESS ) {
uint16 charCfg = BUILD_UINT16( pValue[0], pValue[1] );
if ( battServiceCB ) {
(*battServiceCB)( (charCfg == GATT_CFG_NO_OPERATION) ? BATT_LEVEL_NOTI_DISABLED : BATT_LEVEL_NOTI_ENABLED); } } break;
default:
status = ATT_ERR_ATTR_NOT_FOUND; break; }
return ( status ); }
2、这段程序为从机发送通知的示例,主机还需要做两件事情,一是通过Write过程将从机的CFG值写为0x0001,然后由第一步中的write特征值回调函数处理,并调用此函数。二是主机中需要有通知消息的处理过程
//linkDBItem_t是蓝牙建立链接之后的一个结构体,每个链接有自己的一个Handle值,如果当前蓝牙只有一个链接,则该handle值为0; plinkItem的值是从LinkDB_PerformFunc()传进来的。 static void battNotifyCB( linkDBItem_t *pLinkItem ) {
//检查是否已经建立蓝牙连接
if ( pLinkItem->stateFlags & LINK_CONNECTED ) {
//取 cfg的值,看是否为0x0001;(0x0001为Notify,0x0002为Indicate) uint16 value = GATTServApp_ReadCharCfg( pLinkItem->connectionHandle, battLevelClientCharCfg ); if ( value & GATT_CLIENT_CFG_NOTIFY ) {
attHandleValueNoti_t noti;
//此处的handle是将要发送的数据的handle,不是cfg的handle noti.handle = battAttrTbl[BATT_LEVEL_VALUE_IDX].handle; noti.len = 1;
noti.value[0] = battLevel;
GATT_Notification( pLinkItem->connectionHandle, ¬i, FALSE ); } } }
广播时间模式
1.保持无限广播:
General Discovery mode下,先设置TGAP_GEN_DISC_ADV_MIN = 0。GAP_SetParamValue(TGAP_GEN_DISC_ADV_MIN,0),再使能广播。
至于 GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime );不用管,因为:
当TGAP_GEN_DISC_ADV_MIN = 0时。GAPROLE_ADVERT_OFF_TIME是无效的。 2.单次限时广播:
先设置广播的持续时间,如3s:
Limited Discovery mode下,GAP_SetParamValue(TGAP_LIM_ADV_TIMEOUT, 3);//单位秒 General Discovery mode下,GAP_SetParamValue(TGAP_GEN_DISC_ADV_MIN,3000);//单位ms 然后注意设置gapRole_AdvertOffTime = 0。
GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime ); 这样你开启一次广播,持续3秒后就自动停止了。 3.循环限制广播:
先设置你每次的广播时间,如10秒:TGAP_LIM_ADV_TIMEOUT = 10。GAP_SetParamValue(TGAP_LIM_ADV_TIMEOUT,10)。 然后设置关闭广播的持续时间,如20秒: gapRole_AdvertOffTime = 20000。
GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime ); 这样的效果就是:广播10秒,停止20秒。广播10秒...如此循环。
BLE芯片CC254x 系统资源
1.CC254x 内核
1.1.内核介绍
CC254x内部采用的是增强型8051内核,指令执行速度较标准的8051要快,主要基于: l 增强型8051的单周期指令是1个时钟周期,而标准8051需要12个时钟周期; l 没有了浪费的总线状态(wastedbus states);
由于一个指令周期能与存储中指令预取保持同步,使得大多数单周期指令能在一个时钟周期内完成,此外,增强型8051内核也包含一个“second data pointer”和一个扩展的18个中断单元。
1.2.存储空间
8051有分离的程序存储空间和数据存储空间,可细分成4中不同的存储空间: l CODE:只读程序存储,寻址空间64KB;
l DATA:可读写数据存储空间,可被直接或间接寻址,256 bytes,低128 byte 可被直接或间接寻址,高128 bytes只能间接寻址(SFR除外,SFR为直接寻址)
l XDATA:片外数据存储,寻址空间64K, l SFR:寄存器区域,直接寻址;
2. 时钟系统
CC254x内部时钟系统分两部分,系统时钟(system clock)和睡眠看门狗时钟。
2.1.系统时钟
· CPU运行主频,分频之后也为Timer1、Timer3、Timer4计数时钟; · 支持2种时钟源,内部16MHz RC晶振或外部的32MHz晶振; · 上电默认是IRC 16MHz;
· IRC 16MHz 启动时间比32MHz时间短,功耗低,但是精度差,不能用于射频相关的数据传输,射频相关操作必须要等32MHz时钟稳定之后才能进行;
2.2.睡眠看门狗时钟
· 为睡眠定时器和看门狗运行提供时钟;
· 支持2种时钟源,内部32KHz RC晶振或外部的32.768KHz晶振; · 上电默认是内部32KHz;
· IRC 32KHz 启动时间比外部32.768KHz时间短,功耗低,但是精度差;
· 当开启IRC 32KHz校准功能(使用外部的32MHz分频,SLEEPCMD.OSC32K_CALDIS = 1;CLKCONCMD. OSC32K = 1),IRC 32KHz能以32.753KHz工作;
2.3.时钟初始化代码分析
摘自TI-BLE-v1.2.1 HAL source code: ……
// start 16MHz RCOSC & 32MHz XOSC waitfor stable 32MHz XOSC START_HSOSC_XOSC();
// switch to the 16MHz HSOSC and wait until it isstable SET_OSC_TO_HSOSC();
// set 32kHz OSC and wait until it is stable SET_32KHZ_OSC();
// switch to the 32MHz XOSC and wait until it isstable SET_OSC_TO_XOSC();
//stop 16MHz RCOSC STOP_HSOSC(); ……
这段代码有对IRC 16MHz进行开关控制(SLEEPCMD.Bit2),实际根据手册,SLEEPCMD.Bit2始终为1,无需配置,个人猜测最初的CC254x或者CC253x可以对IRC16MHz进行开关控制,后来取消了这部分,改为上电默认IRC16MHz 打开,且可以默认它已经运行稳定(CLKCONCMD.OSC = 1; CLKCONSTA.OSC = 1; ),所以实际时钟初始化可以只是: ……
// set 32kHz OSC and wait until it is stable SET_32KHZ_OSC();
// switch to the 32MHz XOSC and wait until it isstable SET_OSC_TO_XOSC(); ……
3.电源管理
CC254x包含5种电源模式:Active ,idle,powermode1/2/3(PM1-PM3), 其中的PM1-PM3也称为睡眠模式。
3.1.电源模式
CC254x的5种电源模式涉及晶振和片内1.8Vvoltage regulator digital部分的开关控制,高频率晶振包括X-OSC (32 MHz) 和IRC-OSC (16 MHz) ,低频率晶振包括X-OSC (32.768 KHz) 和IRC-OSC (32 KHz) 。 · Active 模式:为正常工作的全功能模式,片内1.8V 电压转换芯片、高频晶振(32MHz或16MHz)、低频晶振(32.768KHz或32KHz)都处于正常工作状态;
· IDLE模式:除了CPU内核处于“IDLE”外,其它等同于Active模式; · PM1模式:适应于能快速唤醒,睡眠时间不超过3ms的应用场合; · PM2模式:睡眠时间超过3ms,一般使用Sleeptimer定时唤醒; · PM3模式:最低功耗状态,睡眠时间超过3ms,一般使用外部IO中断方式唤醒。 Power mode Active IDLE PM1 PM2 PM3
CC254x睡眠模式和IDLE模式切换到Active 模式方法: Power mode Active IDLE Wakeup to Active mode / POR, BOD, External reset, External interrupt , Sleep timer expires PM1 POR, BOD, External reset, External interrupt , Sleep timer expires PM2 POR, External reset, CRC reset (CC2541 only), External interrupt , Sleep timer expires PM3 POR, External reset, CRC reset (CC2541 only), External interrupt, High-Frequency OSC X-OSC or IRC-OSC X-OSC or IRC-OSC None None None Low-Frequency OSC X -OSC or IRC-OSC X -OSC or IRC-OSC X-OSC or IRC-OSC X -OSC or IRC-OSC None voltage regulator ON ON ON OFF OFF 3.2.电源管理控制
CC254x使用寄存器PCON.IDLE和SLEEP.MODE来控制,进入睡眠模式一般先设置要进入哪种非Active模式(IDLE、PM1-PM3): SLEEP.MODE [1:0] Mode 00 01 10 11 Active/Idle PM1 PM2 PM3 设置完成睡眠模式之后,使PCON.IDLE= 1,将立即使CC254x进入相应的非Active模式,在user’sguide里面特别有说明,在进入非Active模式,需要PCON.IDLE = 1指令必须4字节对齐地址,且之后的第一条指令必须是非4字节对齐存放。 对于PM3,由于其BOD已经不起作用,对于CC2541可以利用SRCRC.RESULT来判断电压是否Brownout。 3.3.电源管理代码分析
设定SLEEP.MODE [1:0]之后,调用halSetSleepMode进入非Active模式,唤醒之后从PCON.IDLE= 1之后的指令开始执行,halSetSleepMode函数定义如下。 #pragma location =\voidhalSetSleepMode(void); ……
void halSetSleepMode(void) {
PCON =PCON_IDLE;
HAL_DISABLE_INTERRUPTS(); }
汇编之后: halSetSleepMode: CODE
MOV 0x87, #0x1 CLR 0xa8.7
这里面需要注意的是“PCON.IDLE =1”指令必须是4字节对齐地址,而接下来的指令(唤醒之后执行的第一条指令不能是4字节对齐地址) 打开xcl文件: ……
-D_CODE_START=0x0000
-D_CODE_END=0x7FFF // Last address for ROOT bank. ……
-D_SLEEP_CODE_SPACE_START=(_CODE_END-7) -D_SLEEP_CODE_SPACE_END=(_CODE_END)
-Z(CODE)SLEEP_CODE=_SLEEP_CODE_SPACE_START-_SLEEP_CODE_SPACE_END ……
可以看出halSetSleepMode放置在0x7FF8的地址,满足4字节对齐要求,同时
“PCON = PCON_IDLE”占3个字节,即HAL_DISABLE_INTERRUPTS()地址在0x7FFB,不是4字节对齐,也满足要求。
cc2540 cc2541 低功耗实测和总结-与注意事项 - 低功耗小于10uA CC2541 CC2540 实现超低功耗是非常重要的: 我们来总结一下实现方法:
1、有定时器在跑时会一直跑在 PM2 电流在 300uA左右。 没有定时器跑后会到 PM3 , 电流会少于10uA 。 这个定时器是指 osal 的定时器, 例如:
启动了osal_start_timerEx( keyfobapp_TaskID, KFD_TOGGLE_BUZZER_EVT, 2000 ); 但没到时间:
需要说明的是 keyfob 中的 低功耗一直都是进不去 PM3 的, 这是由于有一个查询电量的定时器一直在跑:
osal_start_timerEx( keyfobapp_TaskID, KFD_BATTERY_CHECK_EVT, BATTERY_CHECK_PERIOD ); 把它注释掉 就会进 PM3 了。 电流 小于 10uA 。
因此,如果你想低功耗到但是又想启用定时器是不现实的。
2、如果有外部中断,比如开关量如按键, 一定,一定,一定需要用下降沿中断, 目前上升沿中断调不出
来, 并且,常态时如果是低电平输入, 会比较耗电。实测,低电平输入会比高电平输入多200uA 左右。
总结一下: 常态下是PM1
要进入 PM2, 首先,确认你的option的编译宏设置了 POWER_SAVING 然后代码中, 需要执行 osal_pwrmgr_device( PWRMGR_BATTERY ); 即可, 电流还有200uA 呀, 怎么办? 要进入 Pm3, 需要你没有 osal的定时器在跑。
正在阅读:
TI CC254x学习笔记整理12-09
课程理论流派04-02
2016年行政事业会计练习题02-02
马克思主义原理课实践教学方案及选题范围01-11
学生宿舍管理系统(毕业设计_论文)介绍05-01
ISO22000:2015质量和食品安全管理手册(全套)04-12
商务谈判与沟通技巧期末试题(2011)09-01
国内外建筑行业ERP及其应用比较研究03-19
《筑梦前行 不负韶华》国旗下的讲话范文03-23
- exercise2
- 铅锌矿详查地质设计 - 图文
- 厨余垃圾、餐厨垃圾堆肥系统设计方案
- 陈明珠开题报告
- 化工原理精选例题
- 政府形象宣传册营销案例
- 小学一至三年级语文阅读专项练习题
- 2014.民诉 期末考试 复习题
- 巅峰智业 - 做好顶层设计对建设城市的重要意义
- (三起)冀教版三年级英语上册Unit4 Lesson24练习题及答案
- 2017年实心轮胎现状及发展趋势分析(目录)
- 基于GIS的农用地定级技术研究定稿
- 2017-2022年中国医疗保健市场调查与市场前景预测报告(目录) - 图文
- 作业
- OFDM技术仿真(MATLAB代码) - 图文
- Android工程师笔试题及答案
- 生命密码联合密码
- 空间地上权若干法律问题探究
- 江苏学业水平测试《机械基础》模拟试题
- 选课走班实施方案
- 整理
- 笔记
- CC254x
- 学习
- TI
- 计算机控制系统复习题及答案
- 安徽医科大学在职人员攻读公共卫生硕士专业学位研究生招生简章、招生人数,参考书目,内部讲义,押题
- 20千伏以下配网预算定额--线路部分--章节说明内容
- 需求工程(习题集)最新
- 幼儿徒手体操的创编原则与策略
- Abaqus错误与警告信息汇总
- 2018年四川省德阳市中考数学试卷( 答案+解析)
- (期末考试复习)金融学试题库
- 小学安全工作应急预案
- 关于基层治理与基层民主的文献综述
- 企业会计准则第14号-收入试题及答案
- 领导包级包班教师包学生工作实施方案
- 论郭沫若《女神》的语言艺术风格
- 高二地理必修三教学计划
- 福建省建筑边坡与深基坑工程管理规定
- 浅谈如何提高纳税遵从度
- 公共组织绩效管理在线作业
- 操作系统第4章习题带答案
- 合规风险管理实施方案(李卓)
- 五年级语文复习(看拼音写词语)