如果要使用协议栈中提供的串口,则需要定义HAL_UART和HAL_UART TRUE【hal_board_cfg.h】。首先初始化串口,在主函数中调用HalDriverInit()时,在函数中初始化串口,主要是配置管脚和DMA通道。然后在osal_start_system()开始系统后,会调用Hal_ProcessPoll()来读取时间和串口,<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
void Hal_ProcessPoll ()
{
HalTimerTick();
#if (defined HAL_UART) && (HAL_UART == TRUE)
HalUARTPoll();
#endif
}
//来看下串口poll函数,我们只看UART0的,因为我的开发板使用这个串口
void HalUARTPoll( void )
{
#if ( HAL_UART_0_ENABLE | HAL_UART_1_ENABLE )
static uint8 tickShdw;
uartCfg_t *cfg;
uint8 tick;
#if HAL_UART_0_ENABLE
//当发生串口接收中断时cfg0就会改变,如果串口没有数据输入cfg0为空,当接收到数据时cfg0将在串口中断服务程序中被改变
if ( cfg0 )
{
cfg = cfg0;
}
#endif
// Use the LSB of the sleep timer (ST0 must be read first anyway).
//系统上电后,睡眠定时器就会自动启动做自增计数ST0即睡眠定时器启动到现在计算值的最低8位
tick = ST0 - tickShdw;
tickShdw = ST0;
//要注意接下来的是个循环
do
{
if ( cfg->txTick > tick )
{
cfg->txTick -= tick;
}
else
{
cfg->txTick = 0;
}
if ( cfg->rxTick > tick )
{
cfg->rxTick -= tick;
}
else
{
cfg->rxTick = 0;
}
//是使用DMA方式还是使用中断方式
#if HAL_UART_ISR
#if HAL_UART_DMA
if ( cfg->flag & UART_CFG_DMA )
{
pollDMA( cfg );
}
else
#endif
{
pollISR( cfg );
//中断方式
static void pollISR( uartCfg_t *cfg )
{
//如果串口没有接收到数据,也就是说没有发生过串口接收中断,那么cfg应为是为空的,则cnt=0
//如果发生了串口中断,则cnt计算出串口缓存中还有多少数据没有读出,这个缓存并不是硬件寄存器的缓存,而是程序中开辟一段空间
uint8 cnt = UART_RX_AVAIL( cfg );
if ( !(cfg->flag & UART_CFG_RXF) )
{
//这里是针对流控制的,如果又有新的数据接收到了那么就要重置超时时间(超时时间由睡眠定时器来控制),而且需要把已经读出的数据数目减去!
// If anything received, reset the Rx idle timer.
if ( cfg->rxCnt != cnt )
{
cfg->rxTick = HAL_UART_RX_IDLE;
cfg->rxCnt = cnt;
}
/* It is necessary to stop Rx flow in advance of a full Rx buffer because
* bytes can keep coming while sending H/W fifo flushes.
*/
//当接收缓存超过安全界限的时候停止RX流
if ( cfg->rxCnt >= (cfg->rxMax - SAFE_RX_MIN) )
{
RX_STOP_FLOW( cfg );
}
//关于安全界限,在程序中有下面一段:
/* Need to leave enough of the Rx buffer free to handle the incoming bytes
* after asserting flow control, but before the transmitter has obeyed it.
* At the max expected baud rate of 115.2k, 16 bytes will only take ~1.3 msecs,
* but at the min expected baud rate of 38.4k, they could take ~4.2 msecs.
* SAFE_RX_MIN and DMA_RX_DLY must both be consistent according to
* the min & max expected baud rate.
*/
//如果声明了流控制,为保证数据的正确接收需要在RX缓存区中预留出足够的空间。CC2430可以使用的最大串口波特率为115.2k。这个安全界限的数字跟使用的波特率还有串口tick有关。
#if !defined( SAFE_RX_MIN )
#define SAFE_RX_MIN 48 // bytes - max expected per poll @ 115.2k
// 16 bytes @ 38.4 kBaud -> 4.16 msecs -> 138 32-kHz ticks.
#define DMA_RX_DLY 140
// 2 bytes @ 38.4 kBaud -> 0.52 msecs -> 17 32-kHz ticks.
#define DMA_TX_DLY 20
#endif
//超时计数利用的是睡眠定时器,而睡眠定时器是以32Khz时钟计数的,所以1微妙约为33个计数值(如果使用外部32.768KHz晶振)
// The timeout tick is at 32-kHz, so multiply msecs by 33.
#define RX_MSECS_TO_TICKS 33
//超时时间设为传输一个字节的时间,之所以是6而不是8我觉得是排除掉串口协议中的停止位和起始位的结果
// The timeout only supports 1 byte.
#if !defined( HAL_UART_RX_IDLE )
#define HAL_UART_RX_IDLE (6 * RX_MSECS_TO_TICKS)
#endif
}
}
}
#elif HAL_UART_DMA
pollDMA( cfg );
#endif
/* The following logic makes continuous callbacks on any eligible flag
* until the condition corresponding to the flag is rectified.
* So even if new data is not received, continuous callbacks are made.
*/
if ( cfg->rxHead != cfg->rxTail )
{
//如果接收缓存中有数据,当接收数据时rxHead会增计数,当读取数据时rxTail会增计数,两个标志的初始值都为0,所以这两个标志的差值就指示了缓存中有多少的数据
uint8 evt;
if ( cfg->rxHead >= (cfg->rxMax - SAFE_RX_MIN) )
{
//已保存的数据已经超过了安全界限,发送接收满事件
evt = HAL_UART_RX_FULL;
}
else if ( cfg->rxHigh && (cfg->rxHead >= cfg->rxHigh) )
{
evt = HAL_UART_RX_ABOUT_FULL;
}
else if ( cfg->rxTick == 0 )
{
//超时事件
evt = HAL_UART_RX_TIMEOUT;
}
else
{
evt = 0;
}
//如果发生事件,并且配置了回调函数则调用回调函数
if ( evt && cfg->rxCB )
{
cfg->rxCB( ((cfg->flag & UART_CFG_U<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />1F)!=0), evt );
//(cfg->flag & UART_CFG_U1F)!=0)判读是那个串口,如果是串口1则为1,否则为0
}
}
//下面的没看懂,下面的判断好像是没有用一样,不管是哪个条件都break了!
if ( cfg == cfg0 )
{
break;
}
else
break;
} while ( TRUE );
#else
return;
#endif
}
//在来看一下串口中断,就是将U0DBUF的数据存放到cfg0->rxBuf里面,并且更改rxHead标志
HAL_ISR_FUNCTION( halUart0RxIsr, URX0_VECTOR )
{
cfg0->rxBuf[cfg0->rxHead] = U0DBUF;
if ( cfg0->rxHead == cfg0->rxMax )
{
cfg0->rxHead = 0;
}
else
{
cfg0->rxHead++;
}
}
//cfg和回调函数在HalUARTOpen (SERIAL_APP_PORT, &uartConfig)中配置
用户1328825 2010-4-1 09:26