嵌入式开发之串口通讯

news2024/11/29 14:53:54

    串口通信(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++);
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot会员制医疗预约服务管理信息系统

针对会员制医疗预约服务行业的管理现状&#xff0c;本会员制医疗预约服务管理信息系统主要实现以下几个目标&#xff1a; 1.系统界面简洁&#xff0c;操作简便。 2.拥有精准&#xff0c;高效的查询功能。 3.使管理人员能够及时的获得精确的报表。 4.对数据…

docker入门(Linux环境下安装Docker,Docker构建镜像)

docker入门(利用docker部署web应用) 一:什么是Docker 1.1 官方解释 Docker is the world’s leading software containerization platform。 Docker公司开发&#xff0c;开源&#xff0c;托管在github跨平台&#xff0c; 支持Windows、Macos、Linux。 1.2 抽象解释 docker…

【状态设计优化DP】ABC307 E

E - Distinct Adjacent (atcoder.jp) 题意&#xff1a; 思路&#xff1a; 组合问题&#xff0c;考虑DP或组合数 组合数不好考虑&#xff0c;我们去考虑DP 因为是个环&#xff0c;我们把环拆成一条链&#xff0c;然后加一个N1&#xff0c;颜色和起点1相同&#xff0c;在这条…

天台玻璃折叠门可实现室内外空间的无缝连接

天玻璃折叠门是指安装在天台上的可折叠开合的玻璃门&#xff0c;可用于将室外空间与室内空间进行隔离或连接。设计天台玻璃折叠门时需要注意以下几点&#xff1a; 1. 结构稳固性&#xff1a;选择坚固、稳定的材料和结构设计&#xff0c;确保门体在风力和其他外力作用下不易摇晃…

如何规范的设计数据库表

前言对于后端开发同学来说&#xff0c;访问数据库&#xff0c;是代码中必不可少的一个环节。系统中收集到用户的核心数据&#xff0c;为了安全性&#xff0c;我们一般会存储到数据库&#xff0c;比如&#xff1a;mysql&#xff0c;oracle等。后端开发的日常工作&#xff0c;需要…

制作搭建宠物商城小程序,打造便捷的宠物购物体验

随着宠物市场的不断发展&#xff0c;宠物商城小程序成为了满足宠物爱好者需求的重要工具。在现代社会&#xff0c;宠物已经成为人们生活中不可或缺的一部分。作为宠物爱好者&#xff0c;我们对于宠物食品、用品、医疗保健品等需求日益增长。而宠物商城小程序则为我们提供了一个…

python_day5_file

open()打开函数&#xff1a; f open(name,mode,encoding) name:要打开的目标文件名 mode:访问模式&#xff1a;只读r、写入w、追加a 等 encoding:编码格式&#xff0c;常为UTF-8 f open("D:\Test.txt", "r", encoding"UTF-8") print(type(f))r…

Dbeaver 显示字段备注信息

一、全局设置显示字段描述

@所有人,酷雷曼年中答卷,请查收!

2023 酷雷曼VR年中答卷 顺势而行 携手共赢 七月既至&#xff0c;年过已半。 半年来&#xff0c; 我们持续以优质的产品研发、 专业的客户服务、 不断交付的技术方案&#xff0c; 将那些关于VR的美好向往&#xff0c; 变成真实可感的确定&#xff0c; 让每一种相信&am…

Vue+element实现el-table行内编辑并校验

el-table行内编辑情况情况概要&#xff1a;之前在开发过程中对于element数据的新增&#xff0c;修改&#xff0c;删除。一般直接结合el-form使用。也就是新增的时候点新增然后出来一个弹框&#xff0c;里面嵌套一个表单&#xff0c;然后保存就好了。这次项目中要求所有的新增&a…

如何学习编写安全的PHP代码? - 易智编译EaseEditing

