Help with functions and passing of a pointer

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi just dabbling a bit with passing an arrays pointer to a function and struggling a bit.

 

I am getting an error in the following code calling the WriteUSART function in Main(). I have tried quite a few different declarations and ampersand locations etc 

#include <avr/io.h>
#include <stdio.h>



void WriteUSART(uint8_t outlen, uint8_t outbuf);
// void WriteUSART(uint8_t,uint8_t);  // wonder if this works


uint8_t outbuf[] = {65,66,67,68,69};                // Random ASCII 
uint8_t outlen  = sizeof(outbuf)/sizeof(outbuf[0]); // Array length


//////////////////////// MAIN////////////////////////
int main(void)
{

void WriteUSART(uint8_t outlen, uint8_t *outbuf);   // Calling My Finction

    while(1);
    return 0;
}


//////////////////// My Functions //////////////////////

void WriteUSART(uint8_t outlen, uint8_t *outbuf)

{
for (int8_t i=0;i<outlen;i++)  {
                        
    while ( !( UCSR1A & (1<<UDRE1)) ) ; // Wait until Port 1 is ready to send
    UDR1 = &outbuf;                     // Load 'Byte' into Port 1 
// UDR1 = outbuf   // or this one
    outbuf++;                           // increase Pointer x1 (hopefully!!)
                               }
outlen=0;

}

Just wondered what I'm doing wrong 

thanks

Last Edited: Tue. Dec 8, 2020 - 10:14 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Docara wrote:
passing an arrays pointer to a function

That's all standard 'C' stuff - not specific to AVR.

 

I would suggest that you experiment on a PC - that gives you a far more "comfortable" environment for stepping through code and seeing what's hapening

 

Docara wrote:
I am getting an error

What error, exactly?

 

Copy & Paste from the Atmel Microchip Studio 'Output' window

 

https://www.avrfreaks.net/commen...

 

Docara wrote:
I have tried quite a few different declarations and ampersand locations etc 

Just throwing random syntax into your editor is not a great approach - maybe check your 'C' textbook, or look for some tutorials on pointers ... ?

 

Here are some 'C' learning & reference materials: https://blog.antronics.co.uk/2011/08/08/so-youre-thinking-of-starting-with-c/

 

Also: http://c-faq.com/ptrs/index.html

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your prototype for your WriteUSART() function doesn't match the implementation:

Docara wrote:

void WriteUSART(uint8_t outlen, uint8_t outbuf);

Docara wrote:

void WriteUSART(uint8_t outlen, uint8_t * outbuf)

 

Also, this is not the correct syntax for calling any function - irrespective of whether the parameters are pointers or not:

