首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > 单片机 >

!uart中断有关问题

2012-12-30 
求助!!uart中断问题我的一个uart中断接收的程序,使用环形buffer,问题是总是不能接收数据,通过串口调试助手

求助!!uart中断问题
我的一个uart中断接收的程序,使用环形buffer,问题是总是不能接收数据,通过串口调试助手发送数据没用,对uart中断接收很是迷茫,不知道uart什么时候产生接收中断啊,板子是C8051F340

//UART
//-----------------------------------------
// Includes
//-----------------------------------------
#include <C8051F340.h>                 // SFR declarations
#include <stdio.h>                     // printf is declared here

//-----------------------------------------
// 16-bit SFR Definitions for the 'F34x
//-----------------------------------------
sfr16 TMR2     = 0xCC;                 // Timer2 low and high bytes together

//-----------------------------------------
// User-defined types, structures, unions etc
//-----------------------------------------
#ifndef BYTE
#define BYTE unsigned char
#endif

#ifndef UINT
#define UINT unsigned int
#endif

//-----------------------------------------
// Global Constants
//-----------------------------------------
#define BAUDRATE           115200      // Baud rate of UART in bps
#define SYSCLK             24000000    // Internal oscillator frequency in Hz



sbit LED_1 = P3^4;                       // LED='1' means ON
sbit LED_2 = P3^5;
#define IN_LEN 16
unsigned char in_buffer[IN_LEN];
unsigned int inhead,intail;


bit infull;
bit readflag;
//-----------------------------------------
// Function Prototypes
//-----------------------------------------
void PCA0_Init (void);
void OSCILLATOR_Init (void);
void PORT_Init (void);
void TIMER2_Init (void);
void UART0_Init (void);
int test_rx(char* str,int len);
void Init_Device (void);
void UART_interrupt( void );

void UART0_Send_data(unsigned char Send_data)
{
SBUF0=Send_data; 
while(!TI0);
TI0=0; 
}
void UART0_Send_Longdata(unsigned char *str, unsigned int Stringlen)
{
     unsigned int i = 0 ; 
do { 
       UART0_Send_data(*(str+i)); 
    i++; 
   } while (i<Stringlen); 
}

