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.
Revision 0:fe18ab08e05d, committed 2011-11-21
- Comitter:
- elmicro
- Date:
- Mon Nov 21 10:29:41 2011 +0000
- Commit message:
- Initial Revision
Changed in this revision
main.cpp | Show annotated file Show diff for this revision Revisions of this file |
mbed.bld | Show annotated file Show diff for this revision Revisions of this file |
diff -r 000000000000 -r fe18ab08e05d main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Nov 21 10:29:41 2011 +0000 @@ -0,0 +1,210 @@ +#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 +};
diff -r 000000000000 -r fe18ab08e05d mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon Nov 21 10:29:41 2011 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/63bcd7ba4912