int main(void)
{

    void WriteUSART(uint8_t outlen, uint8_t *outbuf);   // Calling My Finction

 

It should be something like

int main(void)
{

    WriteUSART( outlen,  *outbuf );   // Calling My Function

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Whilst all valid points I am using AS7 to build my program. To cut and paste directly from AS is a pain because what I have already is somewhat spread around. What I posted I cut a paste from AS into Codeblocks with just the parts that I am struggling with. I have viewed some examples online and copied / pasted code examples but I am still getting an error.

 

Before I post to forums I do try and solve things myself. Posting questions like this is the last resort for me I am old school and certainly not a 16yr old student after homework answer.

 

I apologise if I took your reference to a 'textbook' as a subtle dig and out of context.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Don't blame Andy for thinking your a student, we see many posts like yours from students, after all, regardless of our age, we are all learning!

 

Perhaps this example will help:

/*************************************************************************
Function: uart_puts()
Purpose:  transmit string to UART
Input:    string to be transmitted
Returns:  none          
**************************************************************************/
void uart_puts(const char *s )
{
    while (*s) 
      uart_putc(*s++);

}/* uart_puts */

 

 

FF = PI > S.E.T

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Docara wrote:
 I am still getting an error.

And you still haven't told us what that  error that is!

 

What I was saying was that you should copy & paste the error message.

 

I apologise if I took your reference to a 'textbook' as a subtle dig 

No - a textbook is the obvious place to go for a reference on pointers & their use.

 

When I need to look-up some unfamiliar syntax, I will get out my K&R - which I'd count as a "textbook"

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Mon. Dec 7, 2020 - 06:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Caught me with time on my hands.

/*
 * Pointers.c
 * Org:	Docara
 * Corrected: Cmdrzin
 */ 

#include <avr/io.h>
#include <stdio.h>

//void WriteUSART(uint8_t outlen, uint8_t outbuf);
//void WriteUSART(uint8_t,uint8_t);  // wonder if this works..No
void WriteUSART(uint8_t,uint8_t*);  // wonder if this works..Yes

uint8_t outbuf[] = {65,66,67,68,69};                // Random ASCII
uint8_t outlen  = sizeof(outbuf)/sizeof(outbuf[0]); // Array length

//////////////////////// MAIN////////////////////////
int main(void)
{
//	void WriteUSART(uint8_t outlen, uint8_t *outbuf);   // Calling My Finction
	WriteUSART(outlen, outbuf);   // Calling My Function
//or
	WriteUSART(outlen, &outbuf[0]);   // Calling My Function

	while(1);
	return 0;
}

//////////////////// My Functions //////////////////////
void WriteUSART(uint8_t outlen, uint8_t *outbuf)
{
	for (int8_t i=0;i<outlen;i++)  {

//		while ( !( UCSR1A & (1<<UDRE1)) ) ; // Wait until Port 1 is ready to send
		while ( !( UCSR0A & (1<<UDRE0)) ) ;		// Using an ATmega328P target

//		UDR1 = &outbuf;                     // Load 'Byte' into Port 1
//		UDR1 = *outbuf;                     // Load 'Byte' into Port 1
		UDR0 = *outbuf;			// Using an ATmega328P target
// UDR1 = outbuf   // or this one
		outbuf++;                           // increase Pointer x1 (hopefully!!)
// or could use
//		UDR0 = *outbuf++;

	}
//	outlen=0;	Not needed.
}

Compiles with no errors. Now, go to a C reference manual or textbook and try to understand why your code failed and these corrections didn't.

Have fun.

"If you find yourself in an even battle, you didn't plan very well."
https://www.gameactive.org
https://github.com/CmdrZin

Last Edited: Mon. Dec 7, 2020 - 08:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank all so much for spending time replying

 

Gawd!! I was soooo close !

It's really weird and frustrating, you get blind to the code your staring at and you start doing stupid things when things don't work as expected - why did I put declarations in my function call, why?

 

Cmdrzin

void WriteUSART(uint8_t,uint8_t*); 

Interesting, I've not seen the asterix positioned there before. Does that have a specific term so I can research it more? Looking at this line I'm presuming that you are declaring a pointer of name yet to be determined??? (And have also just realised that I have used an 8bit declaration size for a pointer value)

 

Also I'm presuming you mentioned port0 and the 328P for people reading this in the future so I won't comment on this.

 

Compiles with no errors. Now, go to a C reference manual or textbook and try to understand why your code failed and these corrections didn't.

Have fun.

"Have fun" Mmm that one phrase for what I'm feeling LOL

 

 

Kiobk

 

I like this :-)

void uart_puts(const char *s )
{
    while (*s) 
      uart_putc(*s++);

}/* uart_puts */

 

awneil 

 

By way of an explanation - I'm getting really quite sensitive to replies I get from forums. The problem I find is (generally) the forum replies seems to assume you are 16yr old kid with the attention span of an ant who want easy quick answers to homework. The issue for the rest of use trying to learn is, twofold 1) generally the types of question asked by novices usually do sound like homework questions and 2)  you need a certain level of knowledge before they can start proceeding on your own where do you get it?. eg if you don't know what say, a function is you can't search for the term.

Yes of course you can buy a book (if you have disposable income and in employment) then which one do you get?  What with the current Covid paranoia you can't easily walk around a book store in London these days, and getting stuck a 7pm at night is not conducive to shopping.

 

Anyway, I would ask the responders to posts here (and other forums) to just step back a moment before they start writing dismissive or derogatory comments to questions. I find, due to the poor state of written English,  it is often easy to identify the 'demographic' of homework dodgers, and answer appropriately to a genuine question. 

 

Whilst you jumped on me somewhat :-

That's all standard 'C' stuff - not specific to AVR.

 

I would suggest that you experiment on a PC - that gives you a far more "comfortable" environment for stepping through code and seeing what's hapening

I am coming back to electronics after 30yrs - This is a nice forum and I respectively remind you, to use any uC these days you need to know C! Because I am using multiple (different AVRs) why shouldn't I post a programming question here when the answer to a C programming question is pertinent and perhaps uniquely relevant to an AVR product.

 

Thank all again for talking the time to reply to my question it is very much appreciated

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Docara wrote:
Interesting, I've not seen the asterix positioned there before. Does that have a specific term so I can research it more? Looking at this line I'm presuming that you are declaring a pointer of name yet to be determined??? (And have also just realised that I have used an 8bit declaration size for a pointer value)
An asterisk in C denotes a "pointer". It means "pass the address of something of this type" not just the normal "pass something of this type". So in:

Docara wrote:

void WriteUSART(uint8_t,uint8_t*); 

the first parameter is going to be an actual uint8_t value (so basically a number between 0 and 255) but the second parameter is saying "pass the address of one or more uint8_t items". The actual thing that is passed is a RAM/ROM address. How big the number is depends on the kind of CPU you are building the code for. In AVR pointers are 16 bit so the thing passed will be some value between 0x0000 and 0xFFFF which is the address (in RAM because for AVR all data is in RAM) of one or more uint8_t items. In fact it's because you don't actually know how many uint8_t might be at the given address that you may also have to pass that separate, first parameter which in something WriteUSART(13, &mystring) would mean "&mystring is the address of the bytes in memory and at that address you are going to find 13 bytes to be used".

 

Note the use of &, it is the "other side" of *. When you use * you are saying "this is an address of something" but to pass that address you (usually) need to use &object where & is C's "address of" operator. So when you say "&object" you are saying "don't pass 'object' itself, pass the "address of" 'object'"

 

One slightly confusing thing is that when you have arrays like:

char mytext[] = "Hello";

then while mytext[1] is a char (in fact it is the letter e) then the symbol "mytext" used on its own with no subscript actually means "the address of 'mytext'" - so sometimes you don't need to use & at all. However all of:

WriteUSART(5, mytext);
WriteUSART(5, &mytext);
WriteUSART(5, &mytext[0]);

can all be used. Usually you would just pass it without any "&" as it makes the code easier to read. But note that while you can do this with arrays you can't do it with other data like structs and things:

struct {
    int n;
    long l;
    char c;
} mystruct = {
    12345,
    0xBABEFACE,
    'x'
};

...
  WriteUSART(7, mystruct);
  WriteUSART(7, &mystruct);

In this "mystruct" on its own and &mystruct are two very different things. You will have all kinds of issues if you start passing structs around when you actually intend to pass the address of structs.

 

While you can learn a lot about this by googling "pointers and address of in C" you may find it most enlightening to google "the difference between pass by value and pass by reference in C".

 

Basically when you pass the value of a variable in C that is "pass by value", when you pass the address of a variable that is "pass by reference".

 

The other use of pass by reference is not just when you want to pass the address of the start of list of items (like an array of uint8_t say) but when you sometimes want the value of a variable to be available in a function but you actually want to be able to modify the variable that was being passed so in:

int addOne(int n) {
    return n + 1;
}

int main(void) {
    int m = 37
    m = addOne(m);
}

then when the 37 value in 'm' is passed to the called function it arrives there in "n" but nothing that is then done to n itself will change m. To get m updated this function needs to pass a result back and then that is assigned to m to update it. As an alternative:

int addOne(int * n) {
    *n = *n + 1;
}

int main(void) {
    int m = 37
    addOne(&m);
}

In this m is set to 37 then the address of m in memory is passed to the addOne() function. Within that function *n (that is the location that n is pointing to) is read in, one is added then that is written back to the "location that n is pointing to". So the "m" variable location itself will be updates. So after the call to addOne() the "m" location will now hold 38.

Docara wrote:
The problem I find is (generally) the forum replies seems to assume you are 16yr old kid with the attention span of an ant who want easy quick answers to homework. The issue for the rest of use trying to learn is, twofold 1) generally the types of question asked by novices usually do sound like homework questions and 2)  you need a certain level of knowledge before they can start proceeding on your own where do you get it?. eg if you don't know what say, a function is you can't search for the term.
Try to ignore Andy - he can be a bit of an aggressive idiot some time and likes to be condescending to beginners without knowing whether he is talking to beginners or not. If this system had some kind of mute function you could just turn off his replies but sadly such a facility does not exist. 

 

