uart接收中断,带解释,可以拷贝直接用

main.c
#include "LPC17xx.h"

#include "uart.h"




int main(void)

{

    // CMSIS的启动代码里面已经调用了 SystemInit.这里不必再次调用.

    // SystemInit();




    // 初始化UART0, 波特率96000,这个波特率可变,在使用12M晶振时,把波特率调低可有效减少乱码

    uart_init(96000);




    uart_send('\r');

    uart_send('\n');

    uart_send('O');

    uart_send('K');




    while(1);

}


uart.c

 
#include "LPC17xx.h"




#define IER_RBR   0x01

#define IER_THRE  0x02

#define IER_RLS   0x04




#define IIR_PEND  0x01

#define IIR_RLS   0x03

#define IIR_RDA   0x02

#define IIR_CTI   0x06

#define IIR_THRE  0x01




#define LSR_RDR   0x01

#define LSR_OE   0x02

#define LSR_PE   0x04

#define LSR_FE   0x08

#define LSR_BI   0x10

#define LSR_THRE  0x20

#define LSR_TEMT  0x40

#define LSR_RXFE  0x80




#define LPC_UART   LPC_UART0

#define UART_IRQn   UART0_IRQn




void uart_init(unsigned int uart_buad)

{

    unsigned int Fdiv;

    unsigned int pclkdiv, pclk;

   

   /* 引脚功能选择,RxD0 是 P0.3, TxD0 是 P0.2 */

    LPC_PINCON->PINSEL0 &= ~0x000000F0;

    LPC_PINCON->PINSEL0 |= 0x00000050;  







    /* By default, the PCLKSELx value is zero, thus, the PCLK for

    all the peripherals is 1/4 of the SystemFrequency. 

 

 默认情况下,PCLKSEL的值为0,PCLK为系统时钟的四分之一*/

    /* Bit 6~7 是 UART0 */

    pclkdiv = (LPC_SC->PCLKSEL0 >> 6) & 0x03;//03=0000 0011   

    switch ( pclkdiv )

    {

    case 0x00:

    default:

        pclk = SystemCoreClock/4;    //PCLKSEL为00,就是系统时钟的四分之一

        break;

    case 0x01:

        pclk = SystemCoreClock;   //PCLKSEL为01,就为系统时钟

        break;

    case 0x02:

        pclk = SystemCoreClock/2;  //PCLKSEL为10,就为系统时钟的二分之一

        break;

    case 0x03:

        pclk = SystemCoreClock/8;  //PCLKSEL为11,就为系统时钟的八分之一

        break;

    }




  /*LCR线控制寄存器,决定发送和接受数据的格式,8位字符长度,1个停止位,使能除数锁存  */

    LPC_UART0->LCR = 0x83;  




    /*设置波特率,时钟必须为目标波特率的16倍,Fdiv是除数锁存器的值*/

    Fdiv = ( pclk / 16 ) / uart_buad;  /*baud rate */

    LPC_UART0->DLM = Fdiv / 256;

    LPC_UART0->DLL = Fdiv % 256;




  /* 又是LCR线控制寄存器,这回等于03,也就是禁止访问除数锁存 */

    LPC_UART0->LCR = 0x03; 

  

     /* FCR为FIFO控制寄存器,0x07=0000 0111,FIFO使能,RX FIFO,TX FIFO复位,RX触发选择,这里选择了触发点为0(1个字符) */

    LPC_UART0->FCR = 0x07;   /* Enable and reset TX and RX FIFO. */




    /* LSR线状态寄存器,提供TX RX 的状态信息,下面是发送部分的设置,在高位




#define LSR_THRE  0x20    = 0010 0000

#define LSR_TEMT  0x40    =  0100 0000 

这两个一或,就是说5位和6位为1,5位为1表明发送FIFO为空,6位为1,表明发送FIFO和发送移位寄存器UnTSR都为空。

当都为空的时候,左右相等,while循环结束,继续执行下面的语句,确保开始的时候,发送FIFO和发送移位寄存器都是空的。  */

    while (( LPC_UART->LSR & (LSR_THRE|LSR_TEMT)) != (LSR_THRE|LSR_TEMT) ); 




   /*         #define LSR_RDR   0x01

   这是接收方面的设置,在低位。当接收缓冲RBR包含未读取的字符时,0位为1,RBR包含有效数据

   如果RBR为1,包含数据,就一直执行下面的语句。如果为0,RBR中没有数据了,就跳出。

             */

  while ( LPC_UART->LSR & LSR_RDR )

    {

        Fdiv = LPC_UART->RBR;  /* Dump data from RX FIFO 这句话是把RBR中的数据全部清空*/ 

     }




       /*   IER中断使能,  

           #define IER_RBR   0x01   =0000 0001

           #define IER_THRE     0x02   =0000 0010

           #define IER_RLS   0x04   =0000 0100

    

     也就是0,1,2位全部置1

     使能接收数据可用中断和字符超市中断,使能发送中断,使能接收线状态中断   */

    LPC_UART->IER = IER_RBR | IER_THRE | IER_RLS; 

     /* Enable the UART Interrupt */

    NVIC_EnableIRQ(UART_IRQn);

}

   /*接收中断,其实就是,接收字节数达到接收FIFO的触发点RDA或者接收超时。*/

void uart_send(char ch)    

{

    /* THRE status, contain valid data */

    while ( !(LPC_UART->LSR & LSR_THRE) );

    /* write data */

    LPC_UART->THR = ch;

}


it.c




#include "LPC17xx.h"

#include "uart.h"




#define IIR_RDA   0x02




void UART0_IRQHandler(void)

{

    unsigned int iir;




    /*IIR中断标志寄存器,读取中断标志寄存器,  */

    iir = LPC_UART0->IIR;

    iir >>= 1;       /* 跳过中断状态*/

    iir &= 0x07;    /* check bit 1~3, interrupt identification */




    if (iir == IIR_RDA)     /* 0x02=0000 0010,中断标志:010:接收数据可用(RDA), */

    {

 

         uart_send(LPC_UART0->RBR);

    }

}

你可能感兴趣的:(程序设计,嵌入式/硬件电路)