TMS320C6748_UART中断

UART2输入时钟为PLL1_SYSCLK2,PLL1_SYSCLK2是PLL1_SYSCLK1的2分频,PLL1_SYSCLK1的频率默认为456MHz,PLL时钟树如图:

(指南P130)

(指南P131)

定义UART2输入时钟频率如下:

// 时钟
#define SYSCLK_1_FREQ (456000000)
#define SYSCLK_2_FREQ (SYSCLK_1_FREQ/2)
#define UART_2_FREQ (SYSCLK_2_FREQ)

主函数如下:

int main(void)
{
  // 外设使能配置
  PSCInit();
 
  // GPIO 管脚复用配置
  GPIOBankPinMuxSet();
 
  // DSP 中断初始化
  InterruptInit();
 
  // UART 初始化
  UARTInit();
 
  // UART 中断初始化
  UARTInterruptInit();
 
  // 主循环
  for(;;)
  {
 
  }
}

其中,GPIOBankPinMuxSet();函数如下:

void GPIOBankPinMuxSet(void)
{
  // UART2 禁用流控
  UARTPinMuxSetup(2, FALSE);
}

UARTPinMuxSetup函数为创龙开发板特有的配置函数,该函数位于starterware/application/platform目录工程中的UART.C文件里。该函数对系统配置模块0(System Configuration Module 0,SYSCFG0)的引脚复用控制寄存器4(Pin Multiplexing Control 4 Register,PINMUX4,地址值为0x01C1 4130h)进行设置,将GP1[2]脚功能设置为UART2_TXD,该脚作为UART2的发送脚,将GP1[3]脚功能设置为UART2_RXD,该脚作为UART2的接收脚。PINMUX4寄存器地址及其各字段含义如下所示,UARTPinMuxSetup附在图后。

(指南P204)

(指南P225)

(指南P225)

(指南P226)

/****************************************************************************/
/* */
/* 管脚复用配置 */
/* */
/****************************************************************************/
void UARTPinMuxSetup(unsigned int instanceNum, unsigned int modemCtrlChoice)
{
  unsigned int svPinMuxRtsCts = 0;
  unsigned int svPinMuxTxdRxd = 0;
 
  if(0 == instanceNum)
  {
    if(TRUE == modemCtrlChoice)
    {
      svPinMuxRtsCts = (HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(3)) & \
                        ~(SYSCFG_PINMUX3_PINMUX3_27_24 | \
                          SYSCFG_PINMUX3_PINMUX3_31_28));
 
      HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(3)) = \
        (PINMUX3_UART0_CTS_ENABLE | \
         PINMUX3_UART0_RTS_ENABLE | \
         svPinMuxRtsCts);
    }
 
  svPinMuxTxdRxd = (HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(3)) & \
                    ~(SYSCFG_PINMUX3_PINMUX3_23_20 | \
                      SYSCFG_PINMUX3_PINMUX3_19_16));
 
  HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(3)) = \
    (PINMUX3_UART0_TXD_ENABLE | \
     PINMUX3_UART0_RXD_ENABLE | \
     svPinMuxTxdRxd);
  }
 
  else if(1 == instanceNum)
  {
    if(TRUE == modemCtrlChoice)
    {
      svPinMuxRtsCts = (HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(0)) & \
                        ~(SYSCFG_PINMUX0_PINMUX0_23_20 | \
                          SYSCFG_PINMUX0_PINMUX0_19_16));
 
      HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(0)) = \
        (PINMUX0_UART1_CTS_ENABLE | \
         PINMUX0_UART1_RTS_ENABLE | \
         svPinMuxRtsCts);
    }
 
    svPinMuxTxdRxd = (HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(4)) & \
                      ~(SYSCFG_PINMUX4_PINMUX4_31_28 | \
                        SYSCFG_PINMUX4_PINMUX4_27_24));
 
    HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(4)) = \
      (PINMUX4_UART1_TXD_ENABLE | \
       PINMUX4_UART1_RXD_ENABLE | \
       svPinMuxTxdRxd);
  }
 
  else if(2 == instanceNum)
  {
 
    if(TRUE == modemCtrlChoice)
    {
      svPinMuxRtsCts = (HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(0)) & \
                        ~(SYSCFG_PINMUX0_PINMUX0_31_28 | \
                          SYSCFG_PINMUX0_PINMUX0_27_24));
 
      HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(0)) = \
        (PINMUX0_UART2_CTS_ENABLE | \
         PINMUX0_UART2_RTS_ENABLE | \
         svPinMuxRtsCts);
    }
 
    svPinMuxTxdRxd = (HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(4)) & \
                      ~(SYSCFG_PINMUX4_PINMUX4_23_20 | \
                        SYSCFG_PINMUX4_PINMUX4_19_16));
 
    HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(4)) = \
      (PINMUX4_UART2_TXD_ENABLE | \
       PINMUX4_UART2_RXD_ENABLE | \
       svPinMuxTxdRxd);
 
  }
 
  else
  {
 
  }
}

