嵌入式开发之串口通讯

    串口通信(Serial Communication), 是指外设和计算机间,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式。这种通信方式使用的数据线少,在远距离通信中可以节约通信成本,但其传输速度比并行传输低,是嵌入式开发中的法宝,也是必备技能之一。

知乎大佬这篇文章讲的比较详细,大家可以移步去看看,我部分摘录

详解串口通信UART - 知乎

通用异步接受器-发送器(UART)把数据的字节按照比特顺序发送。另一端的UART把比特组装为字节。每个UART包含一个移位寄存器,这是串行和并行形式之间转换的基本方法。通过一根线或其他媒介的串行通信比通过多根线的并行通信具有更低成本。UART 通常不直接产生或接收不同设备之间使用的外部信号。单独的接口设备用于将 UART 的逻辑电平信号与外部信号电平转换,这些信号电平可以是标准化的电压电平、电流电平或其他信号。

通信有3种模式:

  • 单工(仅在一个方向,没有规定接收设备将信息发送回发送设备)
  • 全双工(两个设备同时发送和接收)
  • 半双工(设备轮流发送和接收)

数据帧

UART 串​​行通信中的数据被组织成称为数据包或帧的块。

对于串口通讯的软件编写,一般有两种模式,查询和终端模式,

      查询就是用循环底层对于寄存器的状态值进行判断,如果有接收到数据则读取,但这种方式很占用CPU时间,在等待数据是CPU不能做其他任务。

     所以一般采用中断模式进行数据的接收,发送可以直接发送或者中断方式发送,一般uart会自带一定数量的fifo,可以通过控制寄存器来设置硬件缓冲大小,以及半满全满的缓冲,然后再将数据在中断来临时读出放入软件层面的ring环形缓冲区里面,再配合一定的api供其他应用进行功能调用,做协议解析等。以下就是一个典型的中断接收的串口驱动,基于PIC32,支持ucosii rtos,大家可以从中学习到串口驱动的基本用法,让硬件层和应用层进行分离,实现通用的可移植的代码。欢迎大家一起交流技术。

 

#define COMM_GLOBALS
//#include <plib.h>
#include "COMMRTOS_LIB.H"
#include "bsp_peripherals.h"
//#define	GetSystemClock() 			(80000000ul)
//#define	GetPeripheralClock()		(GetSystemClock()/(1 << OSCCONbits.PBDIV))

//uart id
//RS232-1                         U1A
//RS232-2                         U1B
//RS485                           U3B
#define UART1                   UART1A
#define UART2                   UART1B
#define UART3                   UART3B
#define CTS_UART1               0
#define CTS_UART2               0
#define CTS_UART3               0
//uart baudrate
#define  UART1_BAUDRATE           (9600)
#define  UART2_BAUDRATE           (9600)
#define  UART3_BAUDRATE           (9600)
//uart int prio level
#define UART1_INT_PRIORITY_LEVEL  INT_PRIORITY_LEVEL_1
#define UART2_INT_PRIORITY_LEVEL  INT_PRIORITY_LEVEL_2
#define UART3_INT_PRIORITY_LEVEL  INT_PRIORITY_LEVEL_3
//uart int sub prio level
#define UART1_INT_SUB_PRIORITY_LEVEL  INT_SUB_PRIORITY_LEVEL_0
#define UART2_INT_SUB_PRIORITY_LEVEL  INT_SUB_PRIORITY_LEVEL_0
#define UART3_INT_SUB_PRIORITY_LEVEL  INT_SUB_PRIORITY_LEVEL_0

#define UART1TXIntEnable(enable)  mU1ATXIntEnable(enable) 
#define UART2TXIntEnable(enable)  mU1BTXIntEnable(enable) 
#define UART3TXIntEnable(enable)  mU3BTXIntEnable(enable) 

//#define PutcUART1(c)  putcUART3
/*$PAGE*/
/*
*********************************************************************************************************
*                                               CONSTANTS
*********************************************************************************************************
*/
    
/*
*********************************************************************************************************
*                                               DATA TYPES
*********************************************************************************************************
*/

typedef struct {
    INT16U     RingBufRxCtr;                /* Number of characters in the Rx ring buffer              */
    OS_EVENT  *RingBufRxSem;                /* Pointer to Rx semaphore                                 */
    INT8U     *RingBufRxInPtr;              /* Pointer to where next character will be inserted        */
    INT8U     *RingBufRxOutPtr;             /* Pointer from where next character will be extracted     */
    INT8U      RingBufRx[COMM_RX_BUF_SIZE]; /* Ring buffer character storage (Rx)                      */

    INT16U     RingBufTxCtr;                /* Number of characters in the Tx ring buffer              */
    OS_EVENT  *RingBufTxSem;                /* Pointer to Tx semaphore                                 */
    INT8U     *RingBufTxInPtr;              /* Pointer to where next character will be inserted        */
    INT8U     *RingBufTxOutPtr;             /* Pointer from where next character will be extracted     */
    INT8U      RingBufTx[COMM_TX_BUF_SIZE]; /* Ring buffer character storage (Tx)                      */

} COMM_RING_BUF;

