Author Topic: PIC PORT value with Switch statements  (Read 11959 times)

0 Members and 1 Guest are viewing this topic.

Offline Hal9000Topic starter

  • Supreme Robot
  • *****
  • Posts: 338
  • Helpful? 0
PIC PORT value with Switch statements
« on: February 16, 2007, 09:30:39 AM »
Hi there,

I am using RB4, RB5, RB6 and RB7 on a PIC16F628a microcontroller

Each pin goes low when it recieves sound, in order that timer readings (from Timer1) can be taken and then output these to the screen.

Say if RB1 recieves the sound (goes low) before the others, it should be assigned Timerreading = 0
RB4 is next, say
Then RB3
And finally RB2

Then output from RS232 RB1=0,RB2=70,RB3=60,RB4=20, for example

The problem I am having is where to start with conditional loops. Ovbiously a switch statement would be ideal, but I don't know how it could be implemented.

Would it be something like:

switch (PORT B)

case 0b00001110:
 //Stuff that happens when RB7 is activated (i.e set the timer reading for RB7 to 0, start timer and poll for the other pins)
break;
case 0b00001101:
 //Stuff that happens when RB6 is activated (i.e set the timer reading for RB6 to 0, start timer and poll for the other pins)
break;
case 0b00001011:
 //Stuff that happens when RB5 is activated (i.e set the timer reading for RB5 to 0, start timer and poll for the other pins)
break;
case 0b00000111:
 //Stuff that happens when RB4 is activated (i.e set the timer reading for RB4 to 0, start timer and poll for the other pins)
break;
default:
break;

Thing is RB0,RB1,RB2 and RB3 are doing different things, and will always be changing state, therefore meaning that my switch statement wouldnt work, right?

I was looking at http://www.learn-c.com/experiment1.htm, but it's all very confusing.

Thanks for taking a look!
« Last Edit: February 16, 2007, 09:33:08 AM by Hal9000 »
"The truth is, you can't hide from the truth, cos the truth is all there is" - Handsome Boy Modeling School

Offline JesseWelling

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 707
  • Helpful? 0
  • Only You Can Build A Robot!
Re: PIC PORT value with Switch statements
« Reply #1 on: February 16, 2007, 11:46:04 AM »
Are you making the sound?
E.G. are you doing some kind of sonar here or just trying to detect any sound?

Offline Admin

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: PIC PORT value with Switch statements
« Reply #2 on: February 16, 2007, 02:17:21 PM »
Quote
Thing is RB0,RB1,RB2 and RB3 are doing different things, and will always be changing state

Have you considered running interrupts?

Basically call an interrupt when a pin changes, then go to your case based stuff to 1) figure out which pin changed and 2) run your action code.

Offline Hal9000Topic starter

  • Supreme Robot
  • *****
  • Posts: 338
  • Helpful? 0
Re: PIC PORT value with Switch statements
« Reply #3 on: February 17, 2007, 05:00:37 AM »
Thanks for your replies.

I am not making sound, but simply detecting the time difference between sound arriving at different locations from one source.

I have considered using interrupt on pin changes, but my application will also have to know where the interrupt came from, so I would then have to poll for the sensors.

Therefore, as I was saying, if the sound was recieved at RB4 first, then this would start the timer, and assign the timervalue belonging to RB4 to 0.

If RB5 was to get the sound next, then it would assign a timer value to this
Then If RB7 was to get the sound next, then it would assign a timer value to this
Then If RB6 was to get the sound next, then it would assign a timer value to this and then output ALL the values over RS232

If you can imagine, after I did one interrupt, not only would I have to poll for the sensor, but I would also have to carry on with some other form of loop anyway, for the other sensors after the first. This is how i arrived at switch statements.

e.g (To get a logical idea, I have used the word 'if'. This is not indicative that I will be using If statements)

If RB4
then poll for RB5, RB6, RB7<---------------see below
If RB5
then poll for RB4, RB6, RB7
If RB6
then poll for RB4, RB5, RB7
If RB7
then poll for RB4, RB5, RB6


To poll for RB5,RB6 and RB7 you would have another switch statement

If RB5
then poll for RB6, RB7<----------------------see below
If RB6
then poll for RB5, RB7
If RB7
then poll for RB5, RB6

To poll for RB6 and RB7 you would have another switch statement

If RB6
then poll for RB7<---------------see below
If RB7
then poll for RB6

At this point, you would then wait for RB7, which is now the last sensor to detect the sound. After you have all the timing readings, you would then output them all over RS232, which I already have set up.

But, I guess my whole question was, how would you implement a switch statement with only the last 4 bits?

