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

12F629, LEDs and serial

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



Joined: 09 Feb 2009
Posts: 28

View user's profile Send private message

12F629, LEDs and serial
PostPosted: Mon Feb 09, 2009 6:36 pm     Reply with quote

Would it be possible to use RS232 (soft uart) and updating LEDs all in the same time using the 12F629 microcontroller and CCS. I basically would like to have a main loop updating the LEDs and be able to receive from the serial port. The serial interface will be used to change how many LEDs will be updated. I suppose it would involve some kind of a interrupt.

Is it doable without using assembler and what would I have to think about?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Feb 09, 2009 7:11 pm     Reply with quote

What are the LEDs doing ? Are they simply turned on/off by a serial
port command, or are they blinking in patterns, and the patterns are
controlled by serial port commands ?

Are the LEDs in fact 7-segment displays ?
test153



Joined: 09 Feb 2009
Posts: 28

View user's profile Send private message

PostPosted: Tue Feb 10, 2009 4:32 am     Reply with quote

The LEDs are connected in a double matrix allowing 12 LEDs to be controlled using only five pins, therefore only one LED can be on at a time so the processor needs to switch the LEDs on and off continuously. The serial port will be used to control how many of the 12 LEDs will be on.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Feb 10, 2009 5:18 pm     Reply with quote

Here's a demo program. Pin A3 has to be used for serial reception
because it's an input-only pin, and you need the other five pins to drive
your LEDs. If you need anything beyond this, you should write the code
for it. I didn't test this in hardware, but it will probably work.
Code:
#include <12F629.h>
#fuses INTRC_IO,NOWDT,NOBROWNOUT,NOPROTECT,NOMCLR
#use delay(clock=4000000)
#use rs232(baud=9600, rcv=PIN_A3)

#define write_OLED(x) \
output_bit(PIN_A0, x & 1); \
output_bit(PIN_A1, x & 2); \
output_bit(PIN_A2, x & 4); \
output_bit(PIN_A4, x & 8); \
output_bit(PIN_A5, x & 0x10)

