打印
[技术问答]

M058SSAN串口不停的进入发送中断

[复制链接]
4633|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yizhiyu|  楼主 | 2013-11-5 22:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
刚刚调了下M058SSAN的串口,发现初始化串口后不停的进入串口发送中断,进入调试后可以看到RDA_IF和RDA_INT在串口初始化之后就为1,一旦开中断就不停的进入中断。这个寄存器又是只读的,这咋整啊。
沙发
戈卫东| | 2013-11-6 08:11 | 只看该作者
在开始发送时才允许这个中断,发送完成再关闭.
这类"发送寄存器空"中断都需要这样处理的.

使用特权

评论回复
板凳
yizhiyu|  楼主 | 2013-11-6 10:32 | 只看该作者
就算在开始发送时允许这个中断,此时“发送寄存器空”标志已经置位了,一开中断不就进入发送中断了。后面的程序不就收影响了?

使用特权

评论回复
地板
yizhiyu|  楼主 | 2013-11-6 13:11 | 只看该作者
/*---------------------------------------------------------------------------------------------------------*/
/*                                                                                                         */
/* Copyright(c) 2010 Nuvoton Technology Corp. All rights reserved.                                         */
/*                                                                                                         */
/*---------------------------------------------------------------------------------------------------------*/

/*-----------------------------------------------------------------------------
  Nuvoton Technoledge Corp creadted by PU20  
  XTAL = 12MHz, BPS = 115200
*-----------------------------------------------------------------------------*/

/*
//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------
//
// <e0> Clock Configuration
//   <h> Enable Clock Source (PWRCON)
//                  <q1.0> Crystal 12MHz
//                                        <q1.3> Internal RC 10kHz
//                  <q1.2> Internal RC 22MHz
//         </h>
// <e2> Enable PLL (PLLCON)
//    <o3.19> PLL Clock Source Selection
//                  <0=> Crystal 12MHz        <1=> Internal RC 22MHz
// </e2>
//    <o4.0..2> HCLK System Clock Source Selection (CLKSEL0)
//                  <0=> Crystal 12MHz        
//                  <2=> PLL Clock            <3=> Internal RC 10KHz
//                  <4=> Internal RC 22MHz
// </e0>
//-------- <<< end of configuration section >>> ------------------------------
*/

#include <stdio.h>
#include <stdint.h>
#include "M051.h"
#include "Register_Bit.h"
#include "Common.h"
#include "UART.h"
#include "Retarget.h"
#include "Macro_SystemClock.h"

#define CLOCK_SETUP           0
#define CLOCK_EN              0xF
#define PLL_Engine_Enable     1
#define PLL_SEL               0x00080000
#define CLOCK_SEL             0x2

#define RXBUFSIZE 64


/* Global variables */                                                                                       
volatile uint8_t comRbuf[RXBUFSIZE];/*receive buffer*/
volatile uint16_t comRbytes = 0;                /* Available receiving bytes */
volatile uint16_t comRhead         = 0;
volatile uint16_t comRtail         = 0;
volatile int32_t g_bWait         = 1;

uint8_t i = 0xff;//在这里定义一个 i 变量
/*-----------------------------------------------------------------------------
  Function:                UART0_IRQHandler                                                                        

  Parameter:                                                                                                                                                                                          
                        None                                    
  Returns:                                                                                                
                       None                                                                                      
  Description:                                                                                            
                       UART0 ISR routine.                                    
*-----------------------------------------------------------------------------*/
void UART0_IRQHandler(void)
{
        static uint16_t count=0xff;
        uint8_t bInChar[1]={0xFF};
        i =0xff;        //赋值 i =0xff;
        if(UA0_ISR & RDA_INT)//RX-FIFO中的字节数等于RFITL(默认为1)时产生接收中断,
        {
                printf("\nInput:");//
               
                /* Get all the input characters */
                while(UA0_ISR & RDA_IF)//
                {
                    /* Check RX empty */
                        while (UA0_FSR & RX_EMPTY);
                        bInChar[0] = UA0_RBR;                                          

                        printf("%c ", bInChar[0]);
                       
                        if(bInChar[0] == '0')       
                        {       
                                g_bWait = 0;
                        }
               
                        /* Check if buffer full */
                        if(comRbytes < RXBUFSIZE)
                        {
                                /* Enqueue the character */
                                comRbuf[comRtail] = bInChar[0];
                                comRtail = (comRtail == (RXBUFSIZE-1)) ? 0 : (comRtail+1);
                                comRbytes++;
                        }                       
                }
                printf("\nTransmission Test:");
        }
        else if(UA0_ISR & THRE_INT)
        {   
      //          P36_DOUT = 0x00;         
        uint16_t tmp;
        tmp = comRtail;
                if(comRhead != tmp)
                {
                        bInChar[0] = comRbuf[comRhead];
                        /* Wait Tx empty */
                        while ((UA0_FSR&TX_EMPTY) == 0x00);
                        UA0_THR = bInChar[0];                                               
                        comRhead = (comRhead == (RXBUFSIZE-1)) ? 0 : (comRhead+1);
                        comRbytes--;
                }
        }       
}

