{"id":96045,"date":"2017-04-26T07:00:00","date_gmt":"2017-04-26T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=96045"},"modified":"2019-03-13T01:10:38","modified_gmt":"2019-03-13T08:10:38","slug":"20170426-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20170426-00\/?p=96045","title":{"rendered":"Why are there two incompatible ways of specifying a serial port baud rate?"},"content":{"rendered":"<p>One of my colleagues tracked down a bug in their code that communicates over a serial port. (Remember serial ports?) <\/p>\n<p><a HREF=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa363214(v=vs.85).aspx\">The <code>DCB<\/code> structure<\/a> specifies the baud rate as an integer. To request 2400 baud, you set the <code>BaudRate<\/code> to 2400. There are some convenient defined constants for this purpose. <\/p>\n<pre>\n#define CBR_110             110\n#define CBR_300             300\n#define CBR_600             600\n#define CBR_1200            1200\n#define CBR_2400            2400\n#define CBR_4800            4800\n#define CBR_9600            9600\n#define CBR_14400           14400\n#define CBR_19200           19200\n#define CBR_38400           38400\n#define CBR_56000           56000\n#define CBR_57600           57600\n#define CBR_115200          115200\n#define CBR_128000          128000\n#define CBR_256000          256000\n<\/pre>\n<p>Meanwhile, <a HREF=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa363189(v=vs.85).aspx\">the <code>COMMPROP<\/code> structure<\/a> also has a way of specifying the baud rate, but it is done by setting the <code>dwMaxBaud<\/code> to a bitmask:<\/p>\n<pre>\n#define BAUD_075          ((DWORD)0x00000001)\n#define BAUD_110          ((DWORD)0x00000002)\n#define BAUD_134_5        ((DWORD)0x00000004)\n#define BAUD_150          ((DWORD)0x00000008)\n#define BAUD_300          ((DWORD)0x00000010)\n#define BAUD_600          ((DWORD)0x00000020)\n#define BAUD_1200         ((DWORD)0x00000040)\n#define BAUD_1800         ((DWORD)0x00000080)\n#define BAUD_2400         ((DWORD)0x00000100)\n#define BAUD_4800         ((DWORD)0x00000200)\n#define BAUD_7200         ((DWORD)0x00000400)\n#define BAUD_9600         ((DWORD)0x00000800)\n#define BAUD_14400        ((DWORD)0x00001000)\n#define BAUD_19200        ((DWORD)0x00002000)\n#define BAUD_38400        ((DWORD)0x00004000)\n#define BAUD_56K          ((DWORD)0x00008000)\n#define BAUD_128K         ((DWORD)0x00010000)\n#define BAUD_115200       ((DWORD)0x00020000)\n#define BAUD_57600        ((DWORD)0x00040000)\n#define BAUD_USER         ((DWORD)0x10000000)\n<\/pre>\n<p>My colleague accidentally set the <code>DCB.BaudRate<\/code> to a <code>BAUD_xxx<\/code> value, and since these values are untyped integers, there was no compiler warning. <\/p>\n<p>My colleague asked for the historical background behind why there are two easily-confused ways of doing the same thing. <\/p>\n<p>The <code>DCB<\/code> structure dates back to 16-bit Windows. It tracks the feature set of the 8250 UART, since that is what came with the IBM PC XT.&sup1; In particular, there is no need to ask what baud rates are supported by the serial chip because you already know what baud rates are supported by the serial chip: The 8250 and 16650 support baud rates that are divisors of 115200.&sup2; <\/p>\n<p>Enter Windows NT. This operating system wanted to run on things that weren&#8217;t IBM PCs. Crazy. In particular, those systems may have serial communications chips that support a different set of baud rates. That&#8217;s where the <code>COMMPROP<\/code> structure came in: It reports baud rates as a bitmask that is filled out by <a HREF=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa363259(v=vs.85).aspx\">the <code>Get&shy;Comm&shy;Properties<\/code> function<\/a>. That way, the program that wants to do serial communications can find out what baud rates are supported by the current hardware. And since it&#8217;s reporting a set of values, a bitmask seems the natural way of representing it. <\/p>\n<p>The program inspects the bitmask, decides which of the available baud rates it wants to use, and puts the desired value (as an integer, not a bitmask) in the <code>Baud&shy;Rate<\/code> member of the <code>DCB<\/code>. <\/p>\n<p>That&#8217;s my attempt to reverse-engineer the history of the two incompatible ways of representing baud rates. <\/p>\n<p>&sup1; The PS\/2 line introduced the 16550 UART which is backward-compatible with the 8250. In particular, it supports the same baud rates. <\/p>\n<p>&sup2; Other baud rates like 110 are approximations. For example 110 is really 115200 &divide; 1048 = 109.92 baud. <a HREF=\"https:\/\/www.allaboutcircuits.com\/technical-articles\/the-uart-baud-rate-clock-how-accurate-does-it-need-to-be\/\">This article<\/a> claims that microcontrollers &#8220;rarely offer an internal oscillator that has accuracy better than &plusmn;1.5%,&#8221; so an error of 0.07% is easily lost in the jitter. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Toto, I don&#8217;t think we&#8217;re on an IBM PC XT any more.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-96045","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Toto, I don&#8217;t think we&#8217;re on an IBM PC XT any more.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/96045","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=96045"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/96045\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=96045"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=96045"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=96045"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}