CortexM4F232系列的UART 9bit 模式

通过查阅LM4F232H5QC的数据手册,对UART口可以使能9位模式,并且支持对自身地址编程,即设置UART9BITADDR寄存器,比如应用在RS485网络,M4单片机做从机的时候,只要收到地址和自身一样的地址,就会触发中断,并将后面的数据放入fifo中,如果地址不匹配,就自动丢弃后面的数据,

数据手册原文如下:If the byte received that follows 9th bit set then it will be compared with UART9BITADDRRNG (address

range read-only status register). Upon not finding a match, the rest of the data bytes with the 9th

bit cleared are dropped. If a match is found, then an interrupt is generated to the NVIC for further action. The subsequent data bytes with the cleared 9th bit are stored in the FIFO.

郁闷的是因为TI数据手册说的比较模糊,也没有例程,自己摸索了下配置如下:

ROM_UARTConfigSetExpClk(UART0_BASE, ROM_SysCtlClockGet(), 115200,

                           (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |

                            UART_CONFIG_PAR_ZERO));

//   HWREG(UART0_BASE + UART_O_CTL) |= UART_CTL_LBE;

   UARTStdioInit(0);

   //

   // enable the 9 bit mode

   //

  UART9BitAddrSet(UART0_BASE, 0x55, 0xFF);

  UART9BitEnable(UART0_BASE);

  UARTFIFOEnable(UART0_BASE);

  UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);

   //

   // Enable the UART interrupt.

   //

   ROM_IntEnable(INT_UART0);

   ROM_UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT | UART_INT_9BIT );

中断函数如下:

   ulStatus = ROM_UARTIntStatus(UART0_BASE, true);

   //

   // Clear the asserted interrupts.

   //

   ROM_UARTIntClear(UART0_BASE, ulStatus);

   //UARTprintf("UART_INT_happen %x \r\n", ulStatus);

  // if(ulStatus & UART_INT_TX)

   if(ulStatus & UART_INT_9BIT)

   {

    status = ulStatus;

      //UARTprintf("UART_INT_9BIT Address Match  \r\n");

       UART9BitDisable(UART0_BASE);

    g_ucBuf = ROM_UARTCharGet(UART0_BASE);

   }

   if(ulStatus & (UART_INT_RX | UART_INT_RT))

   {

    status = ulStatus;

       //UARTprintf("UART_INT_RX  \r\n");

       UART9BitEnable(UART0_BASE);

       while(ROM_UARTCharsAvail(UART0_BASE))

       {

           //

           // Read the next character from the UART and write it back to the UART.

           //

           g_ucBuf = ROM_UARTCharGetNonBlocking(UART0_BASE);

           //UARTprintf("UART_Data %x \r\n", g_ucBuf);

    //       ROM_UARTCharPutNonBlocking(UART0_BASE, g_ucBuf);

       }

   }

现在问题是在触发了9bit中断之后,后续的接收中断要在fifo半满的时候才会触发,即接收了八个数据时候触发。那么如果在接收了不到8个数据时候,又来了一个地址,就会丢失。

上述的中断函数是试了好多次设置的,我试过如果不在9bit中断处理里面关闭9bit中断,后续的数据接收中断也不会触发,  这和datasheet上面说的不太一样哦,上面说后续的数据会放在fifo中, 我就郁闷了,希望哪位大侠指导下。

  • star hou:

    1.在新的地址到来前,把FIFO中的数据读出来就行呀。设置一个合理的FIFO深度就可以了

    2.文档中所说的后续数据,就是在确认了接收到一个地址后的数据将会放入FIFO中。正如你知道的,超过8个数据就会触发FIFO中断。

  • 我有一个需求:

    只需要硬件引发第9位UART中断即可,然后由软件来判断地址匹配,不用硬件!

    请问LM4F可以实现吗?

  • liu kun :

    可以的,可以按硬件的思路来做呗

  • 我是说由LM4F引发第9位UART中断即可,然后由软件来判断地址匹配?看数据手册不确定是否可以?如果行的话,就要准备做方案了。请指点,谢谢!

  • liu kun :

    按照文档的说法是,匹配了地址寄存器中的地址才会触发中断

  • 你的想法可以实现,但不是引发9bit中断,9bit中断只能在地址匹配时候引发,你可以用引发校验错误中断去做判断处理,比如设置校验位为: UART_CONFIG_PAR_ZERO,这种情况下,只要是校验错误的中断就可判断为地址,然后在中断处理中去比较是不是地址匹配。

  • hi JSW-p j :

    1:合理的深度的话,现在FIFO做浅是1/8深度,即两个数据才会触发中断,在实际使用过程中还是会丢地址,除非一个数据一次中断,但是这样子FIFO的意义就失去了

    2:还有不理解的是,为什么要在9bit匹配中断出发后要禁用9bit中断,不然接收中断就触发不了呢?如果这个问题能解决就不存在第1个问题了