中断处理(串口中断)

来源:互联网 发布:订房软件 编辑:程序博客网 时间:2024/05/29 10:57


#define GPNCON     (*((volatile unsigned long *)0x7F008830))
#define GPNDAT     (*((volatile unsigned long *)0x7F008834))

#define EINT0CON0  (*((volatile unsigned long *)0x7F008900))
#define EINT0MASK  (*((volatile unsigned long *)0x7F008920))

#define EINT0PEND  (*((volatile unsigned long *)0x7F008924))

#define PRIORITY    (*((volatile unsigned long *)0x7F008280))
#define SERVICE     (*((volatile unsigned long *)0x7F008284))
#define SERVICEPEND (*((volatile unsigned long *)0x7F008288))


#define VIC0IRQSTATUS  (*((volatile unsigned long *)0x71200000))
#define VIC0FIQSTATUS  (*((volatile unsigned long *)0x71200004))
#define VIC0RAWINTR    (*((volatile unsigned long *)0x71200008))
#define VIC0INTSELECT  (*((volatile unsigned long *)0x7120000c))
#define VIC0INTENABLE  (*((volatile unsigned long *)0x71200010))
#define VIC0INTENCLEAR (*((volatile unsigned long *)0x71200014))
#define VIC0PROTECTION (*((volatile unsigned long *)0x71200020))
#define VIC0SWPRIORITYMASK (*((volatile unsigned long *)0x71200024))
#define VIC0PRIORITYDAISY  (*((volatile unsigned long *)0x71200028))

#define VIC0VECTADDR0      (*((volatile unsigned long *)0x71200100))
#define VIC0VECTADDR1      (*((volatile unsigned long *)0x71200104))
#define VIC0ADDRESS        (*((volatile unsigned long *)0x71200f00))

#define VIC1IRQSTATUS  (*((volatile unsigned long *)0x71300000))
#define VIC1VECTADDR5      (*((volatile unsigned long *)0x71300114))
#define VIC1INTENABLE  (*((volatile unsigned long *)0x71300010))
#define VIC1ADDRESS        (*((volatile unsigned long *)0x71300f00))

 

void eint0_3_irq(void)
{
 int i;
 
 printf("eint0_3_irq\n\r");  /* K1~K4 */
 for (i = 0; i < 4; i ++)
 {
  if (EINT0PEND & (1<<i))
  {
   if (GPNDAT & (1<<i))
   {
    printf("K%d released\n\r", i+1);
   }
   else
   {
    printf("K%d pressed\n\r", i+1);
   }
  }
 }

}

void eint4_11_irq(void)
{
 int i;
 printf("eint4_11_irq\n\r"); /* K5~K6 */
 for (i = 4; i < 6; i ++)
 {
  if (EINT0PEND & (1<<i))
  {
   if (GPNDAT & (1<<i))
   {
    printf("K%d released\n\r", i+1);
   }
   else
   {
    printf("K%d pressed\n\r", i+1);
   }
  }
 }

}

void irq_init(void)
{
 key_irq_init();
 uart_irq_init();
}


void uart_irq(void)
{
 /* 调用具体的中断处理函数 */
 do_uart_irq();
 /* 清中断 */
 VIC1ADDRESS = 0;
}


void uart_irq_init(void)
{
 VIC1INTENABLE |= (1<<5);   /* bit5: int_uart0 */
 VIC1VECTADDR5 = uart_irq;
}

void key_irq_init(void)
{
 /* 配置GPIO引脚为中断引脚 */
 /* GPN0~5 设为中断引脚 */
 GPNCON &= ~(0xfff);
 GPNCON |= 0xaaa;

 /* 设置中断触发方式为: 双边沿触发 */
 EINT0CON0 &= ~(0xfff);
 EINT0CON0 |= 0x777;

 /* 使能中断 */
 EINT0MASK &= ~(0x3f);

 /* 在中断控制器里使能这些中断 */
 VIC0INTENABLE |= (0x3); /* bit0: eint0~3, bit1: eint4~11 */

 VIC0VECTADDR0 = eint0_3_irq;
 VIC0VECTADDR1 = eint4_11_irq;
}


void do_irq(void)
{
 int i = 0;

 void (*the_isr)(void);

 if (VIC0IRQSTATUS)


 {
  the_isr = VIC0ADDRESS;
   
  /* 2.1 分辨是哪个中断 */
  /* 2.2 调用它的处理函数 */ 
  /* 2.3 清中断 */ 

  the_isr();
  
  EINT0PEND   = 0x3f;  /* 清中断 */
  VIC0ADDRESS = 0;
 }
 else if (VIC1IRQSTATUS)
 {
  the_isr = VIC1ADDRESS;
   
  /* 2.1 分辨是哪个中断 */
  /* 2.2 调用它的处理函数 */ 
  /* 2.3 清中断 */ 

  the_isr();
 }
}

 