/*
*********************************************************************************************************
*                                            GLOBAL VARIABLES
*********************************************************************************************************
*/

COMM_RING_BUF  Comm1Buf;
COMM_RING_BUF  Comm2Buf;
COMM_RING_BUF  Comm3Buf;

/*********************************************************************************************************
** 函数名称: CommTxImmdt() 
** 功能描述: 打开发送中断,把发送缓冲区的数据发送出去
**           
** 输 入  : 
             'ch'   串口号,取值范围为COMM1,COMM2 
** 输 出  : 无
** 全局变量: 无
** 调用模块: 无
** 
** 作 者: 
** 日 期: 
**-------------------------------------------------------------------------------------------------------
** 修 改: 
** 日 期: 
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void CommTxImmdt(INT8U ch)
{
    INT8U   err;


    switch (ch) {
        case COMM1:
            //if((U0IER & 0x02) == 0){                            // 如果发送中断是关的
            //    U0IER |= 0x02;                                  // 开发送中断
            //    U0THR = CommGetTxChar(COMM1, &err);             // 往发送寄存器写初始值
            //}
            //UART1TXIntEnable(1);
            INTEnable(INT_SOURCE_UART_RX(UART1), INT_ENABLED);
            UARTSendDataByte(UART1, CommGetTxChar(COMM1, &err));
            break;
        case COMM2:
            //if((U1IER & 0x02) == 0){                            // 如果发送中断是关的
            //    U1IER |= 0x02;                                  // 开发送中断
            //    U1THR = CommGetTxChar(COMM2, &err);             // 往发送寄存器写初始值
           // }
            //UART2TXIntEnable(1);
            INTEnable(INT_SOURCE_UART_RX(UART2), INT_ENABLED);
            UARTSendDataByte(UART2, CommGetTxChar(COMM2, &err));

            break;
        case COMM3:
            //if((U1IER & 0x02) == 0){                            // 如果发送中断是关的
            //    U1IER |= 0x02;                                  // 开发送中断
            //    U1THR = CommGetTxChar(COMM2, &err);             // 往发送寄存器写初始值
           // }
            //UART3TXIntEnable(1);
             INTEnable(INT_SOURCE_UART_RX(UART3), INT_ENABLED);
             UARTSendDataByte(UART3, CommGetTxChar(COMM3, &err));

            break;
        default:
            break;
    }
}

/*$PAGE*/
/*
*********************************************************************************************************
*                                    REMOVE CHARACTER FROM RING BUFFER
*
*
* Description : This function is called by your application to obtain a character from the communications
*               channel.  The function will wait for a character to be received on the serial channel or
*               until the function times out.
* Arguments   : 'ch'    is the COMM port channel number and can either be:
*                           COMM1
*                           COMM2
*               'to'    is the amount of time (in clock ticks) that the calling function is willing to
*                       wait for a character to arrive.  If you specify a timeout of 0, the function will
*                       wait forever for a character to arrive.
*               'err'   is a pointer to where an error code will be placed:
*                           *err is set to COMM_NO_ERR     if a character has been received
*                           *err is set to COMM_RX_TIMEOUT if a timeout occurred
*                           *err is set to COMM_BAD_CH     if you specify an invalid channel number
* Returns     : The character in the buffer (or NUL if a timeout occurred)
*********************************************************************************************************
*/

INT8U  CommGetChar (INT8U ch, INT16U to, INT8U *err)
{
#if CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL
    CPU_SR  cpu_sr;
#endif
    INT8U          c;
    INT8U          oserr;
    COMM_RING_BUF *pbuf;


    switch (ch) {                                          /* Obtain pointer to communications channel */
        case COMM1:
             pbuf = &Comm1Buf;
             break;

        case COMM2:
             pbuf = &Comm2Buf;
             break;
        case COMM3:
             pbuf = &Comm3Buf;
             break;
        default:
             *err = COMM_BAD_CH;
             return (NUL);
    }
    OSSemPend(pbuf->RingBufRxSem, to, &oserr);             /* Wait for character to arrive             */
    if (oserr == OS_TIMEOUT) {                             /* See if characters received within timeout*/
        *err = COMM_RX_TIMEOUT;                            /* No, return error code                    */
        return (NUL);
    } else {
        OS_ENTER_CRITICAL();
        pbuf->RingBufRxCtr--;                              /* Yes, decrement character count           */
        c = *pbuf->RingBufRxOutPtr++;                      /* Get character from buffer                */
        if (pbuf->RingBufRxOutPtr == &pbuf->RingBufRx[COMM_RX_BUF_SIZE]) {     /* Wrap OUT pointer     */
            pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0];
        }
        OS_EXIT_CRITICAL();
        *err = COMM_NO_ERR;
        return (c);
    }
}

