Hi, I was musing over WormFood's AVR baud rate calculations page:
http://www.wormfood.net/avrbaudcalc.php It seems for faster baudrates, the required UBRRL value is of such a low resolution that major errors are unavoidable. So it occurred to me that, if accurate timing for other functionality is not critical, and if one is using the internal clock, one can tune OSCCAL to get very close to the real target baudrate. For example, consider an ATmega32 running with 8MHz internal RC oscillator, wanting to talk at 115kb/s. The required UBRRL value is 3, which unfortunately gives an effective baud rate of 125000, which my tty port is not coping with. However, writing a different value to OSCCAL has brought the effective baud rate close enough so that the AVR UART is talking to my tty port just fine, without errors. Here's the math: let: - BRgot be the effective baud rate, when the AVR is running at its selected clock frequency (eg, 8MHz when CKSEL=0x04) - BRwant be the desired baud rate - OCgot be the factory OSCCAL value - OCwant be the OSCCAL value required to give the desired baud rate - Fmin be the frequency that the AVR's IntRC generates when OSCCAL=0 - Fmax be the frequency that IntRC generates at OSCCAL=255 - Fgot be the actual frequency that the AVR's IntRC generates with OSCCAL left at the factory value - Fwant be the frequency required such that the uart generates the desired baud rate Then, given that Fmax = 2 * Fmin, Fgot = Fmin * (1 + OCgot / 255) and Fwant = Fmin * (1 + OCwant / 255) Now, Fwant / Fgot = BRwant / BRgot (1 + OCwant / 255) / (1 + OCgot / 255) = BRwant / BRgot (1 + OCwant / 255) = BRwant / BRgot * (1 + OCgot / 255) OCwant / 255 = BRwant / BRgot * (1 + OCgot / 255) - 1 And finally: OCwant = 255 * (BRwant / BRgot * (1 + OCgot / 255) - 1) So for an 8MHz IntRC ATmega, with a factory OSCCAL of 0xb1, wanting to talk at 115k, the baudrate generated at UBRRL=3 is 125000 (according to WormFood's page. My ATmega32 has a factory OSCCAL of 0xb1 So in this scenario: OCwant = 255 * (115200 / 125000 * (1 + 0xb1 / 255) - 1) = 0x8f And we also get: Fwant = 115200 / 125000 * 8000000 = 7372800 Hz I tried this, and got mostly corrupted chars. But OSSCAL = 0x90 has given me perfect 115200k comms. I'm wondering if it's an issue of temperature - or whether the factory OSCCAL of 0xb1 might have been out. If one wants good timing, one can recompile the code with: #define F_CPU 7372800 and end up with reasonable timing with the delay function Anyway, I'm open to better ideas on this. I have an app that really needs to talk as fast as possible without errors, so any better suggestion would be appreciated. Keep in mind though that I only have convenient access here to crystals of a fairly limited range of frequencies (eg 4MHz, 8MHz, 10MHz, 20MHz) Cheers David _______________________________________________ AVR-GCC-list mailing list AVR-GCC-list@nongnu.org http://lists.nongnu.org/mailman/listinfo/avr-gcc-list