Bill, one good workaround for zero error baudrate is to use zero error usart crystals You will always have zero error baud rate. 7.3728MHz, 14.7456MHz etc.
On Sat 22 Oct 2022, 5:14 PM Bill Beek <[email protected] wrote: > Hi Rob, > I applied the function unchanged to 3 types: 16F876A, 18F2520 and > 18F25K22. > On the first 2 the function worked fine. So very useful for me. > The function is used as a library "usart_dynamic" with the following 2 > lines added: > if (defined(usart_hw_serial) == FALSE) then > const bit usart_hw_serial = TRUE ; default is async mode (not sync) > end if > In the library "serial_hardware" I have changed the call to the correct > library and the new function. > I have change the name of this lib of coarse. It worked right away. > The 18F25K22 does not want to generate the correct Baud rate, the relevant > registers do have the correct values. > I will look with the oscilloscope to see what kind of Baud rate is really > generated. > > Thanks again for your help, > Kind regards Bill. > > On Friday, October 21, 2022 at 7:23:33 PM UTC+2 [email protected] wrote: > >> Hi Bill, >> >> Thanks and good to hear that you might becomd a fan of JAL. >> >> I saw that your PIC had an 8-bit baudrate generator so you would only >> need this part of the code: >> >> -- use classic (8 bit) baudrate register >> -- <SPBRG> = ( Fosc / ( 4 * Baudrate ) ) -1 >> -- first try high baudrate, will generate highest accuarcy >> -- to get the right rounding (5 + 10*f(x)) /10 >> usart_calculation =((5 + ((10 * clock) / (16 * baudrate))) / 10) >> - 1 >> usart_div = word(usart_calculation) >> -- special case if divider is 0, test if deviation is not too >> much >> if usart_div == 0 then >> if (100 * (baudrate - (clock / 16))) / baudrate >= >> max_deviation then >> -- Asynchronous baudrate is too high >> succes = FALSE >> end if >> end if >> -- if divider small enough calculate divider and set high-speed >> real_baud = clock / 16 / (usart_div + 1) >> if usart_div <= 255 then >> if (real_baud > baudrate) then >> if (100 * (real_baud - baudrate) / baudrate >= >> max_deviation) then >> -- Asynchronous baudrate deviation is too large >> succes = FALSE >> end if >> else >> if (100 * (baudrate - real_baud) / baudrate >= >> max_deviation) then >> -- Asynchronous baudrate deviation is too large >> succes = FALSE >> end if >> end if >> SPBRGL = byte(usart_div) >> TXSTA_BRGH = TRUE >> -- try the low-speed mode >> else >> usart_div_low = ((((10 * clock) / (64 * baudrate)) + 5) / 10) >> - 1 >> -- here divider will never be 0 >> -- but special case to consider, >> -- if baudrate is just a little too low >> if (usart_div_low > 255) & (100 * ((clock / (64 * 256 )) - >> baudrate)) / >> baudrate < max_deviation then >> SPBRGL = 255 >> TXSTA_BRGH = FALSE >> -- now calculate divider and set high-speed / low-speed >> bit >> elsif usart_div_low <= 255 then >> SPBRGL = byte(usart_div_low) >> TXSTA_BRGH = FALSE >> else >> -- Asynchronous baudrate is too low >> succes = FALSE >> end if >> end if >> end if >> >> Good luck testing. >> >> Kind regards, >> >> Rob >> >> ------------------------------ >> *Van:* [email protected] <[email protected]> namens Bill >> Beek <[email protected]> >> *Verzonden:* donderdag 20 oktober 2022 19:15 >> >> *Aan:* jallib <[email protected]> >> *Onderwerp:* Re: [jallib] Baudrate control >> Hi Rob, >> I am going to try out the function you have sent, I see that it is >> suitable for various PIC's and also test whetherthe chosen X-tal frequency >> is good enough for the desired baudates. I myself use an 18.432 MHz x-tal >> that I still found in my junkbox. in that casemy code can >> be more simple because of the very small spread, but obviously not for >> general use. >> I'll let you know if it worked out. B.T.W. this is very instructive for >> me. and I'm going to appreciate JAL more and more. >> Thank you for your effort, >> Kind regards Bill. >> >> On Tuesday, October 18, 2022 at 7:23:04 PM UTC+2 [email protected] >> wrote: >> >> Hi Bill, >> >> I understand what you try to do but it does not work because the hardware >> baudrate setting is calculated at compile time not at runtime. >> >> In the library usart_common.jal you find the procedure that calculates >> the baudrate settings. >> >> I once changed this code to be dynamic and created the following code but >> I do not remember if I ever tested it (it compiled as far as I know 🙂). >> >> I did not use it because it is a lot of code for only calculating and >> setting the baudrate. That's why I suggested the other code. >> >> You could leave out the part which calculates it for synchronous mode and >> based on the PIC you are using you could leave out the 8-bit or 16-bit >> baudrate generator since your PIC has only one of them. In that case the >> code size is much smaller. >> >> You could give it a try and if it works let me know. >> >> Kind regards, >> >> Rob >> >> >> -- >> ------------------------------------------------------------------------------ >> -- Title: Calculate and set baudrate dynamically for USART 1 >> -- Arguments: baudrate >> -- Returns: TRUE when succesful, otherwise FALSE >> -- Notes: Uses bit-constant 'usart_hw_serial' to determine mode of >> operation: >> -- * TRUE: Asynchronous communications (default) >> -- * FALSE: Synchronous communications >> -- >> ------------------------------------------------------------------------------ >> function _calculate_and_set_baudrate_dynamic(dword in baudrate) return >> bit is >> >> const max_deviation = 5 -- maximum % deviation of the desired baudrate >> var dword usart_calculation, real_baud, usart_div_low, >> usart_div_sync, clock >> var word usart_div >> var bit succes = TRUE >> >> clock = dword(target_clock) >> >> if (usart_hw_serial == TRUE) then -- USART in asynchronous >> mode >> if (defined(BAUDCON_BRG16) == TRUE) then -- use 16 bit baudrate >> register >> BAUDCON_BRG16 = TRUE >> TXSTA_BRGH = TRUE >> usart_calculation = ((5 + ((10 * clock) / (4 * baudrate))) / 10) >> - 1 >> usart_div = word(usart_calculation) >> real_baud = clock / 4 / ((usart_div & 0xffff) + 1) >> if (real_baud > baudrate) then >> if (100 * (real_baud - baudrate) / baudrate >= >> max_deviation) then >> -- Asynchronous baudrate deviation is too large >> succes = FALSE >> end if >> else >> if (100 * (baudrate - real_baud) / baudrate >= >> max_deviation) then >> -- Asynchronous baudrate deviation is too large >> succes = FALSE >> end if >> end if >> SPBRGL = byte(usart_div) -- MSB >> SPBRGH = byte(usart_div >> 8) -- LSB >> else >> -- use classic (8 bit) baudrate register >> -- <SPBRG> = ( Fosc / ( 4 * Baudrate ) ) -1 >> -- first try high baudrate, will generate highest accuarcy >> -- to get the right rounding (5 + 10*f(x)) /10 >> usart_calculation =((5 + ((10 * clock) / (16 * baudrate))) / 10) >> - 1 >> usart_div = word(usart_calculation) >> -- special case if divider is 0, test if deviation is not too >> much >> if usart_div == 0 then >> if (100 * (baudrate - (clock / 16))) / baudrate >= >> max_deviation then >> -- Asynchronous baudrate is too high >> succes = FALSE >> end if >> end if >> -- if divider small enough calculate divider and set high-speed >> real_baud = clock / 16 / (usart_div + 1) >> if usart_div <= 255 then >> if (real_baud > baudrate) then >> if (100 * (real_baud - baudrate) / baudrate >= >> max_deviation) then >> -- Asynchronous baudrate deviation is too large >> succes = FALSE >> end if >> else >> if (100 * (baudrate - real_baud) / baudrate >= >> max_deviation) then >> -- Asynchronous baudrate deviation is too large >> succes = FALSE >> end if >> end if >> SPBRGL = byte(usart_div) >> TXSTA_BRGH = TRUE >> -- try the low-speed mode >> else >> usart_div_low = ((((10 * clock) / (64 * baudrate)) + 5) / 10) >> - 1 >> -- here divider will never be 0 >> -- but special case to consider, >> -- if baudrate is just a little too low >> if (usart_div_low > 255) & (100 * ((clock / (64 * 256 )) - >> baudrate)) / >> baudrate < max_deviation then >> SPBRGL = 255 >> TXSTA_BRGH = FALSE >> -- now calculate divider and set high-speed / low-speed >> bit >> elsif usart_div_low <= 255 then >> SPBRGL = byte(usart_div_low) >> TXSTA_BRGH = FALSE >> else >> -- Asynchronous baudrate is too low >> succes = FALSE >> end if >> end if >> end if >> else -- USART in synchronous mode >> usart_div_sync = ( clock / ( 4 * baudrate )) - 1 >> -- special case if divider is 0 or negative >> -- test if baudrate is a little bit too high >> if usart_div_sync <= 0 then >> if (100 * (baudrate - (clock / 4))) / baudrate >= max_deviation >> then >> -- Synchronous baudrate is too high >> succes = FALSE >> end if >> end if >> -- special case to consider, if baudrate is just a little too high >> if (usart_div_sync > 255) & (100 * ((clock / (4 * 256)) - >> baudrate)) / >> baudrate < max_deviation then >> SPBRGL = 255 >> elsif (usart_div_sync <= 255) then >> SPBRGL = byte(usart_div_sync) >> else >> -- Synchronous baudrate is too low >> succes = FALSE >> end if >> end if >> >> return succes >> >> end function >> >> >> >> >> ------------------------------ >> *Van:* [email protected] <[email protected]> namens Bill >> Beek <[email protected]> >> *Verzonden:* dinsdag 18 oktober 2022 11:34 >> >> *Aan:* jallib <[email protected]> >> *Onderwerp:* Re: [jallib] Baudrate control >> Hello Rob, >> Thank you for your cooperation, yesterday I had already seen the code. >> Now let's figure out how I can fit it into my program. >> Maybe my question was not entirely clear so I send a piece of the code to >> show how I imagined it. >> >> Kind regards, Bill. >> >> MCU = 16F876A 20 MHz The problem here is that var "set" must be a >> constant. >> Short vars for testing only. >> >> var byte c1,c2,c3 >> var byte set -- Baud indicator >> const serial[8]={1200,2400,4800,9600,19200,38400,57600,115200} >> ;var dword serial[8]={1200,2400,4800,9600,19200,38400,57600,115200} >> >> pin_c1_direction = INPUT >> pin_c2_direction = INPUT >> pin_c3_direction = INPUT >> >> include serial_hardware >> >> if pin_c1 then >> c1 = 1 >> else >> c1 = 0 >> end if >> >> if pin_c2 then >> c2 = 2 >> else >> c2 = 0 >> end if >> >> if pin_c3 then >> c3 = 4 >> else >> c3 = 0 >> end if >> >> set = c1 + c2 + c3 + 1 >> >> const serial_hw_baudrate = serial[set] >> ;var dword serial_hw_baudrate = serial[set] >> serial_hw_init() >> >> >> >> >> On Tuesday, October 18, 2022 at 7:14:34 AM UTC+2 [email protected] >> wrote: >> >> Hello Bill, >> >> I posted an example but never received it my self so this is a retry. >> >> Kind regards, >> >> Rob >> >> >> Op maandag 17 oktober 2022 om 19:52:25 UTC+2 schreef [email protected]: >> >> Hi Bill, >> >> I applied the suggestion of Kiste in one of my programs. Here is a part >> of that program. This is for a PIC running at 48 MHz target clock. >> >> I had to look up a specific baudrate to see if it was valid. If so I set >> the new baudrate. >> >> You see 4 parts (not all needed) >> >> 1. Define valid bauddrates. You could skip this >> 2. Check if a given baudrate is valid. You could skip this too. >> 3. The baudrate calculation based on the given baudrate + initialize >> the USART. You need this. Note: baudrate calculation is of type dword. >> 4. The intiallization routine of the USART with the calculation. You >> need this. >> >> >> ; List of baudrates supported. See page 262 of the datasheet. >> ; Formula for baudrate calclation for 8 byte asynchronous mode >> ; with for sync = FALSE and brg16 = TRUE and brgh = FALSE: >> ; brg = target_clock/(baudrate * 16) - 1 >> const dword SUPPORTED_BAUDRATES[] = { >> 110, 300, 600, 1200, 2400, 4800, 9600, 14400, >> 19200, 28800, 38400, 57600, 115200, 230400 >> } >> >> ; Check if the given baudrate is supported and return TRUE if so. >> function supported_baudrate(dword in baudrate) return bit is >> >> var byte index >> var bit found = FALSE >> >> for count(SUPPORTED_BAUDRATES) using index loop >> if (SUPPORTED_BAUDRATES[index] == baudrate) then >> found = TRUE >> end if >> end loop >> >> return found >> >> end function >> >> baudrate_calculation = (target_clock/(current_baudrate * 16)) >> - 1 >> usart_init(word(baudrate_calculation)) >> >> ; Initialize the USART with the given baudrate value. The USART is >> enabled. >> procedure usart_init(word in baudrate_value) Is >> >> usart_disable() >> ; Use 16 bit baudrate generator and set baudrate >> BAUDCON = 0b0000_1000 >> SPBRG = baudrate_value >> ;Initialise transmitter, 8 bits, asynchronous mode, low speed. >> TXSTA = 0b0000_0000 >> ; Initialise receiver and serial port, 8 bits >> RCSTA = 0b1000_0000 >> usart_enable() >> >> end procedure >> >> >> Hope this helps. >> >> Kind regards, >> >> Rob >> ------------------------------ >> *Van:* [email protected] <[email protected]> namens Bill >> Beek <[email protected]> >> *Verzonden:* maandag 17 oktober 2022 19:40 >> *Aan:* jallib <[email protected]> >> *Onderwerp:* Re: [jallib] Baudrate control >> >> Thanks Kiste for your reply. My teacher said more than 50 years ago that >> poking in memory was not a good way of programming, >> but I did think that this was also a possibility. If this turns out to be >> the only possibility, >> I'm not sure how to go about it I don't see anything in the >> documentation about writing directly in the PIC memory >> except that you can use assembler instructions. Unfortunately I am not >> well informed about the PIC asm code. >> A long time ago I programmed various micro processors. >> I would like to hear if you want to share a piece of code what i can >> alter for my needs. >> >> Thanks in advance, Bill. >> >> >> On Monday, October 17, 2022 at 4:47:20 PM UTC+2 Kiste wrote: >> >> Hi Bill, >> >> I've used different baud rates, but I did not modify the serial libraries >> for that. I just calculated the register values by hand and poked the >> different values to the different registers. The baud rate calculation in >> the libraries is not a thing which is good to be done at runtime. For >> certain baud rates, the lib will refuse to compile and inform you, that >> your desired baud rate cannot be set due to a deviation from the desired >> value which is to large to reliably work. That can't be done at runtime for >> a start. >> >> Greets, >> Kiste >> >> Am Montag, 17. Oktober 2022, 15:39:54 MESZ hat Bill Beek < >> [email protected]> Folgendes geschrieben: >> >> >> Hello everyone, Is there anyone who has a solution to my problem. I am >> working on a serial LCD now that I have this working, I want to select the >> baud rate before running the program. Unfortunately, the "const >> serial_hw_baudate" do not easily change. In the library "usart_common" I >> changed all the constants in a variable "var dword" but I keep getting >> error messages from this lib. Maybe I'm overlooking something, or is there >> a simple method to set the Baud rate under software control. >> Kind regards, Bill >> >> -- >> You received this message because you are subscribed to the Google Groups >> "jallib" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected]. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/jallib/2b1be8c6-547c-4f0c-97bb-43fc851e4bf4n%40googlegroups.com >> <https://groups.google.com/d/msgid/jallib/2b1be8c6-547c-4f0c-97bb-43fc851e4bf4n%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> >> -- >> You received this message because you are subscribed to the Google Groups >> "jallib" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected]. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/jallib/81855104-44d2-4941-b199-807927d341dan%40googlegroups.com >> <https://groups.google.com/d/msgid/jallib/81855104-44d2-4941-b199-807927d341dan%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> >> -- >> You received this message because you are subscribed to a topic in the >> Google Groups "jallib" group. >> To unsubscribe from this topic, visit >> https://groups.google.com/d/topic/jallib/vc1s65yXPkQ/unsubscribe. >> To unsubscribe from this group and all its topics, send an email to >> [email protected]. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/jallib/8852c568-89d0-4224-95fa-ecd30b6cdc3an%40googlegroups.com >> <https://groups.google.com/d/msgid/jallib/8852c568-89d0-4224-95fa-ecd30b6cdc3an%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> >> -- >> You received this message because you are subscribed to a topic in the >> Google Groups "jallib" group. >> To unsubscribe from this topic, visit >> https://groups.google.com/d/topic/jallib/vc1s65yXPkQ/unsubscribe. >> To unsubscribe from this group and all its topics, send an email to >> [email protected]. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/jallib/5d0d8e28-8738-4449-a2f0-270cae592709n%40googlegroups.com >> <https://groups.google.com/d/msgid/jallib/5d0d8e28-8738-4449-a2f0-270cae592709n%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > -- > You received this message because you are subscribed to the Google Groups > "jallib" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To view this discussion on the web visit > https://groups.google.com/d/msgid/jallib/d50afd69-5b72-4559-b107-3cc12ed76cb3n%40googlegroups.com > <https://groups.google.com/d/msgid/jallib/d50afd69-5b72-4559-b107-3cc12ed76cb3n%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "jallib" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/jallib/CAM%2Bj4qsYVcvgDEC25%3Dax9qNQmUoQcH_GBmmFg9Nj1Z66_U%2B5Qw%40mail.gmail.com.