/*$PAGE*/
/*
*********************************************************************************************************
*                                  GET TX CHARACTER FROM RING BUFFER
*
*
* Description : This function is called by the Tx ISR to extract the next character from the Tx buffer.
*               The function returns FALSE if the buffer is empty after the character is extracted from
*               the buffer.  This is done to signal the Tx ISR to disable interrupts because this is the
*               last character to send.
* Arguments   : 'ch'    is the COMM port channel number and can either be:
*                           COMM1
*                           COMM2
*               'err'   is a pointer to where an error code will be deposited:
*                           *err is set to COMM_NO_ERR         if at least one character was available
*                                                              from the buffer.
*                           *err is set to COMM_TX_EMPTY       if the Tx buffer is empty.
*                           *err is set to COMM_BAD_CH         if you have specified an incorrect channel
* Returns     : The next character in the Tx buffer or NUL if the buffer is empty.
*********************************************************************************************************
*/

INT8U  CommGetTxChar (INT8U ch, INT8U *err)
{
    INT8U          c;
    COMM_RING_BUF *pbuf;


    switch (ch) {                                          /* Obtain pointer to communications channel */
        case COMM1:
             pbuf = &Comm1Buf;
             break;

        case COMM2:
             pbuf = &Comm2Buf;
             break;
        case COMM3:
             pbuf = &Comm3Buf;
             break;
        default:
             *err = COMM_BAD_CH;
             return (NUL);
    }
    if (pbuf->RingBufTxCtr > 0) {                          /* See if buffer is empty                   */
        pbuf->RingBufTxCtr--;                              /* No, decrement character count            */
        c = *pbuf->RingBufTxOutPtr++;                      /* Get character from buffer                */
        if (pbuf->RingBufTxOutPtr == &pbuf->RingBufTx[COMM_TX_BUF_SIZE]) {     /* Wrap OUT pointer     */
            pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0];
        }
        OSSemPost(pbuf->RingBufTxSem);                     /* Indicate that character will be sent     */
        *err = COMM_NO_ERR;
        return (c);                                        /* Characters are still available           */
    } else {
        *err = COMM_TX_EMPTY;
        return (NUL);                                      /* Buffer is empty                          */
    }
}

/*$PAGE*/
/*
*********************************************************************************************************
*                                  INITIALIZE COMMUNICATIONS MODULE
*
*
* Description : This function is called by your application to initialize the communications module.  You
*               must call this function before calling any other functions.
* Arguments   : none
*********************************************************************************************************
*/

void  CommInit (void)
{
    COMM_RING_BUF *pbuf;


    pbuf                  = &Comm1Buf;                     /* Initialize the ring buffer for COMM1     */
    pbuf->RingBufRxCtr    = 0;
    pbuf->RingBufRxInPtr  = &pbuf->RingBufRx[0];
    pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0];
    pbuf->RingBufRxSem    = OSSemCreate(0);

    pbuf->RingBufTxCtr    = 0;
    pbuf->RingBufTxInPtr  = &pbuf->RingBufTx[0];
    pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0];
    pbuf->RingBufTxSem    = OSSemCreate(COMM_TX_BUF_SIZE);



    pbuf                  = &Comm2Buf;                     /* Initialize the ring buffer for COMM2     */
    pbuf->RingBufRxCtr    = 0;
    pbuf->RingBufRxInPtr  = &pbuf->RingBufRx[0];
    pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0];
    pbuf->RingBufRxSem    = OSSemCreate(0);

    pbuf->RingBufTxCtr    = 0;
    pbuf->RingBufTxInPtr  = &pbuf->RingBufTx[0];
    pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0];
    pbuf->RingBufTxSem    = OSSemCreate(COMM_TX_BUF_SIZE);

    pbuf                  = &Comm3Buf;                     /* Initialize the ring buffer for COMM3     */
    pbuf->RingBufRxCtr    = 0;
    pbuf->RingBufRxInPtr  = &pbuf->RingBufRx[0];
    pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0];
    pbuf->RingBufRxSem    = OSSemCreate(0);

    pbuf->RingBufTxCtr    = 0;
    pbuf->RingBufTxInPtr  = &pbuf->RingBufTx[0];
    pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0];
    pbuf->RingBufTxSem    = OSSemCreate(COMM_TX_BUF_SIZE);

    UART_INIT();
}
void CommTxIntEn(INT8U ch)
{
    INT8U   err;

    switch (ch) {
        case COMM1:
            INTEnable(INT_SOURCE_UART_TX(UART1), INT_ENABLED);
            break;
        case COMM2:
            INTEnable(INT_SOURCE_UART_TX(UART2), INT_ENABLED);
            break;
        case COMM3:
             INTEnable(INT_SOURCE_UART_TX(UART3), INT_ENABLED);
            break;
        default:
            break;
    }
}

/*$PAGE*/
/*
*********************************************************************************************************
*                                   SEE IF RX CHARACTER BUFFER IS EMPTY
*
*
* Description : This function is called by your application to see if any character is available from the
*               communications channel.  If at least one character is available, the function returns
*               FALSE otherwise, the function returns TRUE.
* Arguments   : 'ch'    is the COMM port channel number and can either be:
*                           COMM1
*                           COMM2
* Returns     : TRUE    if the buffer IS empty.
*               FALSE   if the buffer IS NOT empty or you have specified an incorrect channel.
*********************************************************************************************************
*/

