Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

C programming question

Status
Not open for further replies.

timtalk

New Member
Is there a simple way to take a string and split one letter at a time out to a temp var. I.E. I want to call a subroutine such as
Code:
convert1("Hi There");
and have that routine
Code:
convert1(temp)
{
take value of temp, split out first letter, send to convert(), split out second letter, send to convert(), etc.
}

I know in ASM it's very simple just using dt but I'm unable to find a C equal. Any help would be appreciated. Thanks!
 
Ok I was able to make it do one char at a time after a little help from above. Here's what i've done
Code:
sndlcd("end");

and then in the sndlcd routine I just did a
Code:
sndlcd(char i)


and i became the one letter value that I wanted. Again thanks with the help there.

Next problem/question

The above code works great for a PIC connected via 4 bit to the LCD. I'm now wanting to use a 74HCT164 shift register inbetween (this should reduce the number of pins in total that I'm using. In order to make it work properly tho I need to be able to take the above code and when I get into the sndlcd routine I need to be able to instead of outputing to OUTPUT_A a 8 bit char I need to take that 8 bit char and split it down to 1 char at a time starting from the far right of the char... I.e. the letter T would be 01010100 I need to be able to output to data pin the 0, then send a pulse a signal pin, then send the next 0 to the data pin, pulse signal pin, send the 1 to the data pin, pulse, etc... I think i've sort of figured it out.. but I'm not sure. The results that i've gotten sort of say that I'm not doing it right but here's what I have so far.

Code:
msg = 'T';
for(ct=0;ct<8;++ct)
   {
      output_bit(PIN_A0,shift_right(msg,1,0));
      delay_routine_1min;
    }

I've tried the above and all I get is pin RA0 turned on and it stays on.. which does not seem right. I would think that I would get 0 voltage the first min, 0 volts the second min, 5 volts the next min, etc ending with 0 volts.
 
You have to call a shift right function? The C convention is to use the shift right operator: >>.

Maybe this would work:

Code:
msg = 'T'; 
for(ct=0;ct<8;++ct) 
   {
      output_bit(PIN_A0, msg.0); 
      delay_routine_1min;
      msg = msg >> 1;
    }

Mike
 
what you have shown is almost exactly what I've just been trying. For some reason tho something seems to be wrong. When I plug the pic in I get a extreamly fast pulse up to 5 volts and then back to 0 and it stays at 0 from that point on. With the 1 min delay in there tho it should hold each bit condition for 1 min before changing correct???
 
Hey Tim,

Here's another hint ;) :

Take the following function :

Code:
int my_function()
{
    return 0;
}

Writing the following later in the program would be perfectly legal :

Code:
printf( "my_function ==%d, my_function() ==%d", my_function, my_function() );

What will be the printf output, and why? ;) When you can answer that, you'll know what's wrong with your code. ;)

I'm not trying to be a smartass you know, just trying to help by making you work a little :lol:
 
I appreciate the help. I'm still very new to this and never formaly trained in pic's or C. I know a web based programming language PERL very well and it is similar to C so I am able to muddle thru in some areas. That and my trusty C/C++ programmers bible and a bit of help from here and slowly the light gets brighter. I've read thru what you've posted and I believe that the answer would always be 0 in the examples you've shown. I guess that i'm still at a loss to understand how that relates, but i'm sure it does and i'm just missing the point. Been messing with this all day and starting to make dumb mistakes now...
 
Ok Tim,

I think I am just confusing you know. Here's the answer :

my_function() is a function call. Writing the function name followed by brackets actually calls the function, which returns 0. So my_function() == 0.

my_function without brackets is the function address i.e. my_function is a pointer. So my_function != 0. Writing my_function as is and without the brackets doesn't call the function.

Now, what does that tell you about your code? (look at the code you posted above)

I know Perl too. Its syntax is so anarchistic!, you might have a bit of a hard time adapting to the stricter C rules at first, but it shouldn't take long until it becomes second nature ;)
 
I hear what your saying and I fully understand that. I don't think that i've done what your saying tho.. Or if I have I'm unable to see it.. the only code that I see that I've posted about the outputing of a single bit is the following
Code:
msg = 'T'; 
for(ct=0;ct<8;++ct) 
   { 
      output_bit(PIN_A0,shift_right(msg,1,0)); 
      delay_routine_1min; 
    }

and I said that that I agreed with upand_at_them when he said that I needed to use

Code:
msg = 'T'; 
for(ct=0;ct<8;++ct) 
   { 
      output_bit(PIN_A0, msg.0); 
      delay_routine_1min; 
      msg = msg >> 1; 
    }

that the shift right routine was what I was missing. I tried to use a routine like that and it did not seem to be working properly. I've just now found out tho that the 1 min timmer that I thought I had in place was not in place and so that routine maybe working and it was just going thru it so fast that my standard digital multimeter could not see the changes on RA0. (I know I need a scope!!! that's on the christmas list for this year). So i'm currently reworking my counter and then will try the code again and will report back my findings.
 
Tim,
Exactly, your 1 minute delay doesn't work. That's what I'm trying to tell you! :lol: Look at what you wrote closely :

Code:
msg = 'T'; 
for(ct=0;ct<8;++ct) 
   { 
      output_bit(PIN_A0,shift_right(msg,1,0)); 
      delay_routine_1min; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    }
 
HEHEHHEHE.. sorry I did not actually cut and paste that from my code. I was trying to indicate that I had a 1 min timer call in that location (which I did have and it was calling to it, just not waiting near as long as I had expected). I see now what you were saying. I'm sorry for being misleading I had ment that simply as a note that there was a call to a timmer.
 
