S3C2451开发板除了可以使用上篇博文中提到的查询法,还可以使用其他的方式实现串口的发送和接收。中断法和DMA法就是典型的方法。
DMA(DIRECT MEMORY ACCESS)即直接存储器存取,是指外部设备不通过CPU而直接与系统内存交换数据的接口技术。 要把外设的数据读入内存或把内存的数据传送到外设,一般都要通过CPU控制完成,如CPU程序查询或中断方式。利用中断进行数据传送,可以大大提高CPU的利用率。
中断传送是由CPU通过中断服务程序来传送,每次要保护断点,保护现场需要多条指令,每条指令要有取指和执行时间。为了充分利用CPU的高速性能和实时操作的要求,一般中断服务程序要求是尽量的简短,所以当要实现大量数据交换的情况,如从磁盘调入程序或图形数据,如果采用中断传送方式,必然会引起频繁中断的情况,需要执行很多与数据传送无关的中断指令,所以会大大降低系统的执行效率,无法提高数据传送速率。对于一个高速I/O设备,以及批量交换数据的情况,只能采用DMA方式,才能解决效率和速度问题。DMA在外设与内存间直接进行数据交换,而不通过CPU,这样数据传送的速度就取决于存储器和外设的工作速度。
(1)查询方式:主要用于CPU不太忙且传送速度不高的情况下。无条件传送方式作为查询方式的一个特例,主要用于对简单I/O设备的控制或CPU明确知道外设所处状态的情况下。
(2) 中断方式:主要用于CPU的任务比较忙的情况下,尤其适合实时控制和紧急事件的处理
(3) DMA方式(直接存储器存取方式):主要用于高速外设进行大批量数据传送的场合
S3C2451串口中断库函数编写:
s3c2451_irq.h
#ifndef _S3C2451_IRQ_H
#define _S3C2451_IRQ_H
#include "typedef.h"
typedef struct {
U32 SRCPND;
U32 INTMOD;
U32 INTMSK;
U32 null;
U32 INTPND;
U32 INTOFFSET;
U32 SUBSRCPND;
U32 INTSUBMSK;
U32 PRIORITY_MODE;
U32 PRIORITY_UPDATE;
}volatile* IRQ_MemMabPtr;
#define IRQ1_BASE_PTR ((IRQ_MemMabPtr)0x4A000000)
#define IRQ2_BASE_PTR ((IRQ_MemMabPtr)0x4A000040)
#define INT_ADC (1<<31)
#define INT_RTC (1<<30)
#define INT_SPI1 (1<<29)
#define INT_UART0 (1<<28)
#define INT_IIC0 (1<<27)
#define INT_USBH (1<<26)
#define INT_USBD (1<<25)
#define INT_NAND (1<<24)
#define INT_UART1 (1<<23)
#define INT_SPI0 (1<<22)
#define INT_SDI0 (1<<21)
#define INT_SDI1 (1<<20)
#define INT_CFCON (1<<19)
#define INT_UART3 (1<<18)
#define INT_DMA (1<<17)
#define INT_LCD (1<<16)
#define INT_UART2 (1<<15)
#define INT_TIMER4 (1<<14)
#define INT_TIMER3 (1<<13)
#define INT_TIMER2 (1<<12)
#define INT_TIMER1 (1<<11)
#define INT_TIMER0 (1<<10)
#define INT_WDT (1<<9)
#define INT_TICK (1<<8)
#define nBATT_FLT (1<<7)
#define INT_CAM (1<<6)
#define EINT8_23 (1<<5)
#define EINT4_7 (1<<4)
#define EINT3 (1<<3)
#define EINT2 (1<<2)
#define EINT1 (1<<1)
#define EINT0 (1<<0)
#define SUBINT_DMA7 (1<<30)
#define SUBINT_DMA6 (1<<29)
#define SUBINT_AC97 (1<<28)
#define SUBINT_WDT (1<<27)
#define SUBINT_ERR3 (1<<26)
#define SUBINT_TXD3 (1<<25)
#define SUBINT_RXD3 (1<<24)
#define SUBINT_DMA5 (1<<23)
#define SUBINT_DMA4 (1<<22)
#define SUBINT_DMA3 (1<<21)
#define SUBINT_DMA2 (1<<20)
#define SUBINT_DMA1 (1<<19)
#define SUBINT_DMA0 (1<<18)
#define SUBINT_LCD4 (1<<17)
#define SUBINT_LCD3 (1<<16)
#define SUBINT_LCD2 (1<<15)
#define SUBINT_CAM_P (1<<12)
#define SUBINT_CAM_C (1<<11)
#define SUBINT_ADC (1<<10)
#define SUBINT_TC (1<<9)
#define SUBINT_ERR2 (1<<8)
#define SUBINT_TXD2 (1<<7)
#define SUBINT_RXD2 (1<<6)
#define SUBINT_ERR1 (1<<5)
#define SUBINT_TXD1 (1<<4)
#define SUBINT_RXD1 (1<<3)
#define SUBINT_ERR0 (1<<2)
#define SUBINT_TXD0 (1<<1)
#define SUBINT_RXD0 (1<<0)
typedef enum{
DISABLE = 0,
ENABLE
}Functionalstate;
extern void IRQ_ClearSRCPND(unsigned int irqx); //清楚主标志寄存器内容
extern void IRQ_ClearSUBSRCPND(unsigned int irqx); //清楚子标志寄存器内容
extern void IRQ_INTMSK_Init(unsigned int irqx, Functionalstate newstate); //主屏蔽寄存器开启关闭
extern void IRQ_INTSUBMSK_Init(unsigned int irqx, Functionalstate newstate); //子屏蔽寄存器开启关闭
extern Functionalstate IRQ_GetSRCPND(unsigned int irqx); //获取主标志寄存器有没有响应
extern Functionalstate IRQ_GetSUBSRCPND(unsigned int irqx); //获取子标志寄存器有没有响应
#endif
s3c2451_irq.c
#include "s3c2451_irq.h"
IRQ_MemMabPtr const IRQ_BASE_PTR[2] = { IRQ1_BASE_PTR, IRQ2_BASE_PTR};
/**函数名:IRQ_ClearSRCPND
*参数:中断源irqx
*功能:清楚主标志寄存器内容
**/
void IRQ_ClearSRCPND(unsigned int irqx)
{
IRQ_BASE_PTR[0]->SRCPND |= irqx;
IRQ_BASE_PTR[0]->INTPND |= irqx;
}
/**函数名:IRQ_ClearSUBSRCPND
*参数:中断源irqx
*功能:清楚子标志寄存器内容
**/
void IRQ_ClearSUBSRCPND(unsigned int irqx)
{
IRQ_BASE_PTR[0]->SUBSRCPND |= irqx;
}
/**函数名:IRQ_INTMSK_Init
*参数:中断源irqx
*功能:主屏蔽寄存器开启关闭
**/
void IRQ_INTMSK_Init(unsigned int irqx, Functionalstate newstate)
{
if(newstate == ENABLE)
{
IRQ_BASE_PTR[0]->INTMSK &= ~irqx;
}
else
{
IRQ_BASE_PTR[0]->INTMSK |= irqx;
}
}
/**函数名:IRQ_INTSUBMSK_Init
*参数:中断源irqx
*功能:子屏蔽寄存器开启关闭
**/
void IRQ_INTSUBMSK_Init(unsigned int irqx, Functionalstate newstate)
{
if(newstate == ENABLE)
{
IRQ_BASE_PTR[0]->INTSUBMSK &= ~irqx;
}
else
{
IRQ_BASE_PTR[0]->INTSUBMSK |= irqx;
}
}
/**函数名:IRQ_GetSRCPND
*参数:中断源irqx
*返回值:
*功能:获取主标志寄存器有没有响应
**/
Functionalstate IRQ_GetSRCPND(unsigned int irqx)
{
if((IRQ_BASE_PTR[0]->SRCPND & irqx) == irqx)
{
return ENABLE;
}
else
{
return DISABLE;
}
}
/**函数名:IRQ_GetSUBSRCPND
*参数:中断源irqx
*返回值:
*功能:获取子标志寄存器有没有响应
**/
Functionalstate IRQ_GetSUBSRCPND(unsigned int irqx)
{
if((IRQ_BASE_PTR[0]->SUBSRCPND & irqx) == irqx)
{
return ENABLE;
}
else
{
return DISABLE;
}
}
s3c2451_it.h
#ifndef _S3C2451_IT_H
#define _S3C2451_IT_H
extern void __irq UART0_IRQ(void);
#endif
s3c2451_it.c
#include "s3c2451_it.h"
#include "main.h"
void __irq UART0_IRQ()
{
U8 data;
data = UART_RecvData(UART0);
if(data == 'a')
{
UART_printf("点亮led1\n");
GPIO_WriteBit(GPIOB, GPIO_Pin_5, BIT_RESET);
}
else if(data == 'b')
{
UART_printf("熄灭led1\n");
GPIO_WriteBit(GPIOB, GPIO_Pin_5, BIT_SET);
}
else if(data == 'c')
{
UART_printf("蜂鸣器响\n");
GPIO_WriteBit(GPIOB, GPIO_Pin_0, BIT_SET);
}
else if(data == 'd')
{
UART_printf("蜂鸣器不响\n");
GPIO_WriteBit(GPIOB, GPIO_Pin_0, BIT_RESET);
}
IRQ_ClearSRCPND(INT_UART0);
IRQ_ClearSUBSRCPND(SUBINT_RXD0);
}
s3c2451_uart.c添加函数:
/**函数名:My_interrupt_Uart
*参数:波特率brandrate,
* 中断处理函数Hander_IRQ
*功能:本人常用的串口初始化设置
**/
void My_interrupt_Uart(U32 brandrate, U32 Hander_IRQ)
{
UART_InitTypedef uart_inittypedef;
uart_inittypedef.brandrate = brandrate; //波特率
uart_inittypedef.datalength = DataLength_8Bit;
uart_inittypedef.mode = Mode_rx_tx;
uart_inittypedef.parity = Parity_No;
uart_inittypedef.stop = STOP_ONE;
UART_INIT(UART0, uart_inittypedef);
UART_interrupt_init(UART0, Hander_IRQ);
IRQ_INTMSK_Init(INT_UART0, ENABLE);
IRQ_INTSUBMSK_Init(SUBINT_RXD0, ENABLE);
}
main函数:
void Main(void)
{
My_interrupt_Uart(115200, (U32)UART0_IRQ);
LED_INIT();
while(1);
}