韦东山旧1期学习笔记】11.S3C2440 中断实验(四)串口中断实验

串口中断实验

我们之前做过串口的实验,使用的是启用FIFO功能,以轮询的形式发送和接收数据。采用一位起始位,八位数据位,零位校验位,一位停止位的数据帧格式。
现在我们要添加中断功能,通过中断来接收数据。需要说明的一点是,我们之所以不使用中断来发送数据,是因为我们的串口一直在打印东西,所以如果开启了发送中断,那么会一直进IRQ中断。

设置FIFO中断触发条件

这个功能比较简单,我们首先需要设置FIFO中断触发条件,如下图所示:
在这里插入图片描述
我们将中断设置为发送FIFO剩余48字节、接收FIFO多于8字节时产生中断。因为我们后面没有清除掉发送中断掩码,所以不会产生发送中断。

UFCON0 &= (~(0xF0));
UFCON0 |= ((0x3 << 6) | (0x1 << 4));

中断控制器设置

我们需要在中断控制器中取消串口UART0相对应的接收和发送中断屏蔽。
在这里插入图片描述
在这里插入图片描述
通过上图我们可知,UART0对应的中断还细分了三个子中断,所以我们既要设置INTMSK,也要设置INTSUBMSK。
在这里插入图片描述
在这里插入图片描述
我们将UART0的接收中断 和 错误中断打开。

INTMSK = (~(0x1 << 28));
INTSUBMSK = (~(0x5));

至此,我们开启了UART0的接收、发送和错误中断。

串口0中断处理函数

由中断偏移寄存器INTOFFSET寄存器可知:UART0对应的硬件中断号是28。
在这里插入图片描述
所以当中断号是28的时候,我们就需要进行串口中断处理了。

void uart0_handle_irq(int num) {
	unsigned int dataCount = 0;
	unsigned int status = 0;
	switch(num){
		case UART0_TX_IRQ:
			dataCount = ((UFSTAT0 >> 8) & 0x3F);
			printf("%d bytes data in Tx FIFO.\n\r", dataCount);
		break;
		case UART0_RX_IRQ:
			//将收到的数据打印出来
			dataCount = UFSTAT0 & (0x3F);
			while(dataCount) {
				uart0_putc(URXH0);
				dataCount = UFSTAT0 & (0x3F);
			}
			printf("\n\r");
		break;
		case UART0_ERR_IRQ:
			status = UERSTAT0;
			if(status & 0x1) {
				printf("Overrun Error is occured.\n\r");
			}
			if(status & 0x2) {
				printf("Parity Error is occured.\n\r");
			}
			if(status & 0x4) {
				printf("Frame Error is occured.\n\r");
			}
			if(status & 0x8) {
				printf("Break is received.\n\r");
			}
		break;
		default:
			printf("UART0 Unknown is interrupted.\n\r");
		break;
	}
}
void irqExpHandler(void) {
	//现在处于SVC模式
	//我们先获取硬件中断号
	unsigned int interruptNum = INTOFFSET;
	int subInterruptNum = 0;
	printf("\n\rIRQ Interrupt Number: %d\n\r", interruptNum);
	//按键 按下后为低电平
	unsigned int isKeyUp = 0;
	int ledNum = -1;
	switch(interruptNum){
		case 0:
			//EINT0中断 s2按键
			isKeyUp = (GPFDAT & 0x1);
			ledNum = LED1;
			
		break;
		case 2:
			//EINT2 s3按键
			isKeyUp = (GPFDAT & (0x1 << 2));
			ledNum = LED2;
		break;
		case 5:
			//EINT8_23 s4按键
			isKeyUp = (GPGDAT & (0x1 << 3));
			ledNum = LED4;
		break;
		case 28:
			subInterruptNum = SUBSRCPND & 0x7;
			if(SUBSRCPND & 0x1) {
				//INT_RXD0
				uart0_handle_irq(UART0_RX_IRQ);
			}
			if(SUBSRCPND & 0x2) {
				//INT_RXD0
				uart0_handle_irq(UART0_TX_IRQ);
			}
			if(SUBSRCPND & 0x4) {
				//INT_RXD0
				uart0_handle_irq(UART0_ERR_IRQ);
			}
		break;
		default:
		break;
	}
	if(ledNum > 0) {
		if(isKeyUp) {
			//熄灭LED1
			led_off(ledNum);
			printf("Key is Up.LED%d is turn off.\n\r", ledNum);
		}else {
			led_on(ledNum);
			printf("Key is Down.LED%d is turn on.\n\r", ledNum);
		}
	}
	
	//处理完毕,从源头开始清理中断标志
	//注意是写1清零
	if(interruptNum == 5) {
		EINTPEND = (0x1 << 11);
	}
	SUBSRCPND = subInterruptNum;
	SRCPND = (0x1 << interruptNum);
	INTPND = (0x1 << interruptNum);

	printf("IRQ Interrupt is Handled\n\r");
}

实验主函数

我们的实验主函数一直在死循环打印字符,别的什么也不做。

char gCh = 'A';
int main(void) {
	leds_init();
	keys_init_irq();
	printf("%s\n\r", "IRQ Test.");
	dump_norFlash(80);
	
	while(1) {
		printf("%c(0x%02x) ", gCh, gCh);
		gCh++;
		wait(888888);
	}
	return 0;
}

实验结果

只要我们往串口助手内写入的字符达到8个,就会产生IRQ中断,并将我们输入的内容打印出来。
在这里插入图片描述

发布了25 篇原创文章 · 获赞 2 · 访问量 1063

猜你喜欢

转载自blog.csdn.net/BakerTheGreat/article/details/104564757