CC2640协处理器SensorController移植sc_uart串口程序到simple_peripheral工程,实现串口与手机的通信

协处理器串口程序移植过程

(1)通过sensorcontroller软件配置好串口初始化程序

(2)将生成的IAR project代码复制到simple_peripheral工程相应文件夹下

CC2640协处理器SensorController移植sc_uart串口程序到simple_peripheral工程,实现串口与手机的通信_第1张图片

(1)      将.c和.h文件添加当工程中的GY_SerialPort/UART中,并添加编译路径

CC2640协处理器SensorController移植sc_uart串口程序到simple_peripheral工程,实现串口与手机的通信_第2张图片

(2)      改写sc_uart.c文件,这个文件由main_tirtos.c根据开发者自身需求改写而成,这里,包含了串口初始化函数,串口RX接收回调函数,串口打印函数,以及串口任务往app层的回调任务。sc_uart.h则包含了这些函数的借口,保留给app.c使用。

#include "scif.h"

#include "sc_uart.h"

 

#define BV(n)               (1 << (n))

 

 

// Display error message if the SCIF driverhas been generated with incorrect operating system setting

#ifndef SCIF_OSAL_TIRTOS_H

   #error "SCIF driver has incorrect operating system configurationfor this example. Please change to 'TI-RTOS' in the Sensor Controller Studioproject panel and re-generate the driver."

#endif

 

// Display error message if the SCIF driverhas been generated with incorrect target chip package

#ifndefSCIF_TARGET_CHIP_PACKAGE_QFN48_7X7_RGZ

   #error "SCIF driver has incorrect target chip package configurationfor this example. Please change to 'QFN48 7x7 RGZ' in the Sensor ControllerStudio project panel and re-generate the driver."

#endif

 

 

 

 

/*********************************************************************

 *LOCAL PARAMETER

 */

GY_UartRxBufCallbackGY_UartReviceDataCallback;

 

 

/*********************************************************************

 *@fn     GY_UartTask_RegisterPacketReceivedCallback

 *

 *@brief   注册串口接收回调任务(将串口接收的数据传给app任务去处理)

 *

 *@param   callback -> 串口接收数据回调(包括数据buf及len)

 *

 *@return  None.

 */

voidGY_UartTask_SC_RegisterPacketReceivedCallback(GY_UartRxBufCallback callback)

{

 GY_UartReviceDataCallback = callback;

}

 

 

 

void scCtrlReadyCallback(void) {

 

}

/*********************************************************************

 *@fn      scTaskAlertCallback

 *

 *@brief   sensor controller任务进程警报回调,在这里等同于串口RX的接收回调

 *         我们可以从这里拿到UART RX接收到的数据

 *

 *@param   none

 *

 *@return  None.

 */