int32_t main()
{
       /* UART Clock is ext12MHz */
        UARTClkSource_ex12MHZ;                            
        Un_Lock_Reg();
        /* Enable external 12M Crystal */
        PWRCON |= XTL12M_EN;
        /* Wait until 12M clock is stable. */
        while((CLKSTATUS & XTL12M_STB) == 0);        
       
        /* Set external crystal as the system clock        */
        CLKSEL0 = (CLKSEL0 & (~HCLK)) | HCLK_12M;
        P3_PMD = 0x5555;
        UART_Init();
        P36_DOUT = 0xff;
        printf("\nUART Sample Demo. (Press '0' to exit)\n");

        /* Enable Interrupt */
        UA0_IER        |= (RDA_IEN        | THRE_IEN | RLS_IEN);
        NVIC_ISER = UART0_INT;
//        while(1);
        while(g_bWait);
       
        while(i--);   //在这里加入一个延迟,这样下面的程序根本执行不了了。

        /* Disable Interrupt */
        UA0_IER        &= ~(RDA_IEN        | THRE_IEN | RLS_IEN);

        /* Disable I & F bit */
        NVIC_ICER = UART0_INT;               
       
        printf("\nUART Sample Demo End.\n");
       
        return 1;
}       
上面是新唐给的串口历程,感觉这个程序很不好。我调试时发现执行完UART_Init函数和使能发送中断后,程序会进入串口中断。这样减少了while(g_bWait);后面的执行时间。虽然历程可以正确演示,但是只要加一个while(i--)延时一回,并在串口中断中置 i=0xFF,如此就算你你输入了0,main函数也退不出来。也就是虽然while(g_bWait)执行过去了,但是执行不过while(i--)。i 可能被自减了几次就被串口中断赋值成了0xff。还有一个执行串口中断函数时发生了接收或者发送事件,是不会打断当前中断吧。

使用特权

评论回复
5
yizhiyu|  楼主 | 2013-11-6 13:11 | 只看该作者
戈卫东 发表于 2013-11-6 08:11
在开始发送时才允许这个中断,发送完成再关闭.
这类"发送寄存器空"中断都需要这样处理的. ...

就算在开始发送时允许这个中断,此时“发送寄存器空”标志已经置位了,一开中断不就进入发送中断了。后面的程序不就收影响了?

使用特权

评论回复
6
戈卫东| | 2013-11-6 13:59 | 只看该作者
THRE_INT之类的中断就是这样,它没事做的时候会产生中断,于是你没有给它任务的时候(没有数据需要通过UART发送)就关掉它.
一般来说,如果你和程序每次只发一个字节,那就根本不要允许这个中断. 但是如果每次发送一个数据包,那么可以在送出第一字节之后允许这个中断,让ISR完成余下的数据发送,避免查询它的状态浪费CPU时间.当最后一个字节写到发送缓冲器,就可以再次关闭它的中断了.

使用特权

评论回复
7
szjosun| | 2013-11-6 14:29 | 只看该作者
关注一下!

使用特权

评论回复
8
yizhiyu|  楼主 | 2013-11-6 20:48 | 只看该作者
戈卫东 发表于 2013-11-6 13:59
THRE_INT之类的中断就是这样,它没事做的时候会产生中断,于是你没有给它任务的时候(没有数据需要通过UART发 ...

谢谢!日后得注意了使用。在上面的代码中while(g_bWait--);之所以有机会执行到,是因为中断响应的原因吧。所以在之前加入一些延迟的话while(g_bWait--);就没机会执行了。               

使用特权

评论回复
9
地瓜patch| | 2013-11-27 18:54 | 只看该作者
呵呵,我也犯过这样的错误n次

使用特权

评论回复
10
niuyaliang| | 2013-11-27 20:32 | 只看该作者
发送完必须要关闭中断

使用特权

评论回复
11
万法归宗| | 2013-11-27 22:36 | 只看该作者
进中断后关闭,出中断前打开

使用特权

评论回复
12
zhangjin_comeon| | 2013-11-27 23:05 | 只看该作者
这个有点难

使用特权

评论回复
13
从小木丁丁| | 2013-12-24 15:32 | 只看该作者
进中断后关闭,出中断前打开,这个靠谱

使用特权

评论回复
14
clyu| | 2013-12-24 15:40 | 只看该作者
yizhiyu 发表于 2013-11-6 10:32
就算在开始发送时允许这个中断,此时“发送寄存器空”标志已经置位了,一开中断不就进入发送中断了。后面的 ...

写数据到发送交寄存器之后,这个标志就会自动清0了

使用特权

评论回复
15
shmily53| | 2014-1-21 20:54 | 只看该作者
这块板子点灯 _GPIO_SET_PIN_MODE(P3, 6, GPIO_PMD_OUTPUT);
             GPIO_PIN_DATA(3, 6)=0 ;
还少什么语句么

使用特权

评论回复
16
zxf0168| | 2014-2-11 19:35 | 只看该作者
有开有关,你打开就得关闭不是

使用特权

评论回复
17
yyxlmq1314| | 2017-1-5 15:31 | 只看该作者
楼主跟我遇到的问题基本一致,其实应该是一直进RDA接收中断了,很容易出错,暂时找不到办法来解决,楼主最后是怎么解决的?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

12

主题

76

帖子

0

粉丝