微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 基于CC2640蓝牙4.2的串口透传(结项)

基于CC2640蓝牙4.2的串口透传(结项)

时间:10-02 整理:3721RD 点击:
经过这近2个月对CC2640R2开发板的学习,现在开始对它进行结项,要做的就是一个蓝牙透传的处理,主要是把手机端的数据通过蓝牙再通过串口传输到其他MCU使用,这里我就用PC端的串口助手打印出来看。好了,接下来我就来讲讲我的蓝牙透传的具体实现过程。
1.首先在CC2640R2_LAUNCHXL.h中修改串口pin 我在这里把串口的RX设置为IOID4,TX设置为IOID5.如下所示:
#define CC2640R2_LAUNCHXL_UART_RX               IOID_4          /* RXD */
#define CC2640R2_LAUNCHXL_UART_TX               IOID_5          /* TXD */
这个是我使用的串口引脚,我也就按这个引脚把它连接到USB转串口的引脚上,如下图所示:

2.接下来就是透传的实现过程,首先在我static void SimpleBLEPeripheral_taskFxn(UArg a0, UArg a1)这个函数中创建了几个不同的事件,主要用来进行串口数据的收发,已经保存一些设置好的配置信息。如下所示的设置:
#define SBP_PERIODIC_EVT                      Event_Id_00
#define SPP_RECV_FROM_UART_TIMEOUT_EVT        Event_Id_01
#define SPP_SEND_DATA_NOTIFY_DATA_EVENT       Event_Id_02
#define SBP_SAVE_DATA_EVENT                   Event_Id_03

3.就是初始化串口和对串口数据的处理部分,首先调用协议栈自带的uart初始化函数
  NPITLUART_initializeTransport(sbTHD_RxBuf, sbTHD_TxBuf, THD_UART_CallBack);