BOOLEAN  CommIsEmpty (INT8U ch)
{
#if CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL
    CPU_SR  cpu_sr;
#endif
    BOOLEAN        empty;
    COMM_RING_BUF *pbuf;


    switch (ch) {                                          /* Obtain pointer to communications channel */
        case COMM1:
             pbuf = &Comm1Buf;
             break;

        case COMM2:
             pbuf = &Comm2Buf;
             break;
        case COMM3:
             pbuf = &Comm3Buf;
             break;
        default:
             return (TRUE);
    }
    OS_ENTER_CRITICAL();
    if (pbuf->RingBufRxCtr > 0) {                          /* See if buffer is empty                   */
        empty = FALSE;                                     /* Buffer is NOT empty                      */
    } else {
        empty = TRUE;                                      /* Buffer is empty                          */
    }
    OS_EXIT_CRITICAL();
    return (empty);
}

/*$PAGE*/
/*
*********************************************************************************************************
*                                   SEE IF TX CHARACTER BUFFER IS FULL
*
*
* Description : This function is called by your application to see if any more characters can be placed
*               in the Tx buffer.  In other words, this function check to see if the Tx buffer is full.
*               If the buffer is full, the function returns TRUE otherwise, the function returns FALSE.
* Arguments   : 'ch'    is the COMM port channel number and can either be:
*                           COMM1
*                           COMM2
* Returns     : TRUE    if the buffer IS full.
*               FALSE   if the buffer IS NOT full or you have specified an incorrect channel.
*********************************************************************************************************
*/

BOOLEAN  CommIsFull (INT8U ch)
{
#if CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL
    CPU_SR  cpu_sr;
#endif
    BOOLEAN        full;
    COMM_RING_BUF *pbuf;


    switch (ch) {                                          /* Obtain pointer to communications channel */
        case COMM1:
             pbuf = &Comm1Buf;
             break;

        case COMM2:
             pbuf = &Comm2Buf;
             break;

        case COMM3:
             pbuf = &Comm3Buf;
             break;
        default:
             return (TRUE);
    }
    OS_ENTER_CRITICAL();
    if (pbuf->RingBufTxCtr < COMM_TX_BUF_SIZE) {           /* See if buffer is full                    */
        full = FALSE;                                      /* Buffer is NOT full                       */
    } else {
        full = TRUE;                                       /* Buffer is full                           */
    }
    OS_EXIT_CRITICAL();
    return (full);
}

/********************************************************************************************************
*                                            OUTPUT CHARACTER
*
*
* Description : This function is called by your application to send a character on the communications
*               channel.  The function will wait for the buffer to empty out if the buffer is full.
*               The function returns to your application if the buffer doesn't empty within the specified
*               timeout.  A timeout value of 0 means that the calling function will wait forever for the
*               buffer to empty out.  The character to send is first inserted into the Tx buffer and will
*               be sent by the Tx ISR.  If this is the first character placed into the buffer, the Tx ISR
*               will be enabled.
* Arguments   : 'ch'    is the COMM port channel number and can either be:
*                           COMM1
*                           COMM2
*               'c'     is the character to send.
*               'to'    is the timeout (in clock ticks) to wait in case the buffer is full.  If you
*                       specify a timeout of 0, the function will wait forever for the buffer to empty.
* Returns     : COMM_NO_ERR      if the character was placed in the Tx buffer
*               COMM_TX_TIMEOUT  if the buffer didn't empty within the specified timeout period
*               COMM_BAD_CH      if you specify an invalid channel number
********************************************************************************************************/
INT8U  CommPutChar (INT8U ch, INT8U c, INT16U to)
{
#if CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL
    CPU_SR  cpu_sr;
#endif   
 INT8U          oserr;
    COMM_RING_BUF *pbuf;


    switch (ch) {                                          /* Obtain pointer to communications channel */
        case COMM1:
             pbuf = &Comm1Buf;
             break;

        case COMM2:
             pbuf = &Comm2Buf;
             break;
        case COMM3:
             pbuf = &Comm3Buf;
             break;
        default:
             return (COMM_BAD_CH);
    }

    OSSemPend(pbuf->RingBufTxSem, to, &oserr);             /* Wait for space in Tx buffer              */
    if (oserr == OS_TIMEOUT) {
        return (COMM_TX_TIMEOUT);                          /* Timed out, return error code             */
    }
    OS_ENTER_CRITICAL();
    pbuf->RingBufTxCtr++;                                  /* No, increment character count            */
    *pbuf->RingBufTxInPtr++ = c;                           /* Put character into buffer                */
    if (pbuf->RingBufTxInPtr == &pbuf->RingBufTx[COMM_TX_BUF_SIZE]) {     /* Wrap IN pointer           */
        pbuf->RingBufTxInPtr = &pbuf->RingBufTx[0];
    }
    if (pbuf->RingBufTxCtr == 1) {                         // See if this is the first character       
        CommTxIntEn(ch);                                   // Yes, Enable Tx interrupts                
    }
    OS_EXIT_CRITICAL();
    return (COMM_NO_ERR);
}

