freetech

kinetis的UART串口(中断模式)

0
阅读(3939)

前面的例子中,串口的收发采用查询模式,程序要不断查询串口状态,这样不利于将CPU解放出来做其它事情。本例采用中断方式实现数据发送与接收。

要使用中断方式,需做下面3件事情:

1、UART5_C2寄存器的接收中断使能,发送中断使能。

2、NVICISER寄存器使能UART对应中断。

3、中断向量表填入中断服务程序入口。

下面是代码:

/*
* main implementation: use this 'C' sample to create your own application
*
*/

#define GPIO_PIN_MASK            0x3C000000
#define GPIO_PIN(x)                ((1<<x)&GPIO_PIN_MASK)
#include <stdio.h>

#include "derivative.h" /* include peripheral declarations */
struct _uart_buf
{
    int index;
    char buf[100];
} uart_tx,uart_rx;

void MCG_Init()
{
  SIM_SCGC6 |= 0x20000000; //SIM_SCGC6: RTC=1                     
  if ((RTC_CR & RTC_CR_OSCE_MASK) == 0u)//Only if the OSCILLATOR is not already enabled
  {
    RTC_CR &= ~0x3C00; //RTC_CR: SC2P=0,SC4P=0,SC8P=0,SC16P=0                    
    RTC_CR |= 0x0100;  //RTC_CR: OSCE=1                    
    RTC_CR &= ~0x0200; //RTC_CR: CLKO=0                    
  }   
  /* System clock initialization */
  /* SIM_CLKDIV1: OUTDIV1=0,OUTDIV2=1,OUTDIV3=1,OUTDIV4=3,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0 */
  SIM_CLKDIV1 = (uint32_t)0x01130000UL; /* Update system prescalers */
  /* SIM_SOPT2: PLLFLLSEL=0 */
  SIM_SOPT2 &= (uint32_t)~0x00010000UL; /* Select FLL as a clock source for various peripherals */
  /* SIM_SOPT1: OSC32KSEL=0 */
  SIM_SOPT1 &= (uint32_t)~0x00080000UL; /* System oscillator drives 32 kHz clock for various peripherals */
  /* Switch to FEE Mode */ 
  SIM_SOPT2 |= (uint32_t)0x01UL;// SIM_SOPT2: MCGCLKSEL=1 0-System oscillator (OSCCLK), 1-32 kHz RTC oscillator
  MCG_C2 = (uint8_t)0x00U; // MCG_C2: ??=0,??=0,RANGE=0,HGO=0,EREFS=0,LP=0,IRCS=0                           
  MCG_C1 = (uint8_t)0x02U; // MCG_C1: CLKS=0,FRDIV=0,IREFS=0,IRCLKEN=1,IREFSTEN=0                           
  MCG_C4 |= 0xE0; //MCG_C4: DMX32=1,DRST_DRS=3                          
  MCG_C5 = 0x00; // MCG_C5: ??=0,PLLCLKEN=0,PLLSTEN=0,PRDIV=0                           
  MCG_C6 = 0x00;// MCG_C6: LOLIE=0,PLLS=0,CME=0,VDIV=0                            
  while((MCG_S & MCG_S_IREFST_MASK) != 0x00U) //Check that the source of the FLL reference clock is the external reference clock.
  {
  }
  while((MCG_S & 0x0CU) != 0x00U) // Wait until output of the FLL is selected
  {   
  }   
}
void UART_Init()
{
      // SIM_SCGC1: UART5=1
      SIM_SCGC1 |= (uint32_t)0x0800UL;
      // SIM_SCGC5: PORTE=1
      SIM_SCGC5 |= (uint32_t)0x2000UL;
      // PORTE_PCR9: ISF=0,MUX=3 做UART
      PORTE_PCR9 = (uint32_t)((PORTE_PCR9 & (uint32_t)~0x01000400UL) | (uint32_t)0x0300UL);
      // PORTE_PCR8: ISF=0,MUX=3 做UART
      PORTE_PCR8 = (uint32_t)((PORTE_PCR8 & (uint32_t)~0x01000400UL) | (uint32_t)0x0300UL);                          
      NVICISER1 |= 1<<23;//使能中断NVICISERn=m,其中n=55/32,m=55%32
      NVICISER1 |= 1<<24;//使能中断NVICISERn=m,其中n=56/32,m=56%32
      UART5_C4 = 0x14;    //波特率微调
      UART5_BDH = (312>>8) & 0x1F;//设波特率9600bps
      UART5_BDL = 312&0xFF;
      UART5_C2 |= (1<<7)|(1<<5)|(1<<2);//允许收、发中断,允许接收
      UART5_C1 |= 1<<7;//使用回环模式
}
int main(void)
{
    int i;
    MCG_Init();
    UART_Init();
    for(i=0;i<100;i++)
    {
        uart_tx.buf[i] = i;
        uart_rx.buf[i] = 0;
    }
    uart_tx.index = 1;
    uart_rx.index = 0;
    printf("Hello (Kinetis) World in 'C' from MK60DX256Z derivative! \n\r");
    UART5_D = uart_tx.buf[0];//发送要在中断前先发第一字节
    UART5_C2 |= 1<<3;
    for(;;)
    {
        //while( (UART5_S1&(1<<7)) == 0);
    }
    return 0;
}
void uart5_isr(void)
{
    unsigned char tmp;
    tmp = UART5_S1;
    //发送
    if( (tmp&(1<<7)) != 0)
    {
        UART5_D = uart_tx.buf[uart_tx.index];
        uart_tx.index++;
        if(uart_tx.index >= 100)
        {
            uart_tx.index = 0;
        }   
    }
    //接收
    if( (tmp&(1<<5)) != 0)
    {
        uart_rx.buf[uart_rx.index] = UART5_D;
        uart_rx.index++;
        if(uart_rx.index >= 100)
        {
            uart_rx.index = 0;
        }
    }
}

把kinetis_sysinit.c的__vect_table{}的71号中断的(tIsrFunc)UNASSIGNED_ISR   换成 (tIsrFunc)uart5_isr。