UART baud rate test for LPC11U35

Dependencies:   USBDevice mbed

Fork of UranusTest by Siwei Xu

Committer:
swxu
Date:
Fri May 19 17:48:11 2017 +0000
Revision:
3:98e614fc55c5
Parent:
2:626c243adc03
add doc string

Who changed what in which revision?

UserRevisionLine numberNew contents of line
swxu 0:ae1f7d2c4fbc 1 #include "mbed.h"
swxu 0:ae1f7d2c4fbc 2 #include "USBSerial.h"
swxu 0:ae1f7d2c4fbc 3
swxu 1:7d1fb66613d9 4 #include <time.h>
swxu 1:7d1fb66613d9 5
swxu 3:98e614fc55c5 6 /**
swxu 3:98e614fc55c5 7 * Python script for high baud rate test on Host PC
swxu 3:98e614fc55c5 8 *
swxu 3:98e614fc55c5 9 * @code
swxu 3:98e614fc55c5 10 * #!/usr/bin/env python
swxu 3:98e614fc55c5 11 *
swxu 3:98e614fc55c5 12 * import os
swxu 3:98e614fc55c5 13 * import sys
swxu 3:98e614fc55c5 14 * import serial
swxu 3:98e614fc55c5 15 *
swxu 3:98e614fc55c5 16 * PORT = '/dev/ttyUSB0'
swxu 3:98e614fc55c5 17 * BAUD = 9600
swxu 3:98e614fc55c5 18 *
swxu 3:98e614fc55c5 19 * def main(args):
swxu 3:98e614fc55c5 20 * port = len(args) > 1 and args[1] or PORT
swxu 3:98e614fc55c5 21 * baud = len(args) > 2 and args[2] or BAUD
swxu 3:98e614fc55c5 22 * count = 0
swxu 3:98e614fc55c5 23 * with serial.Serial(port, baud) as s:
swxu 3:98e614fc55c5 24 * while True:
swxu 3:98e614fc55c5 25 * b = s.read()
swxu 3:98e614fc55c5 26 * count += 1
swxu 3:98e614fc55c5 27 * sys.stdout.write('%x ' % b)
swxu 3:98e614fc55c5 28 * sys.stdout.flush()
swxu 3:98e614fc55c5 29 * if __name__ == '__main__':
swxu 3:98e614fc55c5 30 * main(sys.argv)
swxu 3:98e614fc55c5 31 * @endcode
swxu 3:98e614fc55c5 32 */
swxu 3:98e614fc55c5 33
swxu 1:7d1fb66613d9 34 DigitalOut led0(P0_20);
swxu 1:7d1fb66613d9 35 DigitalOut led1(P0_21);
swxu 1:7d1fb66613d9 36 DigitalOut led2(P0_11);
swxu 1:7d1fb66613d9 37
swxu 2:626c243adc03 38 USBSerial vcom; // Virtual serial port over USB
swxu 2:626c243adc03 39 Serial uart(P0_19, P0_18);
swxu 2:626c243adc03 40
swxu 2:626c243adc03 41 void serial_baud(int baudrate);
swxu 2:626c243adc03 42
swxu 2:626c243adc03 43 void uart_send_test()
swxu 1:7d1fb66613d9 44 {
swxu 2:626c243adc03 45 for (int i = 0; i < 20; i++) {
swxu 2:626c243adc03 46 uart.printf("%s: %d %d\r\n", __FUNCTION__, clock(), i);
swxu 2:626c243adc03 47 wait(0.1);
swxu 1:7d1fb66613d9 48 }
swxu 1:7d1fb66613d9 49 }
swxu 1:7d1fb66613d9 50
swxu 2:626c243adc03 51 void try_baudrate(int baudrate)
swxu 2:626c243adc03 52 {
swxu 2:626c243adc03 53 vcom.printf("try UART baudrate: %d...\r\n", baudrate);
swxu 1:7d1fb66613d9 54
swxu 2:626c243adc03 55 serial_baud(baudrate);
swxu 1:7d1fb66613d9 56
swxu 2:626c243adc03 57 vcom.printf("press button to start\r\n");
swxu 1:7d1fb66613d9 58 DigitalIn btn(P0_1, PullUp);
swxu 2:626c243adc03 59 while (btn.read()) wait(0.010);
swxu 1:7d1fb66613d9 60
swxu 2:626c243adc03 61 uart.printf("UART under baudrate %d is OK!\r\n", baudrate);
swxu 2:626c243adc03 62 uart_send_test();
swxu 2:626c243adc03 63
swxu 2:626c243adc03 64 vcom.printf("done try UART baudrate: %d\r\n", baudrate);
swxu 1:7d1fb66613d9 65 }
swxu 0:ae1f7d2c4fbc 66
swxu 0:ae1f7d2c4fbc 67 int main(void) {
swxu 0:ae1f7d2c4fbc 68 uart.format();
swxu 0:ae1f7d2c4fbc 69
swxu 1:7d1fb66613d9 70 uart.printf("BUILD: %s %s\r\n", __DATE__, __TIME__);
swxu 1:7d1fb66613d9 71 uart.printf("System core clock: %d\r\n", SystemCoreClock);
swxu 2:626c243adc03 72
swxu 2:626c243adc03 73 int timeout = 10;
swxu 2:626c243adc03 74 while (timeout--) {
swxu 2:626c243adc03 75 led2 = !led2;
swxu 2:626c243adc03 76 wait(1);
swxu 2:626c243adc03 77 }
swxu 1:7d1fb66613d9 78
swxu 2:626c243adc03 79 for (int i = 1; i < 9; i++) {
swxu 2:626c243adc03 80 try_baudrate(115200 * i);
swxu 2:626c243adc03 81 }
swxu 1:7d1fb66613d9 82
swxu 0:ae1f7d2c4fbc 83 while(1) {
swxu 1:7d1fb66613d9 84 // led2 = button.read();
swxu 0:ae1f7d2c4fbc 85 clock_t ts = clock();
swxu 0:ae1f7d2c4fbc 86
swxu 0:ae1f7d2c4fbc 87 uart.printf("Hello UART! %d\r\n", ts);
swxu 1:7d1fb66613d9 88 vcom.printf("I am a virtual vcom port %d\r\n", ts);
swxu 1:7d1fb66613d9 89
swxu 1:7d1fb66613d9 90 led0 = !led0; wait(1);
swxu 1:7d1fb66613d9 91 led1 = !led1; wait(1);
swxu 1:7d1fb66613d9 92 // led2 = !led2; wait(1);
swxu 0:ae1f7d2c4fbc 93 }
swxu 1:7d1fb66613d9 94 }
swxu 2:626c243adc03 95
swxu 2:626c243adc03 96
swxu 2:626c243adc03 97
swxu 2:626c243adc03 98 void serial_baud(int baudrate) {
swxu 2:626c243adc03 99 LPC_SYSCON->UARTCLKDIV = 0x1;
swxu 2:626c243adc03 100 uint32_t PCLK = SystemCoreClock;
swxu 2:626c243adc03 101 // First we check to see if the basic divide with no DivAddVal/MulVal
swxu 2:626c243adc03 102 // ratio gives us an integer result. If it does, we set DivAddVal = 0,
swxu 2:626c243adc03 103 // MulVal = 1. Otherwise, we search the valid ratio value range to find
swxu 2:626c243adc03 104 // the closest match. This could be more elegant, using search methods
swxu 2:626c243adc03 105 // and/or lookup tables, but the brute force method is not that much
swxu 2:626c243adc03 106 // slower, and is more maintainable.
swxu 2:626c243adc03 107 uint16_t DL = PCLK / (16 * baudrate);
swxu 2:626c243adc03 108
swxu 2:626c243adc03 109 uint8_t DivAddVal = 0;
swxu 2:626c243adc03 110 uint8_t MulVal = 1;
swxu 2:626c243adc03 111 int hit = 0;
swxu 2:626c243adc03 112 uint16_t dlv;
swxu 2:626c243adc03 113 uint8_t mv, dav;
swxu 2:626c243adc03 114 if ((PCLK % (16 * baudrate)) != 0) { // Checking for zero remainder
swxu 2:626c243adc03 115 int err_best = baudrate, b, a;
swxu 2:626c243adc03 116 for (mv = 1; mv < 16 && !hit; mv++)
swxu 2:626c243adc03 117 {
swxu 2:626c243adc03 118 for (dav = 0; dav < mv; dav++)
swxu 2:626c243adc03 119 {
swxu 2:626c243adc03 120 // baudrate = PCLK / (16 * dlv * (1 + (DivAdd / Mul))
swxu 2:626c243adc03 121 // solving for dlv, we get dlv = mul * PCLK / (16 * baudrate * (divadd + mul))
swxu 2:626c243adc03 122 // mul has 4 bits, PCLK has 27 so we have 1 bit headroom which can be used for rounding
swxu 2:626c243adc03 123 // for many values of mul and PCLK we have 2 or more bits of headroom which can be used to improve precision
swxu 2:626c243adc03 124 // note: X / 32 doesn't round correctly. Instead, we use ((X / 16) + 1) / 2 for correct rounding
swxu 2:626c243adc03 125
swxu 2:626c243adc03 126 if ((mv * PCLK * 2) & 0x80000000) // 1 bit headroom
swxu 2:626c243adc03 127 dlv = ((((2 * mv * PCLK) / (baudrate * (dav + mv))) / 16) + 1) / 2;
swxu 2:626c243adc03 128 else // 2 bits headroom, use more precision
swxu 2:626c243adc03 129 dlv = ((((4 * mv * PCLK) / (baudrate * (dav + mv))) / 32) + 1) / 2;
swxu 2:626c243adc03 130
swxu 2:626c243adc03 131 // datasheet says if DLL==DLM==0, then 1 is used instead since divide by zero is ungood
swxu 2:626c243adc03 132 if (dlv == 0)
swxu 2:626c243adc03 133 dlv = 1;
swxu 2:626c243adc03 134
swxu 2:626c243adc03 135 // datasheet says if dav > 0 then DL must be >= 2
swxu 2:626c243adc03 136 if ((dav > 0) && (dlv < 2))
swxu 2:626c243adc03 137 dlv = 2;
swxu 2:626c243adc03 138
swxu 2:626c243adc03 139 // integer rearrangement of the baudrate equation (with rounding)
swxu 2:626c243adc03 140 a = b = ((PCLK * mv / (dlv * (dav + mv) * 8)) + 1) / 2;
swxu 2:626c243adc03 141
swxu 2:626c243adc03 142 // check to see how we went
swxu 2:626c243adc03 143 b = abs(b - baudrate);
swxu 2:626c243adc03 144 if (b < err_best)
swxu 2:626c243adc03 145 {
swxu 2:626c243adc03 146 err_best = b;
swxu 2:626c243adc03 147 float er = b * 100.0 / baudrate;
swxu 2:626c243adc03 148 vcom.printf("b: %d, er: %f, err_best: %d\r\n", a, er, err_best);
swxu 2:626c243adc03 149
swxu 2:626c243adc03 150 DL = dlv;
swxu 2:626c243adc03 151 MulVal = mv;
swxu 2:626c243adc03 152 DivAddVal = dav;
swxu 2:626c243adc03 153
swxu 2:626c243adc03 154 if (b == baudrate)
swxu 2:626c243adc03 155 {
swxu 2:626c243adc03 156 hit = 1;
swxu 2:626c243adc03 157 break;
swxu 2:626c243adc03 158 }
swxu 2:626c243adc03 159 }
swxu 2:626c243adc03 160 }
swxu 2:626c243adc03 161 }
swxu 2:626c243adc03 162 }
swxu 2:626c243adc03 163
swxu 2:626c243adc03 164 // set LCR[DLAB] to enable writing to divider registers
swxu 2:626c243adc03 165 LPC_USART->LCR |= (1 << 7);
swxu 2:626c243adc03 166
swxu 2:626c243adc03 167 // set divider values
swxu 2:626c243adc03 168 LPC_USART->DLM = (DL >> 8) & 0xFF;
swxu 2:626c243adc03 169 LPC_USART->DLL = (DL >> 0) & 0xFF;
swxu 2:626c243adc03 170 LPC_USART->FDR = (uint32_t) DivAddVal << 0
swxu 2:626c243adc03 171 | (uint32_t) MulVal << 4;
swxu 2:626c243adc03 172
swxu 2:626c243adc03 173 // clear LCR[DLAB]
swxu 2:626c243adc03 174 LPC_USART->LCR &= ~(1 << 7);
swxu 2:626c243adc03 175
swxu 2:626c243adc03 176 vcom.printf("PCLK: %d\r\n", SystemCoreClock);
swxu 2:626c243adc03 177 vcom.printf("DL: %d\r\n", DL);
swxu 2:626c243adc03 178 vcom.printf("DivAddVal: %d\r\n", DivAddVal);
swxu 2:626c243adc03 179 vcom.printf("MulVal: %d\r\n", MulVal);
swxu 2:626c243adc03 180 vcom.printf("FDR: %d\r\n", LPC_USART->FDR);
swxu 2:626c243adc03 181 }
swxu 2:626c243adc03 182
swxu 2:626c243adc03 183