void scTaskAlertCallback(void) {

 

   // Clear the ALERT interrupt source

   scifClearAlertIntSource();

 

   // Echo all characters currently in the RX FIFO

   //获取串口接收的数据长度

   int rxFifoCount = scifUartGetRxFifoCount();

   

   

   //获取串口RX接收的数据

    uint8_trxbuf[200] = {0};

   for(int i=0; i

    {

     rxbuf[i] = scifUartRxGetChar();

    }

   GY_UartReviceDataCallback(rxbuf, rxFifoCount);      //给app任务一个串口读回调

 

   // Clear the events that triggered this

   scifUartClearEvents();

 

   // Acknowledge the alert event

   scifAckAlertEvents();

   

}

/*********************************************************************

 *@fn      GY_UartTask_SC_Init

 *

 *@brief   sensor controller串口进程任务初始化

 *         这个初始化函数是由sensor controller studio生成main函数改写

 *

 *@param   None

 *

 *@return  None.

 */

void ScUARTInit (void)

{

   // Initialize the Sensor Controller

   scifOsalInit();

   scifOsalRegisterCtrlReadyCallback(scCtrlReadyCallback);

   scifOsalRegisterTaskAlertCallback(scTaskAlertCallback);

   scifInit(&scifDriverSetup);

 

   // Start the UART emulator

   scifExecuteTasksOnceNbl(BV(SCIF_UART_EMULATOR_TASK_ID));

 

   // Enable baud rate generation

   scifUartSetBaudRate(115200);

 

   // Enable RX (10 idle bit periods required before enabling start bitdetection)

   scifUartSetRxFifoThr(SCIF_UART_RX_FIFO_MAX_COUNT / 2);

   scifUartSetRxTimeout(10 * 2);

   scifUartSetRxEnableReqIdleCount(10 * 2);

   scifUartRxEnable(1);

 

   // Enable events (half full RX FIFO or 10 bit period timeout

   scifUartSetEventMask(BV_SCIF_UART_ALERT_RX_FIFO_ABOVE_THR |BV_SCIF_UART_ALERT_RX_BYTE_TIMEOUT);

 

}

比较一下,改写后与改写前的区别

void scTaskAlertCallback(void) {

 

   // Wake up the OS task

   //唤醒任务进程,这边接收到串口数据会起作用

   Semaphore_post(Semaphore_handle(&semScTaskAlert));

 

} // scTaskAlertCallback

void taskFxn(UArg a0, UArg a1) {

 

   // Initialize the Sensor Controller

   //初始化SensorController驱动,注意着四个都需要

   scifOsalInit();

    scifOsalRegisterCtrlReadyCallback(scCtrlReadyCallback);

   scifOsalRegisterTaskAlertCallback(scTaskAlertCallback);

   scifInit(&scifDriverSetup);

 

   // Start the UART emulator

   //开始串口模拟进程,相当于打开串口功能

   scifExecuteTasksOnceNbl(BV(SCIF_UART_EMULATOR_TASK_ID));

 

   // Enable baud rate generation

   //设置串口波特率

   scifUartSetBaudRate(57600);

 

   // Enable RX (10 idle bit periods required before enabling start bitdetection)

   //使能RX接收

   scifUartSetRxFifoThr(SCIF_UART_RX_FIFO_MAX_COUNT / 2);

    scifUartSetRxTimeout(10* 2);

   scifUartSetRxEnableReqIdleCount(10 * 2);

   scifUartRxEnable(1);

 

   // Enable events (half full RX FIFO or 10 bit period timeout

   //启动时间(半完整RX FIFI或10位周期超时)

   scifUartSetEventMask(BV_SCIF_UART_ALERT_RX_FIFO_ABOVE_THR |BV_SCIF_UART_ALERT_RX_BYTE_TIMEOUT);

 

   // Main loop

   while (1) {

 

       // Wait for an ALERT callback

       //串口中断回调阻塞

       Semaphore_pend(Semaphore_handle(&semScTaskAlert),BIOS_WAIT_FOREVER);

 

       // Clear the ALERT interrupt source

       //清除中断标志

       scifClearAlertIntSource();

 

       // Echo all characters currently in the RX FIFO

       //串口TX打印串口RX接收到的数据

       int rxFifoCount = scifUartGetRxFifoCount();

       while (rxFifoCount--) {

           scifUartTxPutChar((char) scifUartRxGetChar());

       }

 

       // Clear the events that triggered this

       //清除串口事件

       scifUartClearEvents();

 

       // Acknowledge the alert event

       //确认中断事件

       scifAckAlertEvents();

    }

 

} // taskFxn

可以看出来,改写前的taskFxn任务函数中的初始化过程即为改写后的ScUARTInit()串口进程任务初始化函数。改写钱的while(1)循环中的代码就是scTaskAlertCallback任务进程警报回调函数,只不过是多了一个给app任务串口读回调函数。

scTaskAlertCallback接收到串口数据会起作用。

(3)      改写simple_peripheral.c文件,实现获取串口数据的回调,实现与手机端通信的接口。

首先就是添加sc_uart.h的头文件。

声明变量:

static Queue_Struct uartRxMsg;

static Queue_Handle uartRxQueue;

然后在SimpleBLEPeripheral_init初始化函数中增加sensorcontroller串口的初始化

uartRxQueue =Util_constructQueue(&uartRxMsg);//如果这条语句不加,手机能扫描到蓝牙,但是连接不上

  //初始化sensorcontroller 串口

 ScUARTInit();

  //上电后发送串口测试信息

 ScUARTWrite("This my uart test!\r\n",sizeof("This my uarttest!\r\n"));

 GY_UartTask_SC_RegisterPacketReceivedCallback(TransUartReceiveDataCallback);

  //打开LCD显示

 dispHandle = Display_open(Display_Type_LCD,NULL);
其中GY_UartTask_SC_RegisterPacketReceivedCallback是sc_uart.c中的串口接收回调函数,将串口接收的数据传给app任务去处理。TransUartReceiveDataCallback的定义如下

串口数据回调,作用是从app 下获取串口端接收的数据。

static voidTransUartReceiveDataCallback(uint8_t *buf, uint16_t len)

{

 uint8_t *pMsg;

  //Create dynamic pointer to message.

  if((pMsg = ICall_malloc(200)))

  {

   pMsg[0] = len;

   memcpy(pMsg+1, buf, len);

   // Enqueue the message.

   Util_enqueueMsg(uartRxQueue,sem, (uint8*)pMsg);

  }

}

接下来就要修改任务函数SimpleBLEPeripheral_taskFxn,增加串口接收数据队列处理

   //串口接收回调函数队列中的RX消息不为空

   while(!Queue_empty(uartRxQueue))

    {

      uint8_t *pMsg = (uint8_t*)Util_dequeueMsg(uartRxQueue);

     if(pMsg)

     {

       Simple_Peripheral_NotiData(pMsg+1,pMsg[0]);

       //将串口数据发送手机端

       ICall_free(pMsg);

     }

     

}

 

接收到手机数据通过串口及LCD打印出来

static void SimpleBLEPeripheral_processCharValueChangeEvt(uint8_tparamID)

{

#ifndefFEATURE_OAD_ONCHIP

  uint8_t newValue;

 

  switch(paramID)

  {

    case SIMPLEPROFILE_CHAR1:

     SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR1, &newValue);

     

      Display_print1(dispHandle, 4, 0,"Char 1: %d", (uint16_t)newValue);

      Display_print1(dispUHandle,0,0,"Char1: %d" , (uint16_t)newValue);

      ScUARTWrite(&newValue,1);

      break;

 

    case SIMPLEPROFILE_CHAR3:

     SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR3, &newValue);

 

      Display_print1(dispHandle, 4, 0,"Char 3: %d", (uint16_t)newValue);

      Display_print1(dispUHandle,0,0,"Char3: %d" , (uint16_t)newValue);

      break;

 

    default:

      // should not reach here!

      break;

  }