(0b00001111)

Cheers

Ian
"The truth is, you can't hide from the truth, cos the truth is all there is" - Handsome Boy Modeling School

Offline Admin

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: PIC PORT value with Switch statements
« Reply #4 on: February 17, 2007, 08:15:51 AM »
this is probably how id do it. timingarray[] would store both the port number and the time recorded.

Code: [Select]
interrupt:
  {
  if RB4 = high && timingarray does not have number=4 yet
     number=4;

  if RB5 = high && timingarray does not have number=5 yet
     number=5;

  if RB6 = high && timingarray does not have number=6 yet
     number=6;

  if RB7 = high && timingarray does not have number=7 yet
     number=7;

  timingarray[i]=number;
  i++;
  timingarray[i]=time_from_timer();
  i++;
  }

main loop:
  wait for sound
  if i=7 //array is full and all sensors recorded
     printf(the array);

edit: after posting that code, i realized that the 'bracket i bracket' also means use italics . . . i also had my i++ in the wrong spot.
« Last Edit: February 17, 2007, 10:26:21 AM by Admin »

Offline Hal9000Topic starter

  • Supreme Robot
  • *****
  • Posts: 338
  • Helpful? 0
Re: PIC PORT value with Switch statements
« Reply #5 on: February 17, 2007, 09:08:06 AM »
Oh I see now, yeah, i'll give this a try

Thanks :)
"The truth is, you can't hide from the truth, cos the truth is all there is" - Handsome Boy Modeling School

Offline Hal9000Topic starter

  • Supreme Robot
  • *****
  • Posts: 338
  • Helpful? 0
Re: PIC PORT value with Switch statements
« Reply #6 on: February 17, 2007, 10:21:50 AM »
ahh, ok lol. yeah, thats a pretty easy mistake to make with arrays!
"The truth is, you can't hide from the truth, cos the truth is all there is" - Handsome Boy Modeling School

Offline Hal9000Topic starter

  • Supreme Robot
  • *****
  • Posts: 338
  • Helpful? 0
Re: PIC PORT value with Switch statements
« Reply #7 on: February 17, 2007, 10:28:10 AM »
Actually, i'm a bit confused about the whole CCP thing......and interrupts in general. Is it true there is a naming convention for these CCPs?

what I have here (from some example code) is

Uint16 at 0x2007 __CONFIG = CONFIG_WORD;

static void Intr(void) interrupt 0
{
}

"The truth is, you can't hide from the truth, cos the truth is all there is" - Handsome Boy Modeling School

Offline Hal9000Topic starter

  • Supreme Robot
  • *****
  • Posts: 338
  • Helpful? 0
Re: PIC PORT value with Switch statements
« Reply #8 on: February 17, 2007, 10:29:23 AM »
/**
 * Simple Interrupt-On-B4...B7-Changed example.
 * Derived from http://tams-www.informatik.uni-hamburg.de/applets/hades/webdemos/72-pic/08-counter/count.html
 *
 * The manual says this interrupt occurs when any pin from B4 through B7
 * "changes", but this isn't exactly true.  The interrupt occurs when
 * the value WRITTEN TO B4...B7 doesn't match the value READ FROM B4...B7.
 *
 * So we set PORTB as all inputs, enable the pullup resistors to pull
 * them all high, and write 0xff to PORTB so the output matches the input.
 * Then we wait for the interrupt signalling something's pulled one down.
 *
 * When the interrupt occurs, we read the value from PORTB and write it
 * back so that the outputs match the inputs again.  If we didn't do
 * this, the interrupt would fire CONSTANTLY  instead of just ONCE since
 * the pin has ALWAYS CHANGED.
 */
#define __16f628a
#include "pic/pic16f628a.h"
#include "tsmtypes.h"
 
// Set the __CONFIG word:
// I usually set it to _EXTCLK_OSC&_WDT_OFF&_LVP_OFF&_DATA_CP_OFF&_PWRTE_ON
Uint16 at 0x2007  __CONFIG = CONFIG_WORD;

static Uint8 count;
static Uint8 breg;

// No C equivalent, so we make one with inline ASM.
// Pin interrupts can wake a PIC up, timer interrupts will not
#define sleep() __asm sleep __endasm

