程序编译通过,且单步执行时,串口能进入中断,且中断响应程序执行正确,但一旦全速执行,中断可进,但中断响应程序中,接收数据发生错误,我用的是串口调试助手模拟上位机给串口发送数据。
#include "config.h" #define UART_BPS 9600; //定义通信波特率 #define LEDCON 0xf0000000; uint8 rcv_buf[8];
uint8 rcv_new; /*volatile uint8 rcv_new;*/
void DelayNS(uint32 dly) { uint32 i; for(;dly>0;dly--) { for(i=0;i<5000;i++); } }
/* uint8 UART0_RcvByte(void)
{ uint8 rcv_data;
while((U0LSR&0x01)==0); //U0RBR为空的话, 一直等待
rcv_data=U0RBR; //数据保存在串口0的一位寄存器中 return(rcv_data); }
void UART0_RcvStr(uint8 *s,uint32 n) //以n个字节为一字符串,n由main函数中给出 { for (;n>0;n--) { *s++=UART0_RcvByte(); } } */ void UART0_SendByte(uint8 data) { U0THR=data; while((U0LSR&0x40)==0); } void UART0_SendBuf(uint8 *str) { while(1) { if(*str=='\0') break; UART0_SendByte(*str++); } } void UART0_Init(void) {
uint16 Fdiv;
U0LCR = 0x83; // DLAB = 1,可设置波特率 Fdiv = (Fpclk / 16) / UART_BPS; // 设置波特率 U0DLM = Fdiv / 256; U0DLL = Fdiv % 256; U0LCR = 0x03; } // 初始化串口模式
void __irq IRQ_UART0 (void) { uint8 i,j,k; uint8 temp; //取得的数据 uint8 strlen; //所需数据长度 uint8 checksum; uint8 h1,h2,h3; //h1,h2半字节校验,h2放高字节累加和校验,h1放低字节累加和校验 uint8 check_buf[2]; uint8 *p; uint8 SendStr_1[]="OK!\r\n"; uint8 SendStr_2[]="wrong!\r\n" ; uint8 SendStr_3[]="Resend\r\n"; IO2CLR=0xf0000000; /*IO2DIR=0xf0000000; IO2CLR=0xa0000000; */ //测试是否进中断用,实验结果表明可进入中断 2008 9.24 if ((U0IIR & 0x0F) == 0x04); rcv_new = 1; // 设置接收到新的数据标志 /*IO2DIR=0xf0000000; IO2CLR=0xa0000000;*/ //再次测试串口是否能进入中断,实验结果可行 2008 9 24 for (i=0; i<8; i++) { rcv_buf = U0RBR; // 读取FIFO的数据,并清除中断 } if(rcv_buf[0]==0x24) // 接收到开始字符$ { checksum=0; for(strlen=0;strlen<6;strlen++) //半字节校验 { checksum=checksum^rcv_buf[strlen+1]; h2=checksum&0x0F; h1=((checksum>>4)&0x0F); } h3=(h1<<4)^h2; if(h3==rcv_buf[7]) //累加和校验通过 { for(j=2;j<7;j++) //将数据再次返回上位机,进行再次验对 UART0_SendByte(rcv_buf[j]); rcv_new=0; //清楚接收标志位,等待上位机的回应 U0FCR=U0FCR|0x07; //复位Rx FIFO 和Tx FIFO while((U0LSR&0x01)==0); //U0RBR 为空的话,一直等待 rcv_new=1; for(k=0;k<2;k++) { temp=U0RBR; check_buf[k]=temp; } //将上位机返回的check值,放入buf中,U0RBR中每次只能放一个字节 p=check_buf; if (strcmp(p,"OK")==0) { rcv_new=1; //接收到验证码,通过上位机的验证 UART0_SendBuf(SendStr_1); //返回确认信号,提醒上位机准备开始记录 rcv_new=0; //清楚接收标志位 U0FCR=U0FCR|0x07; //复位Rx FIFO 和Tx FIFO switch(rcv_buf[6]) //根据上位机给出的激励电流值大小 { case 0x31: //电流值为1A IO1SET=0x200000; //p1.21 IO2SET=0xf0000000; IO2CLR=0x10000000; break; case 0x32: //电流值为2A IO1SET=0x400000; //p1.22 IO2SET=0xf0000000; IO2CLR=0x20000000; break; case 0x33: //电流值为3A IO1SET=0x600000; //p1.21 p1.22 IO2SET=0xf0000000; IO2CLR=0x30000000; break; case 0x34: //电流值为4A IO1SET=0x800000; //p1.23 IO2SET=0xf0000000; IO2CLR=0x40000000; break; case 0x35: //电流值为5A IO1SET=0xA00000; //p1.21 p1.23 IO2SET=0xf0000000; IO2CLR=0x50000000; break; case 0x36: //电流值为6A IO1SET=0xC00000; //p1.23 p1.22 IO2SET=0xf0000000; IO2CLR=0x60000000; break; case 0x37: //电流值为7A IO1SET=0xE00000; //p1.21 p1.22 p1.23 IO2SET=0xf0000000; IO2CLR=0x70000000; break; case 0x38: //电流值为8A IO1SET=0x1000000; //p1.24 IO2SET=0xf0000000; IO2CLR=0x80000000; break; } } else //数据验证错误 UART0_SendBuf(SendStr_3); U0FCR=U0FCR|0x07; } else //累加校验不通过 // UART0_SendByte(h2); //将0换为rcv_buf[3],作为实验之用,实验结果表明正确,在半字检验未通过时,返回值正确 2008 9 24 UART0_SendBuf(SendStr_2); //调整程序,使得返回值更实际 2008 9 25 U0FCR=U0FCR|0x07; //复位Rx FIFO 和Tx FIFO } else UART0_SendBuf(SendStr_3); U0FCR=U0FCR|0x07; //复位Rx FIFO 和Tx FIFO VICVectAddr = 0x00; // 中断处理结束 }
int main(void) { /* rcv_new=0;*/ PINSEL0 = 0x00000005; // 设置I/O连接到UART0 IO1DIR=0x1ff0000; //p1.16-p1.24为输出 I/O IO2DIR=0xf0000000; //p2.28-p2.31为输出 LED //IO2DIR=LEDCON; // 配置LED控制为输出 UART0_Init(); U0FCR=0x81; //触发点为8字节,且使能对于FIFO的访问 U0IER=0x01; //使能RDA中断 VICIntSelect = 0x00000000; // 设置所有通道为IRQ中断 VICVectCntl0 = 0x26; // UART0中断通道分配到IRQ slot 0,即优先级最高 VICVectAddr0 = (uint32)IRQ_UART0; // 设置UART0向量地址 VICIntEnable = 0x00000040; // 使能串口中断 while(1); // 等待中断 return(0); }
|