#endif//!FEATURE_OAD_ONCHIP

}

将串口RX接收到的数据发送给手机端

voidSimleBLEPeripheral_NotiData(uint8_t *buf,uint16_t len)

{

  uint8_t notiValue[21]={0};

  notiValue[0]=len;

  memcpy(notfiValue+1,buf,len);

 SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, sizeof(uint8_t),

                               ¬fiValue);

 

}

以上移植好以后,编译通过烧录app程序,实现现象:串口只能发送一个字节的数据,手机也只能发送一个自己的数据

 

那么如果想要发送任意字节的数据包,该如何改写呢?

首先,我们选择app工程的Options选项/C/C++Compiler,如图

CC2640协处理器SensorController移植sc_uart串口程序到simple_peripheral工程,实现串口与手机的通信_第3张图片

定义一个PROFILE_Multibyte,相当定义了宏定义#definePROFILE_Multibyte 1,下面开始改写代码

(1)simple_peripheral.c文件中

static voidSimpleBLEPeripheral_processCharValueChangeEvt(uint8_t paramID)

{

#ifndefFEATURE_OAD_ONCHIP

#ifdef PROFILE_Multibyte

 uint8_t newValue[21];//定义CC2640蓝牙接收手机发送数据,最大20,还有一个为长度

#else

 uint8_t newValue;//默认情况下值接收一个字节数据

#endif

  switch(paramID)

  {

    case SIMPLEPROFILE_CHAR1:

#ifdef  PROFILE_Multibyte

     SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR1, newValue);//获取CHAR1的数据

      ScUARTWrite(newValue+1,newValue[0]);//将手机接收到的数据通过串口打印出来

     //GY_UartTask_Write(newValue+1,newValue[0]);

#else

     SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR1, &newValue);//默认情况下只接收一个字节

      ScUARTWrite(&newValue,1);

#endif

      Display_print0(dispHandle, 4, 0,"Char 1:");

      Display_print1(dispHandle, 5, 0,"%s", newValue+1);

      break;

 

    case SIMPLEPROFILE_CHAR3:

     SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR3, &newValue);

 

      //Display_print1(dispHandle, 4, 0,"Char 3: %d", (uint16_t)newValue);

      break;

 

    default:

      // should not reach here!

      break;

  }

