NXP

lpc1343 UART

2019-07-12 13:02发布

全文内容来自以下网址:http://bbs.eeworld.com.cn/thread-103593-6-1.html 本节我们来使用LPC1343UART接口做一个简单的收发实验。   大家之前应该都有使用51AVR一类单片机做过异步串行收发实验,当然串口在电子开发中的应用地位就无需多言。我们直接进入主题。   本次试验这样设计,用PC作为上位机向UART发送一个(串)字节,然后LPC1343收到这个(串)字节后再发回UART,PC上的串口观察软件显示出来。   我们来看NXP带给我们的UART例程来看看UART的设置以及工作过程。首先是主函数: int main (void) {   UARTInit(115200);//初始化UART接口并设置为波特率115200NVIC也在内一并设置 while (1)   {     if ( UARTCount != 0 )     {       LPC_UART->IER = IER_THRE | IER_RLS;       UARTSend( (uint8_t *)UARTBuffer, UARTCount );//发送数据       UARTCount = 0;   LPC_UART->IER = IER_THRE | IER_RLS | IER_RBR;       }   } }   从主函数就可以看到本次例程的目的了:初始化UART——一旦接收到数据之后立即停止接收——发送——开启下一次接收。最重要的当然是初始化函数UARTInit()   void UARTInit(uint32_t baudrate) {   uint32_t Fdiv;   uint32_t regVal;     UARTTxEmpty = 1;   UARTCount = 0;     NVIC_DisableIRQ(UART_IRQn);    //关闭UART中断,避免此后的初始化有中断打断 LPC_IOCON->PIO1_6 &= ~0x07;      LPC_IOCON->PIO1_6 |= 0x01;       LPC_IOCON->PIO1_7 &= ~0x07;     LPC_IOCON->PIO1_7 |= 0x01;         LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);   LPC_SYSCON->UARTCLKDIV = 0x1;         LPC_UART->LCR = 0x83;               regVal = LPC_SYSCON->UARTCLKDIV; Fdiv=(((SystemCoreClock*LPC_SYSCON->SYSAHBCLKDIV)/regVal)/16) //baudrate ;                                   LPC_UART->DLM = Fdiv / 256;   //写入波特率计算值高位                     LPC_UART->DLL = Fdiv % 256;  //写入波特率计算值低位   LPC_UART->LCR = 0x03;       LPC_UART->FCR = 0x07;          regVal = LPC_UART->LSR;     while (( LPC_UART->LSR & (LSR_THRE|LSR_TEMT)) != (LSR_THRE|LSR_TEMT) );   while ( LPC_UART->LSR & LSR_RDR )   {     regVal = LPC_UART->RBR;    }       NVIC_EnableIRQ(UART_IRQn);   #if TX_INTERRUPT   //是否使用发送中断,本次例程使用   LPC_UART->IER = IER_RBR | IER_THRE | IER_RLS;  #else   //所以执行此else   LPC_UART->IER = IER_RBR | IER_RLS;     #endif   return; }   打星号的地方是笔者认为比较值得关注的地方: 1UARTIO口设置,根据上述函数中的语句查找相关寄存器,可以发现它将P16P17设置为:UART_RXDUART_TXD功能; 2、选择UART时钟分频数,此处1分频,和波特率设置有直接关系; 3、选择数据格式,此处选择数据长度8位,无校验,1位停止位,并开启除数锁存; 4、除数锁存器:分为LSB8位)和MSB8位),用来填入对应某波特率的计数值,更改之前解除锁定,更改完毕恢复锁定,这样就可以锁定波特率了(可以这样简单的理解); 5、计算波特率,此处是重点了。首先我们肯定知道系统核心频率为72MHz,即SystemCoreClock=72 000 000(参考本系列前几章内容)。而UART作为AHB总线上的设备,自然要经过AHB分频器,在此处,AHB分频系数并未做过特别设置,所以为默认值1。时钟经过AHB分频之后要经过UART分频器进行再分频,分频系数仍为1(第2点)。因此我们来计算这个公式: Fdiv = (((SystemCoreClock*LPC_SYSCON->SYSAHBCLKDIV)/regVal)/16)/baudrate 其中SystemCoreClock=72000000LPC_SYSCON->SYSAHBCLKDI=1regVal=1baudrate=115200,所以可以计算出: Fdiv=39.0625≈0x27 这个便是产生115200波特率所要填入除数锁存器的值。逆过来就可以计算出计数值对应的波特率。 6、线状态寄存器(下文稍加讲述)是以读操作来清空的; 其实这个函数,对于用户来说,只需要填入想要产生的波特率作为函数参数就可以完成LPC1343UART初始化以及波特率设定工作。 设定完成之后,UART就开始工作了,因为初始化函数里面开启了启用缓存数据可用中断、线状态中断所以当有数据从上位机向UART发送数据时,进入中断服务函数: void UART_IRQHandler(void) {   uint8_t IIRValue, LSRValue;   uint8_t Dummy = Dummy; IIRValue = LPC_UART->IIR;    IIRValue >>= 1;              IIRValue &= 0x07;           if (IIRValue == IIR_RLS)        {     LSRValue = LPC_UART->LSR;         if (LSRValue & (LSR_OE | LSR_PE | LSR_FE | LSR_RXFE | LSR_BI))     {             UARTStatus = LSRValue;       Dummy = LPC_UART->RBR;         return;     }     if (LSRValue & LSR_RDR)              {             UARTBuffer[UARTCount++] = LPC_UART->RBR;       if (UARTCount == BUFSIZE)       {         UARTCount = 0;             }     }   }   else if (IIRValue == IIR_RDA)   {         UARTBuffer[UARTCount++] = LPC_UART->RBR;     if (UARTCount == BUFSIZE)     {       UARTCount = 0;         }   }   else if (IIRValue == IIR_CTI)   {         UARTStatus |= 0x100;       }   else if (IIRValue == IIR_THRE)     {         LSRValue = LPC_UART->LSR;           if (LSRValue & LSR_THRE)     {       UARTTxEmpty = 1;     }     else     {       UARTTxEmpty = 0;     }   }   return; } 这个中断服务函数是一个if…else if….else if结构。在进入此中断服务函数后,读取   中断标识寄存器判断中断源,选择进入相应的if环节执行相应语句。我们看看UART都有哪些中断。第一个是RLSReceive Line Status即接收线中断: 可以在用户手册查看到接受线中断分别有以下多种: RDR Receiver Data Ready,接受数据就绪中断; OEOverrun Error,即溢出错误中断; PE:Parity Error,校验错误中断; FE:Framing Error,帧错误中断; BI:Break Interrupt,间隔状态中断; THRETransmitter Holding Register Empty,发送保持寄存器空中断; TEMPTransmitter Empty,发送保持寄存器与临时寄存器空中断; RXFEError in RX FIFORX错误中断; 对照上述中断服务函数第一个if部分,当判断确定为线中断之后,即判断是否是OE——RXFE中的任何一个错误,如果有错误,则读出数据有效保存,如果有错误,则读出数据但丢弃。 所以,线中断在进行数据校验的场合才会使用。而本次实验中并未用到数据校验位。所以此中断不会进入。 当不使用校验功能之时,收到数据之后会进入第一个else if结构: else if (IIRValue == IIR_RDA) {} 在进入此部分之后将数据读出。 当接受一个字符(5~8位不等)超时时,会进入接受字符超时中断部分。 发送完成中断在本次试验中并未使能,略过。 如此我们应该可以预知本次试验中当PC上位机发送一个(串)字符之后,会进入中断服务函数并且进入else if (IIRValue == IIR_RDA{}环节,将收到的数据保存在UARTBuffer中,并使UARTCount++。然后退出中断函数之后,回到主函数,执行发送部分: if ( UARTCount != 0 )     {       LPC_UART->IER = IER_THRE | IER_RLS;       UARTSend( (uint8_t *)UARTBuffer, UARTCount );//发送数据       UARTCount = 0;   LPC_UART->IER = IER_THRE | IER_RLS | IER_RBR;       } } 找到UARTSend() void UARTSend(uint8_t *BufferPtr, uint32_t Length) {   while ( Length != 0 )   {       #if !TX_INTERRUPT//未使用中断发送方式,所以编译此部分       while ( !(LPC_UART->LSR & LSR_THRE) );//等待发送保持寄存器空       LPC_UART->THR = *BufferPtr;//将待发数据写入发送保持寄存器 #else             while ( !(UARTTxEmpty & 0x01) );       LPC_UART->THR = *BufferPtr;       UARTTxEmpty = 0;   #endif       BufferPtr++;       Length--;   }   return; } UART数据发送函数,第一个参数要求填入存放待发送数据(注意为8位,即字符型数据)的数组名,第二个参数为待发数据长度。通过注释可以看到发送的过程很简单,等待发送保持寄存器为空后将数据写入发送保持寄存器就完成了发送。 这样我们就将本次的UART收发试验的过程初始化——等待接收——UART中断——保存数据——发送数据分析完毕。 NXP赠送的这个LPC1343并没有挂载UART接口,而只留了P16P17两个IO给用户拓展,所以笔者使用了其他开发板的串口连接,需要注意的是,我们手上的这块开发板是3.3V供电,而市面上比较多采用的MAX2325V供电。所以或者使用LPC1343评估板的5VMAX232供电,或者使用3.3V供电的电平转换芯片。笔者这里使用了3.3V供电的ST232芯片。 导入lpc1343.examples->uart,编译链接。连好硬件,从串口调试终端发送一个(串)数据,可以看到串口调试终端的接收框里准确的显示了我们所发送的数据,本次实验完结。

热门文章