Embedded ARM LPC1768 UART0配置,波特率错误

Embedded ARM LPC1768 UART0配置,波特率错误,embedded,serial-port,arm,lpc,clockrates,Embedded,Serial Port,Arm,Lpc,Clockrates,我的波特率应该是115200,但它是892.9 void UART0_Init(int pclk, int baudrate) { unsigned long int DLest; //unsigned long int pclk; unsigned int temp; // Turn on power to UART0 SC->PCONP |= PCUART0_POWERON; // Set PINSEL0 so that P0.2 =

我的波特率应该是115200,但它是892.9

void UART0_Init(int pclk, int baudrate)
{
    unsigned long int DLest;
    //unsigned long int pclk;
    unsigned int temp;
    // Turn on power to UART0
    SC->PCONP |=  PCUART0_POWERON;

    // Set PINSEL0 so that P0.2 = TXD0, P0.3 = RXD0
    PINCON->PINSEL0 = (PINCON->PINSEL0 & ~0xf0) | (1 << 4) | (1 << 6);

    UART0->LCR = 0x83;      // 8 bits, no Parity, 1 Stop bit, DLAB=1
    DLest =  (pclk / 16) /  baudrate;   // Set baud rate
    UART0->DLM = DLest / 256;
    UART0->DLL = DLest % 256;
   // UART0->FDR =
    UART0->IER = 0x7;       //enable RBR (b0), THRE(b1), RLS(b2)
    UART0->LCR = 0x03;      // 8 bits, no Parity, 1 Stop bit DLAB = 0
    UART0->FCR = 0x07;      // Enable and reset TX and RX FIFO
}
void prvSetupHardware( void )
{
    /* Disable peripherals power. */
    SC->PCONP = 0;

    /* Enable GPIO power. */
    SC->PCONP = PCONP_PCGPIO;

    /* Disable TPIU. */
    PINCON->PINSEL10 = 0;

    if ( SC->PLL0STAT & ( 1 << 25 ) )
    {
        /* Enable PLL, disconnected. */
        SC->PLL0CON = 1;            
        SC->PLL0FEED = PLLFEED_FEED1;
        SC->PLL0FEED = PLLFEED_FEED2;
    }

    /* Disable PLL, disconnected. */
    SC->PLL0CON = 0;                
    SC->PLL0FEED = PLLFEED_FEED1;
    SC->PLL0FEED = PLLFEED_FEED2;

    /* Enable main OSC. */
    SC->SCS |= 0x20;            
    while( !( SC->SCS & 0x40 ) );

    /* select main OSC, 12MHz, as the PLL clock source. */
    SC->CLKSRCSEL = 0x1;        
    SC->PCLKSEL0 = 0xAAAAAAAA;  /* PCLK is 1/2 CCLK */
    SC->PCLKSEL1 = 0xAAAAAAAA;


    /*Fcc0 = 400MHz, M = 50, N = 3*/
    SC->PLL0CFG = 0x20031;

    SC->PLL0FEED = PLLFEED_FEED1;
    SC->PLL0FEED = PLLFEED_FEED2;

    /* Enable PLL, disconnected. */
    SC->PLL0CON = 1;                
    SC->PLL0FEED = PLLFEED_FEED1;
    SC->PLL0FEED = PLLFEED_FEED2;

    /* Set clock divider. */
    /*Clock = 100MHz, Fcc0 = 400MHz*/
    SC->CCLKCFG = 0x03;//divided by 4.

    /* Configure flash accelerator. */
    SC->FLASHCFG = 0x403a;

    /* Check lock bit status. */
    while( ( ( SC->PLL0STAT & ( 1 << 26 ) ) == 0 ) );   

    /* Enable and connect. */
    SC->PLL0CON = 3;                
    SC->PLL0FEED = PLLFEED_FEED1;
    SC->PLL0FEED = PLLFEED_FEED2;
    while( ( ( SC->PLL0STAT & ( 1 << 25 ) ) == 0 ) );   

    /* Configure the clock for the USB. */

    if( SC->PLL1STAT & ( 1 << 9 ) )
    {
        /* Enable PLL, disconnected. */
        SC->PLL1CON = 1;            
        SC->PLL1FEED = PLLFEED_FEED1;
        SC->PLL1FEED = PLLFEED_FEED2;
    }

    /* Disable PLL, disconnected. */
    SC->PLL1CON = 0;                
    SC->PLL1FEED = PLLFEED_FEED1;
    SC->PLL1FEED = PLLFEED_FEED2;

    SC->PLL1CFG = 0x23;
    SC->PLL1FEED = PLLFEED_FEED1;
    SC->PLL1FEED = PLLFEED_FEED2;

    /* Enable PLL, disconnected. */
    SC->PLL1CON = 1;                
    SC->PLL1FEED = PLLFEED_FEED1;
    SC->PLL1FEED = PLLFEED_FEED2;
    while( ( ( SC->PLL1STAT & ( 1 << 10 ) ) == 0 ) );

    /* Enable and connect. */
    SC->PLL1CON = 3;                
    SC->PLL1FEED = PLLFEED_FEED1;
    SC->PLL1FEED = PLLFEED_FEED2;
    while( ( ( SC->PLL1STAT & ( 1 << 9 ) ) == 0 ) );


    /* Configure the LEDs. */
    vParTestInitialise();

    /*pclk = 100MHZ/2, baud = 115200 */
    UART0_Init(100000000/2, 115200);


    /* Set the sleep mode to highest level sleep*/
    SC->PCON = 0x0;
    SCB->SCR = 0x0;

    /*set push button interrupt */
    PINCON->PINSEL4 |= 0x00100000;
    SC->EXTMODE =0;
    NVIC_SetPriority( EINT0_IRQn, configUIButton1_INTERRUPT_PRIORITY );
    NVIC_EnableIRQ( EINT0_IRQn );
    NVIC_SetPriority( UART0_IRQn, configUIButton1_INTERRUPT_PRIORITY + 1 );
    NVIC_EnableIRQ( UART0_IRQn );

}
void UART0\u Init(int-pclk,int-baudrate)
{
无符号长整型;
//无符号长整数pclk;
无符号整数温度;
//打开UART0的电源
SC->PCONP |=PCUART0|u通电;
//设置PINSEL0,使P0.2=TXD0,P0.3=RXD0
PINCON->PINSEL0=(PINCON->PINSEL0&~0xf0)|(1dlm=DLest/256;
UART0->DLL=DLest%256;
//UART0->FDR=
UART0->IER=0x7;//启用RBR(b0)、THRE(b1)、RLS(b2)
UART0->LCR=0x03;//8位,无奇偶校验,1个停止位DLAB=0
UART0->FCR=0x07;//启用并重置TX和RX FIFO
}
无效prvSetupHardware(无效)
{
/*禁用外围设备电源*/
SC->PCONP=0;
/*启用GPIO电源*/
SC->PCONP=PCONP\u PCGPIO;
/*禁用TPIU*/
PINCON->PINSEL10=0;
如果(SC->PLL0STAT&(1 PLL0CON=1;
SC->PLL0FEED=PLLFEED\U FEED1;
SC->PLL0FEED=PLLFEED\U FEED2;
}
/*禁用PLL,断开连接*/
SC->PLL0CON=0;
SC->PLL0FEED=PLLFEED\U FEED1;
SC->PLL0FEED=PLLFEED\U FEED2;
/*启用主OSC*/
SC->SCS |=0x20;
而(!(SC->SCS&0x40));
/*选择主OSC 12MHz作为PLL时钟源*/
SC->CLKSRCSEL=0x1;
SC->PCLKSEL0=0xaaaaaa;/*PCLK为1/2 CCLK*/
SC->PCLKSEL1=0xaaaa;
/*Fcc0=400MHz,M=50,N=3*/
SC->PLL0CFG=0x20031;
SC->PLL0FEED=PLLFEED\U FEED1;
SC->PLL0FEED=PLLFEED\U FEED2;
/*启用PLL,断开连接*/
SC->PLL0CON=1;
SC->PLL0FEED=PLLFEED\U FEED1;
SC->PLL0FEED=PLLFEED\U FEED2;
/*设置时钟分频器*/
/*时钟=100MHz,Fcc0=400MHz*/
SC->CCLKCFG=0x03;//除以4。
/*配置闪存加速器*/
SC->FLASHCFG=0x403a;
/*检查锁位状态*/
而(((SC->PLL0STAT&(1pll0con=3;
SC->PLL0FEED=PLLFEED\U FEED1;
SC->PLL0FEED=PLLFEED\U FEED2;
而(((SC->PLL0STAT&(1 PLL1STAT&(1 PLL1CON=1;
SC->PLL1FEED=PLLFEED\U FEED1;
SC->PLL1FEED=PLLFEED\U FEED2;
}
/*禁用PLL,断开连接*/
SC->PLL1CON=0;
SC->PLL1FEED=PLLFEED\U FEED1;
SC->PLL1FEED=PLLFEED\U FEED2;
SC->PLL1CFG=0x23;
SC->PLL1FEED=PLLFEED\U FEED1;
SC->PLL1FEED=PLLFEED\U FEED2;
/*启用PLL,断开连接*/
SC->PLL1CON=1;
SC->PLL1FEED=PLLFEED\U FEED1;
SC->PLL1FEED=PLLFEED\U FEED2;
而(((SC->PLL1STAT&(1 PLL1CON=3;
SC->PLL1FEED=PLLFEED\U FEED1;
SC->PLL1FEED=PLLFEED\U FEED2;
而(((SC->PLL1STAT&(1 PCON=0x0;
SCB->SCR=0x0;
/*设置按钮中断*/
PINCON->PINSEL4 |=0x00100000;
SC->EXTMODE=0;
NVIC设置优先级(EINT0 IRQn,配置按钮1中断优先级);
NVIC启用IRQ(EINT0 IRQn);
NVIC_设置优先级(UART0_IRQn,配置按钮1_中断_优先级+1);
NVIC_EnableIRQ(UART0_IRQn);
}
我已确认我的cclk以100MHz运行


我用Kunil(UART\u中断\u演示)的示例项目中的代码替换UART init代码:

void uart\u init(整数波特率){
int errorStatus=-1;//<失败
长整数系统频率=100000000;
//UART时钟(FCCO/PCLK\U UART0)
无符号整数uClk=系统频率/4;
无符号整数calcBaudrate=0;
无符号整数温度=0;
无符号整数mulFracDiv,dividerAddFracDiv;
无符号整数除法器=0;
无符号整数mulFracDivOptimal=1;
无符号int dividerAddOptimal=0;
无符号整数除法临时值=0;
无符号整数相对误差=0;
无符号int relativeOptimalError=100000;
//打开UART0的电源
SC->PCONP |=PCUART0|u通电;
//将P0.2和P0.3模式更改为TXD0和RXD0
PINCON->PINSEL0=(1>4;/*除以16*/
/*
*公式是:
*波特率=uClk*(mulFracDiv/(mulFracDiv+dividerAddFracDiv)/(16*DLL)
*/
/*
*mulFracDiv和dividerAddFracDiv的值应符合以下表达式:
*0DLL=(无符号字符)dividerOptimal;
UART0->LCR&=~DLAB\U启用;
UART0->FDR=((多FCR |=FIFO_启用;
//将FIFO设置为在至少有14个字符可用时触发
UART0->FCR |=(3 IER=RBR_IRQ_启用;
//启用UART中断(对于Cortex-CM3 NVIC)
NVIC_EnableIRQ(UART0_IRQn);
}
而且它有效


我必须仔细检查一下,看看有什么问题。我怀疑寄存器设置的顺序是关闭的。

怀疑UART的clk与cclk进一步分开。您需要检查数据表并进行相应的更新。

请查看。 启动主PLL后,无法设置SC->PCLKSEL0,因此分频器保持在CCLK/4。 只需移动线路
/*将外围总线设置为与PLL输出相同(64 MHz)*/
SC->PCLKSEL0=0x05555555;


在启用PLL之前,我需要一个简化的LPC1768 UART1端口驱动程序,所以我已经基于CMSIS代码编写了一个波特率计算器应用程序

您提供外围时钟频率和所需波特率,它将生成DLL、分数乘法器和除法器,并最终使用计算值重新计算,以指示可达到的波特率

我用25MHz的外围时钟和115200&9600的波特率成功地测试了它。它不计算DLM,对于4800以上的波特率,DLM通常为0

它可以从免费软件下载站点获得。

我要维护自己的声誉,为此,我上传的应用程序不含病毒

嗯 标记

根据Drew的要求,我在下面的代码中添加了CMSIS函数

/*********************************************************************//**
 * @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;
}
/*
/*********************************************************************//**
 * @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;
}