LPC2148 UART中断

时间:2019-08-08 10:18:23

标签: c interrupt uart

我正在使用带有中断的UART1上的LPC2148和SIM800L。首先,当我在memset(buff, 0 , sizeof(buff));中使用while(1)时,程序运行良好,但是当while(1)循环再次运行时,它会反复打印错误,但是当我注释memset(buff, 0, sizeof(buff));时,它将运行良好。

那么为什么它不使用memset函数接收数据?

 #include <lpc214x.h>
 #include <stdio.h>
 #include <string.h>


 __irq void uart1_interrupt(void);

 void init_uart1(void);                     //////initialize uart1
 void uart1_write(char data);           //////send char on uart1
 void uart1_send_string(char *str);//////send string on uart1

 void Uart0_string(char *str);          //////send string on uart0
 void U0write(char data);                   //////send 
 char on uart0
 void init_uart0(void);                     //////initialize uart0

 void pll_init(void);
 void timer_init(void);
 void delay_ms(unsigned int ms);

 //void clear_data();                               /////clear buffer

 char buff[160];
 //char sms_receive[60];
 int i, a = 0;

 int main(void)
 {
    pll_init();
    timer_init();
    init_uart0();
    //init_uart1();


    VICVectAddr0 = (unsigned) uart1_interrupt;   /////attach interrupt routine
    VICVectCntl0 = (1<<5)|7;                                                                    ////enable uart irq slot for uart1
    VICIntEnable |= (1<<7); ////enable uart1 interrupt 
    VICIntSelect = 0x00000000;
    init_uart1();

    Uart0_string("gsm test\r\n");


    delay_ms(3000);

    while(1)
    {
        uart1_send_string("AT\r\n");
        delay_ms(400);
        if(strstr(buff,"OK"))
        {
            Uart0_string(buff);
        }

        else
        {
            Uart0_string("ERROR ");
        }

        delay_ms(3000);

        uart1_send_string("AT+CNMI=?\r\n");
        delay_ms(400);
        if(strstr(buff,"+CNMI"))
        {
            Uart0_string(buff);
        }

        else
        {
                Uart0_string("ERROR ");
        }

        delay_ms(3000);
        //clear_data();
        memset(buff, 0 , sizeof(buff)); 
    }
  }


 /*void clear_data()
 {
    for(i = 0; i<=sizeof(buff); i++)
    {
        buff[i] = 0;
    }
 }*/

 __irq void uart1_interrupt(void)
 {
    buff[a] = U1RBR;
    a++;
    VICVectAddr = 0x00;
 }

 void init_uart1(void)
 {
    PINSEL0 = PINSEL0 | 0x00050000;    ////UART1 pin selection

    U1LCR = 0x83;            ////8 bit, no parity, 1 stop bit, DLAB - 1
    U1DLL = 0x56;                ////86 in decimal
    U1DLM = 0x00;
    U1FDR = 0xF2;

    U1LCR &= 0x0f;          /////setting DLAB bit to 0

    U1IER = 0x01;               ////enable interrupt
 }

 void uart1_write(char data)
 {
    U1IER = 0x00;
    while(!(U1LSR &(1<<5)));        ////U1LSR contains THRE status bit, wait while THR is empty
    U1THR = data;
    U1IER = 0x01;
 }

 void uart1_send_string(char *str)
 {
    U1IER = 0x00;
    while(*str != '\0')
    {
        uart1_write(*str++);
    }
    U1IER = 0x01;
 }


 /*char uart1_receive()
 {
    while(!(U1LSR & (1<<0)));
    return U1RBR;
 }*/

 void init_uart0()
 {
    PINSEL0 = 0x00000005;   ////selects TxD P0.0 and RxD P0.1

    U0LCR = 0x83;           ////8 bit, no parity 1 stop bit, DLAB = 1
    U0DLL = 0x56;     //// 86 in decimal
    U0DLM = 0x00;
    U0FDR = 0xF2;           ////MULVAL and DIVADDVAL values

    U0LCR &= 0x0F;
 }

 void U0write(char data)
 {
    while(!(U0LSR & (1<<5)));  ///////wait till THR is not empty
    U0THR = data;                            /////// write data to Transmit in U0THR

 }

 void Uart0_string(char *str)
 {
    while(*str != '\0')
    {
        U0write(*str++);
    }
 }

 void pll_init(void)
 {
    PLL0CON = 0x01;        /////enable PLL////
    PLL0CFG = 0x24;              /////configure PLL/////
    PLL0FEED = 0xAA;             //////feed sequence/////
    PLL0FEED = 0x55;             //////feed sequence/////

    while(!(PLL0STAT & 0x00000400)); ///is locked////

    PLL0CON = 0x03;     ////connect PLL////
    PLL0FEED = 0xAA;
    PLL0FEED = 0x55;

    //VPBDIV = 0x01; /////// PCLK = CCLK = 60MHz
    VPBDIV = 0x00;   /////// PCLK = 60/4 = 15MHz
 }

 void timer_init(void)
 {
    //T0TCR = 0x00;
    T0CTCR = 0x0;       ////selection of timer mode with every rising pclk edge
    T0PR = 14999;           ////prescale register value will generate 1 ms at 60MHz
    T0TCR = 0x02;     ////reset the timer counter and prescale couter
 }

 void delay_ms(unsigned int ms)
 {
    //T0TC = 0x00000000;
    T0TCR = 0x02;     /////reset timer. Timer should be reset
    T0TCR = 0x01;     /////enable timer to generate delay
    T0MR0 = ms;
    while(T0TC < T0MR0); /////wait until Timer counter register reaches desired delay
    T0TCR = 0x00;     /////disable timer

 }

使用memset(buff, 0, sizeof(buff))

时的输出
gsm test
AT
OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)

OK
ERROR ERROR ERROR ERROR
不使用memset(buff,0,sizeof(buff))时

输出。我想使用memset(buff,0,sizeof(buff))实现此输出

gsm test
AT
OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)

OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)

OK
AT
OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)

OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)

OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)

OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)

OK
AT
OK

2 个答案:

答案 0 :(得分:0)

a在开始时仅重置一次。中断在每个字符上递增a。当您的主循环重复执行时,ISR(中断服务程序)将进一步增加它,最后在buf之后覆盖内存。

这就是为什么没有memset()时您将重复相同结果的原因。 buf的内容始终从其开头进行检查,但是接收到的答案将依次存储。

在循环中的每个条目上重置a,应该有帮助。

但是,从多个线程中写入(和/或读取)相同的变量会导致灾难。寻找有关多线程编程的课程。是的,使用中断意味着要使用多个线程进行编程。

答案 1 :(得分:0)

while(1)函数中的main循环没有对char buff[160]进行任何输入。这仅在中断处理程序中完成。因此,当您使用memset填充缓冲区时,它会以字符串终止符'\0'和语句开头

if(strstr(buff,"OK"))

if(strstr(buff,"+CNMI"))

为假– NULL表示未找到匹配项–因此将输出错误消息。

还请注意,您在中断处理程序__irq void uart1_interrupt(void)中拥有

buff[a] = U1RBR; 
a++;

a不受限制或重置或包装以防止缓冲区溢出。因此,有一场灾难正在等待发生。