The curious thing is that about 10-15 years ago this forum used to be full of people being aggressive to beginners to the point where many AVR users posts on other forums to say they were "too scared to post on AVRFreaks for fear of the response they would get". For the most part we have managed to moderate away this kind of behaviour but sadly we do still see instances of it.

 

Back then we had just one rule "don't post if what you are about to say is not helpful" - perhaps everyone needs a reminder of this?

Last Edited: Tue. Dec 8, 2020 - 10:52 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Docara wrote:
Interesting, I've not seen the asterix positioned there before.

* asterisk wink

 

But that is where it always goes when declaring a pointer.

 

Does that have a specific term so I can research it more?

No - it's nothing special

 

you could read it two ways:

uint8_t* myPointer; // myPointer is of type uint8_t*

Or:

uint8_t *myPointer; // *myPointer is of type uint8_t

 

The 'C' language doesn't care about the whitespace; you could equally write

uint8_t * myPointer; 

Or

uint8_t
*
myPointer
;

etc, etc, ...

 

 

 

Looking at this line I'm presuming that you are declaring a pointer of name yet to be determined?

No: that's just a function prototype - all it needs to do is give the types of the parameters - it doesn't need to name them.

 

 

 

(And have also just realised that I have used an 8bit declaration size for a pointer value)