Ok I've given up.. I can not get the following code to work properly. I'm using a pic16f628A chip as can be seen in the code. All I expect this code to do at this time is to turn RA0 on or off (depending on it's current state) every min.

Code:
#include <16F628A.h>
#fuses INTRC_IO,NOPROTECT,NOBROWNOUT,NOMCLR,NOLVP,NOWDT,PUT // must include this line !!
#use fixed_io(A_OUTPUTS=40,41,42,43,44,46,47)
#use delay(clock=20000000)
#define D7  PIN_A3
#define D6  PIN_A2
#define D5  PIN_A1
#define D4  PIN_A0
#define RS  PIN_A4
#define RW  PIN_A6
#define E  PIN_A7
#define INTS_PER_SECOND 76     // (20000000/(4*256*256))
#byte port_A=5
SET_TRIS_A( 0x20 );
BYTE sec;      // A running seconds counter
BYTE min;
BYTE hour;
BYTE int_count;    // Number of interrupts left before a second has elapsed



char x;


#int_rtcc                          // This function is called every time
void clock_isr() {                 // the RTCC (timer0) overflows (255->0).
                                   // For this program this is apx 76 times
if(--int_count==0)
   {           // per second.
      ++sec;
      if ( sec >= 60)
           {
           if(x == 0)
               {
               output_high(D4);
               x = 1;
               }
           else
               {
               output_low(D4);
               x = 0;
               }
           sec = 0;
           min++;
           if ( min >= 60)
               {
               min = 0;
               hour++;
               if ( hour >= 24)
                  {
                  hour = 0;
                  }
               }
            }   
      int_count=INTS_PER_SECOND;
    }

}


main()
{
OUTPUT_A(0x00);  //make sure all pins are at 0
x = 0;

   int_count=INTS_PER_SECOND;
   set_timer0(0);
   setup_counters( RTCC_INTERNAL, RTCC_DIV_256 | RTCC_8_BIT);
   enable_interrupts(INT_RTCC);
   enable_interrupts(GLOBAL);

   while(1)
   {
   clock_isr();   // i've added this in after it did not work without it. 
                      //Of course it still does not work....
   }


}

Currently it turns RA0 off and then does nothing after that.
 
Tim,

Hopefully, a PIC C coder will chime in. In the meantime, let me take a stab at C on the PIC ;)

I've been living off C and C++ programming under Win32 and Linux for the past 6 years. I also know the PIC architecture and programming basics (and a bit more) in ASM. But I can't help you. Why? Because there's way too much compiler specific crap!... :lol: There's a lot that can go wrong in the above code, and one has to be familiar with the specific compiler used to be able to spot potential errors. There are so much compiler-implemented shortcuts... :evil: it's quite ugly.

That code would be trivial to write in ASM. A lot of forum members could help you with an ASM version of the above.

Why are you using C?

Do you already know the PIC architecture and ASM programming, and are trying to gear up to C? In that case, don't give up, you'll eventually get the hang of it, and C on the PIC is good to know before tackling bigger, complex projects.

Or are you trying to learn PIC programming using C because you only know a high level language (Perl), and are intimidated by ASM? If the latter is true, you might want to reconsider your language choice, given that 1) you're gonna learn the PIC architecture a lot faster in ASM 2) the lack of available support from online communities like Electro Tech.

Out of curiosity, what compiler are you using? I dabbled with Hi-Tech's PIC C Lite, but it doesn't look like that's what you have?...
 
As Joel suggests, the program would probably be easier to write using assembler, and certainly more readable and less prone to errors.

You're also making the program more complicated than required by using interrupts (for no good reason?), a simple delay loop is probably all that's required?.
 
I am using PICC. The reason is that yes I'm a bit more comfortable in C because it's closer to a language I already know well. I've read thru hours and hours of info on ASM and just can not get my head around how it works. It uses things like W and a few others that somehow just don't make sense to me. I've read thru Nigels pages hoping for the light to come on and it all to make sense. In C things just seem to make sense, i.e. while this or that is true go round and round untill it's not true, or if this is true do this if not do that. In ASM I don't see equilevents to those functions. I'm sure they are there i'm just unable to spot them. Then In C we use things like port_A, and port_B to define a bank on the pic, from what I've gathered in ASM W outputs to whatever bank is currently choosen via another command??? I do appreciate the suport that I've gotten here. Other fourms i've found to be either not supported or supported by those who treat a basic question as a question that's not worth answering.
 
Yeah, I understand how ASM can be very confusing at first. The huge advantage it has is that it's very close to what's happening in hardware.

W is the microcontroller's hand. The PIC grabs and puts data using that hand, and since it only has one, almost everything goes through W. It's called a register. Think of it as a very, very fast temporary memory location inside the CPU module. It's your workspace, where calculations, bit manipulations and general purpose work is done before the result gets written to memory locations, be it port pins, RAM, EEPROM, etc...

If you'd rather stick to C, have you tried to find a forum for your specific compiler? I'm not trying to send you away, but like I said, there are so much non-standard, compiler-specific shortcuts in the code that it makes it very hard to help without a solid experience with your compiler.
 
i would agree with Joel Rainville and i also think that you (timtalk) should stick with C. infact ive heard (yet to confirm!) that if you use microchip's C compiler and write code for an 18 series PIC then the code generated by the C compiler will be very close to an equivalent piece of assembly code. maybe thats because the 18 series PICs have a C optimized instruction set. but you can also use PICC for 16 series PICs even if they werent meant to be programmed in C.
 
Joel Rainville said:
almost everything goes through W..... It's your workspace, where calculations, bit manipulations and general purpose work is done before the result gets written to memory locations, be it port pins, RAM, EEPROM, etc...

Should be, until you want to set/clear/toggle/shift a bit in W, dec/inc the value in W, check if W is zero, test for zero or 1 in a certain bit.....Luckily, there are tricks to do just that. I find it strange unable to use many of the instructions on W.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top