PIC USART communication problem - Page 1
Forum section: electronics / general

author: wicket
author_rank: Contributor
timestamp: March 17, 2014, 09:59:04 am
content: Hi,I'm using a PIC16F628A USART to communicate with my SE T610 GSM. MikroC compiler.Circuit:How program works - when RB0 goes high, uC transmits "at" command to my GSM and it responds "OK". I've included a char compare routine to see if the response is indeed "OK". And it works - if it receives charsO,K,\nor\rthe LED turns on.My problem - I'm trying to use the exact same program and circuit (with appropriate pin adjustments, of course) with my PIC18F4520 and PIC16F887 but it doesn't work.Transmittion works fine, I've tried "atd" command instead of "at", and GSM makes a call, which means transmission is ok. And uC also receives something back, because interrupt does occur (i've tested it), but when I compare incoming chars, none of them are what they are supposed to be ("OK\n\r").I've also connected the GSM to my PC directly and tested it using putty to make sure it's not GSMs fault. It works perfectly.Voltage levels of Tx and Rx pins are correct, I've also tried different Fosc's and baudrates, but couldn't make it work. Unfortunatley I don't have an access to any oscilloscope to check what am I actually receiving.I don't understand why it works on 16F628A, but not on other two PICs. I suspect it has something to do with USART configuration. I've read all 3 datasheets but it seems to me nothing should change regarding USART init.I would really appreciate any help.Code from PIC16F887, where I'm using PORD intead of PORTB I/O:Code:volatile unsigned char uart_rd = 0; // serial input byte (RCREG)unsigned int b = 0;// UART Initializationvoid uartinit(){UART1_Init(9600); // initialize UART module at 9600 bpsDelay_ms(100); // let it stabilizePIE1.B5 = 1; // turn on USART interrupt bit RCIE}// UART Interrupt: Receive charactervoid interrupt(){if (PIR1.B5) // if interrupt occurs - if RCIF = 1(RCREG full){uart_rd = RCREG; // read incoming byte (character)if (uart_rd == 79) PORTD.B1 = 1; //if incoming byte is "O", turn on LEDPIR1.B5 = 0; // reset RCIF flag bit to 0}}// Main programvoid main(){uartinit();INTCON = 0b11000000; // enable PEIE and GIE interruptsADCON1 = 0b0111; // configure all pins as digitalTRISD = 0b01;PORTD = 0b00;while (1){if ((PORTD.B0 == 1) && (b == 0)) // if input goes high{b = 1; // set flag, so this if loop is disabled in futureUART1_Write_Text("at"); // phones response should be "OK"UART1_Write(13); // \r}}}

author: dannyf
author_rank: Super Contributor
timestamp: March 17, 2014, 11:17:26 am
content: The usart portion of the code looks ok. Issue is likely somewhere else, like pin setup - analog and comparator off....

author: wicket
author_rank: Contributor
timestamp: March 17, 2014, 12:06:54 pm
content: 16F887 datasheetPossible, yes. I've set all analog pins to digital using ADCON1 = 0b0111; as described in datasheet, but I can't seem to find comparators module with this PIC.

author: Skimask
author_rank: Super Contributor
timestamp: March 17, 2014, 12:25:53 pm
content: Page 87 & 109

author: wicket
author_rank: Contributor
timestamp: March 17, 2014, 01:03:54 pm
content: Whoops, I downloaded 877 datasheet instead of 887.I've corrected the code, but it still doesn't work:Code:volatile unsigned char uart_rd = 0; // serial input byte (RCREG)unsigned int b = 0;// UART Initializationvoid uartinit(){UART1_Init(9600); // initialize UART module at 9600 bpsDelay_ms(100); // let it stabilizePIE1.B5 = 1; // turn on USART interrupt bit RCIE}// UART Interrupt: Receive charactervoid interrupt(){if (PIR1.B5) // if interrupt occurs - if RCIF = 1(RCREG full){uart_rd = RCREG; // read incoming byte (character)if (uart_rd == 79) PORTD.B1 = 1; //if incoming byte is "O", turn on LEDPIR1.B5 = 0; // reset RCIF flag bit to 0}}// Main programvoid main(){uartinit();INTCON = 0b11000000; // enable PEIE and GIE interruptsANSEL = 0b00000000; // configure all pins as digitalCM1CON0.B7 = 0; // comparators offCM2CON0.B7 = 0;TRISD = 0b01;PORTD = 0b00;while (1){if ((PORTD.B0 == 1) && (b == 0)) // if input goes high{b = 1; // set flag, so this if loop is disabled in futureUART1_Write_Text("at"); // phones response should be "OK"UART1_Write(13); // \r}}}I get into interrupt routine, but received byte is still not O, K, \n or \r.