void UART_interrupt(void) interrupt 4
{
    if (RI0)
       {
      in_buffer[intail] = SBUF0; // 从串口接收一个字符


         RI0 = 0; // 清接收中断标志RI0
          
  intail = (intail+1)%(IN_LEN-1);  //向输入缓冲写数据
          if( intail == inhead ) infull = 1 ; //输入缓冲满
  readflag = 1 ;
       }


//-----------------------------------------
// main() Routine
//-----------------------------------------
void main (void)
{
   bit rxf = 1;
     char rx[8];
   bit  flag = 1;
   xdata char c[]="enter a string :\n";
   xdata char r[]="controll bits is wrong!\nenter again:";
   Init_Device ();  
  
  LED_1 = 0;
  LED_2 = 0;
  while(1){
  rxf = 1 ;
rx[0]= 0;
   UART0_Send_Longdata(c,sizeof(c));
  while( rxf ){
      if(readflag){
int i=0;
for(  ; inhead%(IN_LEN-1) < intail ; inhead = (inhead+1)%(IN_LEN-1) ){
rx[i]=in_buffer[inhead%(IN_LEN-1)];
i++;

}

}
      if( test_rx(rx,8) ) rxf = 0;
  else UART0_Send_Longdata(r,sizeof(r));
  }

  switch( rx[4] )
  {
 case '0' : 
 if( rx[5] == '0' ) LED_1 = 0 ;
else  LED_1 = 1 ;
LED_2 = 0 ;
break;
     case '1' :
 if( rx[5] == '0' ) LED_1 = 0 ;
else  LED_1 = 1 ;
 LED_2 = 1 ;
break;
     default:
        printf("wrong input about LED\n");
        while(1){
  LED_1 = ~LED_1;
  LED_2 = ~LED_2;
  }
  break;


  }
}
}

//-----------------------------------------
// Initialization Subroutines
//-----------------------------------------
int test_rx(char* str,int len){
   if( str[0] == 'A' && str[1] == '5'
      && str[2] == 'A' && str[3] == '1'
  && str[len-2] == 'B' && str[len-1] == '7') return 1;
   else return 0 ;
}


//-----------------------------------------
// PCA0_Init
//-----------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This function disables the watchdog timer.


//
//-----------------------------------------
void PCA0_Init (void)
{
   PCA0MD   &= ~0x40;
   PCA0MD    = 0x00;
}

//-----------------------------------------
// OSCILLATOR_Init
//-----------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This function initializes the system clock at 24 MHz (intosc->clkmul/2).
//
//-----------------------------------------
void OSCILLATOR_Init (void)
{
   int i = 0;
   OSCICN    = 0x83;
   CLKMUL    = 0x80;
   for (i = 0; i < 20; i++);    // Wait 5us for initialization
   CLKMUL    |= 0xC0;
   while ((CLKMUL & 0x20) == 0);
   CLKSEL    = 0x02;
}

//-----------------------------------------
// PORT_Init
//-----------------------------------------

//
//-----------------------------------------
void PORT_Init (void)
{

   P1MDOUT   = 0x0D;       //spi sck miso mosi cs配置
   P2MDOUT   = 0x00;
   P2SKIP    = 0x03;
 
      P3MDOUT   = 0x30;       //LED D1 D2
   P3SKIP    = 0x0C;
   XBR0      = 0x03;  //spi i/o使能
   XBR1      = 0x40;  //7:弱上拉使能,6:交叉开关使能
}

//-----------------------------------------
// TIMER2_Init
//-----------------------------------------
//
// Return Value : None
// Parameters   : None
//
// Initializes Timer2 to be clocked by SYSCLK for use as a delay timer.
//
//-----------------------------------------
void TIMER2_Init (void)
{
   CKCON    |= 0x10;
}

//-----------------------------------------
// UART0_Init
//-----------------------------------------
//
// Return Value : None
// Parameters   : None
//
// Configures the UART0 using Timer1, for <BAUDRATE> and 8-N-1. Once this is
// set up, the standard printf function can be used to output data.
//
//-----------------------------------------
void UART0_Init (void)
{

   SCON0 = 0x10;                       // SCON0: 8-bit variable bit rate


                                       //        level of STOP bit is ignored
                                       //        RX enabled
                                       //        ninth bits are zeros
                                       //        clear RI0 and TI0 bits

   

   if (SYSCLK/BAUDRATE/2/256 < 1)
   {
      TH1 = -(SYSCLK/BAUDRATE/2);
      CKCON &= ~0x0B;                  // T1M = 1; SCA1:0 = xx
      CKCON |=  0x08;
   } 
   else if (SYSCLK/BAUDRATE/2/256 < 4)
   {
      TH1 = -(SYSCLK/BAUDRATE/2/4);
      CKCON &= ~0x0B;                  // T1M = 0; SCA1:0 = 01
      CKCON |=  0x09;
   }
   else if (SYSCLK/BAUDRATE/2/256 < 12)
   {
      TH1 = -(SYSCLK/BAUDRATE/2/12);
      CKCON &= ~0x0B;                  // T1M = 0; SCA1:0 = 00
   } else
   {
      TH1 = -(SYSCLK/BAUDRATE/2/48);
      CKCON &= ~0x0B;                  // T1M = 0; SCA1:0 = 10
      CKCON |=  0x02;
   }

   TL1 = TH1;                          // init Timer1
   TMOD &= ~0xf0;                      // TMOD: timer 1 in 8-bit autoreload
   TMOD |=  0x20;
   TR1 = 1;                            // START Timer1
   TI0 = 1;                            // Indicate TX0 ready



    ES0 = 1 ;
REN0 = 1;
inhead = 0 ;
intail = 0;
//UART_interrupt();
}



//-----------------------------------------
// Init_Device
//-----------------------------------------
//
// Return Value : None
// Parameters   : None
//
// Calls all device initialization functions.
//
//-----------------------------------------
void Init_Device (void)
{
   PCA0_Init ();
   OSCILLATOR_Init ();
   PORT_Init ();
   TIMER2_Init ();
   UART0_Init ();
   //UART_interrupt();
}


//-----------------------------------------
// End Of File
//-----------------------------------------


[解决办法]
你这帖子没人认真看的,看代码比写还累。
哪里不明白问哪里比较好
[解决办法]
引用
数据手册上说RI0中断标志位是由硬件来置1的

1 置1之后就进入中断服务函数了。
引用
in_buffer[intail] = SBUF0;

为什么这么读。

2 in_buffer = xxx. //xxx为串口的缓存SBUF(具体看手册,可能就是你这里的SBUF0)。

3 感觉你intail的变量有点乱用了。
[解决办法]
while( rxf ){//<<<死循环了,rxf一直是1,主函数后半执行不到
               if(readflag){
                 int i=0;
                 for(  ; inhead%(IN_LEN-1) < intail ; inhead = (inhead+1)%(IN_LEN-1) ){//<<<有问题的条件,一直为假
                     rx[i]=in_buffer[inhead%(IN_LEN-1)];
                     i++;
                   }
  
             }

缓冲区定义的长度IN_LEN,下标是0 - (IN_LEN-1),而这个(inhead+1)%(IN_LEN-1)与(intail+1)%(IN_LEN-1)只能表达0 - (IN_LEN-2),
问题不少啊

热点排行