管脚复用配置完成后,就要对UART进行初始化了。初始化参考步骤如图所示:

(指南P1427)

UART初始化函数中,首先配置UART2的参数。设置UART2波特率为115200bps,UART2模块的内存地址为0x01D0D000,波特率在UART模块的DLL(Divisor LSB Latch)和DLH(Divisor MSB Latch)寄存器中设置,DLL存储Divisor的低8位,DLH存储Divisor的高8位,在波特发生器(Baud generator)中对UART输入时钟进行分频,分频系数为Divisor,从而产生波特时钟(baud clock,BCLK)。波特时钟BCLK的值应为波特率的16倍或13倍,具体是16倍还是13倍取决于过采样率,如果是16倍过采样,则16个波特时钟才完成1bit的传输,如果是13倍过采样则是13个波特时钟。计算公式及UART时钟发生框图如下所示:

(指南P1419)

(指南P1419)

设置UART的帧格式为数据位8,停止位1,无校验位,帧格式在流控制LCR(Line Control Register)中定义。设置过采样模式(Over-Sampling Mode,OSM)为16倍过采样,采样模式在MDR(Mode Definition Register)寄存器中定义。

(手册P23)

(指南P1430)

完成UART2初始化后,就开始使能UART2。使能UART2,只要设置PWREMU_MGMT寄存器的UTRST、URRST和FREE3位就行了。

(指南P1447)

然后使能接收和发送FIFO,在FCR寄存器中对相应位进行设置。通过使能FIFO,可以减少软件对CPU的过度开销,因为FIFO可以对要发送或接收的字符进行缓存(buffering),所以不用每接收或者发送一个字节就中断一次这样频繁地打断CPU的进程,只有当FIFO满了之后才通知CPU,一次把所有的数据处理完,大大提高了CPU的工作效率。

使能FIFO后还要设置FIFO级别,接收器FIFO可以设置为1字节满,4字节满,8字节满或14字节满共4个级别。

(指南P1436)

这样,UART初始化就完成了,UART初始化代码如下:

void UARTInit(void)
{
  // 配置 UART2 参数
  // 波特率 115200 数据位 8 停止位 1 无校验位
  UARTConfigSetExpClk(SOC_UART_2_REGS, UART_2_FREQ, BAUD_115200,
    UART_WORDL_8BITS, UART_OVER_SAMP_RATE_16);
  // 使能 UART2
  UARTEnable(SOC_UART_2_REGS);
 
  // 使能接收 / 发送 FIFO
  UARTFIFOEnable(SOC_UART_2_REGS);
 
  // 设置 FIFO 级别
  UARTFIFOLevelSet(SOC_UART_2_REGS, UART_RX_TRIG_LEVEL_1);
}