It's a pointer to an 8-bit value

 

 

Yes of course you can buy a book (if you have disposable income and in employment) then which one do you get?  What with the current Covid paranoia you can't easily walk around a book store in London these days, and getting stuck a 7pm at night is not conducive to shopping.

I did give you some references - which includes a free, online text reference book.

 

 

why shouldn't I post a programming question here when the answer to a C programming question is pertinent and perhaps uniquely relevant to an AVR product.

Sorry: the point was not that you shouldn't post it here, just that it's not AVR-specific - and, thus, that you don't need to restrict yourself to AVR-specific resources to answer it.

 

Hence the suggestion to try this stuff out on a PC, where you have a more "comfortable" environment - away from the added complications & restrictions of small, embedded microcontrollers.

 

There is a section here for General programming questions: https://www.avrfreaks.net/forums/compilers-and-general-programming

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Tue. Dec 8, 2020 - 11:09 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Docara wrote:
16yr old kid with the attention span of an ant

That's not really a good comparison. Surely no-one can question the determination and work ethic of an ant.

Usually we compare human attention span against that of a goldfish.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
void WriteUSART(uint8_t,uint8_t*); 

Interesting, I've not seen the asterix positioned there before.

That's a "prototype function declaration" for WriteUSART.  It says "sometime in the future I'll be defining a function WriteUSART that has a uint8_t and a pointer to uint8_t as arguments. (but for some reason I don't want to give the arguments NAMES yet.  That might give your too much information!  hah hah!)"

 

Looking at this line I'm presuming that you are declaring a pointer of name yet to be determined???

It doesn't really declare the pointer at all; it just describes the function.

 

Later, you would need an actual function definition looking something like:

void WriteUSART(uint8_t byteCount, uint8_t* bufferPointer) {
    while (byteCount--) {  // for each character
        USART_putchar(*bufferPointer);  // access byte at ptr location
        bufferPointer++;  // increment pointer to next byte
    }
}

 

You can probably start holy-war-style discussions on whether one should write "uint8_t* ptr" or "uint8_t *ptr";  the "type" is "int8_t *" (pointer to a uint8_t), but the precedence groups the "*" with the variable name, so that "uint8_t* p, c;" only defines one pointer.  (probably one of those "in retrospect, that's not the way we should have done it, but it's too late now" language decisions.)
 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

westfw wrote:
You can probably start holy-war-style discussions on whether one should write "uint8_t* ptr" or "uint8_t *ptr";  the "type" is "int8_t *"
And just to be different my example above would have it as "uint8_t * ptr" where the * is neither gound to the type or the variable but is surrounded by white space so it's easier to see and less likely to be over-looked !