Siwei Xu
/
uart_baudrate_test
UART baud rate test for LPC11U35
Fork of UranusTest by
main.cpp
- Committer:
- swxu
- Date:
- 2017-05-19
- Revision:
- 3:98e614fc55c5
- Parent:
- 2:626c243adc03
File content as of revision 3:98e614fc55c5:
#include "mbed.h" #include "USBSerial.h" #include <time.h> /** * Python script for high baud rate test on Host PC * * @code * #!/usr/bin/env python * * import os * import sys * import serial * * PORT = '/dev/ttyUSB0' * BAUD = 9600 * * def main(args): * port = len(args) > 1 and args[1] or PORT * baud = len(args) > 2 and args[2] or BAUD * count = 0 * with serial.Serial(port, baud) as s: * while True: * b = s.read() * count += 1 * sys.stdout.write('%x ' % b) * sys.stdout.flush() * if __name__ == '__main__': * main(sys.argv) * @endcode */ DigitalOut led0(P0_20); DigitalOut led1(P0_21); DigitalOut led2(P0_11); USBSerial vcom; // Virtual serial port over USB Serial uart(P0_19, P0_18); void serial_baud(int baudrate); void uart_send_test() { for (int i = 0; i < 20; i++) { uart.printf("%s: %d %d\r\n", __FUNCTION__, clock(), i); wait(0.1); } } void try_baudrate(int baudrate) { vcom.printf("try UART baudrate: %d...\r\n", baudrate); serial_baud(baudrate); vcom.printf("press button to start\r\n"); DigitalIn btn(P0_1, PullUp); while (btn.read()) wait(0.010); uart.printf("UART under baudrate %d is OK!\r\n", baudrate); uart_send_test(); vcom.printf("done try UART baudrate: %d\r\n", baudrate); } int main(void) { uart.format(); uart.printf("BUILD: %s %s\r\n", __DATE__, __TIME__); uart.printf("System core clock: %d\r\n", SystemCoreClock); int timeout = 10; while (timeout--) { led2 = !led2; wait(1); } for (int i = 1; i < 9; i++) { try_baudrate(115200 * i); } while(1) { // led2 = button.read(); clock_t ts = clock(); uart.printf("Hello UART! %d\r\n", ts); vcom.printf("I am a virtual vcom port %d\r\n", ts); led0 = !led0; wait(1); led1 = !led1; wait(1); // led2 = !led2; wait(1); } } void serial_baud(int baudrate) { LPC_SYSCON->UARTCLKDIV = 0x1; uint32_t PCLK = SystemCoreClock; // First we check to see if the basic divide with no DivAddVal/MulVal // ratio gives us an integer result. If it does, we set DivAddVal = 0, // MulVal = 1. Otherwise, we search the valid ratio value range to find // the closest match. This could be more elegant, using search methods // and/or lookup tables, but the brute force method is not that much // slower, and is more maintainable. uint16_t DL = PCLK / (16 * baudrate); uint8_t DivAddVal = 0; uint8_t MulVal = 1; int hit = 0; uint16_t dlv; uint8_t mv, dav; if ((PCLK % (16 * baudrate)) != 0) { // Checking for zero remainder int err_best = baudrate, b, a; for (mv = 1; mv < 16 && !hit; mv++) { for (dav = 0; dav < mv; dav++) { // baudrate = PCLK / (16 * dlv * (1 + (DivAdd / Mul)) // solving for dlv, we get dlv = mul * PCLK / (16 * baudrate * (divadd + mul)) // mul has 4 bits, PCLK has 27 so we have 1 bit headroom which can be used for rounding // for many values of mul and PCLK we have 2 or more bits of headroom which can be used to improve precision // note: X / 32 doesn't round correctly. Instead, we use ((X / 16) + 1) / 2 for correct rounding if ((mv * PCLK * 2) & 0x80000000) // 1 bit headroom dlv = ((((2 * mv * PCLK) / (baudrate * (dav + mv))) / 16) + 1) / 2; else // 2 bits headroom, use more precision dlv = ((((4 * mv * PCLK) / (baudrate * (dav + mv))) / 32) + 1) / 2; // datasheet says if DLL==DLM==0, then 1 is used instead since divide by zero is ungood if (dlv == 0) dlv = 1; // datasheet says if dav > 0 then DL must be >= 2 if ((dav > 0) && (dlv < 2)) dlv = 2; // integer rearrangement of the baudrate equation (with rounding) a = b = ((PCLK * mv / (dlv * (dav + mv) * 8)) + 1) / 2; // check to see how we went b = abs(b - baudrate); if (b < err_best) { err_best = b; float er = b * 100.0 / baudrate; vcom.printf("b: %d, er: %f, err_best: %d\r\n", a, er, err_best); DL = dlv; MulVal = mv; DivAddVal = dav; if (b == baudrate) { hit = 1; break; } } } } } // set LCR[DLAB] to enable writing to divider registers LPC_USART->LCR |= (1 << 7); // set divider values LPC_USART->DLM = (DL >> 8) & 0xFF; LPC_USART->DLL = (DL >> 0) & 0xFF; LPC_USART->FDR = (uint32_t) DivAddVal << 0 | (uint32_t) MulVal << 4; // clear LCR[DLAB] LPC_USART->LCR &= ~(1 << 7); vcom.printf("PCLK: %d\r\n", SystemCoreClock); vcom.printf("DL: %d\r\n", DL); vcom.printf("DivAddVal: %d\r\n", DivAddVal); vcom.printf("MulVal: %d\r\n", MulVal); vcom.printf("FDR: %d\r\n", LPC_USART->FDR); }