Example software showing how to use TestBed\'s RS485 feature with mbed\'s hardware UART1. Currently only the setup routine and a \"SendText\" routine are implemented. Can easily be used to develop receiving messages and invoking IRQ handling.

Dependencies:   mbed

main.cpp

Committer:
elmicro
Date:
2011-11-21
Revision:
0:fe18ab08e05d

File content as of revision 0:fe18ab08e05d:

#include "mbed.h"

DigitalOut myled(LED1);
Serial pc(USBTX, USBRX);

void RS485_Init(void);
void RS485_SendChar(unsigned char data);
void RS485_SendText(char *pString);

extern const unsigned int BRLookUp[][3];


void RS485_Init(unsigned int iBR, unsigned int iPCLK)
{
/* ===================================================================
    routine:    RS485_Init
    purpose:    Sets all required parameters for UART1 as RS485
                using following signals:
             
                mbed | LPC1768 | function
                -----+---------+---------
                P21  | P2[5]   | DTR - '1' for TX
                P25  | P2[1]   | RX
                P26  | P2[0]   | TX
    
    parameters: <iBR>        Desired baudrate
                <iPCLK>      Current peripheral clock in Hz
                             (mbed standard is 24000000)
    date:       2011-11-21
    author:     Stefan Guenther | Elektronikladen
    co-author:    
    notes:      Calculation of baudrate based on NXP's algorithm in 
                the LPC17xx manual, Fig. 50 on page 334.

                                        PCLK
                baud = ---------------------------------------
                       16*(256*DLM+DLL)*(1+(DivAddVal/MulVal))
  -------------------------------------------------------------------*/

    unsigned int iDL, iFR, iOffset, x;
    unsigned char cDLM, cDLL, cMULVAL, cDIVADDVAL;    
    
    iDL = iPCLK/(16*iBR);    
    
    if(iDL*16*iBR==iPCLK)           //iDL is an even number    
    {        
        cDIVADDVAL = 0;
        cMULVAL    = 1;
        cDLM       = 0;
        cDLL       = 0;
    } else                          //iDL is an odd number
    {
        iOffset=0;
        do                          //change iFR until it's value is within 1.1 .. 1.9 range
        {
            iOffset+=100;      
            iFR = 1005+iOffset;
            iDL=iPCLK/(0.016*iBR*iFR);
            iFR=iPCLK/(0.016*iBR*iDL);            
        } while((iFR>1900) || (iFR<1100));        
        
        //iFR is now correctly calculated!
        
        cDLM        = (iDL>>8);
        cDLL        = iDL;              
        x = 0;            
        
        do                          //use lookup table to find values for DIVADDVAL and MULVAL
        {
            x++;
        } while(BRLookUp[x][0]<iFR);
            
        cDIVADDVAL = BRLookUp[x][1];
        cMULVAL    = BRLookUp[x][2];            
    }
    //Now, all necessary values are calculated for the desired baudrate according to
    //the current PCLK frequency. These values (cDLM, cDLL, cDIVADDVAL and cMULVAL)
    //now are used to configure UART1 for RS485 communication.
    
    LPC_PINCON->PINSEL4    |= 0x80A;        //RXD1, TXD1, DTR1    
    LPC_SC->PCONP          |= (1<<4);       //Power on UART1    
    //LPC_SC->PCLKSEL                       //clock default is /4, we keep this
    LPC_UART1->LCR          = 0x83;         //sets DLAB; 8bit,1stopbit                
    LPC_UART1->DLL          = cDLL;         //UART Divisor Latch LSB
    LPC_UART1->FDR          = cDIVADDVAL;   //DivAddVal
    LPC_UART1->FDR         |= (cMULVAL<<4); //MulVal     
    LPC_UART1->DLM          = cDLM;         //UART Divisor Latch MSB 
    LPC_UART1->LCR         &=~(1<<7);       //clears DLAB                 
    LPC_UART1->RS485CTRL   &=~(1<<1);       //Receiver enabled 
    LPC_UART1->RS485CTRL   &=~(1<<2);       //AAD disabled 
    LPC_UART1->RS485CTRL   |= (1<<3);       //DTR used for direction control 
    LPC_UART1->RS485CTRL   |= (1<<4);       //direction control enabled 
    LPC_UART1->RS485CTRL   |= (1<<5);       //DTR=1 when transmitting
    //LPC_UART1->IER |= 1;                  //RBR IRQ enable 
    //LPC_UART1->TER &= ~0x80;              //!TXEN - disable transmitter, enable receiver
    //NVIC_EnableIRQ(UART1_IRQn);           //set up CM3 NVIC to process UART1 IRQs
    RS485_SendText("\nRS485 communication port setup succesful!\n\n");
}