static void Intr(void) interrupt 0
{
   PORTA=count;   // PORTA0...A3 is count value.
   count++;   // Increment count

   breg=PORTB;   // Read PORTB inputs into breg.
   PORTB=breg;   /** Write that value back into PORTB latch values.
          * The interrupt compares the inputs to the PORTB
          * latch values, so if we don't update the latch
          * values, the interrupt will fire constantly!
          */

   RBIF=0;      // Clear PORTB4...7 interrupt flag

//   GIE=1;      // Globally enable interrupts.
         /**  We don't need to do this ourselves since
          *  the compiler ALWAYS ADDS THIS FOR US
          *  in interrupt functions!
          *  If you try and DISable interrupts in an
          *  interrupt function it WON'T WORK since
          *  the compiler ALWAYS turns them back ON!
          */
}

static void main(void)
{
   NOT_RBPU=0;      // Enable PORTB pullups

#ifdef __16f628a   // Only compile this section for PIC16f628a
        CMCON = 0x07;   /** Disable comparators.  NEEDED FOR NORMAL PORTA
                         *  BEHAVIOR ON PIC16f628a!
                         */
#endif

   TRISB=0xff;      // PORTB is all inputs
   TRISA=0x00;      // PORTA is all outputs
   PORTB=0xff;      /** The interrupt compares current
             *  inputs to PORTB latch values.
             *  We set latch values to all 1 to start.
             */
   count=0;
   PORTA=count;      // Turn PORTA outputs low

   INTCON=0x00;      // Clear interrupt register completely.
   RBIE=1;         // Enable ONLY PORTB/B4...B7 interrupt.
   GIE=1;         // Globally enable interrupts.

   while(1) sleep();   /** Wait for interrupts.  We COULD
             *  just make an infinite loop here,
             *  but sleeping saves power.
             */
}
"The truth is, you can't hide from the truth, cos the truth is all there is" - Handsome Boy Modeling School

Offline Admin

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: PIC PORT value with Switch statements
« Reply #9 on: February 17, 2007, 10:55:52 AM »
hmmmm i believe you already know more than i do on interrupts . . .

ive done interrupt code on the interrupt pins and timers . . . but that was years ago . . . and im a mechanical engineer . . . (Jesse, this is your cue :P)

i looked through some of my old code, but couldnt really find anything useful to help you

also, for posting code, just do 'bracket code bracket' (your code here) 'bracket /code bracket'

mozilla puts your code into a special box and looks nice, and IE . . . well it makes it look better but not by much . . .

Offline Hal9000Topic starter

  • Supreme Robot
  • *****
  • Posts: 338
  • Helpful? 0
Re: PIC PORT value with Switch statements
« Reply #10 on: February 18, 2007, 12:25:48 PM »
Oh cool. Thanks for all your imput anyway!

It's been a good help in the right direction!

Ian :)
"The truth is, you can't hide from the truth, cos the truth is all there is" - Handsome Boy Modeling School

Offline JesseWelling

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 707
  • Helpful? 0
  • Only You Can Build A Robot!
Re: PIC PORT value with Switch statements
« Reply #11 on: February 18, 2007, 02:38:10 PM »
Interupts on Pic? sorry I never did it on my pic....and I switched to the AVR right after my first (and only) project with a pic
and all my coding on a pic was in assembly.... :-[
sorry.....I'll try to take a look at it tonight see if I can't suse any thing out.

Offline Hal9000Topic starter

  • Supreme Robot
  • *****
  • Posts: 338
  • Helpful? 0
Re: PIC PORT value with Switch statements
« Reply #12 on: February 19, 2007, 04:31:17 AM »
Oh cool! Well, I've been doing a bit of reasearch and about to test something out now. My battery ran out last night and i'm back in uni now for some more hot PIC action.
"The truth is, you can't hide from the truth, cos the truth is all there is" - Handsome Boy Modeling School

Offline JesseWelling

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 707
  • Helpful? 0
  • Only You Can Build A Robot!
Re: PIC PORT value with Switch statements
« Reply #13 on: February 19, 2007, 02:55:57 PM »
I read the whole interupt thing, and it made sense but with out taking a day to learn your compiler I'm afraid I can't say how to implement that in C on a pic with a compiler I don't know. Sorry  :-\

I could tell you more about interupts in general if that would help.

Offline Hal9000Topic starter

  • Supreme Robot
  • *****
  • Posts: 338
  • Helpful? 0
Re: PIC PORT value with Switch statements
« Reply #14 on: February 20, 2007, 05:41:45 AM »
Well, I use the PICC Lite, which doesn't help with making things easy for me.

I have used interrupts before, but only for one device. Therefore I only just recently realised that it differs from compiler to compiler.

So, yeah, i'll try giving things a go, but I might have to resort to loops or whatever if I can't do it.

Thanks for your help :)

Ian :)
"The truth is, you can't hide from the truth, cos the truth is all there is" - Handsome Boy Modeling School

