求助!!uart中断问题

舟遥 2012-12-02 10:09:14
我的一个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
//-----------------------------------------------------------------------------
...全文
368 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
舟遥 2012-12-03
  • 打赏
  • 举报
回复
4楼指正的是,我已经改正了部分代码,这是今天的,但是还是出现接收时还是有问题,比如说,发送一个A5A100B7,第一次只接收了A,然后发送第二次就直接收5A100B7,很混乱的情况,我都搞不懂是为啥,第一次做单片机,对这个很是迷惑

#define BAUDRATE           115200      // Baud rate of UART in bps
void SendCommBuffer(unsigned char   *base, unsigned int  size);
#define DB_SENDMAXSIZE  16
#define DB_RECMAXSIZE   16

bit CommRecDataOverflowFlag,FlagRecComm,SendbufferOver;
unsigned int SendSize  ;
 int CommSendBufferHead  , CommSendBufferTail  ;
unsigned char  CommSendBuffer[DB_SENDMAXSIZE]; 
 int CommRecBufferHead  , CommRecBufferTail  ;
unsigned char  CommRecBuffer[DB_RECMAXSIZE];

void main (void)
{
   bit rxf = 1;
   bit  flag = 1;
   int i = 0;
   char r[]="enter:";
   char rx[8];
   Init_Device ();  
	SendCommBuffer(r,sizeof(r));		
	while(1){
			if(FlagRecComm) {
				int i ;
				for(i=0; CommRecBufferHead != CommRecBufferTail;i++){

				 	rx[i]=CommRecBuffer[CommRecBufferHead];
					CommRecBufferHead = CommRecBufferHead++;
				if(CommRecBufferHead==DB_RECMAXSIZE) CommRecBufferHead = 0 ;
				 }
				SendCommBuffer(rx,sizeof(rx));
				FlagRecComm = 0;
				}
		
		
	};
}

void SendCommBuffer(unsigned char  *base, unsigned int  size) 
{
    unsigned int i,k;
	unsigned char j,t;
	i = 0;
	j = 0;	
	k = DB_SENDMAXSIZE;
	if (!size) { return; }	
	SendSize = size;
	if (!(size%DB_SENDMAXSIZE))
	t = size/DB_SENDMAXSIZE;
	else
	t = size/DB_SENDMAXSIZE+1;
	for (j =0 ;j<t;j++)
	{
		while (i < k) 
		{
			CommSendBuffer[CommSendBufferTail]=base[i]; 	
			i++;
			CommSendBufferTail++; 
		}
		SBUF0=CommSendBuffer[CommSendBufferHead]; 
		while (!SendbufferOver);
		SendbufferOver = 0;
		k = DB_SENDMAXSIZE+k;
		CommSendBufferTail = 0;
	}
	CommSendBufferHead =0;
	CommSendBufferTail = 0;
}
void CommISR(void) interrupt 4
{
	if (TI0 == 1)
	{
		TI0 = 0;
		if (SendSize--)   //SendSize--和--SendSize效果一样
		{
			CommSendBufferHead++; 	
			if (CommSendBufferHead==DB_SENDMAXSIZE)
			{	 
				CommSendBufferHead=0;
				SendbufferOver = 1;
			}
			else
			{	
				SBUF0=CommSendBuffer[CommSendBufferHead];
			} 
		}
	
		else
		{
			SendbufferOver = 1;
		}
	}
	if (RI0 == 1)	
	{	 
		RI0 = 0;
		if (CommRecBufferTail==CommRecBufferHead)
		{
			CommRecDataOverflowFlag=1;				//接收缓冲区溢出
		}
		EA = 0 ;
		CommRecBuffer[CommRecBufferTail]=SBUF0;     //receive data           
	    CommRecBufferTail++;
		
	    if (CommRecBufferTail==DB_RECMAXSIZE)
	    {
	    	CommRecBufferTail=0;
	    }
		EA = 1 ;
		FlagRecComm=1;
   	}
}
h_w_m 2012-12-03
  • 打赏
  • 举报
回复
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), 问题不少啊
Binzo 2012-12-03
  • 打赏
  • 举报
回复
引用
数据手册上说RI0中断标志位是由硬件来置1的
1 置1之后就进入中断服务函数了。
引用
in_buffer[intail] = SBUF0;
为什么这么读。 2 in_buffer = xxx. //xxx为串口的缓存SBUF(具体看手册,可能就是你这里的SBUF0)。 3 感觉你intail的变量有点乱用了。
舟遥 2012-12-03
  • 打赏
  • 举报
回复
引用 1 楼 dsoyy 的回复:
你这帖子没人认真看的,看代码比写还累。 哪里不明白问哪里比较好
感谢dsoyy的回复,冷了一天了,我想请教一下关于串口(uart)中断收发的问题,串口中断发我知道,只要向sbuf0写入数据就会触发ti0引起中断,但是串口收什么时候进入不是很明了,数据手册上说RI0中断标志位是由硬件来置1的,那什么时候进入串口接收中断呢?之前程序运行时,用串口调试助手,点那个发送数据,根本就没反应。今天再试试时,又有数据丢失的情况,就是第一个字节丢失掉了,没有接收,不知道这一般是什么原因引起的?
dsoyy 2012-12-03
  • 打赏
  • 举报
回复
你这帖子没人认真看的,看代码比写还累。
哪里不明白问哪里比较好

27,375

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