author: Psi
author_rank: Super Contributor
timestamp: March 17, 2014, 01:41:36 pm
content: As a test you could loop mcu tx and rx and see if what you send is what you get back. Might gives some clues to help understand where the problem isSave up and buy a scope, so useful for this sort of stuff.

author: wicket
author_rank: Contributor
timestamp: March 17, 2014, 05:38:45 pm
content: Yeah, I tried using intergrated UART tool and it worked all right. I received what i sent.I'm simply lost, duplicating the exact same routine on different PIC... Strange.And yes, I'll definitely get myself a scope.

author: dannyf
author_rank: Super Contributor
timestamp: March 17, 2014, 09:39:55 pm
content: Aside from actual differences between peripherals, you want ckeck analog, comparator, and fuse.

author: David_AVD
author_rank: Super Contributor
timestamp: March 17, 2014, 10:31:47 pm
content: Have you tried using your micro unit with some PC terminal software to see if the baud rate is correct?A loopback will succeed with the wrong baud rate because the micro tx and rx are at the same (incorrect) rate.

author: Skimask
author_rank: Super Contributor
timestamp: March 17, 2014, 11:08:50 pm
content: I think it's time to throw a blinky on all three chips, using the same code base, and making sure blinky does it's blinking at the correct rate.I'm betting you'll find one of them is 4x off.

author: wicket
author_rank: Contributor
timestamp: March 18, 2014, 09:08:44 am
content: Quote from: David_AVD on March 17, 2014, 10:31:47 pmI connected my PIC to TTL - USB converter and tried to used putty, but I cannot type anything into terminal window and I also don't receive anything. But if I use MikroCs integrated UART terminal, it works.What if I insert a parity bit check into my interrupt routine (FERR)? Would that signalize incorrect baudrate or xtal? I've read that UART is extremely sensitive regarding oscillator.

author: David_AVD
author_rank: Super Contributor
timestamp: March 18, 2014, 09:13:56 am
content: Checking that the oscillator is running at the correct speed should be at the top of your list.

author: Skimask
author_rank: Super Contributor
timestamp: March 18, 2014, 09:15:40 am
content: Quote from: wicket on March 18, 2014, 09:08:44 am....hence the earlier suggestion to hook up an LED and write a quick blinky program......(sigh)...

author: wicket
author_rank: Contributor
timestamp: March 18, 2014, 12:10:11 pm
content: Quote from: Skimask on March 18, 2014, 09:15:40 amGonna try it then.

author: granz
author_rank: Regular Contributor
timestamp: March 18, 2014, 03:12:52 pm
content: Quote from: wicket on March 18, 2014, 09:08:44 amPutty won't display characters you type, but they are still sent. Normally, when you see what you are typing, it's because the receiver is echoing the characters back.From what you've said so far, it certainly sounds like the baud rate is set incorrectly. I would double check the CONFIG bits, and the OSCCON register. You can also set OSCCON manually at the top of your main() routine to be sure it is what you expect. I don't use MikroC, but the UART1_Init() library routine will be setting up the UART registers based on what it believes the clock rate is.You could also not use UART1_Init() and just setup the USART registers yourself, it's really only a few lines of code.

author: wicket
author_rank: Contributor
timestamp: March 18, 2014, 03:29:15 pm
content: I understand. Instead of calibrating INTOSC, I'm gonna test it using 3.6864 MHz in 11.0592 MHz crystals, which are supposably the best fit for UART (theoretical 0% baud error).I'm gonna set UART registers myself and also try to duplicate the same program in MPLAB instead of MikroC. I'll let you know how it goes.