Offline snow

  • Full Member
  • ***
  • Posts: 73
  • Helpful? 0
Re: PIC PORT value with Switch statements
« Reply #15 on: February 21, 2007, 08:36:13 AM »
> But, I guess my whole question was, how would you implement a switch statement with only the last 4 bits?

You should use: switch(PORTB&0b00001111), but here you have to implement 16 different cases! 0001, 0010, 0011 (two soundes recieved at the same time).

I would do something like (you can put this code into interrupt routine as well):
Code: [Select]
void main()
{
//set up TRISB and TMR1

unsigned int time4,time5,time6,time7;
unsigned char state;

state=0;

while(1)
{
if(RB4==0)
{
if(state&1<<4==0)
{
time4 = TMR1H<<8 + TMR1L;
state|=1<<4;
}
}

if(RB5==0)
{
if(state&1<<5==0)
{
time5 = TMR1H<<8 + TMR1L;
state|=1<<5;
}
}

if(RB6==0)
{
if(state&1<<6==0)
{
time5 = TMR1H<<8 + TMR1L;
state|=1<<6;
}
}

if(RB7==0)
{
if(state&1<<7==0)
{
time5 = TMR1H<<8 + TMR1L;
state|=1<<7;
}
}

if(state==0b11110000)
{
//rs232(time4); ....

state=0;
}
}


}

Something like this. But you should also make sure your timer doesnt overlap (you can set TMR1 to 0 when you recieve first pulse) or you can track which sensor recieved first and then you do substract its value from all recorded values.

And another thing might(?) happen is that one (or more) sensors wont recieve singal. Make sure you know how will that affect your program exectution. Solution would be to measure time from first recieved signal and start some timer which will reset everything if you dont get all the signals.

I am also working with hitech c compiler. Or sometimes with c30 compiler.

Offline Hal9000Topic starter

  • Supreme Robot
  • *****
  • Posts: 338
  • Helpful? 0
Re: PIC PORT value with Switch statements
« Reply #16 on: February 21, 2007, 11:02:51 AM »
Thanks for that snow! Yeah, it's been pretty difficult, even though it looks like an easy task. I just want to make everything happen as fast as possible. As for the interrupts, I found out that the PIC just generates one general interrupt, and then you have to find out which one it was with if loops hahah. Sounds a bit dodge to me but it goes something like this:

Code: [Select]
static void interrupt
isr(void)                       // Here be interrupt function - the name is
                                // unimportant.
{
        if(T0IF) {                              // timer interrupt
                TMR0 -= 250;                    // reload the timer - 250uS per interrupt
                T0IF = 0;                       // clear the interrupt flag
                if(relay_timer != 0)            // is the relay timer running?
                        relay_timer--;          // decrement it
                if(relay_timer == 0)            // if it has time out
                        RELAY = 1;              // turn the relay off
                PORTB ^= 0x40;                  // toggle a bit to say we're alive
        }
        if(INTF) {                              // did we see a button press?
                RELAY = 0;                      // turn the relay on
                relay_timer = 4000;             // start the timer - 4000 ticks = 1 second
                INTF = 0;                       // clear the interrupt
        }
}


For the high-end devices, the vector address is specified e.g. the timer0
interrupt is usually at location 0x10 (see the data sheet for vector
addresses). Here's the example:

void interrupt timer0_isr(void) @ 0x10
"The truth is, you can't hide from the truth, cos the truth is all there is" - Handsome Boy Modeling School

Offline Hal9000Topic starter

  • Supreme Robot
  • *****
  • Posts: 338
  • Helpful? 0
Re: PIC PORT value with Switch statements
« Reply #17 on: February 22, 2007, 08:04:51 AM »
Ok! I know this is a bit lame to all you who have done it before, but I actually did it! Thanks for all your help!

Code: [Select]

void interrupt isr(void)
{
if(RBIE && RBIF)
{
printf("7");
RBIF = 0;
}
if(TMR1IF && TMR1IE)
{
printf("F");
TMR1IF = 0;
}
}

"The truth is, you can't hide from the truth, cos the truth is all there is" - Handsome Boy Modeling School

Offline Admin

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: PIC PORT value with Switch statements
« Reply #18 on: February 22, 2007, 11:07:10 AM »
post all your code please! :P i might reference it in the future if i ever need to use a PIC . . .

Offline Hal9000Topic starter

  • Supreme Robot
  • *****
  • Posts: 338
  • Helpful? 0
Re: PIC PORT value with Switch statements
« Reply #19 on: February 23, 2007, 04:08:37 AM »
Well, It uses PICCLite, and I'm doing it on the PIC16F628A

