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()容易丢包。
串口打印
}
}
注意:蓝牙连接时记得按一下蓝牙主机端复位键。让主机程序跑起来。