b. 임베디드/dsPIC33CK128MP506

[dsPIC33CK] UART 사용 예제

로봇쟁이 2021. 10. 1. 16:03

개인적으로 UART는 좀 많이 복잡했습니다.

뭔놈의 레지스터가 이리 많은지... 아직도 100% 이해는 못하고 있습니다만, 그래도 동작된 기념으로 초기화 방법에 대해서 작성해 놓으려 합니다.

 

먼저 초기화 코드입니다.

void uartInit_dsPIC33CK(void)
{
	_U1RXIE = 0;
    _U1RXIF = 0;
    _U1TXIE = 0;
    _U1TXIF = 0;

    /* Initialize UARTx Configuration Register */
    U1MODE = 0;
    /*  UART Enable bit
        1 = UART is ready to transmit and receive
        0 = UART state machine, FIFO Buffer Pointers and counters are reset */
    U1MODEbits.UARTEN = 0;
    /*  UART Stop in Idle Mode bit
        1 = Discontinues module operation when device enters Idle mode
        0 = Continues module operation in Idle mode */
    U1MODEbits.USIDL = 0;
    /*  Wake-up Enable bit
        1 = Module will continue to sample the RX pin 
        0 = RX pin is not monitored nor rising edge detected */
    U1MODEbits.WAKE  = 0;
    /*  Receive Break Interrupt Mode bit
        1 = RXBKIF flag when a minimum of 23 (DMX)/11 (asynchronous or LIN/J2602
            low bit periods are detected
        0 = RXBKIF flag when the Break makes a low-to-high transition after 
            being low for at least 23/11 bit periods*/
    U1MODEbits.RXBIMD = 0;
    /*  Send Break Software Override bit - Overrides the TX Data Line:
        1 = Makes the TX line active ('0' when UTXINV = 0, '1'when UTXINV = 1)
        0 = TX line is driven by the shifter */
    U1MODEbits.BRKOVR = 0;
    /*  UART Transmit Break bit
        1 = Sends Sync Break on next transmission;
        0 = Sync Break transmission is disabled or has completed */
    U1MODEbits.UTXBRK = 0;
    /*  High Baud Rate Select bit
        1 = High Speed: Baud rate is baud clock/4
        0 = Low Speed: Baud rate is baud clock/16 */
    U1MODEbits.BRGH = 0;
    /*  Auto-Baud Detect Enable bit (read-only when MOD<3:0> = 1xxx)
        1 = Enables baud rate measurement on the next character ? 
            requires reception of a Sync field (55h);
        0 = Baud rate measurement is disabled or has completed */
    U1MODEbits.ABAUD = 0;
    /*  UART Transmit Enable bit
        1 = Transmit enabled ? except during Auto-Baud Detection
        0 = Transmit disabled ? all transmit counters, pointers and 
            state machines are reset; TX buffer is not flushed, status bits 
            are not reset */
    U1MODEbits.UTXEN = 1;
    /*  UART Receive Enable bit
        1 = Receive enabled ? except during Auto-Baud Detection
        0 = Receive disabled ? all receive counters, pointers and state machines
            are reset; RX buffer is not flushed, status bits are not reset */
    U1MODEbits.URXEN = 1;
    /*  UART Mode bits
        1111 = Smart card 
        1110 = IrDA?2)
        1100 = LIN Master/Slave
        1011 = LIN Slave-Only
        1010 = DMX(2)
        1001 = DALI gear(2)
        1000 = DALI device(2)
        0100 = Asynchronous 9-bit UART with address detect, address
        0011 = Asynchronous 8-bit UART without address detect,even parity 
        0010 = Asynchronous 8-bit UART without address detect, odd parity
        0001 = Asynchronous 7-bit UART
        0000 = Asynchronous 8-bit UART */
    U1MODEbits.MOD = 0;

    /*  Initialize UARTx Configuration Register High */
    U1MODEH =  0;
    /*  Run During Sleep Enable bit
        1 = UART BRG clock runs during Sleep
        0 = UART BRG clock is turned off during Sleep */
    U1MODEHbits.SLPEN = 0;
    /*  UART Running Status bit
        1 = UART clock request is active 
        0 = UART clock request is not active */
    U1MODEHbits.ACTIVE = 0;

    /*  Baud Clock Source Selection bits 
        0b11 = 4x FCY,0b10 = 2x FCY ,0b01 = FCY ,0b00 = FCY */
    U1MODEHbits.BCLKSEL = 0;
    /*  UART Half-Duplex Selection Mode bit
        1 = Half-Duplex mode: UxTX is driven high when transmitting and 
            low when TX is Idle
        0 = Full-Duplex mode: UxTX is driven high at all times 
            when both UARTEN and UTXEN are set */
    U1MODEHbits.HALFDPLX = 0;
    /*  Run During Overflow Condition Mode bit
        1 = When an Overflow Error (OERR) condition is detected, the RX shifter
             continues to run so as to remain synchronized with incoming RX data;
             data is not transferred to UxRXREG when it is full 
        0 = When an Overflow Error (OERR) condition is detected, 
            the RX shifter stops accepting new data (Legacy mode) */
    U1MODEHbits.RUNOVF = 0;
    /*  UART Receive Polarity bit
        1 = Inverts RX polarity; Idle state is low
        0 = Input is not inverted; Idle state is high */
    U1MODEHbits.URXINV = 0;
    /*  Number of Stop Bits Selection bits
        11 = 2 Stop bits sent, 1 checked at receive
        10 = 2 Stop bits sent, 2 checked at receive
        01 = 1.5 Stop bits sent, 1.5 checked at receive
        00 = 1 Stop bit sent, 1 checked at receive */
    U1MODEHbits.STSEL = 0;
    /*  Enable Legacy Checksum (C0) Transmit and Receive bit
        1 = Checksum Mode 1 (enhanced LIN checksum in LIN mode;)
        0 = Checksum Mode 0 (legacy LIN checksum in LIN mode;
            not used in all other modes)*/
    U1MODEHbits.C0EN = 0;
    /*  UART Transmit Polarity bit
        1 = Inverts TX polarity; TX is low in Idle state
        0 = Output data is not inverted; TX output is high in Idle state */
    U1MODEHbits.UTXINV = 0;
    /*  Flow Control Enable bits (Only valid when MOD = 0xxx)
        10 = RTS-CTS (For TX-side) / DCD-DTR (For RX-side) Hardware Flow Control
        01 = XON/XOFF Software Flow Control
        00 = Flow Control Off */
    U1MODEHbits.FLO = 0;

    /*  Initialize UARTx Status Register */
    U1STA = 0;
    /*  Transmit Shifter Empty Interrupt Enable bit
        1 = Interrupt is enabled, 0 = Interrupt is disabled */
    U1STAbits.TXMTIE = 0;
    /*  Parity Error Interrupt Enable bit
        1 = Interrupt is enabled , 0 = Interrupt is disabled */
    U1STAbits.PERIE = 0;
    /*  Auto-Baud Rate Acquisition Interrupt Enable bit
        1 = Interrupt is enabled, 0 = Interrupt is disabled */
    U1STAbits.ABDOVE = 0;
    /*  Checksum Error Interrupt Enable bit
        1 = Interrupt is enabled , 0 = Interrupt is disabled */
    U1STAbits.CERIE = 0;
    /*  Framing Error Interrupt Enable bit
        1 = Interrupt is enabled, 0 = Interrupt is disabled */
    U1STAbits.FERIE = 0;
    /*  Receive Break Interrupt Enable bit
        1 = Interrupt is enabled, 0 = Interrupt is disabled */
    U1STAbits.RXBKIE = 0;
    /*  Receive Buffer Overflow Interrupt Enable bit
        1 = Interrupt is enabled , 0 = Interrupt is disabled */
    U1STAbits.OERIE = 0;
    /*  Transmit Collision Interrupt Enable bit
        1 = Interrupt is enabled, 0 = Interrupt is disabled */
    U1STAbits.TXCIE = 0;
    /*  Transmit Shifter Empty Interrupt Flag bit
        1 = Transmit Shift Register (TSR) is empty 
        0 = Transmit Shift Register is not empty */
    U1STAbits.TRMT = 0;
    /*  Parity Error/Address Received/Forward Frame Interrupt Flag bit
        LIN and Parity Modes:
        1 = Parity error detected, 0 = No parity error detected
        DALI Device Mode:
        1 = Forward frame data, 0 = Back frame data
        Address Mode:
        1 = Address received, 0 = No address detected
        All Other Modes: Not used. */
    U1STAbits.PERR = 0;
    /*  Auto-Baud Rate Acquisition Interrupt Flag bit 
        1 = BRG rolled over during the auto-baud rate acquisition sequence
        0 = BRG has not rolled over during the auto-baud rate acquisition 
            sequence*/
    U1STAbits.ABDOVF = 0;
    /*  Checksum Error Interrupt Flag bit 
        1 = Checksum error , 0 = No checksum error*/
    U1STAbits.CERIF = 0;
    /*  Framing Error Interrupt Flag bit
        1 = Framing Error, 0 = No framing error */
    U1STAbits.FERR = 0;
    /*  Receive Break Interrupt Flag bit 
        1 = A Break was received, 0 = No Break was detected */
    U1STAbits.RXBKIF = 0;
    /*  Receive Buffer Overflow Interrupt Flag bit (must be cleared by software)
        1 = Receive buffer has overflowed
        0 = Receive buffer has not overflowed */
    U1STAbits.OERR = 0;
    /*  Transmit Collision Interrupt Flag bit (must be cleared by software)
        1 = Transmitted word is not equal to the received word
        0 = Transmitted word is equal to the received word */
    U1STAbits.TXCIF = 0;

    /*  Initialize UARTx Status High Register */
    U1STAH = 0;
    /*  UART Transmit Interrupt Select bits
        111 = Sets TX interrupt when there is 1 empty slot left in the buffer
        ....
        000 = Sets TX interrupt when there are 8 empty slots in the buffer;
              TX buffer is empty */
    U1STAHbits.UTXISEL = 7;
    /*  UART Receive Interrupt Select bits
        111 = Triggers receive interrupt when there are 8 words in the buffer;
              RX buffer is full
        ...
        000 = Triggers RX interrupt when there is 1 word or more in the buffer*/
    U1STAHbits.URXISEL = 0;
    /*  TX Write Transmit Error Status bit (must be cleared by software)
        LIN and Parity Modes:
        1 = A new byte was written when the buffer was full or when P2<8:0> = 0 
        0 = No error
        Address Detect Mode:
        1 = A new byte was written when the buffer was full or 
            to P1<8:0> when P1x was full 
        0 = No error
        Other Modes:
        1 = A new byte was written when the buffer was full 
        0 = No error */
    U1STAHbits.TXWRE = 0;
    /*  Stop Bit Detection Mode bit
        1 = Triggers RXIF at the end of the last Stop bit
        0 = Triggers RXIF in the middle of the first (
            or second, depending on the STSEL<1:0> setting) Stop bit */
    U1STAHbits.STPMD = 0;
    /*  UART TX Buffer Empty Status bit
        1 = Transmit buffer is empty; writing ?1? when UTXEN = 0 will reset 
            the TX FIFO Pointers and counters
        0 = Transmit buffer is not empty */
    U1STAHbits.UTXBE = 1;
    /*  UART TX Buffer Full Status bit
        1 = Transmit buffer is full
        0 = Transmit buffer is not full */
    U1STAHbits.UTXBF = 0;
    /*  Receive Idle bit
        1 = UART RX line is in the Idle state
        0 = UART RX line is receiving something */
    U1STAHbits.RIDLE = 0;
    /*  UART in XON Mode bit
        Only valid when FLO<1:0> control bits are set to XON/XOFF mode.
        1 = UART has received XON
        0 = UART has not received XON or XOFF was received */
    U1STAHbits.XON = 0;
    /*  UART RX Buffer Empty Status bit
        1 = Receive buffer is empty; writing ?1? when URXEN = 0 will reset 
            the RX FIFO Pointers and counters
        0 = Receive buffer is not empty */
    U1STAHbits.URXBE = 1;
    /*  UART RX Buffer Full Status bit
        1 = Receive buffer is full
        0 = Receive buffer is not full */
    U1STAHbits.URXBF = 0;

    /*  Initialize UARTx Baud Rate Register bits<15:0> =  BRG<15:0>  */
    U1BRG =  0;

    /*  Initialize UARTx Baud Rate High Register bits<3:0> =  BRG<19:16> */
    U1BRGH = 0;

    /*  Initialize UARTx Receive Buffer Register */
    U1RXREG = 0;
    /*  Received Character Data bits <7-0>*/
    U1RXREGbits.RXREG = 0;

    /*  UARTx Transmit Buffer Register */
    U1TXREG =  0;
    /*  Last Byte Indicator for Smart Card Support bit */
    U1TXREGbits.LAST = 0;
    /*  Transmitted Character Data bits <7-0>
        If the buffer is full, further writes to the buffer are ignored. */
    U1TXREGbits.TXREG = 0;

    /*  Initialize UARTx Timing Parameter 1 Register */
    U1P1 = 0;
    /*  Initialize UARTx Timing Parameter 2 Register */
    U1P2 = 0;
    /*  Initialize UARTx Timing Parameter 2 Register */
    U1P3 = 0;
    /*  Initialize UARTx Timing Parameter 3 Register High */
    U1P3H = 0;
    /*  Initialize UARTx Transmit Checksum Register */
    U1TXCHK = 0;
    /*  Initialize UARTx Receive Checksum Register */
    U1RXCHK = 0;
    /*  Initialize UARTx Smart Card Configuration High Register */
    U1SCCON = 0;
    /*  Initialize UxSCINT: UARTx Smart Card Interrupt Register */
    U1SCINT =  0;

    /*  Initialize UARTx Interrupt Register */
    U1INT = 0;
    /*  Wake-up Interrupt Flag bit
        1 = Sets when WAKE = 1 and RX makes a 1-to-0 transition; t
        0 = WAKE is not enabled or WAKE is enabled, 
            but no wake-up event has occurred */
    U1INTbits.WUIF = 0;
    /*  Auto-Baud Completed Interrupt Flag bit
        1 = Sets when ABD sequence makes the final 1-to-0 transition; 
        0 = ABAUD is not enabled or ABAUD is enabled 
            but auto-baud has not completed */
    U1INTbits.ABDIF = 0;
    /*  Auto-Baud Completed Interrupt Enable Flag bit
        1 = Allows ABDIF to set an event interrupt
        0 = ABDIF does not set an event interrupt */
    U1INTbits.ABDIE = 0;
    /*  UART Running Status bit
        1 = UART clock request is active 
        0 = UART clock request is not active */
    U1MODEHbits.ACTIVE = 0;
    /*  UART Enable bit
        1 = UART is ready to transmit and receive
        0 = UART state machine, FIFO Buffer Pointers and counters are reset */
    U1MODEbits.UARTEN = 0;
    
    // Load a value into Baud Rate Generator.  Example is for 9600.
    // See section 19.3.1 of datasheet.
    //  U1BRG = (Fcy / (16 * BaudRate)) - 1
    //  U1BRG = (3685000 / (16 * 9600)) - 1
    //  U1BRG = 23.8908854 //Round to 23
    U1BRG = (100000000 / 16 / baud) - 1;

	U1MODEbits.BRGH = 0;
	U1MODEbits.UARTEN = 1;

	IFS0bits.U1RXIF = 0;    // Clear the Recieve Interrupt Flag
	IEC0bits.U1RXIE = 1;    // Enable Recieve Interrupts

	_U1RXR = 78;
	_RP79R = 0b000001;
//  RPINR18bits.U1RXR = 78; // RP79 as U1RX        
//  RPOR23bits.RP78R  = 1;  // RP78 as U1TX
}

 

UART 레지스터의 대부분을 초기화 하고 사용한 듯 싶은 코드인데 많이 복잡하네요.

baudrate 부분은 계산식임으로 확인하면 되고 dsPIC는 대부분의 핀이 uart를 사용할수 있도록 되어 있는듯 보이네요.

일단 rx는 인터럽트를 사용하였고 tx는 polling으로 진행하였습니다.

 

해당 부분 샘플 코드입니다.

int32_t uartWrite(uint8_t *p_data, uint32_t length)
{
    int32_t ret = 0;
    uint32_t i = 0;

    while(i<length)
    {
    	U1TXREGbits.TXREG = p_data[i++];          
    }
    ret = i;
    return ret;
}


void __attribute__ ( (interrupt, no_auto_psv) ) _U1RXInterrupt( void )
{
    uartRxHandler(_DEF_UART1, U1RXREG);
    IFS0bits.U1RXIF = 0;
}

 

실제 동작 부분은 별도로 작성하셔야 합니다.

제가 구동하도록 한 부분이 Queue를 사용하여 작성되어짐에 따라 조금 복잡하여 해당 부분은 생략하겠습니다.

 

이상입니다. ^^

 

 

반응형