Some of the stuff isn't commented out, and it doesn't do EXACTLY what I want it to yet, but the main thing is, the interrupt works.....and that's what you wanted, right?

The top part of the interrupt deals with the RB (Interrupt on change) feature

The bottom beals with the Timer1 overflow (see datasheet)

Cheers for now, and hope that helps

Ian :)

Code: [Select]
#include <pic.h>
#include <stdio.h>
#include "usart.h"

/********************************************************************************************************************************
 * Author: Ian Robinson *
 * Date Created: December 2006 *
 * Project: EG3001 Project1 : Ultrasonic 3D position location *
 * Project Synopsis: A project to show ultrasonic 3D position location over an RS-232 link using the principle of trilateration *
 ********************************************************************************************************************************/

__CONFIG(BORDIS & UNPROTECT & MCLRDIS & PWRTEN & WDTDIS & INTIO);

#define PORTBIT(adr, bit) ((unsigned)(&adr)*8+(bit))

static bit LED0 @ PORTBIT(PORTB, 0);
// B1 used for RX
// B2 used for TX
static bit LED3 @ PORTBIT(PORTB, 3);
static bit RX1 @ PORTBIT(PORTB, 4); // RX1 (RB4) TOP RIGHT
static bit RX2 @ PORTBIT(PORTB, 5); // RX2 (RB5) BOTTOM RIGHT
static bit RX3 @ PORTBIT(PORTB, 6); // RX3 (RB6) TOP LEFT  (SET AS INPUTS WHEN TIMER 1 FUNCTIONS)
static bit RX4 @ PORTBIT(PORTB, 7); // RX4 (RB7) BOTTOM LEFT (SET AS INPUTS WHEN TIMER 1 FUNCTIONS)

//TRISB4 =1; //Put RB4 into input mode
//TRISB5 =1; //Put RB5 into input mode
//TRISB6 =1; //Put RB6 into input mode
//TRISB7 =1; //Put RB7 into input mode

/***********************************************Variable Declaration************************************************************/

unsigned int i,j; //for loop pause
unsigned int timerReading;
unsigned int timerReadingRX1;
unsigned int timerReadingRX2;
unsigned int compare;

unsigned int time4=0;
unsigned int time5=0;
unsigned int time6=0;
unsigned int time7=0;

/***********************************************Function Declaration************************************************************/
void initialRecieve(void);
void check1(void);
void check2(void);
/***********************************************Main Function*******************************************************************/

void interrupt isr(void)
{
if(RBIE && RBIF)
{
// if(RB4==0)
// {
// time4 = (TMR1H << 8) + TMR1L;
// }
// if(RB5==0)
// {
// time5 = (TMR1H << 8) + TMR1L;
// }
// RBIF = 0;
time4 = (TMR1H << 8) + TMR1L;
time5 = (TMR1H << 8) + TMR1L;
RBIF = 0;
}

if(TMR1IF && TMR1IE)
{
// TMR1ON = 0;
printf("RB4 is ",time4);
printf("\n");
printf("RB5 is ",time5);
printf("\n");
// printf("%10u\n",time6);
// printf("%10u\n",time7);
// time4,time5,time6,time7 = 0;
// timerReading = 0;
// TMR1ON = 1;
TMR1IF = 0;
}
}


void main(void){

unsigned char input;

INTCON=0; // purpose of disabling the interrupts.

init_comms(); // set up the USART - settings defined in usart.h

T1CON = 0b00001100; // Timer 1 control register set-up
TMR1H = 0; // Clear high bit
TMR1L = 0; // Clear low bit
T1OSCEN = 0; // Disable Built-in oscillator between RB6 and RB7

GIE = 1; // enable global interrupts
PEIE = 1; // enable peripheral interrupts

TMR1IF = 0; // clear Timer 1 interrupt flag
TMR1ON = 1; // start Timer 1
TMR1IE = 1; // enable Timer 1 interrupt


RBIE = 1; // enable interrupt on change
RBIF = 0; // clear interrupt on change flag

timerReading = 0;
compare = 0;

/***********************************************While Loop*********************************************************************/

while(1){

// initialRecieve();

// TMR1ON = 0;
// timerReading = (TMR1H << 8) + TMR1L;
// TMR1ON = 1;
// printf("%10u\t",timerReading);


// if(RB7 == 0)
// {
// //printf("%10u\t",timerReading);
// printf("RB7");
// }

}
}

/***********************************************End of Main and While Loop**************************************************************/

"The truth is, you can't hide from the truth, cos the truth is all there is" - Handsome Boy Modeling School

 


Get Your Ad Here

data_list