author: Skimask
author_rank: Super Contributor
timestamp: March 18, 2014, 05:13:09 pm
content: The point isn't really that your crystal, internal oscillator, etc. is off by 1% or 2% or whatever... The point is figuring out if you've got your oscillator configuration set correctly and therefore your baud rate division is being done correctly.Example...If you do a one second blinky, and actually get a 4 second blinky, might be trying to use the 4xPLL, but it's not actually on, or something along those lines.

author: dannyf
author_rank: Super Contributor
timestamp: March 18, 2014, 11:40:33 pm
content: QuoteThe chip is unlikely to have a pll.9600bps is usually the upper limit for internal rc oscillator. If you suspect that the internal oscillator isn't that accurate, you can try to tune it or lower the baud rate to a point where oscillator errors are sufficiently insignificant.It is generally a good idea to use crystal when high speed uart is used, however.

author: dannyf
author_rank: Super Contributor
timestamp: March 19, 2014, 12:18:44 am
content: I tried the framework of your code and it worked: in my case, I was looping back RX to TX and flipping PORTD.1 on '\n'. So your issues are anything other than the portion of the code posted.One suggestion:Code:INTCON = 0b11000000; // enable PEIE and GIE interruptsI would rewrite that code using bits, if your compiler supports it:Code:PEIE = 1; //enable peripheral interruptsGIE = 1; //enable global interruptsIn case the positions of PEIE and GIE are different from chip to chip.

author: dannyf
author_rank: Super Contributor
timestamp: March 19, 2014, 12:40:08 am
content: Clarify a little bit further: as I don't have your compiler, I had to set CREN and others bits to get my code to work, in the spirit of your code. Your usart initialization may or may not have done similar things. but the isr is identical (functionally).

author: wicket
author_rank: Contributor
timestamp: March 19, 2014, 08:23:03 am
content: Ok, I decided to leave behind my PIC 887 (I only used it to compare to my 628A and 4520) and only focus on 18F4520, which I'll be using in my final product. I also found 7.3728 MHz oscillator, which gives me 0% baud error using BRGH = 1, BRG16 = 0 and desired baud of 9600 bps.Tried a simple 1 second blinky, works fine.To avoid any potencial mess, I also initialized UART myself, instead of inbuilt UART1_Init() library.Also tried PORTD instead of PORTB. Everything is the same, I do get into the interrupt routine, but an led doesn't turn on when comparing incoming chars.I've measured voltage levels of the circuit (I'm powering it from 7805 reg.):Vdd - 5,02 VPIC Tx pin (GSM Rx) - 5,02 VPIC Rx pin (GSM Tx) - 2,78 VSince I don't own a scope, I was measuring PIC Rx voltage during reception and a slight voltage drop does occur (I know multimeter isn't fast enough, but it seems there definitely is something going into the PIC).

author: SL4P
author_rank: Super Contributor
timestamp: March 19, 2014, 08:50:56 am
content: /* ---Here's the exact code I used on PIC16F887 ( 887 !!)Worked fine with internal 8MHz oscillator (INTOSC) - both PIC to PIC and with many serial terminals - FTDI and RS422 linksIt may be worth looking at the FERR flag, as I found that closes the UART until it is cleared and re-initialised as shown below.--- */// =================================================================:::// ---- serial port --------------------------------------#define SER_19200#ifdef SER_9600TRISC6 = 0;SPBRG = 12; // 9600 bps @ 8MHz CLOCKBRGH = 0; // high speed flagBRG16 = 0;#endif#ifdef SER_19200TRISC6 = 0;SPBRG = 25; // 19200bps @ 8MHz CLOCKBRGH = 1; // high speed flagBRG16 = 0;#endif#ifdef SER_57600TRISC6 = 0;SPBRG = 34; // 57600bps @ 8MHz CLOCKBRGH = 1; // high speed flagBRG16 = 1;#endif// ------------------SYNC = 0; // asynchronousRX9 = 0; // 8 bitCREN = 1; // receiver enabledTX9 = 0; // 8 bitTXEN = 1; // enabledSPEN = 1;:::// =================================================================void sendChar(char c) {while ( (TXIF == 0 ) );TXREG = c; // push char to tx registerDelayUs(100); // allow the receiver to digest the char - no handshake}// =================================================================static void interrupt isr(void) {while (RCIF) { // serial character(s) have been received into FIFOCLRWDT();if (OERR) { // over runCREN = 0; CREN = 1; OERR = 0;rptr = rxBuf; wptr = rxBuf; // reset the rx Bufferbreak;}if (FERR) { // framing errrptr = rxBuf; wptr = rxBuf; // reset the rx Bufferdummy = RCREG; // grab the dud characterbreak;}mychar = RCREG; // put char from rx register into buffer:::}// =================================================================

