Chinaunix首页 | 论坛 | 博客
  • 博客访问: 85167
  • 博文数量: 25
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 98
  • 用 户 组: 普通用户
  • 注册时间: 2014-10-10 00:42
文章分类

全部博文(25)

分类: 嵌入式

2018-03-09 20:17:40

首先感谢大佬-甜甜的大香瓜,所提供的免费BLE5教程,这是他的关于CC2640R2的教程


实现的功能:通过SC(SensorController)创建一个ADC采样的工程,生成源码后,将其加入到已有的CC2640R2的CCS工程中,在CCS工程中实现根据ADC值控制LED亮灭,并串口打印具体ADC值。
(附上,点开往下拉,有一栏是SensorControllerStudio,包含三个例子


    1.  构建SC工程(这里只贴代码并简单说明,SC工程创建看TI的教程)
    Initialization Code部分

点击(此处)折叠或打开

  1. fwScheduleTask(1);
    如果你的 任务资源 勾选了RTC-Based Execution Scheduling,就算这部分没有什么初始化代码,也最好加上上面这句。我最开始没有加,出现了在CCS工程中收不到Alert中断的情况,应该就是没有调用这句话,所以就没有执行Execution Code部分。

    Execution Code部分

点击(此处)折叠或打开

  1. adcEnableSync(ADC_REF_FIXED, ADC_SAMPLE_TIME_2P7_US, ADC_TRIGGER_MANUAL);

  2. adcSelectGpioInput(AUXIO_A_ADC_CH1);
  3. adcGenManualTrigger();
  4. adcReadFifo(output.adcValue);

  5. adcDisable();


  6. fwGenAlertInterrupt();

  7. fwScheduleTask(1);
    功能很简单,#1句启动ADC,这里配置为手动触发。#3句选择采样的端口。#4句手动触发ADC采样。#5句读取数据到output类型的变量里,这个变量可在CCS工程中直接使用。#7句关闭ADC。#10句SensorController核心向M3核心发出Alert中断信号,在CCS工程中可以收到这个中断信号。#12句1个RTC滴答后,再次执行Execution Code。

    好了,接下来通过Code Generator生成SCIF(Sensor Controller Interface driver)源码。通过Task Testing可以进行测试。


    2. SC整合进CCS工程(CCS工程是根据甜甜的大香瓜大佬的教程构建的)
   (完整工程看最后) CCS工程文件在“GUA_CC2640R2F_Peripheral”中,其中“ble5_simple_peripheral_cc2640r2lp_app”是应用程序工程,“ble5_simple_peripheral_cc2640r2lp_stack_library”是协议栈工程;SDK文件则在“simplelink_cc2640r2_sdk_peripheral”中。

    接下来手动添加SC生成的源码。在.../GUA_CC2640R2F_Peripheral/ble5_simple_peripheral_cc2640r2lp_app内创建文件夹,命名为“SCIF”,将SC生成的6个文件拷贝到里面。


    打开CCS,将目录定位到“GUA_CC2640R2F_Peripheral”,会自动识别已有的工程。
    创建新的文件 scTask.c 和 scTask.h,编写SC相关代码。源码如下:

点击(此处)折叠或打开

  1. /*
  2.  * scTask.c
  3.  *
  4.  * introduce: 读出数据,送到应用层
  5.  *
  6.  * Created on: 2018年3月7日
  7.  * Author:
  8.  */

  9. #include <ti/sysbios/knl/Clock.h>
  10. #include "util.h"
  11. #include "hal_defs.h"
  12. #include "scif.h"
  13. #include "scif_framework.h"

  14. #include "scTask.h"

  15. /****************** 内部变量 ******************/
  16. static Clock_Struct sClockStruct_SCTask;
  17. static tSCTaskCB sAppDataTransfer = NULL; //应用层函数
  18. static uint16_t sDataBuf; //数据缓存

  19. /****************** 内部函数 ******************/
  20. static void sSCTaskAlertHwiCallback(void);
  21. static void sProcessTaskAlert(UArg a0);


  22. /****************** 函数实现 ******************/
  23. //******************
  24. //name:
  25. //introduce: init scif
  26. //params:
  27. //******************
  28. void initSCIF(tSCTaskCB appDataTransfer)
  29. {
  30. //保存应用层回调的指针
  31.     sAppDataTransfer = appDataTransfer;

  32. //construct clock
  33.     Util_constructClock(&sClockStruct_SCTask,
  34.                         sProcessTaskAlert,
  35.                         0,
  36.                         0,
  37.                         false,
  38.                         0);

  39. //SCIF
  40.     scifOsalInit();
  41.     scifOsalRegisterTaskAlertCallback(sSCTaskAlertHwiCallback); //注册TaskAlert回调函数
  42.     scifInit(&scifDriverSetup);

  43.     //set task tick interval. 确定采集周期
  44.     uint32_t rtc_Hz = 1;
  45.     scifStartRtcTicksNow(0x00010000 / rtc_Hz);

  46.     //configure SC task

  47.     //start SC task. 这个函数可通过或运算开始多个任务: BV(SCIF_TASK_1_ID)|BV(SCIF_TASK_2_ID)
  48.     scifStartTasksNbl(BV(SCIF_TASK_TASK_ID));
  49. }

  50. //******************
  51. //name:
  52. //introduce: Task Alert中断回调. 这个相当于Hwi
  53. //params:
  54. //******************
  55. static void sSCTaskAlertHwiCallback(void)
  56. {
  57.     Util_startClock(&sClockStruct_SCTask);
  58. }

  59. //******************
  60. //name:
  61. //introduce: Task Alert处理函数
  62. //params:
  63. //******************
  64. static void sProcessTaskAlert(UArg a0)
  65. {
  66.     scifClearAlertIntSource();

  67.     //compute times
  68.     //uint32_t execMs = TICK_TO_MS(Clock_getTicks() - sLastTick);

  69.     //SC task prcessing. 读取数据并向应用层发送数据
  70.     //读取
  71.     sDataBuf = scifTaskData.task.output.adcValue;
  72.     sAppDataTransfer(sDataBuf);

  73.     scifAckAlertEvents();
  74. }

点击(此处)折叠或打开

  1. /*
  2.  * scTask.h
  3.  *
  4.  * Created on: 2018年3月7日
  5.  * Author:
  6.  */

  7. #ifndef MYCODE_SCTASK_H_
  8. #define MYCODE_SCTASK_H_

  9. typedef void (*tSCTaskCB)(uint16_t data);

  10. extern void initSCIF(tSCTaskCB app);

  11. #endif /* MYCODE_SCTASK_H_ */
    然后,在simple_peripheral.c中添加代码:

点击(此处)折叠或打开

  1. ......
  2. ......
  3. #include "scTask.h"

  4. //这个宏定义还要添加到ALL_EVENT宏定义中
  5. #define SBP_MY_SCIF_EVT Event_Id_05

  6. static Clock_Struct sClockStruct_SCClock; //SC处理函数的定时器

  7. //SCIF
  8. static void scGetDataCallback(uint16_t data); //接收来自SC的数据
  9. static void appProcessSCTask(void); //数据处理

  10. ......
  11. ......
  12. static void SimpleBLEPeripheral_init(void)
  13. {
  14.     ......
  15.     ......
  16. //SCIF
  17.     initSCIF(scGetDataCallback);
  18.     Util_constructClock(&sClockStruct_SCClock,
  19.                         SimpleBLEPeripheral_clockHandler,
  20.                         0,
  21.                         0,
  22.                         false,
  23.                         SBP_MY_SCIF_EVT);            
  24. }
  25. ......
  26. ......
  27. static void SimpleBLEPeripheral_taskFxn(UArg a0, UArg a1)
  28. {
  29.     ......
  30.     ......    
  31.      //通过sClockStruct_SCClock触发
  32.       if(events & SBP_MY_SCIF_EVT)
  33.       {
  34.           //数据处理函数
  35.           appProcessSCTask();
  36.       }
  37. }
  38. ......
  39. ......

  40. //***自定义函数
  41. static void scGetDataCallback(uint16_t data)
  42. {
  43.     sSCData = data;
  44.     Util_startClock(&sClockStruct_SCClock);
  45. }
  46. //***自定义函数
  47. static void appProcessSCTask(void)
  48. {
  49.     char str[6];
  50.     //set led
  51.     if(sSCData > 1500)
  52.         mySetLed(MY_LED_NO_ALL, LED_MODE_ON);
  53.     else
  54.         mySetLed(MY_LED_NO_ALL, LED_MODE_OFF);

  55.     //send str
  56.     str[0] = sSCData / 1000 + '0';
  57.     str[1] = sSCData % 1000 /100 + '0';
  58.     str[2] = sSCData % 100 / 10 + '0';
  59.     str[3] = sSCData % 10 + '0';
  60.     str[4] = '\r';
  61.     str[5] = '\n';
  62.     mySendUART(str, strlen(str));
  63. }
    
    下面对代码逻辑和流程进行说明。
    大致流程是:SC完成采集,发出Alert中断信号,M3核心中收到中断信号,根据注册的回调函数应答Alert Interrupt,并通过函数指针调用simple_peripheral.c中的函数将数据传递到应用层,然后进行ADC值的判断,并通过串口打印出来。

    具体的代码逻辑:
    在
simple_peripheral.c中,在SimpleBLEPeripheral_init()内进行初始化,调用scTask.c中的
initSCIF(),并将函数指针scGetDataCallback作为参数传入;然后构建定时器sClockStruct_SCClock,它对应的事件号是SBP_MY_SCIF_EVT,它的回调是SimpleBLEPeripheral_clockHandler()
    接着看scTask.c中initSCIF()将传入的函数指针保存到sAppDataTransfer,然后构建了一个定时器sClockStruct_SCTask,它的回调是sProcessTaskAlert,接着进行SC驱动接口的初始化(初始化过程参考TI教程),这里注册了了Alert中断的回调函数sSCTaskAlertHwiCallback
    当收到Alert中断信号时,执行注册的回调函数sSCTaskAlertHwiCallback,启动定时时间为0的定时器sClockStruct_SCTask。定时时间(为0)到后执行定时器回调sProcessTaskAlert,这里先通过scifClearAlertIntSource()清除Alert中断,然后读取SC中的数据,调用sAppDataTransfer()将数据传递出去(实际调用的是保存在其中的scGetDataCallback()),最后使用scifAckAlertEvents()回应Alert事件。
    回到simple_peripheral.c中,scGetDataCallback()首先保存SC传过来的数据,启动定时时间为0的定时器sClockStruct_SCClock,发送SBP_MY_SCIF_EVT事件,在SimpleBLEPeripheral_taskFxn()中处理该事件,就是调用appProcessSCTask()。最后在appProcessSCTask()中对数据处理后,控制LED,并进行串口打印。一次Alert执行完毕。
    啰嗦了这么多,不知道有没有讲明白,感觉还缺少点ti-rtos的知识(捂脸)。。。

给出完整的工程文件,包括CCS工程和SC工程:
链接: 密码:asx5
阅读(3421) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~