#define ULCON0     (*((volatile unsigned long *)0x7F005000))
#define UCON0      (*((volatile unsigned long *)0x7F005004))
#define UFCON0     (*((volatile unsigned long *)0x7F005008))
#define UMCON0     (*((volatile unsigned long *)0x7F00500C))
#define UTRSTAT0   (*((volatile unsigned long *)0x7F005010))
#define UFSTAT0    (*((volatile unsigned long *)0x7F005018))
#define UTXH0      (*((volatile unsigned char *)0x7F005020))
#define URXH0      (*((volatile unsigned char *)0x7F005024))
#define UBRDIV0    (*((volatile unsigned short *)0x7F005028))
#define UDIVSLOT0  (*((volatile unsigned short *)0x7F00502C))
#define UINTP0      (*((volatile unsigned long *)0x7F005030))
 

#define UINTM0    (*((volatile unsigned long *)0x7F005038))


#define GPACON     (*((volatile unsigned short *)0x7F008000))

#define ENABLE_FIFO 1

static delay(void)
{
 volatile int i = 10;
 while (i--);
}

void uart_tx_int_enable(void)
{
 UINTM0 &= ~(1<<2); 


}

void uart_tx_int_disable(void)
{
 UINTM0 |= (1<<2); 
}


void init_uart(void)
{
 GPACON &= ~0xff;
 GPACON |= 0x22;
 
 /* ULCON0 */
 ULCON0 = 0x3;  /* 数据位:8, 无较验, 停止位: 1, 8n1 */
 UCON0  = 0x5 | (1<<9);  /* 使能UART发送、接收, tx interrupt request type = level */
#ifdef ENABLE_FIFO
 UFCON0 = 0x07 | (1<<6); /* FIFO enable, tx fifo trigger level = 16 bytes */ //中断产生条件(FIFO内数据少于多少时,产生中断)


#else
 UFCON0 = 0x00; /* FIFO disable */
#endif
 UMCON0 = 0;
 
 /* 波特率 */
 /* DIV_VAL = (PCLK / (bps x 16 ) ) - 1
  * bps = 57600
  * DIV_VAL = (66500000 / (115200 x 16 ) ) - 1
  *         = 35.08
  */
 UBRDIV0   = 35;

 /* x/16 = 0.08
  * x = 1
  */
 UDIVSLOT0 = 0x1;

UINTM0 = 0xF;    //关闭中断

}

unsigned char getc(void)
{
#ifdef ENABLE_FIFO
 while ((UFSTAT0 & (1<<6)) == 0 && (UFSTAT0 & 0x3f) == 0)delay();
#else 
 while ((UTRSTAT0 & (1<<0)) == 0);
#endif
 
 return URXH0;
}

int getc_nowait(unsigned char *pChar)
{
#ifdef ENABLE_FIFO
 if ((UFSTAT0 & (1<<6)) == 0 && (UFSTAT0 & 0x3f) == 0)
#else
 if ((UTRSTAT0 & (1<<0)) == 0)
#endif  
 {
  return -1;
 }
 else
 { 
  *pChar = URXH0;
  return 0;
 }
}


#define TX_BUF_LEN   2048
static unsigned char txbuf[2047];
static unsigned int r_idx = 0;
static unsigned int w_idx = 0;

static int isFull(void)
{
 if ((w_idx + 1) % TX_BUF_LEN == r_idx)
  return 1;
 else
  return 0;
}

static int isEmpty(void)
{
 return (w_idx == r_idx);
}

static int putData(unsigned char data)
{
 if (isFull())
  return -1;
 else
 {
  txbuf[w_idx] = data;
  w_idx = (w_idx + 1) % TX_BUF_LEN;
  return 0;
 }
}

static int getData(unsigned char *pdata)
{
 if (isEmpty())
 {
  return -1;
 }
 else
 {
  *pdata = txbuf[r_idx];
  r_idx = (r_idx + 1) % TX_BUF_LEN;
  return 0;
 }
}

void putc(char c)
{
 putData(c);   
/* 把数据放到环形缓冲区里去 */

 /* 如果"uart 发送中断"未使能的话,使能"uart 发送中断" */
 uart_tx_int_enable();
}

 

void do_uart_irq(void)
{
 int i;
 int cnt;
 unsigned char c;
 
 if (UINTP0 & (1<<2))
 {
  /* 对于发送中断 */
   if (isEmpty())
   {
    /* 禁止中断 */
   uart_tx_int_disable();
   }
   else
   {
    /* 从环型缓冲区里取出数据, 放到TX   FIFO里去 */
   cnt = (UFSTAT0 >> 8) & 0x3f;                    
   cnt = 64 - cnt;                                        //计算FIFO还剩多少数据空间,继续写入
   for (i = 0; i < cnt; i++)
   {
    if (getData(&c) == 0)
    {
     UTXH0 = c;
    }
    else
    {
     break;
    }
   }
   }
 }

 else if (UINTP0 & (1<<0))
 {
  /* 对于接收中断, 从RX FIFO里取出数据 */
 }

 /* 清中断 */
 UINTP0 = 0xf;
}


 

 

 

0 0
原创粉丝点击