void RS485_SendChar(unsigned char data)
{
    LPC_UART1->TER |= 0x80;                 //enable transmitter
    while (!(LPC_UART1->LSR & 0x20));       //wait for UART1 to be ready - !!could lock up system!!
    LPC_UART1->THR=data;                    //write to THR register triggers transmission
}

void RS485_SendText(char *pString) 
{
    char *pText;                            //initialize pointer
    pText=(char *)pString;                  //set pointer to first character
    while(*pText!=0x00) {                   //0x00 marks end of text string
        RS485_SendChar(*pText);             //send each character seperately
        *pText++;                           //move pointer to next character
    }     
}

int main() {
    RS485_Init(115200, 24000000);           //setup RS485 communication with 115200baud
    
    while(1) {
        myled = 1;
        wait(0.2);
        myled = 0;
        wait(0.2);
    }
}


/* ===================================================================    
    table:      BRLookUp
    purpose:    provides settings for UART configuration (baudrate)    
    date:       2011-02-04
    author:     Stefan Guenther | Elektronikladen    
    source:     NXP's user manual for the LPC17xx (UM10360), Page 335
  -------------------------------------------------------------------*/

const unsigned int BRLookUp[72][3]    =
{
    1000,     0,  1,
    1067,    1,    15,
    1071,    1,    14,
    1077,    1,    13,
    1083,    1,    12,
    1091,    1,    11,
    1100,    1,    9,
    1125,    1,    8,
    1133,    2,    15,
    1143,    1,    7,
    1154,    2,    13,
    1167,    1,    6,
    1182,    2,    11,
    1200,    1,    5,
    1214,    3,    14,
    1222,    2,    9,
    1231,    3,    13,
    1250,    1,    4,
    1267,    4,    15,
    1273,    3,    11,
    1286,    2,    7,
    1300,    3,    10,
    1308,    4,    13,
    1333,    1,    3,
    1357,    5,    14,
    1364,    4,    11,
    1375,    3,    8,
    1385,    5,    13,
    1400,    2,    5,
    1417,    5,    12,
    1429,    3,    7,
    1444,    4,    9,    
    1455,    5,    11,
    1462,    6,    13,
    1467,    7,    15,
    1500,    1,    2,    
    1533,    8,    15,
    1538,    7,    13,
    1545,    6,    11,
    1556,    5,    9,
    1571,    4,    7,
    1583,    7,    12,
    1600,    3,    5,
    1615,    8,    13,
    1625,    5,    8,
    1636,    7,    11,
    1643,    9,    14,
    1667,    2,    3,
    1692,    9,    13,
    1700,    7,    10,
    1714,    5,    7,
    1727,    8,    11,
    1733,    11,    15,
    1750,    3,    4,
    1769,    10,    13,
    1778,    7,    9,
    1786,    11,    14,
    1800,    4,    5,
    1818,    9,    11,
    1833,    5,    6,
    1846,    11,    13,
    1857,    6,    7,
    1867,    13,    15,
    1875,    7,    8,
    1889,    8,    9,
    1900,    9,  10,
    1909,    10,    11,
    1917,    11,    12,
    1923,    12,    13,
    1929,    13,    14,
    1933,    14,    15
};