author: David_AVD
author_rank: Super Contributor
timestamp: March 19, 2014, 09:49:54 am
content: Yes, checking for overruns and frame errors (and reacting to them) is essential.

author: dannyf
author_rank: Super Contributor
timestamp: March 19, 2014, 10:38:47 am
content: Code:if (uart_rd == 10) PORTB.B1 = 1; //if incoming byte is "\n", turn on LEDUseCode:if (uart_rd == 'a') PORTB.B1 ^= 1; //if incoming byte is "\n", turn on LEDand tie RX to TX. Insert a long delay like 500ms in the main loop - don't set b in the main loop.If you observe B1 blinking, your code is working.

author: wicket
author_rank: Contributor
timestamp: March 19, 2014, 01:18:40 pm
content: Using your advices, I programmed the chip in MPLAB (first time using this program, maybe something is way off).First I only tried looping Tx and Rx through UART terminal and it worked fine, I received what I sent, also the LED was turning on/off on defined chars/strings.When I hooked up my GSM, I got the same result as always till now... Transmission works and i get into the interrupt itself, but that's it.Now I'm trying to do FERR and OERR check. I'm reading the18F4520datasheet and it says, that this chip doesn't support hardware parity, but it is possible via software. I simply don't know how to handle this, it probably has to do something with 9-bit reception, whereas the 9th bit is a parity bit?Oh, and I tried to use delays instead of "flag" b in mikroC, but it didn't help. And I don't know how to use a delay in MPLAB, so I couldn't test it there.

author: macboy
author_rank: Super Contributor
timestamp: March 19, 2014, 01:25:49 pm
content: I agree with the above, youmustcheck always for framing and other Rx errors.I always first suspect the baud rate. Try setting BRG one step higher or lower, especially if you see framing errors. Try using a scope to measure the actual baud/bit rate coming out of each device and compare. You must be within 4% error (so each side no more than 2% error high/low from the desired rate). An error of just 5% doesn't sound like much, but consider there are ten bits in each frame (start, data*8, stop), so the tenth bit in each frame will be more 50% out of phase. Then one receiving side will likely see frequent errors. Often when the baud rate error is marginal, only one side sees framing errors.Personal anecdote: I recently set up a terminal server (box with Ethernet and a bunch of network-accessible serial ports) and was getting strange errors talking to many devices. I scoped the signals to the baud rate and saw it was about 4 % low at any baud rate setting. The other device was maybe 1 % high. This caused errors. The fix was easy, just replace a 25 MHz oscillator with a (custom made) 26 MHz one, forcing the baud rate to be always 4% higher. It is now spot-on and can talk error free to everything I have plugged into it.I just saw your post on Parity. Parity is most often not used. You can only use it if the other device does too, and it very very likely does not. There is an extra data bit sent as parity. For PICs, you need to calculate the bit based on your data, then set the (9th) bit in the appropriate register before writing to TXREG. On the receive side, you extract the parity (9th) bit before reading from RXREG, then calculate desired parity from the data bits and compare. Don't concern yourself with this as your device almost certainly does not use it.

