Sorry for the stupid question but, I'm interfacing a PIC18f46k20 to an Atlas pH sensor module. Both are running on 3.3v. Must I use a max232 between or can the pic talk 232 directly to the module?

The reason I'm asking is it seems in the datasheet (pic) that the baud rate generator doesn't generate the 38400 required by the sensor board so I'm thinking the interface chip (max232) would correct for that somehow? Using the formula on page 249, I'm running at the default internal 1MHz and I come up with a negative value for SPBRGH:SPBRG. Or does the autobaud account for this?

  • \$\begingroup\$ I think it's safe to say, that if you got a negative result, that something went wrong with your calculations. \$\endgroup\$
    – gbarry
    Oct 14, 2012 at 2:08

2 Answers 2


All a MAX232 provides is level translation.

"Traditional" RS-232 uses high-voltages to do it's signaling, generally ~+10V to indicate a logical "0", and ~-10V to indicate a logic "1" (though the spec technically says anything > 3V = 0, and < -3V = 1. In real-world applications, you may see a range of signaling levels represented as "RS232").

However, most modern devices do not have the facilities onboard to generate or handle these (relatively) high voltages. As such, things like your PIC will use 0V and VCC for their signalling levels, representing logical "0" and "1" respectively.

What the MAX-232 does is convert an input level of 0V to an output of ~+10V, and an input of VCC to ~-10V. That's all it does. It will not do any baud-rate conversion at all.

In your case, the datasheet for the Atlas Scientific PH sensor states:

The baud rate is: 38400, 8 bits, no parity, with one stop bit.
The voltage swing 0-VCC, not +/- 12 volts
If standard voltage level RS232 is desired, connect an RS232 converter such as a MAX232.

So you don't need a MAX232, as you don't want or need the ~+-10V signalling levels. Assuming you are using the same power supply for the pH sensor and your MCU, you can simply connect the two devices straight together.

As an aside, I would reccomend putting a 1K resistor between the pH sensor's serial output and your MCUs serial input. This way, if you accidentally set the serial input as an output pin, it will not cause the two device's outputs to fight each other, and potentially damage one of them.

You will either need to change the baud rate of the Atlas sensor, or calculate your own baud-rate generator values for the PIC to make it run at 38400 baud you need.

If you cannot achieve the desired baud-rate with your system clock, you have to add an external crystal or resonator, and increase the system clock so you can.

As an aside, I think you're doing something wrong with your math if you're getting negative numbers for SPBRGH:SPBRG.

That said, 38400 baud is pretty high for a 1 Mhz system clock. You're going to be right at the edge of the top-end which you can run the EUSART at.

From the data sheet:

enter image description here


  • SYNC = 0
  • BRG16 = 1
  • BRGH = 1

n = value of SPBRGH, SPBRG register pair $$ BaudRate = \frac{F_{OSC}}{4*(n+1)} $$ $$ BaudRate * 4*(n+1) = F_{OSC} $$ $$ (n+1) = \frac{F_{OSC}}{4*BaudRate} $$ $$ (n+1) = \frac{1,000,000}{4*38400} $$ $$ (n+1) = \frac{1,000,000}{153,800} $$ $$ (n+1) = 6.51041666666667 $$ $$ n = 5.51041666666667 $$

so the closest available SPBRGH, SPBRG value would be 6 or 5.

Then, we calculate the baud rate error, which will likely be very high, since we're down at such small SPBRGH, SPBRG values.

$$ BaudRate = \frac{F_{OSC}}{4*(n+1)} $$ $$ BaudRate _{SPBRGH=6} = \frac{1e6}{4*(6+1)}, BaudRate _{SPBRGH=5} = \frac{1e6}{4*(5+1)} $$ $$ BaudRate _{SPBRGH=6}= 35714 , BaudRate _{SPBRGH=5} = 41666 $$

So the two availalbe baud rates are:

  • SPBRGH=6: 35714, -6.9 % Error
  • SPBRGH=5: 41666, 8.5% Error

Both are too far from your target baud rate to work, so you have to change your system clock rate.

  • \$\begingroup\$ Thanks @FakeName. Where did you get the 4 from in the baudrate calculation, and then change it to 16 in the second line? The formula in the datasheet used 64 as a divisor. (assuming I was running at 8bit asynchronous) At 1MHz and 38400 baud and using 64 as the formula stated, I ended up with (n+1) = <1. That's how I ended up with a negative n. \$\endgroup\$
    – Mark
    Oct 14, 2012 at 3:17
  • \$\begingroup\$ @Mark - Look at the table in my answer (or the datasheet) - There is a different calculation for different settings of BRG16 and BRGH. If BRG16 = 0 and BRG16 = 0, the divisor is 64. \$\endgroup\$ Oct 14, 2012 at 7:33
  • \$\begingroup\$ The 16 in the second line came from the fact that I initially typed up the equations as I was doing the calculations, and started out with BRG16 = 0 and BRGH = 1. Once I looked at the results, I redid it with BRG16 = 1 as well. The fact that the 16 is still there is a typo. \$\endgroup\$ Oct 14, 2012 at 7:34

There are two things that have to match, baud rate and the signalling levels. The PIC does not natively do RS-232 signalling levels. The MAX232 chip (or one of its many variants and similar products from various vendors) takes care of converting the PIC UART signals to RS-232 electrically, if your sensor actually needs real RS-232. Some devices use logic level signals like the PIC produces directly. However, a MAX232 does not do any kind of baud rate conversion.

Think about it. How could it? Converting from a fast baud rate to a slow one means data would have to pile up somewhere. How do you envision this working? The amount of piled-up data would grow indefinitely if the transmitter kept sending at the maximum rate. This makes no sense. A brief look at the MAX232 datasheet also shows it is simply a voltage level translator.

You can only hit certain baud rates with any one PIC clock frequency. The oscillator is divided by either 4, 16, or 64, and then by a integer you can select to get the baud rate. 1 MHz is a slow oscillator, so you won't have much resolution in picking a baud rate until you get down to some pretty slow ones. The best you can do is to start with 1 MHz / 4, which is 250 kHz. 250 kHz / 38400 = 6.5, so that won't work because either 6 or 7 will be too far off. If you use double the oscillator, then you can start with 2 MHz / 4 = 500 kHz. 500 kHz / 38400 = 13.02, so 13 will be close. 500 kHz / 13 = 38462, which is only .16% off, which is plenty close enough.

Another issue though is the accuracy of the internal oscillator. It can be 5% off over temperature and voltage. You have to look at that carefully and see if it is good enough for the possibly more limited set of conditions you are running the PIC at.

All in all, you really need to read the datasheets instead of just guessing.

  • \$\begingroup\$ Olin, thanks for the info. I'm using the default 1MHz internal oscillator just for simplicity. I'll just have to ramp it up some more as you suggested. \$\endgroup\$
    – Mark
    Oct 14, 2012 at 3:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.