BLE 4.0 UART 透传

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).
             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 );

                   // 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()容易丢包。
                             串口打印      
                     }
}

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


你可能感兴趣的:(4.0,UART,BLE,透传)