/*$PAGE*/
/*
*********************************************************************************************************
*                                    INSERT CHARACTER INTO RING BUFFER
*
*
* Description : This function is called by the Rx ISR to insert a character into the receive ring buffer.
* Arguments   : 'ch'    is the COMM port channel number and can either be:
*                           COMM1
*                           COMM2
*               'c'     is the character to insert into the ring buffer.  If the buffer is full, the
*                       character will not be inserted, it will be lost.
*********************************************************************************************************
*/

void  CommPutRxChar (INT8U ch, INT8U c)
{
    COMM_RING_BUF *pbuf;


    switch (ch) {                                          /* Obtain pointer to communications channel */
        case COMM1:
             pbuf = &Comm1Buf;
             break;

        case COMM2:
             pbuf = &Comm2Buf;
             break;
        case COMM3:
             pbuf = &Comm3Buf;
             break;
        default:
             return;
    }

    if (pbuf->RingBufRxCtr < COMM_RX_BUF_SIZE) {           /* See if buffer is full                    */
        pbuf->RingBufRxCtr++;                              /* No, increment character count            */
        *pbuf->RingBufRxInPtr++ = c;                       /* Put character into buffer                */
        if (pbuf->RingBufRxInPtr == &pbuf->RingBufRx[COMM_RX_BUF_SIZE]) { /* Wrap IN pointer           */
            pbuf->RingBufRxInPtr = &pbuf->RingBufRx[0];
        }
        OSSemPost(pbuf->RingBufRxSem);                     /* Indicate that character was received     */
    }
}

/*
*********************************************************************************************************
*                                    UART1_UARTHandler()
*
* Description: This function handles interrupts from the UART1.
*
* Arguments  : None
*
* Returns    : None
*********************************************************************************************************
*/

void UART1_UARTHandler(void)
{
    INT8U c;
    INT8U err;	
// Is this an RX interrupt?
	if(INTGetFlag(INT_SOURCE_UART_RX(UART1)))
	{
		// Clear the RX interrupt Flag
	    INTClearFlag(INT_SOURCE_UART_RX(UART1));
        c=UARTGetDataByte(UART1);
        CommPutRxChar(COMM1,c);
		// Toggle LED to indicate UART activity
		//mPORTAToggleBits(BIT_7);

	}

	// We don't care about TX interrupt
	if ( INTGetFlag(INT_SOURCE_UART_TX(UART1)) )
	{
		INTClearFlag(INT_SOURCE_UART_TX(UART1));
	    c = CommGetTxChar(COMM1, &err);  
        if(err==COMM_NO_ERR)
           UARTSendDataByte(UART1, c);
        else if(err==COMM_TX_EMPTY)
           INTEnable(INT_SOURCE_UART_TX(UART1), INT_DISABLED);
	}
}

void UART2_UARTHandler(void)
{
    INT8U c;
    INT8U err;	
// Is this an RX interrupt?
	if(INTGetFlag(INT_SOURCE_UART_RX(UART2)))
	{
		// Clear the RX interrupt Flag
	    INTClearFlag(INT_SOURCE_UART_RX(UART2));
        c=UARTGetDataByte(UART2);
        CommPutRxChar(COMM2,c);
		// Toggle LED to indicate UART activity
		//mPORTAToggleBits(BIT_7);

	}

	// We don't care about TX interrupt
	if ( INTGetFlag(INT_SOURCE_UART_TX(UART2)) )
	{
		INTClearFlag(INT_SOURCE_UART_TX(UART2));
	    c = CommGetTxChar(COMM2, &err);   
        if(err==COMM_NO_ERR)
           UARTSendDataByte(UART2, c);
        else if(err==COMM_TX_EMPTY)
           INTEnable(INT_SOURCE_UART_TX(UART2), INT_DISABLED);
	}
}

void UART3_UARTHandler(void)
{
    INT8U c;
    INT8U err;	
// Is this an RX interrupt?
	if(INTGetFlag(INT_SOURCE_UART_RX(UART3)))
	{
		// Clear the RX interrupt Flag
	    INTClearFlag(INT_SOURCE_UART_RX(UART3));
        c=UARTGetDataByte(UART3);
        CommPutRxChar(COMM3,c);
		// Toggle LED to indicate UART activity
		//mPORTAToggleBits(BIT_7);

	}

	// We don't care about TX interrupt
	if ( INTGetFlag(INT_SOURCE_UART_TX(UART3)) )
	{
		INTClearFlag(INT_SOURCE_UART_TX(UART3));
	    c = CommGetTxChar(COMM3, &err);    
        if(err==COMM_NO_ERR)
           UARTSendDataByte(UART3, c);
        else if(err==COMM_TX_EMPTY)
           INTEnable(INT_SOURCE_UART_TX(UART3), INT_DISABLED);
	}
}
/*
*********************************************************************************************************
*                                      UART_Init()
*
* Description: This function performs all necessary initializations on the UART.
*
* Arguments  : baud_rate    The desired baud rate for the UART
*
* Returns    : None
*********************************************************************************************************
*/