在这里我使用的回调函数THD_UART_CallBack来进行处理收发的串口数据。
在收到数据后我首先要判断一下这个数据是不是我想要的AT指令,如果是的话那么我就会进入AT指令的处理部分,如果不是AT指令,那么我就会让它通过蓝牙传送给手机端,这样就实现的透传的主要目的。
具体操作如下代码:
if((UartTempData[0]==CMD_IND_BUF[0])&&(UartTempData[1]==CMD_IND_BUF[1])&&(UartTempData[2]==CMD_IND_BUF[2])&&(UartTempData[3]==CMD_IND_BUF[3]))
      {
        for(i=0;i<20;i++)
        {
          if(sbTHD_RxBuf[i+4] != 0x20)
          {
            UartCmdData = sbTHD_RxBuf[i+4];
          }
          else
          {
            CmdLen = i;
            if(nTHD_RxLen == (CmdLen+HEAD_LEN))
            {
              memset(SetData, 0, 20);
            }
            else
            {
              memset(SetData, 0, 20);
              memcpy(SetData, sbTHD_RxBuf+CmdLen+HEAD_LEN+1, nTHD_RxLen-CmdLen-HEAD_LEN-1);
            }
            for(j=i;j<20;j++)
              UartCmdData[j] = 0;
            break;
          }
        }
其中的CMD_IND_BUF是我要进行检查的AT指令的头。
for(i=0;i<CMD_COUNTDATA;i++)
        {
          if((strcmp(UartCmdData, cmdStrTbl)==0))
          {
            CmdId = i;
//            GUA_UART_WriteTransport(&CmdId, 1);
            switch(CmdId)
            {
              case CMD_SETNAME:
                SetName((char *)SetData);
                break;
              case CMD_GETNAME:
                GetName();
                break;
              case CMD_SETBR:
                SetUartBD((char * )SetData);
                break;
              case CMD_GETBR:
                GetUartBD();
                break;
              case CMD_SETTXDLY:
                break;
              case CMD_GETTXDLY:
                break;
              case CMD_SETDBM:
                SetDBM((char *)SetData);
                break;
              case CMD_GETDBM:
                GetDBM();
                break;
              case CMD_SETADVDATA:
                break;
              case CMD_GETADVDATA:
                break;
              case CMD_SETADVINT:
                break;
              case CMD_GETADVINT:
                break;
            }
           break;
       }
       else if(i == (CMD_COUNTDATA-1))        //检查到不是我想要的AT指令
          {
            SPP_Send(sbGUA_RxBuf, nGUA_RxLen);  //把数据传送给蓝牙部分
            memset(sbGUA_TxBuf, 0, sizeof(sbGUA_TxBuf));
            memcpy(sbGUA_TxBuf, CMD_FAILED, 10);
            GUA_UART_WriteTransport(sbGUA_TxBuf, 10);  //同时通过串口回传一个错误的信息
          }
   }
    else    // ATT指令头就检查不对
      {
        if(ConnectedStates == GAPROLE_CONNECTED)   
        {
          SPP_Send(sbGUA_RxBuf, nGUA_RxLen);    //直接把数据通过蓝牙传给主设备端。
        }
      }   
这样就实现了基本的功能了,这里我串口传过来的数据我是使用了堆栈的方式(先进先出的原则)实现的
static uint16 SPP_PushQueue(SppByteFifo* ptr_queue, uint8* ptr_data, uint16 size)
{
    uint16 old_tail = 0;
    if (!ptr_queue || !ptr_data || !size)
    {
        return 0;
    }
    old_tail = ptr_queue->tail;
    if (ptr_queue->cnt > ptr_queue->size)
    {
        return 0;
    }
    if (size > (ptr_queue->size - ptr_queue->cnt))
    {
        __asm("NOP");
        //Full
        return 0;
    }
    ptr_queue->tail += size;
    if (ptr_queue->tail >= ptr_queue->size)
    {
        ptr_queue->tail -= ptr_queue->size;
    }
    if (old_tail >= ptr_queue->tail)
    {
        osal_memcpy(ptr_queue->pbuf + old_tail, ptr_data, ptr_queue->size - old_tail);
        if (old_tail)
        {
           osal_memcpy(ptr_queue->pbuf, ptr_data + ptr_queue->size - old_tail, size - (ptr_queue->size - old_tail));
        }
    }
    else
    {
        osal_memcpy(ptr_queue->pbuf + old_tail, ptr_data, size);
    }
    ptr_queue->cnt += size;
    return size;
}
好了,到这里基本上已经可以实现部分的AT指令和串口透传的功能了,后续我还会继续加入一些相关的AT指令进来的,我这里实现的AT指令主要有:设置设备名字、获取设备名字、设置串口波特率、设置发射功率。获取发射功率。
这里我就演示一下我的部分AT指令和透传的部分。


首先演示一下透传部分如下图所示:
左边这个图片就是我从电脑串口助手端发送的0x30313233343536373839的数据
右边则是我用手机收到的数据为0x30313233343536373839
所以串口的透传部分是OK的啦。
接下来就演示一下我的AT指令部分:ATT 指令为:THD:setName 123(设备名称)




上面三张图片中第一张图片表示未设置设备名称前的蓝牙名称是simple_peripheral;
第二张图片是通过串口发送AT指令来修改设备名称为123,修改成功后会返回THD:OK 响应一下。
第三张图片再次用手机扫描时设备名称已经改为了123了,说明此AT指令设置成功了。


接下来就是getname的ATT指令了AT 指令为:THD:getName
通过串口发送AT指令后串口端会收到蓝牙模块发送过来的串口数据为THD:OK 123(设备名称)
说明此AT指令也可以使用了。
接下来就是串口波特率的设置了如下图所示:



左边图片为修改波特率前的波特率为115200,通过AT指令把它修改成9600的波特率,右边图片即为修改后的波特率9600,显示出来的数据也是OK的,说明设置波特率成功了。
好了,最后就来讲讲设置发射功率的AT指令了。由于没有用频谱分析仪来看,所以这里就没有截图了,只复制一些代码过来,代码详细过程如下:
switch(cf_dbm)  
          {  
            case -21:  
            {  
              HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_MINUS_21_DBM);   //设置发射功率 -21db
              osal_snv_write(SNV_ID_TX_DBM, sizeof(cf_dbm), &cf_dbm);
              THD_UART_WriteTransport(CMD_SUCCESS, 7);  
              break;  
            }         
            case -18:  
            {  
              HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_MINUS_18_DBM);   //设置发射功率 -18db   
              osal_snv_write(SNV_ID_TX_DBM, sizeof(cf_dbm), &cf_dbm);
              THD_UART_WriteTransport(CMD_SUCCESS, 7);
              break;  
            }                     
            case -15:  
            {  
              HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_MINUS_15_DBM);   //设置发射功率 -15db  
              osal_snv_write(SNV_ID_TX_DBM, sizeof(cf_dbm), &cf_dbm);
              THD_UART_WriteTransport(CMD_SUCCESS, 7);   
              break;  
            }         
            case -12:  
            {  
              HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_MINUS_12_DBM);   //设置发射功率 -12db  
              osal_snv_write(SNV_ID_TX_DBM, sizeof(cf_dbm), &cf_dbm);
              THD_UART_WriteTransport(CMD_SUCCESS, 7);  
              break;  
            }              
            case -9:  
            {  
              HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_MINUS_9_DBM);    //设置发射功率 -9db  
              osal_snv_write(SNV_ID_TX_DBM, sizeof(cf_dbm), &cf_dbm);
              THD_UART_WriteTransport(CMD_SUCCESS, 7);  
              break;  
            }         
            case -6:  
            {  
              HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_MINUS_6_DBM);    //设置发射功率 -6db   
              osal_snv_write(SNV_ID_TX_DBM, sizeof(cf_dbm), &cf_dbm);
              THD_UART_WriteTransport(CMD_SUCCESS, 7);
              break;  
            }              
            case -3:  
            {  
              HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_MINUS_3_DBM);    //设置发射功率 -3db   
              osal_snv_write(SNV_ID_TX_DBM, sizeof(cf_dbm), &cf_dbm);
              THD_UART_WriteTransport(CMD_SUCCESS, 7);
              break;  
            }         
            case 0:  
            {  
              HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_0_DBM);          //设置发射功率 0db  
              osal_snv_write(SNV_ID_TX_DBM, sizeof(cf_dbm), &cf_dbm);
              THD_UART_WriteTransport(CMD_SUCCESS, 7);  
              break;  
            }            
            case 1:  
            {  
              HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_1_DBM);          //设置发射功率 1db   
              osal_snv_write(SNV_ID_TX_DBM, sizeof(cf_dbm), &cf_dbm);
              THD_UART_WriteTransport(CMD_SUCCESS, 7);
              break;  
            }  
            case 2:  
            {  
              HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_2_DBM);          //设置发射功率 2db   
              osal_snv_write(SNV_ID_TX_DBM, sizeof(cf_dbm), &cf_dbm);
              THD_UART_WriteTransport(CMD_SUCCESS, 7);
              break;  
            }      
            case 3:  
            {  
              HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_3_DBM);          //设置发射功率 3db   
              osal_snv_write(SNV_ID_TX_DBM, sizeof(cf_dbm), &cf_dbm);
              THD_UART_WriteTransport(CMD_SUCCESS, 7);   
              break;  
            }         
            case 4:  
            {  
              HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_4_DBM);          //设置发射功率 4db   
              osal_snv_write(SNV_ID_TX_DBM, sizeof(cf_dbm), &cf_dbm);  
              THD_UART_WriteTransport(CMD_SUCCESS, 7);
              break;  
            }        
            case 5:  
            {  
              HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_5_DBM);          //设置发射功率 5db     
              osal_snv_write(SNV_ID_TX_DBM, sizeof(cf_dbm), &cf_dbm);
              THD_UART_WriteTransport(CMD_SUCCESS, 7);
              break;  
            }     
       在这里我也做了保存功能,把通过AT指令修改后的参数写入到了snv中了。   
最后再次感谢[size=14.6667px]昇润科技提供的开发板,让我可以对CC2640R2的学习有很大的帮助,也基本上完成了申请此开发板时所提的透传项目的学习,也让我对CC2640R2的串口和蓝牙的一些profile的配置有了很大的提高,[size=14.6667px]还有一些AT指令我也会陆续的把它给添加进来的。


厉害了

此处应该有掌声

小编可以提供代码学习学习吗?

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

网站地图

Top