UART初始化后,还需要进行UART中断初始化。先是注册4号CPU可屏蔽中断的中断服务函数,IntRegister(C674X_MASK_INT4, UARTIsr);,当C674X_MASK_INT4中断发生时,执行UARTIsr函数。然后设置interrupt selector中相应INTSEL字段,将UART2中断事件(中断号为69,SYS_INT_UART2_INT)映射到C674X_MASK_INT4中断,然后使能C674X_MASK_INT4中断。然后,还需要对UART的中断使能寄存器IER(Interrupt Enable Register)进行设置。UART中断请求由4路中断请求复合而成。当这4路中断的任何一路发生时,只要其在IER中相应的位开启了,使能了该路中断,就会产生UART中断请求。

(指南P1428)

(指南P1433)

UART中断初始化代码如下:

void UARTInterruptInit(void)
{
  IntRegister(C674X_MASK_INT4, UARTIsr);
  IntEventMap(C674X_MASK_INT4, SYS_INT_UART2_INT);
  IntEnable(C674X_MASK_INT4);
 
  // 使能中断
  unsigned int intFlags = 0;
  int Flags |= (UART_INT_LINE_STAT | \
                UART_INT_TX_EMPTY | \
                UART_INT_RXDATA_CTI);
  UARTIntEnable(SOC_UART_2_REGS, intFlags);
}

当中断发生后,需要先在中断识别寄存器(The interrupt identification register (IIR))中确定UART中断是由4路中断请求中的哪一路引起的,然后做相应的处理。IIR地址与FCR一样,不过IIR是只读寄存器,FCR则是只写寄存器,这点区别了两者。当中断发生后,IER中相应的位也使能了,在IIR的IPEND位就会清0,表示UART中断发生了。如果UART中断是由发送中断引起的,说明发送FIFO为空,就往THR寄存器(transmitter holding register)写1字节。注意,在FIFO模式下,THR寄存器变成了1个16字节的FIFO。

(指南P1432)

如果UART中断是由接收中断引起的,则检查LSR寄存器(Line Status Register)的DR(Data-ready)字段,确定数据是否已经准备好,即接收器FIFO中是否有数据,如果有,则从RBR寄存器(Receiver Buffer Register)中读取该数据。当UART处于FIFO模式时,RBR为16字节的FIFO。注意,RBR和THR,DLL共享同一地址,要读RBR,需要确保LCR寄存器的DLAB位为0.

(指南P1431)

(指南P1442)

若UART中断是由接收错误引起的,则从RBR中把错误的字节都读出来,并不断检测LSR的错误标志位,直到所有的错误字节都读走了。UART中断服务服务函数如下

void UARTIsr()
{
  static unsigned int length = sizeof(txArray);
  static unsigned int count = 0;
  unsigned char rxData = 0;
  unsigned int int_id = 0;
 
  // 确定中断源
  int_id = UARTIntStatus(SOC_UART_2_REGS);
 
  // 清除 UART2 系统中断
  IntEventClear(SYS_INT_UART2_INT);
 
  // 发送中断
  if(UART_INTID_TX_EMPTY == int_id)
  {
    if(0 < length)
    {
      // 写一个字节到 THR
      UARTCharPutNonBlocking(SOC_UART_2_REGS, txArray[count]);
      length--;
      count++;
    }
    if(0 == length)
    {
      // 禁用发送中断
      UARTIntDisable(SOC_UART_2_REGS, UART_INT_TX_EMPTY);
    }
  }
 
  // 接收中断
  if(UART_INTID_RX_DATA == int_id)
  {
    rxData = UARTCharGetNonBlocking(SOC_UART_2_REGS);
    UARTCharPutNonBlocking(SOC_UART_2_REGS, rxData);
  }
 
  // 接收错误
  if(UART_INTID_RX_LINE_STAT == int_id)
  {
    while(UARTRxErrorGet(SOC_UART_2_REGS))
    {
      // 从 RBR 读一个字节
      UARTCharGetNonBlocking(SOC_UART_2_REGS);
    }
  }
 
  return;
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值