author: granz
author_rank: Regular Contributor
timestamp: March 19, 2014, 01:33:17 pm
content: Your voltage on the GSM Tx PIN (PIC RX) looks suspect. Are you trying to interface a 3.3V (or 2.8V?) device with your PIC at 5V?

author: granz
author_rank: Regular Contributor
timestamp: March 19, 2014, 01:58:00 pm
content: Quote from: dannyf on March 19, 2014, 10:38:47 amTying RX to TX doesn't tell you if the baud rate is what you intend, it will work even with non-standard rates.To the OP:There's absolutely no reason you can't use the internal oscillator (HFINTOSC) at 8 MHz for 9600 baud. If you check the datasheet for the 16F887 for example, you will find that the internal oscillator is specified to +/- 2% over 0 C to 85 C. This gives a maximum error of ((8.16MHz / (64*(12+1)))-9600)/9600 = 2.16%. Assuming you are sitting at room temperature it will be much better. Maximum allowable will be around 4.5% for 8bits+parity+stop bit. Your issue is not about crystals, believe me.

author: Skimask
author_rank: Super Contributor
timestamp: March 19, 2014, 02:03:22 pm
content: 18f4520 - has 4xPLL, other 2 chips don't have it.

author: granz
author_rank: Regular Contributor
timestamp: March 19, 2014, 02:19:51 pm
content: Quote from: Skimask on March 19, 2014, 02:03:22 pmTrue, but why does that matter? The 16F887 has 8 MHz without 4xPLL, and the 16F628A has 4 MHz. No reason you need a 32 MHz oscillator to use a UART at 9600.

author: Skimask
author_rank: Super Contributor
timestamp: March 19, 2014, 03:05:07 pm
content: Quote from: granz on March 19, 2014, 02:19:51 pmI know that. You know that. The O/P might not know that.

author: granz
author_rank: Regular Contributor
timestamp: March 19, 2014, 03:16:02 pm
content: Quote from: Skimask on March 19, 2014, 03:05:07 pmGood point!

author: wicket
author_rank: Contributor
timestamp: March 19, 2014, 06:05:38 pm
content: I have PLL disabled.About 2.78 V on Rx pin - I actually started this project using Arduino Uno and it was a complete success. GSM was the same one I'm using with PIC, Sony Ericsson T610. I've read on arduino forums, that this GSM model should support 5 V Tx/Rx.Quote from: Arduino forumsI've never used Atmel chip by itself, so I don't know if there is a difference, but I measured voltages on Arduino again today and they are the same as with PICs.

author: granz
author_rank: Regular Contributor
timestamp: March 19, 2014, 06:26:31 pm
content: In your PIC 18F4520 datasheet, pg. 335, you will note that the spec for VIH says 0.8 VDD on Schmitt Trigger inputs. Your UART RX pin is a Schmitt Trigger input. That means you need 5V * 0.8 = 4V for the high level, so your GSM phone isn't driving it high enough.Anyhow, even if someone on the Arduino forums talks about interfacing with phones at 2.6V with the (presumably) 5V Arduino, that doesn't mean that is really OK. You shouldn't be driving the RX pin on the phone with 5V from your UART if it is using 2.6V logic. Sometimes pins are tolerant, but you want to check that out for sure. (My guess would be no, the phone isn't rated for 5V on it's RX pin).Edit: Not intending to come across harshly. The Arduino forums are filled with bad ideas from an EE perspective, so just keep that in mind.Hope this helps you solve your problem.

author: dannyf
author_rank: Super Contributor
timestamp: March 19, 2014, 06:31:44 pm
content: The voltage on rx pin reflects its duty cycle.

author: granz
author_rank: Regular Contributor
timestamp: March 19, 2014, 06:34:28 pm
content: Quote from: dannyf on March 19, 2014, 06:31:44 pmThat is a good point, but I assume the OP measured the voltages when no data was being transmitted. Yes?Edit: I re-read where you said you measured the voltages "during reception." It's hard to know what you really measured. Since you don't have a scope, check the level on the TX pin from the phone without any communication going on.