#endif//!FEATURE_OAD_ONCHIP

}

 

(2)simple_gatt_profile.h文件中

#ifdefPROFILE_Multibyte

#definesimpleProfileChar4_len            20

#defineSIMPLEPROFILE_CHAR1_LEN           21//定义CHAR1一次可接收手机的数据包长度

staticuint8 char4ValueLen = 20;           //定义CHAR4一次可接收串口的数据包长度 

#endif

 

(1)      simple_gatt_profile.c文件中

// Characteristic 1 Value

#ifdef PROFILE_Multibyte

static uint8simpleProfileChar1[SIMPLEPROFILE_CHAR1_LEN] = {0};//定义CHAR1接收缓存数组

#else

static uint8 simpleProfileChar1 = 0;//默认情况下一个字节

#endif

 

// Characteristic 4 Value

#ifdef PROFILE_Multibyte

static uint8 simpleProfileChar4[simpleProfileChar4_len]= {0};//定义CHAR4接收数组

#else

static uint8 simpleProfileChar4 = 0;

#endif

 

     // Characteristic Value 1

     {

       { ATT_BT_UUID_SIZE, simpleProfilechar1UUID },

       GATT_PERMIT_READ | GATT_PERMIT_WRITE,

       0,

#ifdef PROFILE_Multibyte

       simpleProfileChar1//数组地址

#else

       &simpleProfileChar1 //char一个字节

#endif

     },

 

 

     // Characteristic Value 4

     {

       { ATT_BT_UUID_SIZE, simpleProfilechar4UUID },

       0,

       0,

#ifdef PROFILE_Multibyte

       simpleProfileChar4

#else

       &simpleProfileChar4

#endif 

     },

 

#ifdef PROFILE_Multibyte

     if ( len == SIMPLEPROFILE_CHAR5_LEN ) //这里的len长度可以自己定义,但在调用该函数的时候对应的形参len要一致

     {

       memcpy( simpleProfileChar1, value, SIMPLEPROFILE_CHAR1_LEN );

     }

#else

           if ( len == sizeof ( uint8 ) )

     {

       simpleProfileChar1 = *((uint8*)value);

     }

#endif

 

 

#ifdef PROFILE_Multibyte

       uint8 *pBuf = value;

       memset(simpleProfileChar4, 0, simpleProfileChar4_len);

       VOID memcpy( simpleProfileChar4, pBuf+1, pBuf[0] );//第一个字节是长度

       // See if Notification has been enabled

       GATTServApp_ProcessCharCfg( simpleProfileChar4Config,simpleProfileChar4, FALSE,

                           simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ),

                            INVALID_TASK_ID,simpleProfile_ReadAttrCB );

#else

       simpleProfileChar4 = *((uint8*)value);

       // See if Notification has been enabled

       GATTServApp_ProcessCharCfg( simpleProfileChar4Config,&simpleProfileChar4, FALSE,

                                   simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ),

                                   INVALID_TASK_ID, simpleProfile_ReadAttrCB );

#endif

 

 

   case SIMPLEPROFILE_CHAR1:

#ifdef PROFILE_Multibyte

     memcpy( value, simpleProfileChar1, SIMPLEPROFILE_CHAR1_LEN );  //simpleProfileChar1 是数组名

#else

     *((uint8*)value) = simpleProfileChar1;

#endif

     break;

 

   case SIMPLEPROFILE_CHAR4:

#ifdef PROFILE_Multibyte

     memcpy( value, simpleProfileChar4, simpleProfileChar4_len );

#else

     *((uint8*)value) = simpleProfileChar4;

#endif

     break;

 

#ifdef PROFILE_Multibyte     

       *pLen = char4ValueLen;

       memcpy( pValue, pAttr->pValue, char4ValueLen );

#else

       *pLen = 1;

       pValue[0] = *pAttr->pValue;

#endif

 

最后重新编译,烧录。

实验现象:

手机用蓝牙调试助手在CHAR1发送20字节以内的数据包可以在水墨屏上显示,且串口会打印出来。在CHAR4可以接收到串口发送的数据。

你可能感兴趣的:(CC2640,CC2640,协处理器,串口sc_uart,移植)