CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Async comm with PIC12F675 at 32.768KHz?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
starfire151



Joined: 01 Apr 2007
Posts: 195

View user's profile Send private message

Async comm with PIC12F675 at 32.768KHz?
PostPosted: Mon Sep 01, 2008 7:06 pm     Reply with quote

Is it possible to get a reliable asynchronous, bi-directional communications link using a PIC12F675 running at 32.768KHz?

I have done some basic tests with a rate of 300 baud (3.333ms/bit) with no success. The clock running at 32.768KHz should mean the instruction cycle is roughly 122us. This should be around 27 instruction cycles per bit. I used the following code to check for output and input:
Code:

#include <12F675.h>
#device adc=8
#fuses NOWDT, LP, NOPROTECT, NOMCLR, PUT, NOBROWNOUT
#use delay(clock=32768)
#use rs232(baud=300, parity=N, xmit=PIN_A2, rcv=PIN_A3, bits=8)

void main()
{
   char ch;
   setup_counters(RTCC_INTERNAL, RTCC_DIV_1);
   set_tris_a(0x08);       // a0, a1, and a2 : outs; a3 : in
   port_a_pullups(0x07);   // pullups on a0 through a2 (no pullup on a3)
   set_rtcc(0);
   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_8 | RTCC_8_BIT);

   ch = 'x';                     // default char
   while(TRUE)
   {
      if(kbhit())
      {
         ch = getc();            // get char
         printf("%c ", ch);      // print char
      }
   }
}

Is there an easier way to get a slow data communications link working between two processors? I only need to communicate one or two characters each way. Is there a way to do this with one wire?

Thanks for any insight...

Dave
Ttelmah
Guest







PostPosted: Tue Sep 02, 2008 2:25 am     Reply with quote

The problem is that 'simple' async, needs quite a lot of work. For transmit, you need to rotate a bit from the source word, and output it for the required time. Probably 'do-able'. However for receive, you need to sample in the 'middle' of the bit time, receive a bit, and rotate this into the required location. I posted on a thread some time ago, the instruction counts involved, and the total is surprisingly large. I'd say you could probably happily do 50bps both ways. Probably handle the transmit OK at perhaps 200bps, but have problems with the receive.
Unless you 'need' 300bps, go down to something like 50bps, or switch to a chip that has a hardware UART.
The alternative is to go 'custom', and write your own routines. If (for instance), you just sample the bits into a byte array, then perform the assembly of the byte after the receive, this would probably work. Even with assembler, getting the timings to work really well at 300bps, will be quite difficult. However for 'comparison', I wrote an assembler transmit and receive, that handled _full duplex_ at 75bps at a similar clock rate, but on a '16' chip, with the advantage of more hardware timers.

Best Wishes
Guest








PostPosted: Tue Sep 02, 2008 2:40 am     Reply with quote

Quote:
Is there a way to do this with one wire?
How about the 'One wire' protocol? Developed by Dallas Semiconductor, now owned by Maxim.

You will have to make some changes to the protocol timings as your clock is too slow, but because you are implementing both the master and slave devices this shouldn't be a problem.

An example driver is provided in the the CCS examples directory. Several more implementations can be found in this forum (search for 'DS1822', a one-wire temperature sensor).
starfire151



Joined: 01 Apr 2007
Posts: 195

View user's profile Send private message

PostPosted: Tue Sep 02, 2008 7:17 am     Reply with quote

Thanks for the replies...

I suspected the software receive routine would be fairly complicated and take a lot of instruction cycles. Thanks for confirming that. Ultimately I need this communication link between two processors. The first is running in a very low power mode (thus the 32.768KHz clock). It controls the power to a second processor running at about 20MHz. At the conclusion of the second processor's program, it needs to send a sequence back to the first processor to tell it to power down the second processor for a period of time. The second processor also has to sometimes communicate a command to tell the first processor to change the power down period.

I had been accomplishing this with a single wire sending a series of pulses from the second processor to the first. The count of pulses received by the first processor would determine the needed action. I had the pulses set to 10ms low and 20ms high with up to 10 pulses being sent (300ms max). The first processor looked for an input high-to-low interrupt and, when seen, would start a 1-second timer. The interrupt would count the number of pulses and the total number would be reported to the background routine at the end of the 1-second period. The count would determine the action. This was a blind output from the second processor, though, with no way for the second processor to confirm the first processor received the command correctly. There have been cases in the field where the command was received incorrectly. I'm trying to add some reliability and confirmation to the interface.

I have checked the 1-wire Maxim protocol a bit but the same problem with data rate will exist. I thought a simple 10-bit baud packet at a slow data rate might be a little more reliable. I could use specific ASCII characters with bit patterns to minimize confusion with invalid commands.

I will check into using 50 baud as this would still only take around 200ms to send a character. Unfortunately Hyperterminal only goes down to 110 baud. Is there a freeware terminal emulator that will go down to 50 baud?

Thanks, again.

Dave
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Tue Sep 02, 2008 9:23 am     Reply with quote

Two bit lines between the processors also would allow a reduced speed I2C protocol, possibly more easy than 1-wire cause it doesn't rely on a specific timing, except for leaving enough time for the slave to recognize the bus level changes.
Guest








low baud rate
PostPosted: Tue Sep 02, 2008 3:16 pm     Reply with quote

I've used a simple 24 Baud( yes, 24 bits per second, yawn...) single wire 3 state protocol communications network for the past 25+ years.Originally a 6800 series processor,later a 68HC11,currently upgrading to a PIC.
It is dead simple but very,very reliable going about 25 miles(yes MILES) over plain old telephone hard copper cables.
Jay
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Sep 02, 2008 4:00 pm     Reply with quote

I2C is a nice protocol using only two wires but slave implementation is very difficult to do in software.
A better alternative would be SPI. Default SPI is full-duplex and uses 3 wires but some non-standard versions exist using two wires at the trade off of being half duplex.

Just curious: The low power processor's only purpose is to wake up the main processor at specified time intervals? If yes, then why not use a standard Real Time Clock chip? These are designed for that exact purpose including 1 or more alarm registers with outputs that will trigger your High Performance CPU.
Using one of these chips will save you the time of designing the low power CPU software, the chips are tested, optimized for low power and don't require to be flash programmed during production.
John P



Joined: 17 Sep 2003
Posts: 331

View user's profile Send private message

PostPosted: Wed Sep 03, 2008 3:54 pm     Reply with quote

I'm certain that you can do this for 300 baud. The only requirement is that the processor mustn't need to be doing anything else at the same time.

Don't use interrupts. Just have the processor sit in a loop polling the incoming data line:

Code:

    while(bit_test(SERIAL_IN))
      ;                                   // Do nothing till line goes low


When you get a low-going edge, have the processor run through a series of NOP statements arranged to take 1.5 bit times altogether. Then store the first data bit.

Code:

    NOP                                  // 1.5 bit times worth of NOPs
    NOP
#ENDASM
    if (bit_test(SERIAL_IN))
      bit_set(new_byte, 0);
    else
   {
      bit_clear(new_byte, 0);
      bit_clear(new_byte, 0);    // This wastes time so 1/0 are equal length
    }
#ASM
    NOP                                 // Now 1 bit times worth of NOPs
    NOP                                 // then look for the next bit


Then repeat for bit 1, bit 2 etc. This scheme should work for 600 baud, but I don't think it will do 1200.

Compared with receiving, transmitting is so easy that I won't bother with it.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group