author: wicket
author_rank: Contributor
timestamp: March 19, 2014, 08:11:49 pm
content: If I have my GSM hooked up to PIC, the TX voltage on the GSM is the same as if the GSM is disconnected from PIC - 2.78 V. RX voltage on the GSM is 5 V when hooked up and 0 V when disconnected from PIC.I did observe the voltage when I have triggered the transmission and there was a slight (approx. 200 mV) voltage drop on GSM TX / PIC RX pin. But that probably doesn't tell you anything because multimeters refresh rate is to slow.

author: qno
author_rank: Frequent Contributor
timestamp: March 19, 2014, 08:27:31 pm
content: Maybe try a Pull-up resistor?

author: granz
author_rank: Regular Contributor
timestamp: March 19, 2014, 08:47:59 pm
content: Quote from: wicket on March 19, 2014, 08:11:49 pmRight. So that 2.78V is definitely a problem for you, since the PIC requires the HIGH level on the RX pin to be > 4V. The normal UART setup is both lines idle HIGH. The receiver does just that, receives, and doesn't set the level on that line, it is set by the opposite TX output. That is exactly why you see 2.78V on the TX pin on the phone and 0V on the RX pin, until you connect the PIC, which then drives that line to 5V.You are getting your interrupt when the PIC RX line goes LOW the first time, but it never goes high enough again to be detected by the PIC, due to it's Schmitt Trigger input.You need a level shifter. You don't want to just pull that line high with a resistor to your 5V, because then you will be back-driving the output of the GSM phone and current will flow into the output. A level shifter can be made simply with one transistor and resistor because of the low speed in this case. The PIC has a bit which can be set/cleared to invert the UART logic.

author: Unknown
author_rank: Unknown
timestamp: March 19, 2014, 09:13:20 pm
content: In my last PIC project I used a RS232 Bluetooth Module and just used a pullup.

author: granz
author_rank: Regular Contributor
timestamp: March 19, 2014, 09:59:33 pm
content: Quote from: jucole on March 19, 2014, 09:13:20 pmThat diagram is showing 5V TTL to 5V CMOS. The issue in that case is that TTL is based on BJTs, where CMOS is, well, MOSFETs. Those systems are both at 5V. Not the same thing here. Yes, you can sometime get away with a pull-up, but it's not the right way to do it. If you use simply a pull-up, you have current flowing through the body diode on the output transistor of the transmitter (GSM phone). If your project with the Bluetooth module is also at 3.3V you are doing the same thing in that case. This is bad idea.If you don't believe me, have a look at this discussion on the TI forums:http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/60581.aspxTo the OP: why not just run your PIC at 3.3V (or 2.7V?), which will avoid these issues.

author: wicket
author_rank: Contributor
timestamp: March 19, 2014, 10:12:29 pm
content: I'm gonna try both - 3.3 V circuit and level shifter. Maybe even a pullup, just for fun.By the way, I really appreciate everyone's help.

author: dannyf
author_rank: Super Contributor
timestamp: March 20, 2014, 12:04:08 am
content: I would try the pull up first.

author: wicket
author_rank: Contributor
timestamp: March 20, 2014, 09:39:12 am
content: I'm looking at a Voltage - Frequency graph onpage 324.Can I even run this chip from 3.3 V?

author: SL4P
author_rank: Super Contributor
timestamp: March 20, 2014, 10:44:41 am
content: Wicket...I'm looking at a Voltage - Frequency graph on page 324.Can I even run this chip from 3.3 V?PIC18LF2420/2520/4420/4520-INDUSTRIALYes but only if clocked at10MHz or lower...The other chip variants don't seem to be so accommodating

author: dannyf
author_rank: Super Contributor
timestamp: March 20, 2014, 11:00:33 am
content: QuotePut in a couple of diodes on the 5v supply line and you will find.Yes, it will - there is considerable room for tolerance for the specs.

author: wicket
author_rank: Contributor
timestamp: March 20, 2014, 12:32:26 pm
content: AMEN! It's finally working! You were right, I replaced my 5 V regulator with 3.3 V one and it started blinking exactly as it should. 2,78 V was clearly not enough for logical high @ 5 V. I first tried it using 3.6864 MHz crystal, but it even works with internal osc. @ 4 MHz.Oh and just so you know, I also tried using pullup @ 5 V, but it didn't help. I can finally move on now, it took me 10 days to get this right, jesus...Anyway, thanks to everyone!

