概述
从主函数main开始
void HalDriverInit (void)
{
/* TIMER */
#if (defined HAL_TIMER) && (HAL_TIMER == TRUE)
#error "The hal timer driver module is removed."
#endif
/* ADC */
#if (defined HAL_ADC) && (HAL_ADC == TRUE)
HalAdcInit();
#endif
/* DMA */
#if (defined HAL_DMA) && (HAL_DMA == TRUE)
// Must be called before the init call to any module that uses DMA.
HalDmaInit();
#endif
/* AES */
#if (defined HAL_AES) && (HAL_AES == TRUE)
HalAesInit();
#endif
/* LCD */
#if (defined HAL_LCD) && (HAL_LCD == TRUE)
HalLcdInit();
#endif
/* LED */
#if (defined HAL_LED) && (HAL_LED == TRUE)
HalLedInit();
#endif
/* UART */
#if (defined HAL_UART) && (HAL_UART == TRUE)
HalUARTInit();
#endif
/* KEY */
#if (defined HAL_KEY) && (HAL_KEY == TRUE)
HalKeyInit();
#endif
/* SPI */
#if (defined HAL_SPI) && (HAL_SPI == TRUE)
HalSpiInit();
#endif
/* HID */
#if (defined HAL_HID) && (HAL_HID == TRUE)
usbHidInit();
#endif
}
hal_uart.c
void HalUARTInit(void)
{
#if HAL_UART_DMA//ZigBee的的串口接收采用的是DMA接收,节省CPU的资源
HalUARTInitDMA();
#endif
#if HAL_UART_ISR
HalUARTInitISR();
#endif
#if HAL_UART_USB
HalUARTInitUSB();
#endif
}
_hal_uart_dma.c
static void HalUARTInitDMA(void)
{
halDMADesc_t *ch;
P2DIR &= ~P2DIR_PRIPO;
P2DIR |= HAL_UART_PRIPO;
#if (HAL_UART_DMA == 1)
PERCFG &= ~HAL_UART_PERCFG_BIT; // Set UART0 I/O to Alt. 1 location on P0.
#else
PERCFG |= HAL_UART_PERCFG_BIT; // Set UART1 I/O to Alt. 2 location on P1.
#endif
PxSEL |= HAL_UART_Px_RX_TX; // Enable Tx and Rx on P1.
ADCCFG &= ~HAL_UART_Px_RX_TX; // Make sure ADC doesnt use this.
UxCSR = CSR_MODE; // Mode is UART Mode.
UxUCR = UCR_FLUSH; // Flush it.
// Setup Tx by DMA.
ch = HAL_DMA_GET_DESC1234( HAL_DMA_CH_TX );
// The start address of the destination.
HAL_DMA_SET_DEST( ch, DMA_UDBUF );
// Using the length field to determine how many bytes to transfer.
HAL_DMA_SET_VLEN( ch, HAL_DMA_VLEN_USE_LEN );
// One byte is transferred each time.
HAL_DMA_SET_WORD_SIZE( ch, HAL_DMA_WORDSIZE_BYTE );
// The bytes are transferred 1-by-1 on Tx Complete trigger.
HAL_DMA_SET_TRIG_MODE( ch, HAL_DMA_TMODE_SINGLE );
HAL_DMA_SET_TRIG_SRC( ch, DMATRIG_TX );
// The source address is incremented by 1 byte after each transfer.
HAL_DMA_SET_SRC_INC( ch, HAL_DMA_SRCINC_1 );
// The destination address is constant - the Tx Data Buffer.
HAL_DMA_SET_DST_INC( ch, HAL_DMA_DSTINC_0 );
// The DMA Tx done is serviced by ISR in order to maintain full thruput.
HAL_DMA_SET_IRQ( ch, HAL_DMA_IRQMASK_ENABLE );
// 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 );
// Setup Rx by DMA.
ch = HAL_DMA_GET_DESC1234( HAL_DMA_CH_RX );
// The start address of the source.
HAL_DMA_SET_SOURCE( ch, DMA_UDBUF );
// 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 );
// 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 );
HAL_DMA_SET_LEN( ch, HAL_UART_DMA_RX_MAX );
// 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 );
}
串口DMA的引脚不是固定的,根据不同的硬件引脚来配置不同的模式。
串口的初始化包括波特率等的初始化
从main函数开始
osal_init_system();//初始化操作系统
// Initialize the system tasks.
osalInitTasks();
SampleApp_Init( taskID );
MT_UART.C
这样一路goto到达波特率的初始化
void SampleApp_Init( uint8 task_id )
{
SampleApp_TaskID = task_id;
SampleApp_NwkState = DEV_INIT;
SampleApp_TransID = 0;
MT_UartInit();//串口初始化
MT_UartRegisterTaskID(task_id);//登记任务号
HalUARTWrite(0,"Hello Worldn",12); //(串口0,'字符',字符个数。)
// Device hardware initialization can be added here or in main() (Zmain.c).
// If the hardware is application specific - add it here.
// If the hardware is other parts of the device add it in main().
#if defined ( BUILD_ALL_DEVICES )
// The "Demo" target is setup to have BUILD_ALL_DEVICES and HOLD_AUTO_START
// We are looking at a jumper (defined in SampleAppHw.c) to be jumpered
// together - if they are - we will start up a coordinator. Otherwise,
// the device will start as a router.
if ( readCoordinatorJumper() )
zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR;
else
zgDeviceLogicalType = ZG_DEVICETYPE_ROUTER;
#endif // BUILD_ALL_DEVICES
#if defined ( HOLD_AUTO_START )
// HOLD_AUTO_START is a compile option that will surpress ZDApp
// from starting the device and wait for the application to
// start the device.
ZDOInitDevice(0);
#endif
// Setup for the periodic message's destination address
// Broadcast to everyone
SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;
SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF;
SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Periodic_DstAddr.addr.shortAddr = a;
// Setup for the flash command's destination address - Group 1
SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup;
SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP;
// Fill out the endpoint description.
SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_epDesc.task_id = &SampleApp_TaskID;
SampleApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc;
SampleApp_epDesc.latencyReq = noLatencyReqs;
// Register the endpoint description with the AF
afRegister( &SampleApp_epDesc );
// Register for all key events - This app will handle all key events
RegisterForKeys( SampleApp_TaskID );
// By default, all devices start out in Group 1
SampleApp_Group.ID = 0x0001;
osal_memcpy( SampleApp_Group.name, "Group 1", 7 );
aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group );
#if defined ( LCD_SUPPORTED )
HalLcdWriteString( "SampleApp", HAL_LCD_LINE_1 );
#endif
}
在这里可以进行波特率的修改
#if !defined MT_UART_DEFAULT_BAUDRATE
#define MT_UART_DEFAULT_BAUDRATE HAL_UART_BR_115200//HAL_UART_BR_38400
#endif
#define HAL_UART_BR_9600 0x00
#define HAL_UART_BR_19200 0x01
#define HAL_UART_BR_38400 0x02
#define HAL_UART_BR_57600 0x03
#define HAL_UART_BR_115200 0x04
void MT_UartInit ()
{
halUARTCfg_t uartConfig;
/* Initialize APP ID */
App_TaskID = 0;
/* UART Configuration */
uartConfig.configured = TRUE;
uartConfig.baudRate = MT_UART_DEFAULT_BAUDRATE;
uartConfig.flowControl = MT_UART_DEFAULT_OVERFLOW;
uartConfig.flowControlThreshold = MT_UART_DEFAULT_THRESHOLD;
uartConfig.rx.maxBufSize = MT_UART_DEFAULT_MAX_RX_BUFF;
uartConfig.tx.maxBufSize = MT_UART_DEFAULT_MAX_TX_BUFF;
uartConfig.idleTimeout = MT_UART_DEFAULT_IDLE_TIMEOUT;
uartConfig.intEnable = TRUE;
#if defined (ZTOOL_P1) || defined (ZTOOL_P2)
uartConfig.callBackFunc = MT_UartProcessZToolData;
我们定义的这个就用MT_UartProcessZToolData进行串口数据的接受
#elif defined (ZAPP_P1) || defined (ZAPP_P2)
uartConfig.callBackFunc = MT_UartProcessZAppData;
#else
uartConfig.callBackFunc = NULL;
#endif
/* Start UART */
#if defined (MT_UART_DEFAULT_PORT)
HalUARTOpen (MT_UART_DEFAULT_PORT, &uartConfig);
#else
/* Silence IAR compiler warning */
(void)uartConfig;
#endif
/* Initialize for ZApp */
#if defined (ZAPP_P1) || defined (ZAPP_P2)
/* Default max bytes that ZAPP can take */
MT_UartMaxZAppBufLen = 1;
MT_UartZAppRxStatus = MT_UART_ZAPP_RX_READY;
#endif
}
//经过网蜂的修改这是一个非常易容的串口接收代码
void MT_UartProcessZToolData ( uint8 port, uint8 event )
{
/* uint8 ch;
uint8 bytesInRxBuffer;
(void)event; // Intentionally unreferenced parameter*/
uint8 flag=0,i,j=0; //flag是判断有没有收到数据,j记录数据长度
uint8 buf[128]; //串口buffer最大缓冲默认是128,我们这里用128.
(void)event; // Intentionally unreferenced parameter
while (Hal_UART_RxBufLen(port)) //检测串口数据是否接收完成
{
HalUARTRead (port,&buf[j], 1); //把数据接收放到buf中读取的时候回调用DMA进行读取数据
j++; //记录字符数
flag=1; //已经从串口接收到信息
}
if(flag==1) //已经从串口接收到信息
{ /* Allocate memory for the data */
//分配内存空间,为机构体内容+数据内容+1个记录长度的数据
pMsg = (mtOSALSerialData_t *)osal_msg_allocate( sizeof
( mtOSALSerialData_t )+j+1);
//事件号用原来的CMD_SERIAL_MSG
pMsg->hdr.event = CMD_SERIAL_MSG;
pMsg->msg = (uint8*)(pMsg+1); // 把数据定位到结构体数据部分
pMsg->msg [0]= j; //给上层的数据第一个是长度
for(i=0;i<j;i++) //从第二个开始记录数据
pMsg->msg [i+1]= buf[i];
osal_msg_send( App_TaskID, (byte *)pMsg ); //登记任务,发往上层发送到上层就是应用层
/* deallocate the msg */
osal_msg_deallocate ( (uint8 *)pMsg ); //释放内存
}
转跳到数据发送的应用层
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{
afIncomingMSGPacket_t *MSGpkt;
(void)task_id; // Intentionally unreferenced parameter
if ( events & SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
while ( MSGpkt )
{
switch ( MSGpkt->hdr.event )
{
case CMD_SERIAL_MSG://新添加接收串口信息
SampleApp_SerialCMD((mtOSALSerialData_t *)MSGpkt);//串口一旦来了数据触发这个函数,稍后转跳到这个函数
break;
// Received when a key is pressed
case KEY_CHANGE://按键触发
SampleApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
break;
// Received when a messages is received (OTA) for this endpoint
case AF_INCOMING_MSG_CMD://有无线数据到来
SampleApp_MessageMSGCB( MSGpkt );
break;
// Received whenever the device changes state in the network
case ZDO_STATE_CHANGE://当网络状态改变,如从未连接上到连上网络
SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
if ( (SampleApp_NwkState == DEV_ZB_COORD)//协调器、路由器、或者终端都执行
|| (SampleApp_NwkState == DEV_ROUTER)
|| (SampleApp_NwkState == DEV_END_DEVICE) )
{
// Start sending the periodic message in a regular interval.//打开定时器
osal_start_timerEx( SampleApp_TaskID,//任务ID号
SAMPLEAPP_SEND_PERIODIC_MSG_EVT,//同一个任务下可以有多个事件,这个是事件的号码。事件号码16位必须只占1位,所以只能定义16个事件
SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );//时间
osal_start_timerEx( SampleApp_TaskID,//任务ID号
SAMPLEAPP_SEND_PERIODIC_MSG_EVT2,//同一个任务下可以有多个事件,这个是事件的号码。事件号码16位必须只占1位,所以只能定义16个事件
SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );//时间
}
else
{
// Device is no longer in the network
}
break;
default:
break;
}
// Release the memory
osal_msg_deallocate( (uint8 *)MSGpkt );
// Next - if one is available
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
// Send a message out - This event is generated by a timer
// (setup in SampleApp_Init()).
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )//周期性发数
{
// Send the periodic message
SampleApp_SendPeriodicMessage();//周期性发送函数
// Setup to send message again in normal period (+ a little jitter)
// osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
// (SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) );
// return unprocessed events
return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);
}
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT2 )//周期性发数
{
// Send the periodic message
//SampleApp_SendPeriodicMessage();//周期性发送函数
// Setup to send message again in normal period (+ a little jitter)
// osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
// (SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) );
// return unprocessed events
return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT2);
}
SAMPLEAPP_SEND_PERIODIC_MSG_EVT2
// Discard unknown events
return 0;
}
串口来了数据会触发这个函数
void SampleApp_SerialCMD(mtOSALSerialData_t *cmdMsg)
{
uint8 i,len,*str=NULL; //len有用数据长度
str=cmdMsg->msg; //指向数据开头
len=*str; //msg里的第1个字节代表后面的数据长度
/********打印出串口接收到的数据,用于提示*********/
for(i=1;i<=len;i++)
HalUARTWrite(0,str+i,1 );
HalUARTWrite(0,"n",1 );//换行
/*******发送出去***参考网蜂 1小时无线数据传输教程*********/
if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,//无线模块的发送
SAMPLEAPP_COM_CLUSTERID,//自己定义一个
len+1, // 数据长度
str, //数据内容
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
{
}
else
{
// Error occurred in request to send.
}
}
通过串口发送到PC机上,代码其实很 简单。
for(i=1;i<=len;i++)
HalUARTWrite(0,str+i,1 );
HalUARTWrite(0,"n",1 );//换行
这么几句话就完成了串口发送数据到PC机的任务
到这里串口相关的问题就讨论到这里
最后
以上就是虚心银耳汤为你收集整理的ZigBee串口的运行流程以及修改的全部内容,希望文章能够帮你解决ZigBee串口的运行流程以及修改所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复