void  UART_INIT (void)
{
     int    pbClk;
     pbClk=GetPeripheralClock();
    // OpenUART1(UART_EN, UART_RX_ENABLE | UART_TX_ENABLE, pbClk/16/UART1_BAUDRATE-1);    // calculate actual BAUD generate value.



//    INT_EN_DIS  INT_Value=INT_ENABLED;
    //uart1
    UARTConfigure(UART1, UART_ENABLE_PINS_TX_RX_ONLY);
    UARTSetFifoMode(UART1, UART_INTERRUPT_ON_TX_NOT_FULL | UART_INTERRUPT_ON_RX_NOT_EMPTY);
    UARTSetLineControl(UART1, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
    UARTSetDataRate(UART1, pbClk, UART1_BAUDRATE);
    UARTEnable(UART1, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));

    INTSetVectorPriority(INT_VECTOR_UART(UART1), UART1_INT_PRIORITY_LEVEL);
    INTSetVectorSubPriority(INT_VECTOR_UART(UART1), UART1_INT_SUB_PRIORITY_LEVEL);
	// Configure UART1 RX Interrupt
	INTEnable(INT_SOURCE_UART_RX(UART1),INT_ENABLED);
	// Configure UART1 TX Interrupt
	//enable as tx data in 
    //INTEnable(INT_SOURCE_UART_TX(UART1),INT_ENABLED);

    //uart2
    UARTConfigure(UART2, UART_ENABLE_PINS_TX_RX_ONLY);
    UARTSetFifoMode(UART2, UART_INTERRUPT_ON_TX_NOT_FULL | UART_INTERRUPT_ON_RX_NOT_EMPTY);
    UARTSetLineControl(UART2, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
    UARTSetDataRate(UART2, pbClk, UART2_BAUDRATE);
    
    UARTEnable(UART2, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));

	// Configure UART1 TX Interrupt
	//INTEnable(INT_SOURCE_UART_TX(UART2), INT_ENABLED);
    INTSetVectorPriority(INT_VECTOR_UART(UART2), UART2_INT_PRIORITY_LEVEL);
    INTSetVectorSubPriority(INT_VECTOR_UART(UART2), UART2_INT_SUB_PRIORITY_LEVEL);
	// Configure UART1 RX Interrupt
	INTEnable(INT_SOURCE_UART_RX(UART2), INT_ENABLED);

    //uart3
    UARTConfigure(UART3, UART_ENABLE_PINS_TX_RX_ONLY);
    UARTSetFifoMode(UART3, UART_INTERRUPT_ON_TX_NOT_FULL | UART_INTERRUPT_ON_RX_NOT_EMPTY);
    UARTSetLineControl(UART3, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
    UARTSetDataRate(UART3, pbClk, UART3_BAUDRATE);
    UARTEnable(UART3, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));

	// Configure UART1 TX Interrupt
	//INTEnable(INT_SOURCE_UART_TX(UART3), INT_ENABLED);
    INTSetVectorPriority(INT_VECTOR_UART(UART3), UART3_INT_PRIORITY_LEVEL);//INT_PRIORITY_LEVEL_2);
    INTSetVectorSubPriority(INT_VECTOR_UART(UART3), UART3_INT_SUB_PRIORITY_LEVEL);
	// Configure UART1 RX Interrupt
	INTEnable(INT_SOURCE_UART_RX(UART3), INT_ENABLED);

    // configure for multi-vectored mode
    //INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);

    // enable interrupts
    //INTEnableInterrupts();


   //WriteString("*** UART Interrupt-driven Application Example ***\r\n");
   //WriteString("*** Type some characters and observe echo and RA7 LED toggle ***\r\n");


	// Let interrupt handler do the work
	//while (1);

//	return 0;

}
void PutString(const char *string,INT8U CommPort)
{
    while(*string != '\0')
    {
       CommPutChar(CommPort,*string,100);
       string++;
    }
}
// helper functions
void WriteString(const char *string,INT8U CommPort)
{
    switch(CommPort)
   {
     case COMM1:
    while(*string != '\0')
    {
       while ( CTS_UART1);		        // wait for !CTS, clear to send
       while ( U1ASTAbits.UTXBF);   // wait while Tx buffer full
       U1ATXREG = *string++;
    }


       //uart=UART1;
       break;
     case COMM2:
    while(*string != '\0')
    {
       while ( CTS_UART1);		        // wait for !CTS, clear to send
       while ( U1BSTAbits.UTXBF);       // wait while Tx buffer full
       U1BTXREG = *string++;
    }
       break;
     case COMM3:
    while(*string != '\0')
    {
       while ( CTS_UART1);		        // wait for !CTS, clear to send
       while ( U3BSTAbits.UTXBF);   // wait while Tx buffer full
       U3BTXREG = *string++;
    }
       break;
     default:
       return;
   }

}
void PutCharacter(const char character,INT8U CommPort)
{

    INT8U uart=UART1;
    switch(CommPort)
   {
     case COMM1:
       while ( CTS_UART1);		        // wait for !CTS, clear to send
       while ( U1ASTAbits.UTXBF);   // wait while Tx buffer full
       U1ATXREG = character;

       //uart=UART1;
       break;
     case COMM2:
       while ( CTS_UART2);		        // wait for !CTS, clear to send
       while ( U1BSTAbits.UTXBF);   // wait while Tx buffer full
       U1BTXREG = character;

       //uart=UART2;
       break;
     case COMM3:
       while ( CTS_UART3);		        // wait for !CTS, clear to send
       while ( U3BSTAbits.UTXBF);   // wait while Tx buffer full
       U3BTXREG = character;

       //uart=UART3;
       break;
     default:
       return;
   }
}