author: granz
author_rank: Regular Contributor
timestamp: March 20, 2014, 07:58:18 pm
content: Quote from: wicket on March 20, 2014, 12:32:26 pmGlad to hear you got it working!

author: Skimask
author_rank: Super Contributor
timestamp: March 20, 2014, 08:03:37 pm
content: Quote from: wicket on March 20, 2014, 12:32:26 pmmeh...don't feel too bad. You aren't the first one to get bit by this sort of thing. (eg. ST vs TTL vs CMOS inputs/outputs, etc.)

author: wicket
author_rank: Contributor
timestamp: March 21, 2014, 07:22:18 am
content: What would be the best way to boost up the 2.78 V signal from GSM? My entire circuit is based on 5 V (relays, sensors, other chips) and it's kinda awkward for me to use 3.3 V now. Can I use the level shifter just for this signal? Are this things fast enough though?

author: Skimask
author_rank: Super Contributor
timestamp: March 21, 2014, 10:23:24 am
content: Easily fast enough for serial signals.

author: dannyf
author_rank: Super Contributor
timestamp: March 21, 2014, 11:00:07 am
content: QuoteNot sure about the best. The easiest would be to use a pull-up (=resistor + diode).

author: granz
author_rank: Regular Contributor
timestamp: March 21, 2014, 02:23:55 pm
content: Use a single transistor and two resistors. See the attached image. You don't have to use a 2N3904 specifically, any garden variety NPN transistor is fine. Depending on how fast you want to run your serial connection, you may need to reduce the values of the resistors. The values shown should be fine for 9600 or 19200 baud.This will invert the signal into the PIC, so you'll need to change the bit in the UART register for active-high/active-low.The resistor/diode level shifting methods are safe for high-output-to-low-input voltage shifting, but there isn't a safe way to do it low-output-to-high-input, you always have some small current flowing back into the low-voltage supply rail. That is bad because the low-voltage supply can potentially charge up to a higher voltage (most regulators can only source current, not sink). Also, the high value resistors used limit the speed.Transistors are dirt cheap, no reason to not use themGood luck!

author: wicket
author_rank: Contributor
timestamp: March 21, 2014, 03:02:08 pm
content: I've managed to get it working @ 5 V using 2k pullup resistor, but there was indeed 0.5 mA flowing back into the GSM. I'm not sure if that's enough to damage something.I'll try to use the transistor now and invert the logic on PIC.

author: granz
author_rank: Regular Contributor
timestamp: March 21, 2014, 03:12:19 pm
content: Quote from: wicket on March 21, 2014, 03:02:08 pmThe main issue is if the GSM phone goes into a low-power mode and requires less than the current flowing back into it on its supply rail. Since the internal voltage regulator won't be able to sink the extra current, the internal supply voltage rail will rise up a higher voltage, which can damage things. Since you are working with a "black box" (the phone) you really don't know what's going on inside it.Edit: Also consider what happens when the battery is removed from the GSM phone: you then have current flowing into the phone's supply rail, but on the output side of the regulator, so the voltage can rise above the normal supply voltage.

author: dannyf
author_rank: Super Contributor
timestamp: March 21, 2014, 03:47:53 pm
content: QuoteThat would require negative logic.What's best is highly subjective. The pull-up idea is simple. But it may not work in all cases.A more complex approach is to use a logic level mosfet (or bjt + diode). It has the advantage of being positive logic and bi-directional.

author: granz
author_rank: Regular Contributor
timestamp: March 21, 2014, 03:52:59 pm
content: Quote from: dannyf on March 21, 2014, 03:47:53 pmHence why I said to switch the bit in the PIC UART config register.

author: wicket
author_rank: Contributor
timestamp: March 21, 2014, 04:21:42 pm
content: Quote from: granz on March 21, 2014, 02:23:55 pmWorks like a charm!I don't have any mosfets at home, so I'll stick to this for now.

