Embedded ARM LPC1768 UART0配置,波特率错误
我的波特率应该是115200,但它是892.9Embedded 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 =
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;
}