当前位置: > 华清远见教育科技集团 > 嵌入式学习 > 讲师博文 > BLE 4.0 UART 透传
BLE 4.0 UART 透传
时间:2016-12-14作者:华清远见

1、这个透传是基于BLE-CC254x-1.3.2开发的,开发软件工具IAR for 8051 8.10版本(版本不同可能打不开)。

2、首先打开文件夹下BLE-CC254x-1.3.2-Serial\Projects\ble\SimpleBLEPeripheral\CC2540DB双击SimpleBLEPeripheral.eww打开相应的工程。

3、接下来进行修改透传程序,由于TI公司写的DMA处理串口函数HalUARTPollDMA()有点复杂,在传输时可能会出现断链的现象。因此,对这个函数进行修改。

4、先看一下DMA的初始化HalUARTInitDMA()

主要是对DMA寄存器的配置,

PERCFG &= ~HAL_UART_PERCFG_BIT; // Set UART0 I/O to Alt. 1 location on P0.
        PxSEL |= HAL_UART_Px_SEL; // Enable Peripheral control of Rx/Tx on Px.
        UxCSR = CSR_MODE; // Mode is UART Mode.
        UxUCR = UCR_FLUSH; // Flush it.

        P2DIR &= ~P2DIR_PRIPO;
        P2DIR |= HAL_UART_PRIPO;

下面就是对DMA的发送和接收的相关设置,刚才打开的是从机设备相关代码,要从串口读取相关数据,因此只修改Rx部分。

// Setup Rx by DMA.
        ch = HAL_DMA_GET_DESC1234( HAL_DMA_CH_RX );

        // Abort any pending DMA operations (in case of a soft reset).
&nnbsp;       HAL_DMA_ABORT_CH( HAL_DMA_CH_RX );

        // The start address of the source.
        HAL_DMA_SET_SOURCE( ch, DMA_UxDBUF );

        // Using the length field to determine how many bytes to transfer.
        HAL_DMA_SET_VLEN( ch, HAL_DMA_VLEN_USE_LEN );

        /* The trick is to cfg DMA to xfer 2 bytes for every 1 byte of Rx.
        * The byte after the Rx Data Buffer is the Baud Cfg Register,
        * which always has a known value. So init Rx buffer to inverse of that
        * known value. DMA word xfer will flip the bytes, so every valid Rx byte
        * in the Rx buffer will be preceded by a DMA_PAD char equal to the
        * Baud Cfg Register value.
        */
        // HAL_DMA_SET_WORD_SIZE( ch, HAL_DMA_WORDSIZE_WORD );
        HAL_DMA_SET_WORD_SIZE( ch, HAL_DMA_WORDSIZE_BYTE ); //by lht

        // The bytes are transferred 1-by-1 on Rx Complete trigger.
        HAL_DMA_SET_TRIG_MODE( ch, HAL_DMA_TMODE_SINGLE_REPEATED );
        HAL_DMA_SET_TRIG_SRC( ch, DMATRIG_RX );

        // The source address is constant - the Rx Data Buffer.
        HAL_DMA_SET_SRC_INC( ch, HAL_DMA_SRCINC_0 );

        // The destination address is incremented by 1 word after each transfer.
        HAL_DMA_SET_DST_INC( ch, HAL_DMA_DSTINC_1 );
        HAL_DMA_SET_DEST( ch, dmaCfg.rxBuf+1 );
        // HAL_DMA_SET_LEN( ch, HAL_UART_DMA_RX_MAX );
        HAL_DMA_SET_LEN( ch, 24);

        // The DMA is to be polled and shall not issue an IRQ upon completion.
        HAL_DMA_SET_IRQ( ch, HAL_DMA_IRQMASK_DISABLE );

     &nbnbsp;  // Xfer all 8 bits of a byte xfer.
        HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS );

        // DMA has highest priority for memory access.
        HAL_DMA_SET_PRIORITY( ch, HAL_DMA_PRI_HIGH);

        volatile uint8 dummy = *(volatile uint8 *)DMA_UxDBUF; // Clear the DMA Rx trigger.
        HAL_DMA_CLEAR_IRQ(HAL_DMA_CH_RX);
        HAL_DMA_ARM_CH(HAL_DMA_CH_RX);
        (void)memset(dmaCfg.rxBuf, (DMA_PAD ^ 0xFF), HAL_UART_DMA_RX_MAX*2);