//===============================
void main()
{
char command;

write_OLED(0);  // Initialize LEDs to all off

while(1)
  {
   command = getc();  // Wait for char
   write_OLED(command);  // Update the LED display
  }   

test153



Joined: 09 Feb 2009
Posts: 28

View user's profile Send private message

PostPosted: Tue Feb 10, 2009 5:34 pm     Reply with quote

Thank you!
I only asked if it was possible but you were kind enough to even post a demo code. Thank you again.
test153



Joined: 09 Feb 2009
Posts: 28

View user's profile Send private message

PostPosted: Tue Feb 10, 2009 8:01 pm     Reply with quote

I have put together the code below and it's working well except that I need to send two characters through the serial port. If I only send one the main loop will not continue, as if the processor was still stuck in the interrupt routine...
Code:
#include <12F629.h>
#fuses INTRC_IO,NOWDT,NOBROWNOUT,NOPROTECT,NOMCLR
#use delay(clock=4000000)
#use rs232(baud=9600, rcv=PIN_A3)

#define ALL_IN  0xff  //address for your chip

char command;

//===============================
#INT_RA
void  serialis_isr(void)
{
disable_interrupts(INT_RA);
command = getc();  // Wait for char
clear_interrupt(INT_RA);
enable_interrupts(INT_RA);
}

void led1() {
   set_tris_a(ALL_IN);
   output_low(PIN_A0);
   output_high(PIN_A5);
}

void led2() {
   set_tris_a(ALL_IN);
   output_low(PIN_A5);
   output_high(PIN_A0);
}

void main()
{

   enable_interrupts(INT_RA3);
   enable_interrupts(GLOBAL);

while(1)
  {
   if (command==49) {led1();}
   if (command==50) {led1(); led2();}
  }   

}
Ttelmah
Guest







PostPosted: Wed Feb 11, 2009 3:42 am     Reply with quote

First, get rid of the enable/disable & clear interrupt lines in the interrupt. Not needed. The hardware disables all interrupts while an interrupt is being serviced, and the compiler automatically clears interrupts for you when the handler finishes.
Change INT_RA, to INT_RA3, which is the pin receiving the serial data. Otherwise if the pins are floating (they all are at times), interrupts can trigger from the other pins, and you will then sit in the interrupt waiting, till the serial data arrives - this is probably what is happening.
Get rid of your 'ALL_IN' fiddling with TRIS. Tris is being set automatically for you by the compiler, making the pins you drive as outputs, into outputs. You are changing them to inputs, before the compiler does this. Because of this, RA, will trigger on the pins (it triggers when an input changes level, if they are left as outputs, this won't happen).

Best Wishes
test153



Joined: 09 Feb 2009
Posts: 28

View user's profile Send private message

PostPosted: Wed Feb 11, 2009 6:19 am     Reply with quote

The pin A0-A2 & A4-A5 need to be inputs, otherwise no current can flow back through them.

Anyway using "#INT_RA3" gives me a compiler error - "Invalid pre-processor directive".

Bellow is the final program and it works as intended but I need all those if statments in the interrupt routine otherwise nothing will happen as if it didn't return back to the main loop.

Code:

#include <12F629.h>
#fuses INTRC_IO,NOWDT,NOBROWNOUT,NOPROTECT,NOMCLR
#use delay(clock=4000000)
#use rs232(baud=9600, rcv=PIN_A3)

char command;

//===============================
void resetPorts() {
input(PIN_A0);
   input(PIN_A1);
   input(PIN_A2);
   input(PIN_A4);
   input(PIN_A5);
}

void led1() {
resetPorts();
   output_low(PIN_A0);
   output_high(PIN_A5);
}

void led2() {
resetPorts();
   output_low(PIN_A5);
   output_high(PIN_A0);
}

void led3() {
resetPorts();
   output_low(PIN_A1);
   output_high(PIN_A5);
}

void led4() {
resetPorts();
   output_low(PIN_A5);
   output_high(PIN_A1);
}

//Next matrix line

void led5() {
resetPorts();
   output_low(PIN_A0);
   output_high(PIN_A4);
}

void led6() {
resetPorts();
   output_low(PIN_A4);
   output_high(PIN_A0);
}

void led7() {
resetPorts();
   output_low(PIN_A1);
   output_high(PIN_A4);
}

void led8() {
resetPorts();
   output_low(PIN_A4);
   output_high(PIN_A1);
}

//Next matrix line

void led9() {
resetPorts();
   output_low(PIN_A0);
   output_high(PIN_A2);
}

void led10() {
resetPorts();
   output_low(PIN_A2);
   output_high(PIN_A0);
}

void led11() {
resetPorts();
   output_low(PIN_A1);
   output_high(PIN_A2);
}

void led12() {
resetPorts();
   output_low(PIN_A2);
   output_high(PIN_A1);
}

void main()
{
  enable_interrupts(INT_RA3);
  enable_interrupts(GLOBAL);
 
    resetPorts();

while(1)
  {
   if (command==49) {led1();}
   if (command==50) {led1(); led2();}
   if (command==51) {led1(); led2(); led3();}
   if (command==52) {led1(); led2(); led3(); led4();}
   if (command==53) {led1(); led2(); led3(); led4(); led5();}
   if (command==54) {led1(); led2(); led3(); led4(); led5(); led6();}
   if (command==55) {led1(); led2(); led3(); led4(); led5(); led6(); led7();}
   if (command==56) {led1(); led2(); led3(); led4(); led5(); led6(); led7(); led8();}
   if (command==57) {led1(); led2(); led3(); led4(); led5(); led6(); led7(); led8(); led9();}
   if (command==58) {led1(); led2(); led3(); led4(); led5(); led6(); led7(); led8(); led9(); led10();}
   if (command==59) {led1(); led2(); led3(); led4(); led5(); led6(); led7(); led8(); led9(); led10(); led11();}
   if (command==60) {led1(); led2(); led3(); led4(); led5(); led6(); led7(); led8(); led9(); led10(); led11(); led12();}
  }   

}

#int_ra
void  int_rb_isr(void)
{
command = getc();  // Wait for char
   if (command==49) {led1();}
   if (command==50) {led1(); led2();}
   if (command==51) {led1(); led2(); led3();}
   if (command==52) {led1(); led2(); led3(); led4();}
   if (command==53) {led1(); led2(); led3(); led4(); led5();}
   if (command==54) {led1(); led2(); led3(); led4(); led5(); led6();}
   if (command==55) {led1(); led2(); led3(); led4(); led5(); led6(); led7();}
   if (command==56) {led1(); led2(); led3(); led4(); led5(); led6(); led7(); led8();}
   if (command==57) {led1(); led2(); led3(); led4(); led5(); led6(); led7(); led8(); led9();}
   if (command==58) {led1(); led2(); led3(); led4(); led5(); led6(); led7(); led8(); led9(); led10();}
   if (command==59) {led1(); led2(); led3(); led4(); led5(); led6(); led7(); led8(); led9(); led10(); led11();}
   if (command==60) {led1(); led2(); led3(); led4(); led5(); led6(); led7(); led8(); led9(); led10(); led11(); led12();}
}


Last edited by test153 on Wed Feb 25, 2009 3:26 pm; edited 1 time in total
Ttelmah
Guest







PostPosted: Wed Feb 11, 2009 10:57 am     Reply with quote

INT_RA3 giving an error, implies you have a fairly old compiler.
You will need to handle this all yourself then.
Basically, you need to read the whole port in the interrupt, and check that the A3 pin has dropped. If it has, call the getc, otherwise just exit the interrupt.
Done like this, you no longer need all the tests in the interrupt, and the interrupt will return, except when a character is received.
As it currently stands, interrupts will be disabled for most of the time, since calling a function both inside, and outsid an interrupt, results in interrupts being disabled in this function....
All your pins will currently stay as outputs, once used.
If you want to control the TRIS, then use 'fast_io', and control it for each operation.

Best Wishes
test153



Joined: 09 Feb 2009
Posts: 28

View user's profile Send private message

PostPosted: Wed Feb 11, 2009 11:18 am     Reply with quote

I don't think I'm using an old compiler, the version I'm using is 4.084.
All the pins are rest to input in the beginning of every ledX() routine by calling resetPorts(). I still want to return from the interrupt routine even if I get a character.

I have modifed the interrupt routine but it's not working at all now.
Code:
#int_ra
void  int_rb_isr(void)
{
if (input_state(pin_A3)==1) {
//command=60; // This works great
command = getc();  // This doesn't work
}
}


Edit: Changing "input_state(pin_A3)==1" to "input_state(pin_A3)==0" did the trick. It seems to work now, will get back after running some more tests...
Ttelmah
Guest







PostPosted: Wed Feb 11, 2009 1:52 pm     Reply with quote

The start bit of a serial character is a _low_, not a high.
Your test is the wrong way round.

Best Wishes
test153



Joined: 09 Feb 2009
Posts: 28

View user's profile Send private message

PostPosted: Wed Feb 11, 2009 4:28 pm     Reply with quote

Thank you for your assistance.
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