author: granz
author_rank: Regular Contributor
timestamp: March 21, 2014, 04:26:13 pm
content: Glad it's working and you can now move on to other (more interesting) things!

author: dannyf
author_rank: Super Contributor
timestamp: March 21, 2014, 04:43:34 pm
content: Here is a bjt - implementation of the phillips' bi-directional level shifter.V1 is the signal to be transmitted and the pick up, in this case, is on the bjt's collector (or emitter in case the transmission is the other way around).If you only care about 2.7v -> 5v transmission, you can eliminate R1 / D1. If you replace Q1 with a mosfet, you can eliminate R2.I typically include them all in the layout but don't solder them in if the transmission is one directional.

author: granz
author_rank: Regular Contributor
timestamp: March 21, 2014, 04:55:15 pm
content: Also, if you aren't sure if the input (RX) on the GSM phone is really 5V tolerant, consider adding level shifting in the other direction as well. In that case (5V down to 2.7V) at only 9600 baud a simple voltage divider will be fine. Try a 1.8k + 2.2k to ground from the PIC TX line and take the output to the phone from the midpoint. (2.2k+2.2k may be close enough, but the output will be a bit low).If you aren't too concerned about damaging the input on the phone, you can just leave it alone, but two resistors is cheap insurance.

author: granz
author_rank: Regular Contributor
timestamp: March 21, 2014, 04:57:24 pm
content: Quote from: dannyf on March 21, 2014, 04:43:34 pmIs a fine circuit for sure, but requires access to the 2.7V supply rail, which I don't believe is available outside the phone....

author: dannyf
author_rank: Super Contributor
timestamp: March 21, 2014, 05:05:37 pm
content: You can simply pad up the output with a led (or diode string) and tie the base to the 5v rail.

author: granz
author_rank: Regular Contributor
timestamp: March 21, 2014, 06:32:16 pm
content: Quote from: dannyf on March 21, 2014, 05:05:37 pmIt is definitely a nice level shifter topography, I've used it for I2C level shifting. I guess I just don't really see the advantage in this case if you add more components to drop down the 5V rail down to 2.7V. Then you have to either string diodes together, or find an LED with the right forward drop after tweaking the current through it.Actually, reading your sentence again, I'm not really sure what you mean "simply pad up the output with an led (or diode string)"? Adding diodes on the collector side (5V side) will just shift the whole 2.7V waveform up by the diode drop. Sure, he could reach the 4V high level required, but then the low level will be up above 1V which is required by the PIC (0.2*VCC for Schmitt Trigger inputs). But perhaps I am misunderstanding what you mean. Either way, I still posit that the inverting unidirectional shifter is the simplest for this application.

author: dannyf
author_rank: Super Contributor
timestamp: March 21, 2014, 07:06:37 pm
content: I would have simply used a pull-up resistor + diode, and call it a day.

author: granz
author_rank: Regular Contributor
timestamp: March 21, 2014, 07:45:24 pm
content: Quote from: dannyf on March 21, 2014, 07:06:37 pmI think you must be thinking of 5V to 2.7V translation, in which case a single diode+resistor is perfectly safe.Show me how you would drive an input > 4V and < 1V from a 2.7V signal with a pull-up resistor and diode only, with no flowing current back into the 2.7V output. You might as well just leave the diode out, and just use a pull-up resistor, as already discussed (not a great idea).

author: David_AVD
author_rank: Super Contributor
timestamp: March 24, 2014, 02:25:38 am
content: Maybe the modem echos commands sent to it?You really need to hook this thing up to some terminal software so you can see exactly what is being sent by each side.

author: wicket
author_rank: Contributor
timestamp: March 24, 2014, 09:01:21 am
content: Isatdisplayed here because I typed it, or is it echoed back, how do I know that?

author: David_AVD
author_rank: Super Contributor
timestamp: March 24, 2014, 09:30:25 am
content: Quote from: wicket on March 24, 2014, 09:01:21 amYou have "local echo" turned off, so the modem must be echoing it back.