只需要修改以上蓝色的部分,

HAL_DMA_SET_WORD_SIZE( ch, HAL_DMA_WORDSIZE_BYTE );

一个字节一个字节的读取串口数据

HAL_DMA_SET_DEST( ch, dmaCfg.rxBuf+1 );

DMA目标缓冲区,这里我们定义25字节大小(可以调大)。

注意: 这个地方的大小是根据项目实际情况设定的,物联网项目中采集环境端发送的数据包是固定的24个字节,根据蓝牙的传输协议,发送数据包时第一个字节是数据长度,因此,maCfg.rxBuf的第一个字节存数据长度。

HAL_DMA_SET_LEN( ch, 24);

重要的就是这, 当缓存区字节数达到24个字节是,状态寄存器就会置1;

4、初始化完后就是对串口DMA的处理,TI给的demo程序会出现断链现象,进行修改。

进入HalUARTPollDMA()函数,主要是对DMA操作,注销原来的代码,添加代码如下,

if((DMAIRQ&0x8) == 0x08) //DMA缓冲区状态标志
        {
                if(rxBufflag == 0) //第一次进入
                {
                        dmaCfg.rxBuf[0] = 14; //定义数据长度
                        SimpleProfile_SetParameter( 6,15, dmaCfg.rxBuf ); //发送数据长度和数据
                        rxBufflag =1;
                }
                else if(rxBufflag == 1) //发送第二次
                {
                        DMAIRQ &= ~(1<<3); //清状态标志
                        for(i=0;i<4000;i++);
                        dmaCfg.rxBuf[14] = 10; //数据长度
                        SimpleProfile_SetParameter( 6,15,&dmaCfg.rxBuf[14]); //发送数据长度和数据
                        rxBufflag =0;
                }
        }

注意: BLE 4.0协议规定了一次发送大不超20个字节,这里我们项目中用到24个字节,超出一次发送的大量,因此,分两次发送,第一次14字节,第二次10字节。(可以修改第二次发送的数据长度,来调节你的发送总的字节数)

6、修改主机端SimpleBLECentral

首先打开文件夹下BLE-CC254x-1.3.2-Serial\Projects\ble\SimpleBLECentral\CC2540双击SimpleBLECentral.eww打开相应的工程。

在simpleBLECentral.c中找到消息处理函数simpleBLECentralProcessGATTMsg()

由于从机是分两次发送的,这里分两次接收。

if( pMsg->msg.handleValueNoti.handle == 0x0038) //CHAR7的通知信息
        {
                if(pMsg->msg.handleValueNoti.value[0] == 14) //接收第一次14个字节数据
                        {
                        osal_memset(Rxbuf,0,24); //Rxbuf 缓冲区清零
                        osal_memcpy(Rxbuf,&pMsg->msg.handleValueNoti.value[1],pMsg->msg.handleValueNoti.value[0]); //数据拷贝

                }
                else if(pMsg->msg.handleValueNoti.value[0] == 10) //接收第二个10字节数据
                {

                        osal_memcpy(Rxbuf+14,&pMsg->msg.handleValueNoti.value[1],10); //对Rxbuf缓冲区拼凑
                        NPI_WriteTransport(Rxbuf,24); //不能连续发送NPI_WriteTransport()容易丢包。
                        串口打印
                }
        }

注意:蓝牙连接时记得按一下蓝牙主机端复位键。让主机程序跑起来。

发表评论
评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)