学习编写安全的PHP代码是保证应用程序安全的重要一环。下面是几个建议来帮助你学习编写安全的PHP代码&#xff1a; 学习安全编程原则&#xff1a; 了解常见的安全漏洞类型&#xff0c;如跨站脚本攻击&#xff08;XSS&#xff09;、SQL注入、跨站请求伪造&#xff08;CSRF&…

如何刷新对黑客的认识?

黑客一般有10种类型 1、白帽黑客 白帽黑客是指通过实施渗透测试&#xff0c;识别网络安全漏洞&#xff0c;为政府及组织工作并获得授权或认证的黑客。他们也确保保护免受恶意网络犯罪。他们在政府提供的规章制度下工作&#xff0c;这就是为什么他们被称为道德黑客或网络安全专…

springboot项目中引入本地依赖jar包,并打包到lib文件夹中

1.springboot项目中引入本地依赖jar包&#xff0c;并打包到lib文件夹中 描述&#xff1a;下载了第三方相关jar包后&#xff0c;项目中引入本地jar&#xff0c;测试环境正常&#xff0c;打包线上报错提示为找到该jar 原因&#xff1a;应该在/WEB-INF/lib/xxx.jar&#xff0c;被…

vite-plugin-mock配置报错“localEnabled”不在类型”ViteMockOptions”中

vue3vite安装vite-plugin-mock之后配置报错&#xff1a; “localEnabled”不在类型”ViteMockOptions”中。 在vite.config.ts中共添加viteMockServe({ localEnabled: command ‘serve’, }),之后报了一下错误&#xff1a; 解决方法&#xff1a;与vite-plugin-mock版本有关&a…

揭示Android黑客之道:通过逆向工程揭开HTTPS流量

抓包是指在计算机网络中&#xff0c;通过监听网络流量并捕获通信数据包的过程。在网络通信中&#xff0c;数据以数据包的形式在网络上进行传输&#xff0c;每个数据包包含了源地址、目标地址、协议信息以及实际的数据内容。 抓包可以帮助我们了解网络通信的细节&#xff0c;包…

linux开发工具:Git

文章目录 1&#xff1a;Git简介2&#xff1a;Git简明指南2.1&#xff1a;创建新仓库2.2&#xff1a;检出仓库2.3&#xff1a;工作流2.4&#xff1a;添加和提交2.5&#xff1a;推送改动2.6&#xff1a;分支2.7&#xff1a;更新与合并2.8&#xff1a;标签2.9&#xff1a;替换本地…

STM32 主从蓝牙模块配置

前言&#xff1a; 最近在调试小车的时候&#xff0c;突然想要用两个蓝牙进行单片机和电脑的交互&#xff0c;之前一直用的都是从机的蓝牙。这里因为需要双机通信&#xff0c;所以也就顺便查询了一些资料&#xff0c;了解一下主从蓝牙模块的使用&#xff0c;以及双机通信的一些使…

在Linux中传输文件文件夹的10个scp命令

scp 命令的基本语法 下面的命令将读作 copy source_file_name进入destination_folder在destination_host使用username account。 > scp source_file_name usernamedestination_host:destination_folder里面有很多参数scp你可以使用的命令。以下是可能在日常使用中使用的参数…

【最短路+状压】CF1846 G

Problem - G - Codeforces 题意&#xff1a; 思路&#xff1a; Code&#xff1a; #include <bits/stdc.h>//#define int long longusing namespace std;const int mxn1e610; const int mxv1e610; const int mxe2e310; const int mod1e97; const int Inf0x3f3f3f3f;stru…

MOSS-RLHF实现大模型和人类价值观对齐

以 ChatGPT 为代表的大型语言模型&#xff08;LLM&#xff09;在各项任务上的高效表现彰显了其广阔发展前景。然而&#xff0c;大模型回复与人类价值偏好经常存在不一致问题。 如何让大模型更好的与人类价值观对齐&#xff0c;理解语言背后的含义&#xff0c;生成更具 “人情味…