6
\$\begingroup\$

My full code is located here.

Basically, I'm transmitting to an Arduino, and I'm not receiving the correct value (you'll notice I'm trying to send d'22'). Here's the method where I actually bit bang the transmission:

// Method for transmitting value using serial bit banging
void uart_tx_bit_bang(unsigned char val) {
    unsigned char i;
    Tx_Pin = 0;                         // Start bit
    uart_time_delay();
    for ( i = 8 ; i != 0 ; --i ) {
        if (val & 0x01) Tx_Pin = 1;   // Begin with LSB
        else            Tx_Pin = 0;
        val >>= 1;
        uart_time_delay();
        }
    Tx_Pin = 1;                         // Stop bit
    uart_time_delay();
}

Since the delay should be 1/baud, uart_time_delay() should be a 104us delay. I'm using __delay_us(104) from the PIC libraries. Any help on this is greatly appreciated.

I'm positive that I'm using the correct baud rate on both ends.

\$\endgroup\$
  • \$\begingroup\$ UARTs actually send the LSB first. \$\endgroup\$ – PeterJ Apr 23 '13 at 4:54
  • \$\begingroup\$ This code sends LSB-first \$\endgroup\$ – markrages Apr 23 '13 at 4:58
  • 1
    \$\begingroup\$ What value are you receiving? Knowing that would help with troubleshooting. \$\endgroup\$ – Gorloth Apr 23 '13 at 4:58
  • \$\begingroup\$ I was receiving several different values, not just one consistent value. \$\endgroup\$ – Willem Ellis Apr 23 '13 at 5:00
  • \$\begingroup\$ @markrages, yes you're right, the reverse loop order and comment through me \$\endgroup\$ – PeterJ Apr 23 '13 at 5:00
4
\$\begingroup\$

While your calculation of 104uS is correct for 9600BPS your loop and the various operations it performs will be adding an additional delay. There are a few ways you could go about tuning the timing:

  • Subtract a constant from your uS delay until it starts working. It'd probably be best to determine the minimum / maximum number it works with and pick the middle value.

  • Do something similar using a scope to check the final timing if you have one available.

  • Look at the assembler output from the compiler and determine how many cycles the loop takes.

I also see you're using the RC clock. I normally like to keep my serial timing within 2% for reliable operation so also check to make sure the part has that much stability when using the RC clock for reliable operation.

\$\endgroup\$
  • \$\begingroup\$ Thanks! I'll give some of these suggestions a go in the morning and get back to you. \$\endgroup\$ – Willem Ellis Apr 23 '13 at 5:18
  • \$\begingroup\$ I'd agree with PeterJ. I usually have to use an external clock (crystal or resonator) to get accurate data transmission. Plus, the bit twiddling within the loop is adding some time onto your delay. \$\endgroup\$ – Kurt E. Clothier Apr 23 '13 at 7:18
  • \$\begingroup\$ So I think I figured it out. I don't think my uart_time_delay() routine is delaying at all. I'm using the built in __delay_us() method. Any thoughts on this? How can I do a more reliable delay in C? I need it to be 1/baud \$\endgroup\$ – Willem Ellis Apr 24 '13 at 5:49
  • \$\begingroup\$ @WillemEllis, I just noticed you have _XTAL_FREQ defined as 4.0 - I think it should be in Hertz so 4000000, that might be doing something odd. \$\endgroup\$ – PeterJ Apr 24 '13 at 6:06
  • \$\begingroup\$ That was it!!! I am so happy right now! I changed the _XTAL_FREQ to 4000000, and lowered the baud rate to 4800, and it works! Thanks @PeterJ \$\endgroup\$ – Willem Ellis Apr 24 '13 at 17:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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