/*
// initialize the UART2 serial port
void initU2( void)
{
    U2BRG 	= BRATE;    
    U2MODE 	= U_ENABLE;
    U2STA 	= U_TX;
    TRTS    = 0;        // make RTS output
    RTS     = 1;        // set RTS default status
} // initU2


// send a character to the UART2 serial port
int putU2( int c)
{
    while ( CTS);		        // wait for !CTS, clear to send
    while ( U2STAbits.UTXBF);   // wait while Tx buffer full
    U2TXREG = c;
    return c;
} // putU2


// wait for a new character to arrive to the UART2 serial port
char getU2( void)
{
    RTS = 0;            // assert Request To Send !RTS
    while ( !U2STAbits.URXDA);	// wait for a new character to arrive
    RTS = 1;
    return U2RXREG;		// read the character from the receive buffer
}// getU2


*/
static char uart_string[600];
/
void Uart_Printf(char *fmt,...)
{
    int i=0;
    va_list ap;

    va_start(ap,fmt);
    vsprintf(uart_string,fmt,ap);
    WriteString(uart_string,UART1);
    va_end(ap);
    for(i=0;i<1000;i++);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/36515.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前后端实现导出导入功能

目录 导出 1.后端代码 &#xff08;1&#xff09;相关依赖 &#xff08;2&#xff09;自定义实体类 &#xff08;3&#xff09;写一个查询方法list &#xff08;4&#xff09;写导出接口 2.前端代码 3.效果示例 导入 1.后端代码 &#xff08;1&#xff09;写导入接口 …

用 Nginx 禁止国外 IP 访问我的网站...

先来说说为啥要写这篇文章&#xff0c;之前看了下 Nginx 的访问日志&#xff0c;发现每天有好多国外的 IP 地址来访问我的网站&#xff0c;并且访问的内容基本上都是恶意的。因此我决定禁止国外 IP 来访问我的网站。 想要实现这个功能有很多方法&#xff0c;下面我就来介绍基于…

OSPFv2基础03_综合实验

目录 1.创建OSPF进程 2.创建OSPF区域 3.使能OSPF 4.创建虚连接&#xff08;可选&#xff09; 5.OSPF常用命令 6.实验配置步骤 7.实验效果 1.创建OSPF进程 OSPF是一个支持多进程的动态路由协议&#xff0c;OSPF多进程可以在同一台路由器上运行多个不同的OSPF进程&#x…

JDK,JRE,JVM的区别

1.JVM JVM&#xff0c;也叫java虚拟机&#xff0c;用来运行字节码文件&#xff0c;可将字节码翻译为机器码&#xff0c;JVM是实现java跨平台的关键&#xff0c;可以让相同的java代码在不同的操作系统上运行出相同的结果。 2.JRE JRE&#xff0c;也叫java运行时环境&#xff…

医疗金融法律大模型:从ChatDoctor到FinBERT/FinGPT/BloombergGPT、ChatLaw/LawGPT_zh

第一部分 各种医疗类ChatGPT&#xff1a;或中英文数据微调LLaMA、或中文数据微调ChatGLM 1.1 基于LLaMA微调的国内外医疗问答模型 1.1.1 ChatDoctor&#xff1a;通过self-instruct技术提示API的数据和医患对话数据集微调LLaMA Github上有一个基于LLaMA模型的医疗微调模型&am…

MySQL基础篇第3章(基本的SELECT语句)

文章目录 1、SQL概述1.1 SQL背景知识1.2 SQL分类 2、SQL语言的规则与规范2.1 基本规则2.2 SQL大小写规范 &#xff08;建议遵守&#xff09;2.3 注释2.4 命名规则2.5 数据导入指令 3、基本的SELECT语句3.0 SELECT...3.1 SELECT...FROM3.2 列的别名3.3 去除重复行3.4 空置参与运…

【JAVA】这几个JAVA学习网站你绝不能错过(教学课程篇)

个人主页&#xff1a;【&#x1f60a;许思王】 文章目录 前言HOW2J.CNw3cschool菜鸟教程慕课网开课吧黑马程序员B站 前言 JAVA很难学&#xff1f;学不会怎么办&#xff1f;找对学习网站&#xff0c;让你轻松解决困难。 HOW2J.CN HOW2J.CN是我自认为最好的JAVA学习网站&#x…

Docker私有仓库搭建与界面化管理

一、关于Registry 官方的Docker hub是一个用于管理公共镜像的好地方&#xff0c;我们可以在上面找到我们想要的镜像&#xff0c;也可以把我们自己的镜像推送上去。 但是有时候我们的使用场景需要我们拥有一个私有的镜像仓库用于管理我们自己的镜像。这个可以通过开源软件Regi…

5.EFLK(ELK+filebeat)+filter过滤

文章目录 EFLK&#xff08;ELKfilebeat&#xff09;部署filebeat修改配置文件logstash配置 logstash的filter过滤grok(正则捕获插件)内置正则表达式调用自定义表达式 mutate(数据修改插件)重命名字段添加字段删除字段转换数据类型替换字段内容以"|"为分割符拆分数据成…

抖音seo源码部署搭建--代码分享

一、 开发环境搭建 抖音SEO源码部署环境搭建可以分为以下几个步骤&#xff1a; 安装必要的软件和工具&#xff1a;需要安装Node.js、NPM、Git等软件和工具&#xff0c;具体安装方法可以参考官方文档。 下载源码&#xff1a;从GitHub或其他源码托管平台下载抖音SEO源码。 安装…

Failed to start connector [Connector[HTTP/1.1-8080]]

1、解决Web server failed to start. Port 8080 was already in use 2、SpringBoot启动报错:“Error starting ApplicationContext. To display the conditions report re-run your application with ‘debug’ enabled.” 3、Failed to start end point associated with Proto…

Docker部署(1)——将jar包打成docker镜像并启动容器

在代码编写完成即将部署的时候&#xff0c;如果采用docker容器的方法&#xff0c;需要将jar包打成docker镜像并通过镜像将容器启动起来。具体的步骤如下。 一、首先下载java镜像 先使用docker search java命令进行搜索。 然而在拉取镜像的时候要注意不能直接去选择pull java ,…

Idea社区版创建SpringBoot

一 下载Spring Initalizr and Assistant插件 选择左上角的File->Settings->Plugins&#xff0c;在搜索框中输入Spring&#xff0c;出现的第一个Spring Boot Helper插件&#xff0c;点击Installed&#xff0c;下载插件。&#xff08;这里已经下载&#xff09; 二 创建Spr…

【设计模式】23种设计模式——单例模式(原理讲解+应用场景介绍+案例介绍+Java代码实现)

单例模式(Singleton) 介绍 所谓类的单例设计模式&#xff0c;就是采取一定的方法&#xff0c;保证在整个的软件系统中&#xff0c;对某个类只能存在一个对象实例&#xff0c;并且该类只提供一个取得其对象实例的方法&#xff08;静态方法&#xff09;。比如Hibernate的Sessio…

MobileNeRF在Windows上的配置

MobileNeRF于2023年提出&#xff0c;源码地址&#xff1a;https://github.com/google-research/jax3d/tree/main/jax3d/projects/mobilenerf &#xff0c;论文为&#xff1a;《MobileNeRF: Exploiting the Polygon Rasterization Pipeline for Efficient Neural Field Renderin…

Minio在Windows的部署并使用Python来操作桶

什么是Minio? MinIO 是一个开源的对象存储服务器&#xff0c;具有高可用性、高性能和可伸缩性。它兼容 Amazon S3 API&#xff0c;因此可以无缝地替代 Amazon S3 作为对象存储的解决方案。 MinIO 可以让你在自己的基础设施中搭建一个对象存储服务&#xff0c;使你能够存储和…

Linux的shell脚本

Linux的shell脚本 &#x1f607;博主简介&#xff1a;我是一名正在攻读研究生学位的人工智能专业学生&#xff0c;我可以为计算机、人工智能相关本科生和研究生提供排忧解惑的服务。如果您有任何问题或困惑&#xff0c;欢迎随时来交流哦&#xff01;&#x1f604; ✨座右铭&…

查看docker运行状态,与查看防火墙运行状态

安装docker这里不细述了&#xff0c;可以通过 docker -version 查看安装的版本&#xff0c;出现成功就表示安装是ok的 查看docker状态是否启动状态&#xff0c;出现running就表示成功 systemctl status docker 如果没有则需要输入启动命令来启动 systemctl start docker 没报错…

对于没有任何基础的初学者,云计算该怎样学习?

想学习任何一门专业技能&#xff0c;可以按下面这一套逻辑梳理&#xff01; 1&#xff09;了解基本内容 云计算这个技术是做什么的&#xff1f;适用哪些场景&#xff1f;有什么优点和缺点&#xff1f; 同时建议先找技术大纲&#xff0c;至少要学哪些技能点&#xff0c;可以网…

6. Springboot快速回顾(集成Dubbo)

Dubbo是实现远程调用的一个框架&#xff0c;阿里巴巴开源的。远程调用就是B服务器可以调用A服务器的方法。大型项目会被拆分成多个模块&#xff0c;部署在不同的服务器上。若将公共模块集中部署在一台服务器上&#xff0c;可以方便其他服务器调用。因此&#xff0c;需要Dubbo。…