首页 > 嵌入式开发 > LPC1768官方串口驱动库错误

LPC1768官方串口驱动库错误

2011年10月29日 发表评论 阅读评论
/*********************************************************************//**
 * @brief		Determines best dividers to get a target clock rate
 * @param[in]	UARTx	Pointer to selected UART peripheral, should be:
 * 				- LPC_UART0: UART0 peripheral
 * 				- LPC_UART1: UART1 peripheral
 * 				- LPC_UART2: UART2 peripheral
 * 				- LPC_UART3: UART3 peripheral
 * @param[in]	baudrate Desired UART baud rate.
 * @return 		Error status, could be:
 * 				- SUCCESS
 * 				- ERROR
 **********************************************************************/
static Status uart_set_divisors(LPC_UART_TypeDef *UARTx, uint32_t baudrate)
{
	Status errorStatus = ERROR;

	uint32_t uClk;
	uint32_t d, m, bestd, bestm, tmp;
	uint64_t best_divisor, divisor;
	uint32_t current_error, best_error;
	uint32_t recalcbaud;

	/* get UART block clock */
	if (UARTx == LPC_UART0)
	{
		uClk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_UART0);
	}
	else if (UARTx == (LPC_UART_TypeDef *)LPC_UART1)
	{
		uClk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_UART1);
	}
	else if (UARTx == LPC_UART2)
	{
		uClk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_UART2);
	}
	else if (UARTx == LPC_UART3)
	{
		uClk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_UART3);
	}

	/* In the Uart IP block, baud rate is calculated using FDR and DLL-DLM registers
	* The formula is :
	* BaudRate= uClk * (mulFracDiv/(mulFracDiv+dividerAddFracDiv) / (16 * (DLL)
	* It involves floating point calculations. That's the reason the formulae are adjusted with
	* Multiply and divide method.*/
	/* The value of mulFracDiv and dividerAddFracDiv should comply to the following expressions:
	* 0 < mulFracDiv <= 15, 0 <= dividerAddFracDiv <= 15 */
	best_error = 0xFFFFFFFF; /* Worst case */
	bestd = 0;
	bestm = 0;
	best_divisor = 0;
	for (m = 1 ; m <= 15 ;m++)
	{
		for (d = 0 ; d < m ; d++)
		{
		  divisor = ((uint64_t)uClk<<28)*m/(baudrate*(m+d));
		  current_error = divisor & 0xFFFFFFFF;

		  tmp = divisor>>32;

		  /* Adjust error */
		  if(current_error > ((uint32_t)1<<31)){
			current_error = -current_error;
			tmp++;
			}

		  if(tmp<1 || tmp>65536) /* Out of range */
		  continue;

		  if( current_error < best_error){
			best_error = current_error;
			best_divisor = tmp;
			bestd = d;
			bestm = m;
			if(best_error == 0) break;
			}
		} /* end of inner for loop */

		if (best_error == 0)
		  break;
	} /* end of outer for loop  */

	if(best_divisor == 0) return ERROR; /* can not find best match */

	recalcbaud = (uClk>>4) * bestm/(best_divisor * (bestm + bestd));

	/* reuse best_error to evaluate baud error*/
	if(baudrate>recalcbaud) best_error = baudrate - recalcbaud;
	else best_error = recalcbaud -baudrate;

	best_error = best_error * 100 / baudrate;

	if (best_error < UART_ACCEPTED_BAUDRATE_ERROR)
		{
			if (((LPC_UART1_TypeDef *)UARTx) == LPC_UART1)
			{
				((LPC_UART1_TypeDef *)UARTx)->LCR |= UART_LCR_DLAB_EN;
				((LPC_UART1_TypeDef *)UARTx)->/*DLIER.*/DLM = UART_LOAD_DLM(best_divisor);
				((LPC_UART1_TypeDef *)UARTx)->/*RBTHDLR.*/DLL = UART_LOAD_DLL(best_divisor);
				/* Then reset DLAB bit */
				((LPC_UART1_TypeDef *)UARTx)->LCR &= (~UART_LCR_DLAB_EN) & UART_LCR_BITMASK;
				((LPC_UART1_TypeDef *)UARTx)->FDR = (UART_FDR_MULVAL(bestm) \
						| UART_FDR_DIVADDVAL(bestd)) & UART_FDR_BITMASK;
			}
			else
			{
				UARTx->LCR |= UART_LCR_DLAB_EN;
				UARTx->/*DLIER.*/DLM = UART_LOAD_DLM(best_divisor);
				UARTx->/*RBTHDLR.*/DLL = UART_LOAD_DLL(best_divisor);
				/* Then reset DLAB bit */
				UARTx->LCR &= (~UART_LCR_DLAB_EN) & UART_LCR_BITMASK;
				UARTx->FDR = (UART_FDR_MULVAL(bestm) \
						| UART_FDR_DIVADDVAL(bestd)) & UART_FDR_BITMASK;
			}
			errorStatus = SUCCESS;
		}

		return errorStatus;
}
将此函数替换库中函数。
分类: 嵌入式开发 标签:
  1. yaox
    2012年8月7日16:18 | #1

    这个驱动库是在哪里下的啊?能发到邮箱吗?谢谢

  2. Applex
  1. 本文目前尚无任何 trackbacks 和 pingbacks.