| Author |
Message |
|
|
Posted: Jan 26, 2012 - 04:23 AM |
|

Joined: Aug 04, 2010
Posts: 76
|
|
I would like to declare a struct and pass its address to a function. That function would then fill in the various values in the struct. That might seem simple enough to those who speak 'C' but for me it is very difficult to do.
It would seem that I am also trying to learn from non-GCC tutorials and books. I've tried a number of combinations and now I'm exhausted of ideas.
I've reduced the code down to almost bare bones. I'm hoping I won't be far away...
My errors include one about being in a parameter list and dereferencing to an incomplete type ?!
I thought I'd followed the tute exactly !
Code:
// 1284P_DS2401.c
// F_CPU is 18432000 Hz
// SPI port
#define SPI_PORT PORTB
#define SPI_DDR DDRB
#define SPI_Reset PB0
#define SPI_CS PB1
#define BAUD 115200
#include <stdint.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <util/delay.h>
#include <util/twi.h>
#include <util/setbaud.h>
#include <util/parity.h>
#include <util/atomic.h>
#include <util/crc16.h>
#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/eeprom.h>
#include <avr/portpins.h>
#include <avr/power.h>
#include <avr/pgmspace.h>
#include <avr/i2c.c>
#include <avr/macro.c>
#include <avr/spi.c>
#include <avr/MCP23S17.c>
#include <avr/CM404.c>
#include <avr/buzzer.c>
#include <avr/heater_cooler.c>
#include <avr/LEDs.c>
#include <avr/motor.c>
#include <avr/usart.c>
#include <avr/external_EEPROMs.c>
#include <avr/MCP4921.c>
#include <avr/1284P_AD.c>
#include <avr/switches.c>
#include <avr/AVR_setup.c>
#include <avr/DS2401.c>
typedef struct Electronic_Serial_Number
{
uint8_t presence;
uint8_t family_code;
uint8_t ESN[6];
uint8_t CRC;
};
struct Electronic_Serial_Number ESN;
uint8_t Read_DS2401(struct Electronic_Serial_Number *ptr);
int main(void)
{
uint8_t i = 0;
struct Electronic_Serial_Number *st_ptr;
st_ptr = &ESN;
//****Setup routines***
AVR_setup();
AD_Init();
SPI_Init_fosc8();
SPI_Init_MCP23S17A();
SPI_Init_MCP23S17B();
Init_LCD();
Clear_LCD_top();
Clear_LCD_bottom();
Return_home_LCD_top();
Return_home_LCD_bottom();
usartInit();
twi_init_99096Hz();
One_Beep();
Heater_ON();
_delay_ms(250);
Heater_OFF();
Cooler_ON();
_delay_ms(500);
Cooler_OFF();
Two_Beeps();
Red_LED_ON();
_delay_ms(500);
Red_LED_OFF();
Orange_LED_ON();
_delay_ms(500);
Orange_LED_OFF();
Green_LED_ON();
_delay_ms(500);
Green_LED_OFF();
Three_Beeps();
_delay_ms(100);
// End of setup routines
i = Read_DS2401(struct Electronic_Serial_Number ESN);
_delay_ms(100);
}
and the functions ...
Code:
// This file contains routines to work with the DS2401 Electronic Serial Number
// Written by S W McLevie
// 26th Jan 2012
// ATMega1284P
void Write0_DS2401(void)
{
// This is a routine to write a 0 to the DS2401.
// The routine has a total cycle time of approx 80us.
DDRD &= ~(1 << 5); // Clear bit 5 in DDRD pin 5 to make it an input
asm("nop"); asm("nop"); asm("nop");
// _delay_us(1);
DDRD |= (1 << 5); // Make bit 5 an output - this will send it low because PORTD pin5 is already cleared to 0
_delay_us(70); // The minimum for the DS2401 is 60us
DDRD &= ~(1 << 5); // Clear bit 5 in DDRD pin 5 to make it an input ... this will tri-state the pin allowing the pullup to pull the line high
_delay_us(10);
}
void Write1_DS2401(void)
{
// This is a routine to write a 1 to the DS2401.
// The routine has a total cycle time of approx 80us.
DDRD &= ~(1 << 5); // Clear bit 5 in DDRD pin 5 to make it an input
asm("nop"); asm("nop"); asm("nop");
// _delay_us(1);
DDRD |= (1 << 5); // Make bit 5 an output - this will send it low because PORTD pin5 is already cleared to 0
_delay_us(10); // The minimum for the DS2401 is 1us with a maximum of 15us
DDRD &= ~(1 << 5); // Clear bit 5 in DDRD pin 5 to make it an input ... this will tri-state the pin allowing the pullup to pull the line high
_delay_us(70);
}
uint8_t Read_DS2401(struct Electronic_Serial_Number *ptr)
{
/*
This function firstly initialises the ROM and checks for its presence then writes the command (33H) to the chip before reading the full 64 bits of information held in the chip. This 64 bits consists of a byte of 'family code', 6 bytes of ID and lastly a CRC byte.
*/
uint8_t bitvalue = 0;
uint8_t bytevalue = 0;
uint8_t readromcommand = 0x33;
uint8_t count = 0;
uint8_t i, j, k = 0;
// This section sends a pulse to test for the presence of the DS2401.
// If the DS2401 responds as expected then the presence byte is written.
// The byte represents the actual width of the presence pulse sent by the DS2401.
DDRD &= ~(1 << 5); // Clear bit 5 in DDRD pin 5 to make it an input
asm("nop"); asm("nop"); asm("nop"); // This delay is just to allow things to settle down.
DDRD |= (1 << 5); // Make bit 5 an output - this will send it low because PORTD pin5 is already cleared to 0
_delay_us(520); // The minimum for the DS2401 is 480us
DDRD &= ~(1 << 5); // Clear bit 5 in DDRD pin 5 to make it an input
_delay_us(5); // tpdh minimum is 15us so start sampling before the pulse is driven low by the DS2401
for(i=0;i<96;i++) // 96 counts of 5us intervals is 480us
{
bitvalue = (PIND & (1 << 5)); // If high the value returned will be 0010 0000 (20h)
if (bitvalue == 0x20)
count++;
_delay_us(5);
}
ptr->presence = count;
// If there is no chip the value returned for 'presence' will be 96 hopefully.
// If the chip is faulty hopefully the count will be either 96 or very low.
// Lets make the return value non-zero. 0 is undefined, 1 is error, 2 is OK.
if ((count > 83) | (count < 10)) return(1);
i = 0;
// The following loop writes the Read Rom command to the chip
while (i < 8)
{
if ((readromcommand & 0x01) == 1)
Write1_DS2401();
else
Write0_DS2401();
readromcommand = (readromcommand >> 1);
i++;
}
_delay_us(10); // I'm not sure about this delay. The original program worked with a value of 10us.
// This next section is reading the family code byte I believe !
bytevalue = 0;
bitvalue = 0;
for (j=0; j<6; j++)
{
DDRD &= ~(1 << 5); // Clear bit 5 in DDRD pin 5 to make it an input
asm("nop"); asm("nop"); asm("nop");
//_delay_us(1);
DDRD |= (1 << 5); // Make bit 5 an output - this will send it low because PORTD pin5 is already cleared to 0
for (i=0;i<16;i++)
asm("nop"); // This delay is 16 x 54ns - roughly 865ns. The DS2401 needs a maximum of 1us.
DDRD &= ~(1 << 5); // Clear bit 5 in DDRD pin 5 to make it an input ... this will tri-state the pin allowing the pullup to pull the line high
_delay_us(20); // The nominal time (trdv) for valid data on the DS2401 is 15us
// Below is the routine to read the pin ...
bitvalue = (PIND & (1 << 5)); // If high the value returned will be 0010 0000 (20h)
bitvalue = (bitvalue << 2); // If the bit returned is '1' bitvalue will be 10000000 (08h) (otherwise 0)
bytevalue = (bytevalue & bitvalue);
bytevalue = (bytevalue >> 1);
_delay_us(50); // trelease is 45us
}
DDRD &= ~(1 << 5); // Clear bit 5 in DDRD pin 5 to make it an input
asm("nop"); asm("nop"); asm("nop");
//_delay_us(1);
DDRD |= (1 << 5); // Make bit 5 an output - this will send it low because PORTD pin5 is already cleared to 0
for (i=0;i<16;i++)
asm("nop"); // This delay is 16 x 54ns - roughly 865ns. The DS2401 needs a maximum of 1us.
DDRD &= ~(1 << 5); // Clear bit 5 in DDRD pin 5 to make it an input ... this will tri-state the pin allowing the pullup to pull the line high
_delay_us(20); // The nominal time (trdv) for valid data on the DS2401 is 15us
// Below is the routine to read the pin ...
bitvalue = (PIND & (1 << 5)); // If high the value returned will be 0010 0000 (20h)
bitvalue = (bitvalue << 2); // If the bit returned is '1' value will be 10000000 (08h) (otherwise 0)
bytevalue = (bytevalue & bitvalue);
bytevalue = (bytevalue >> 1);
ptr->family_code = bytevalue;
_delay_us(50); // trelease is 45us
// This next section is reading the 6 ESN bytes I believe !
bytevalue = 0;
bitvalue = 0;
for (k=0; k<7; k++)
{
for (j=0; j<6; j++)
{
DDRD &= ~(1 << 5); // Clear bit 5 in DDRD pin 5 to make it an input
asm("nop"); asm("nop"); asm("nop");
//_delay_us(1);
DDRD |= (1 << 5); // Make bit 5 an output - this will send it low because PORTD pin5 is already cleared to 0
for (i=0;i<16;i++)
asm("nop"); // This delay is 16 x 54ns - roughly 865ns. The DS2401 needs a maximum of 1us.
DDRD &= ~(1 << 5); // Clear bit 5 in DDRD pin 5 to make it an input ... this will tri-state the pin allowing the pullup to pull the line high
_delay_us(20); // The nominal time (trdv) for valid data on the DS2401 is 15us
// Below is the routine to read the pin ...
bitvalue = (PIND & (1 << 5)); // If high the value returned will be 0010 0000 (20h)
bitvalue = (bitvalue << 2); // If the bit returned is '1' bitvalue will be 10000000 (08h) (otherwise 0)
bytevalue = (bytevalue & bitvalue);
bytevalue = (bytevalue >> 1);
_delay_us(50); // trelease is 45us
}
DDRD &= ~(1 << 5); // Clear bit 5 in DDRD pin 5 to make it an input
asm("nop"); asm("nop"); asm("nop");
//_delay_us(1);
DDRD |= (1 << 5); // Make bit 5 an output - this will send it low because PORTD pin5 is already cleared to 0
for (i=0;i<16;i++)
asm("nop"); // This delay is 16 x 54ns - roughly 865ns. The DS2401 needs a maximum of 1us.
DDRD &= ~(1 << 5); // Clear bit 5 in DDRD pin 5 to make it an input ... this will tri-state the pin allowing the pullup to pull the line high
_delay_us(20); // The nominal time (trdv) for valid data on the DS2401 is 15us
// Below is the routine to read the pin ...
bitvalue = (PIND & (1 << 5)); // If high the value returned will be 0010 0000 (20h)
bitvalue = (bitvalue << 2); // If the bit returned is '1' value will be 10000000 (08h) (otherwise 0)
bytevalue = (bytevalue & bitvalue);
bytevalue = (bytevalue >> 1);
ptr->ESN[j] = bytevalue;
_delay_us(50); // trelease is 45us
}
// This next section is reading the CRC byte I believe !
bytevalue = 0;
bitvalue = 0;
for (j=0; j<6; j++)
{
DDRD &= ~(1 << 5); // Clear bit 5 in DDRD pin 5 to make it an input
asm("nop"); asm("nop"); asm("nop");
//_delay_us(1);
DDRD |= (1 << 5); // Make bit 5 an output - this will send it low because PORTD pin5 is already cleared to 0
for (i=0;i<16;i++)
asm("nop"); // This delay is 16 x 54ns - roughly 865ns. The DS2401 needs a maximum of 1us.
DDRD &= ~(1 << 5); // Clear bit 5 in DDRD pin 5 to make it an input ... this will tri-state the pin allowing the pullup to pull the line high
_delay_us(20); // The nominal time (trdv) for valid data on the DS2401 is 15us
// Below is the routine to read the pin ...
bitvalue = (PIND & (1 << 5)); // If high the value returned will be 0010 0000 (20h)
bitvalue = (bitvalue << 2); // If the bit returned is '1' bitvalue will be 10000000 (08h) (otherwise 0)
bytevalue = (bytevalue & bitvalue);
bytevalue = (bytevalue >> 1);
_delay_us(50); // trelease is 45us
}
DDRD &= ~(1 << 5); // Clear bit 5 in DDRD pin 5 to make it an input
asm("nop"); asm("nop"); asm("nop");
//_delay_us(1);
DDRD |= (1 << 5); // Make bit 5 an output - this will send it low because PORTD pin5 is already cleared to 0
for (i=0;i<16;i++)
asm("nop"); // This delay is 16 x 54ns - roughly 865ns. The DS2401 needs a maximum of 1us.
DDRD &= ~(1 << 5); // Clear bit 5 in DDRD pin 5 to make it an input ... this will tri-state the pin allowing the pullup to pull the line high
_delay_us(20); // The nominal time (trdv) for valid data on the DS2401 is 15us
// Below is the routine to read the pin ...
bitvalue = (PIND & (1 << 5)); // If high the value returned will be 0010 0000 (20h)
bitvalue = (bitvalue << 2); // If the bit returned is '1' value will be 10000000 (08h) (otherwise 0)
bytevalue = (bytevalue & bitvalue);
bytevalue = (bytevalue >> 1);
ptr->CRC = bytevalue;
_delay_us(50); // trelease is 45us
// If we get here then we shall send a return number to indicate that all is well.
// Lets make the return value non-zero. 0 is undefined, 1 is error, 2 is OK.
return(2);
}
|
|
|
| |
|
|
|
|
|
Posted: Jan 26, 2012 - 04:49 AM |
|

Joined: Aug 21, 2002
Posts: 895
Location: Austria
|
|
Wrong Syntax:
Use either
Code:
struct Electronic_Serial_Number
{
uint8_t presence;
uint8_t family_code;
uint8_t ESN[6];
uint8_t CRC;
};
struct Electronic_Serial_Number ESN;
or
Code:
typedef struct
{
uint8_t presence;
uint8_t family_code;
uint8_t ESN[6];
uint8_t CRC;
} Electronic_Serial_Number;
Electronic_Serial_Number ESN;
I prefer the 2nd solution, because it does not neet the "struct" for the declaration of the variables and parameters.
BTW, it would help, if you would post the error-message(s) you've got. |
_________________ /Martin.
|
| |
|
|
|
|
|
Posted: Jan 26, 2012 - 06:42 AM |
|

Joined: Nov 17, 2004
Posts: 13847
Location: Vancouver, BC
|
|
|
Quote:
Wrong Syntax:
Also wrong here:
Code:
uint8_t Read_DS2401(struct Electronic_Serial_Number *ptr);
//Change to
uint8_t Read_DS2401(Electronic_Serial_Number *ptr);
And here it is wrong three times over (struct should not be there, the type should not be there, and you need to take the address of the variable):
Code:
i = Read_DS2401(struct Electronic_Serial_Number ESN);
//Should be:
i = Read_DS2401(&ESN);
|
_________________ Regards,
Steve A.
The Board helps those that help themselves.
|
| |
|
|
|
|
|
Posted: Jan 26, 2012 - 09:27 AM |
|


Joined: Jul 18, 2005
Posts: 62324
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
Like Martin I prefer the typedef route:
Code:
typedef struct {
int n;
char c;
} my_data_type;
void init_data(my_data_type * p) {
p->n = 12345;
p->c = 'A';
}
int main(void) {
my_data_type mydata;
init_data(mydata);
if (mydata.n == 12345) {
UART_send(mydata.c);
}
}
The one time you use a struct tag would be for self-reference:
Code:
typedef struct mydata_tag {
int n;
char c;
struct mydata_tag * next;
} my_data_type;
(usually when creating linked lists). |
_________________
|
| |
|
|
|
|
|
Posted: Jan 26, 2012 - 10:10 AM |
|

Joined: Feb 12, 2005
Posts: 16320
Location: Wormshill, England
|
|
We all know that you can use any valid characters in identifiers. Sometimes conventions assist. Other times they just inflame wars !
Code:
struct cow { ... };
typedef struct cow { ... } cow_t;
typedef struct { ... } COW;
typedef struct { ... } cow;
Personally, I think that the cow_t style is the least confusing. It also means that you can have forward pointer references to the named struct if required. (as in Cliff's self-reference example)
The COW style is not a bad way of doing things. You can use pointer refs at any stage after the typedef. This may be a useful safety check.
I dislike the cow form of typedef but that is just my personal taste. I confess to actually using the COW style.
David. |
|
|
| |
|
|
|
|
|
Posted: Jan 26, 2012 - 10:19 AM |
|

Joined: Aug 04, 2010
Posts: 76
|
|
Thanks guys. I made sure I did exactly what was written in an online tute too ...
I have changed the struct declaration and am left with this error;
In file included from ../1284P_DS2401.c:51:0:
G:\Atmel Projects\1284P_DS2401\1284P_DS2401\..\..\include/avr/DS2401.c:34:46: error: expected ')' before '*' token
make: *** [1284P_DS2401.o] Error 1
Build failed with 1 errors and 0 warnings...
which refers to the function in the line,
uint8_t Read_DS2401(Electronic_Serial_Number *ptr)
Much else seems to have disappeared thankfully.
Cheers, |
|
|
| |
|
|
|
|
|
Posted: Jan 26, 2012 - 10:41 AM |
|


Joined: Jul 18, 2005
Posts: 62324
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
Let's see that line in context. Will the "Electronic_Serial_Number" type be known to the compiler at the moment it reaches this line?
(@David, problem with "COW" is that all upper case says "macro" to a lot of people. Apropos of nothing: the other day I came across code using "str" as a prefix for struct types - I thought that was TRULY awful - my first thought on reading "str" was that it was going to be a character array!) |
_________________
|
| |
|
|
|
|
|
Posted: Jan 26, 2012 - 12:39 PM |
|

Joined: Feb 12, 2005
Posts: 16320
Location: Wormshill, England
|
|
I agree with you. I also use the MACRO convention.
I was just being honest. I used COW as a typedef in my first C programs in 1989 or whenever. In hindsight COW_t or cow_t would be preferable.
I would also guess that Electronic_Serial_Number has not yet come into scope.
David. |
|
|
| |
|
|
|
|
|
Posted: Jan 26, 2012 - 04:04 PM |
|

Joined: Dec 20, 2007
Posts: 943
Location: Portland, Oregon, USA
|
|
| A declaration of the
Code:
typedef struct { type1 field1; /* ... */ } MyType;
style, as advocated by several here, declares an unnamed struct and then assigns a typedef to it. On the previous platform that my group here at work used, none of the typenames were visible to the debugger; only the algorithmically-generated internal names that the compiler made up. And those names made C++ function-name-mangling look like the clearest prose. We pretty much agreed to force ourselves to use the
Code:
typedef struct myStruct { type1 field1; /* ... */ } MyType;
style, to keep the debugger from displaying pointers as things like "(__agmx_PU32sn4flZ_33ewq *) 0xc1aa462". I hear that unnamed structs can also pose portability problems, though I don't understand the reasoning there.
But this is something that (IMO) makes it worthwhile to use the C++ compiler, even if the only blessed feature you ever use is the ability to just say
Code:
struct MyType { type1 field1; /* ... */ };
, and thereafter be able to use "MyType" as if it were a builtin type. |
|
|
| |
|
|
|
|
|
Posted: Jan 26, 2012 - 10:03 PM |
|

Joined: Aug 04, 2010
Posts: 76
|
|
Guys,
I'm of the opinion that there is a massive amount of misinformation on the web. In fact, when you get publishers all offering different solutions one gets to the point of dispair. Perhaps I should take comfort that 'C for Dummies' just openly says its too hard and they don't want to go there !!
I wonder why someone hasn't posted a tute on the subject in the tutorials forum ?
Coding has a way of making one feel small - or perhaps it is 'C'. It is a pretty stupidly abstract language.
I've tried another raft of attempts to get various errors. I know I'm passing an address to the start of the structure but I'm not sure how the funtion will know the actual structure structure eg. ptr->ESN[j]
Rgds, |
|
|
| |
|
|
|
|
|
Posted: Jan 26, 2012 - 11:18 PM |
|

Joined: Nov 17, 2004
Posts: 13847
Location: Vancouver, BC
|
|
|
Quote:
I wonder why someone hasn't posted a tute on the subject in the tutorials forum ?
But this is just basic C, not anything related to the AVR.
Quote:
Perhaps I should take comfort that 'C for Dummies' just openly says its too hard and they don't want to go there !!
In that case I would never recommend that book to anyone if they skip such an important part of the C language. |
_________________ Regards,
Steve A.
The Board helps those that help themselves.
|
| |
|
|
|
|
|
Posted: Jan 26, 2012 - 11:37 PM |
|

Joined: Aug 04, 2010
Posts: 76
|
|
If you don't mind I'd like to discuss a piece of code seen in 'BeeJ's Guide to C' on the Web.
Code:
#include <stdio.h>
struct mutantfrog {
int num_legs;
int num_eyes;
};
void build_beejs_frog(struct mutantfrog *f)
{
f->num_legs = 10;
f->num_eyes = 1;
}
int main(void)
{
struct mutantfrog rudolph;
build_beejs_frog(&rudolph); /* passing a pointer to the struct */
printf("leg count: d\n", rudolph.num_legs); /* prints "10" */
printf("eye count: d\n", rudolph.num_eyes); /* prints "1" */
return 0;
}
I get everything inside the main(). Mine is different in that I declare a variable ESN of type Electronic_Serial_Number outside of the main().
OK.
Another difference is that this example doesn't include a function prototype which is where I might (will!) be incorrect.
When I put a 'struct' in the function declaration like he does I'm sure I get more errors telling me it wont be available outside the function ... |
|
|
| |
|
|
|
|
|
Posted: Jan 27, 2012 - 01:18 AM |
|

Joined: Aug 04, 2010
Posts: 76
|
|
Here's the latest.
I have discovered a need of a space between the * and the pointer for structures but my understanding of the prototype is probably lacking.
How does one pass a pointer to the start of the structure but so that the function has the skeleton (as it were) of the structure ? I think I'm only passing a memory address of the star of the structure!
I still think it doesn't know what *ptr->ESN[j] is exactly (nor *ptr->family_code for that matter)
Code:
typedef struct
{
uint8_t presence;
uint8_t family_code;
uint8_t ESN[6];
uint8_t CRC;
}Electronic_Serial_Number;
Electronic_Serial_Number ESN;
Electronic_Serial_Number * ptr_ESN;
uint8_t Read_DS2401(Electronic_Serial_Number * ptr_ESN);
int main(void)
{
ptr_ESN = &ESN;
...
The function is ...
Code:
uint8_t Read_DS2401(Electronic_Serial_Number * ptr)
{
...
(*ptr).presence = count;
...
ptr->family_code = bytevalue;
...
ptr->ESN[j] = bytevalue;
...
}
The errors are ...
Code:
Build started 27.1.2012 at 11:01:53
.d -c ../1284P_DS2401.c
In file included from ../1284P_DS2401.c:51:0:
G:\Atmel Projects\1284P_DS2401\1284P_DS2401\..\..\include/avr/DS2401.c:34:46: error: expected ')' before '*' token
make: *** [1284P_DS2401.o] Error 1
Build failed with 1 errors and 0 warnings...
|
|
|
| |
|
|
|
|
|
Posted: Jan 27, 2012 - 02:30 AM |
|

Joined: Aug 19, 2003
Posts: 397
Location: Australia
|
|
|
Quote:
How does one pass a pointer to the start of the structure but so that the function has the skeleton (as it were) of the structure ? I think I'm only passing a memory address of the star of the structure!
But that is how C works., you only pass the address of the start of your data, it is up to whatever you pass it to to process it correctly.
In your main() you pass the address of the start of that data-structure with a Read_DS2401( &ESN ); or Read_DS2401( ptr_ESN );
Read_DS2401 'knows' what to expect because you have told it via the declaration
uint8_t Read_DS2401( Electronic_Serial_Number *ptr ) to expect a pointer to a chunk of bytes which is organised as your Electronic_Serial_Number structure.
There are several ways to get exactly the same end-result, as evidenced by the 'struct' versus 'typedef' side-issue.
Also in
Quote:
uint8_t Read_DS2401(Electronic_Serial_Number * ptr)
{
...
(*ptr).presence = count;
...
replace it with ptr->presence = count;
Be carefull with
Quote:
I still think it doesn't know what *ptr->ESN[j] is exactly (nor *ptr->family_code for that matter)
because the code in Read_DS2401 uses ptr->family_code which is not the same as *ptr->family_code |
Last edited by mikech on Jan 27, 2012 - 02:42 AM; edited 1 time in total
|
| |
|
|
|
|
|
Posted: Jan 27, 2012 - 02:37 AM |
|

Joined: Nov 17, 2004
Posts: 13847
Location: Vancouver, BC
|
|
|
Quote:
Another difference is that this example doesn't include a function prototype
A prototype is not necessary as long as the function is visible to the compiler before it is used. In this case, the function is declared in the same file above where it is invoked in main.
Quote:
When I put a 'struct' in the function declaration like he does I'm sure I get more errors telling me it wont be available outside the function ...
That is because you are using typedef, so the "struct" is already part of the typedef.
Quote:
How does one pass a pointer to the start of the structure but so that the function has the skeleton (as it were) of the structure ?
Because you told it what type the variable is.
Quote:
I have discovered a need of a space between the * and the pointer for structures
No you don't.
Quote:
The errors are ...
But which line does that point to? |
_________________ Regards,
Steve A.
The Board helps those that help themselves.
|
| |
|
|
|
|
|
Posted: Jan 27, 2012 - 03:22 AM |
|


Joined: Mar 28, 2001
Posts: 20381
Location: Sydney, Australia (Gum trees, Koalas and Kangaroos, No Edelweiss)
|
|
This thread title reminds me of a medical problem, don't know why.  |
_________________ John Samperi
Ampertronics Pty. Ltd.
www.ampertronics.com.au
* Electronic Design * Custom Products * Contract Assembly
|
| |
|
|
|
|
|
Posted: Jan 27, 2012 - 03:45 AM |
|

Joined: Nov 17, 2004
Posts: 13847
Location: Vancouver, BC
|
|
|
Quote:
replace it with ptr->presence = count;
Not necessary, the two are equivalent. |
_________________ Regards,
Steve A.
The Board helps those that help themselves.
|
| |
|
|
|
|
|
Posted: Jan 27, 2012 - 04:51 AM |
|

Joined: Aug 04, 2010
Posts: 76
|
|
wrt medical procedures ...
It is either the birthing procedure or another one. I guess it depends on whether it keeps giving problems in the use or whether it is like an obstruction that passes and the pain goes away ...
Thanks for the help, I'll get back to it after tea ! |
|
|
| |
|
|
|
|
|
Posted: Jan 27, 2012 - 08:14 AM |
|

Joined: Aug 04, 2010
Posts: 76
|
|
The only error now is on the line which starts the function in an external file.
Code:
uint8_t Read_DS2401(Electronic_Serial_Number *ptr)
Its saying it expects a ) before the *.
Can anyone explain this ? |
|
|
| |
|
|
|
|
|
Posted: Jan 27, 2012 - 08:58 AM |
|


Joined: Jan 14, 2008
Posts: 1147
Location: San Diego
|
|
|
Quote:
The only error now is on the line which starts the function in an external file.
Is Electronic_Serial_Number defined in a header file? From what you posted it looks like it is in the main.c file which means the other C file that holds Read_DS2401() wouldn't know what that struct is, causing an error. |
_________________ ~~John
TWI C source code
|
| |
|
|
|
|
|
Posted: Jan 27, 2012 - 09:21 AM |
|


Joined: Jul 18, 2005
Posts: 62324
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
|
Quote:
Its saying it expects a ) before the *.
Can anyone explain this ?
I already did:
Quote:
Let's see that line in context. Will the "Electronic_Serial_Number" type be known to the compiler at the moment it reaches this line?
So did David
Quote:
I would also guess that Electronic_Serial_Number has not yet come into scope.
I also showed a complete example of using struct pointers:
Quote:
Code:
typedef struct {
int n;
char c;
} my_data_type;
void init_data(my_data_type * p) {
p->n = 12345;
p->c = 'A';
}
int main(void) {
my_data_type mydata;
init_data(mydata);
if (mydata.n == 12345) {
UART_send(mydata.c);
}
}
Are you going to bother reading the replies you are given or not?
As for your ESN thing. the only reason you can use:
Code:
#include <stdio.h>
int * n;
int main(void) {
printf("%d", *n);
}
And the compiler doesn't moan about not knowing what "int *" is, is because it's a type already known to the compiler. But if you try:
Code:
#include <stdio.h>
int * n;
mytype * foo;
int main(void) {
printf("%d", *n);
}
You will get:
Code:
error: expected ')' before '*' token
because in this program the compiler has no idea what "mytype" is. I can correct that in one of two ways:
Code:
#include <stdio.h>
typedef struct {
int n;
char c;
} mytype;
int * n;
mytype * foo;
int main(void) {
printf("%d", *n);
}
or
Code:
#include <stdio.h>
#include "contains_type_definition_for_mytype.h"
int * n;
mytype * foo;
int main(void) {
printf("%d", *n);
}
|
_________________
|
| |
|
|
|
|
|
Posted: Apr 19, 2012 - 11:05 PM |
|


Joined: May 08, 2011
Posts: 228
Location: Tooele/Lake Point/Erda, Utah
|
|
|
clawson wrote:
Like Martin I prefer the typedef route:
Code:
typedef struct {
int n;
char c;
} my_data_type;
void init_data(my_data_type * p) {
p->n = 12345;
p->c = 'A';
}
int main(void) {
my_data_type mydata;
init_data(mydata);
if (mydata.n == 12345) {
UART_send(mydata.c);
}
}
The one time you use a struct tag would be for self-reference:
Code:
typedef struct mydata_tag {
int n;
char c;
struct mydata_tag * next;
} my_data_type;
(usually when creating linked lists).
I hate compiler warnings. They are usually a good indication I have done something wrong. When passing a pointer to a structure as in your example I get this:
../GPS_Functions.c:3: warning: 'struct gps_st' declared inside parameter list
../GPS_Functions.c:3: warning: its scope is only this definition or declaration, which is probably not what you want
It gives an error if I take the struct out of the function header.
typedef struct {
int wYear;
. . .
} gps_st;
Function declaration:
void GetLocalTime(gps_st*);
Function Call:
GetLocalTime(&gps_data);
Function:
void GetLocalTime(struct gps_st * foo){
. . .
If I remove "struct", it will not compile. I have tried it with and without the space after *. |
_________________ I use:
AS6 (under duress)
WinAvr 20100110
Windows 7 & XP
STK 600
AVR ONE!(broken and Atmel won't fix)
JTAGICE3 (only works with AS6)
AVRISP II
So far - '88 '2560
Sometimes my own RTOS
|
| |
|
|
|
|
|
Posted: Apr 19, 2012 - 11:32 PM |
|


Joined: Dec 21, 2006
Posts: 1483
Location: Saar-Lor-Lux
|
|
| You definitely have to clean up this mess:
Code:
#include <avr/i2c.c>
#include <avr/macro.c>
#include <avr/spi.c>
#include <avr/MCP23S17.c>
#include <avr/CM404.c>
#include <avr/buzzer.c>
#include <avr/heater_cooler.c>
#include <avr/LEDs.c>
#include <avr/motor.c>
#include <avr/usart.c>
#include <avr/external_EEPROMs.c>
#include <avr/MCP4921.c>
#include <avr/1284P_AD.c>
#include <avr/switches.c>
#include <avr/AVR_setup.c>
#include <avr/DS2401.c>
- Never (as in NEVER!) include C files! Write proper prototypes for global variables and functions, write global macros as needed and typedefs. And put them in headers.
Include these headers in the C files as needed. That way C files can communicate.
- Never (as in NEVER!) put your files as system files. They are no system files. Use #include "foo.h" or perhaps #include "path/foo.h" and tell the root directory of your project include paths to the compiler by means of -I root.
|
|
|
| |
|
|
|
|
|
Posted: Apr 19, 2012 - 11:51 PM |
|


Joined: May 08, 2011
Posts: 228
Location: Tooele/Lake Point/Erda, Utah
|
|
Confused.
My structure is in a header file.
My comment was only about passing the pointer. I get compiler warnings.
Not sure if you caught that I was only saying that if I did the structure pointer passing as described in the quoted passage, it throws errors. I gave small snippets of my code showing that I am passing the pointer in the exact same way. My structure is in fact inside a .H file that is included.... |
_________________ I use:
AS6 (under duress)
WinAvr 20100110
Windows 7 & XP
STK 600
AVR ONE!(broken and Atmel won't fix)
JTAGICE3 (only works with AS6)
AVRISP II
So far - '88 '2560
Sometimes my own RTOS
|
| |
|
|
|
|
|
Posted: Apr 19, 2012 - 11:53 PM |
|


Joined: May 08, 2011
Posts: 228
Location: Tooele/Lake Point/Erda, Utah
|
|
|
SprinterSB wrote:
You definitely have to clean up this mess:
Code:
#include <avr/i2c.c>
#include <avr/macro.c>
#include <avr/spi.c>
#include <avr/MCP23S17.c>
#include <avr/CM404.c>
#include <avr/buzzer.c>
#include <avr/heater_cooler.c>
#include <avr/LEDs.c>
#include <avr/motor.c>
#include <avr/usart.c>
#include <avr/external_EEPROMs.c>
#include <avr/MCP4921.c>
#include <avr/1284P_AD.c>
#include <avr/switches.c>
#include <avr/AVR_setup.c>
#include <avr/DS2401.c>
That code did not come from me. Not sure if you are replying to my message or some other message. |
_________________ I use:
AS6 (under duress)
WinAvr 20100110
Windows 7 & XP
STK 600
AVR ONE!(broken and Atmel won't fix)
JTAGICE3 (only works with AS6)
AVRISP II
So far - '88 '2560
Sometimes my own RTOS
|
| |
|
|
|
|
|
Posted: Apr 20, 2012 - 12:07 AM |
|


Joined: Jul 23, 2001
Posts: 2438
Location: Osnabrueck, Germany
|
|
|
ibapah wrote:
Confused.
That happens if you append your question to an old thread.
Someone might come around and comments on the old original code instead of your new one.
Code:
void GetLocalTime(struct gps_st * foo){
The "struct" here is wrong.
Quote:
If I remove "struct", it will not compile.
And what does "will not compile" mean? Don't you think that the concrete error message might be of use for us? |
_________________ Stefan Ernst
|
| |
|
|
|
|
|
Posted: Apr 20, 2012 - 12:32 AM |
|


Joined: May 08, 2011
Posts: 228
Location: Tooele/Lake Point/Erda, Utah
|
|
| I wish I could. It was complaining of expecting a ( or ; or something. But right after posting that note, the compiler warnings with the "struct" stopped. No idea. I had built all multiple times. Nothing changed that I know about. Just quit throwing warnings. Actually, that is not totally true, I ran the code with the simulator. That is what caused the warnings to stop. I guess if they come back I will make another posting here along with the actual error when the "struct" is removed. |
_________________ I use:
AS6 (under duress)
WinAvr 20100110
Windows 7 & XP
STK 600
AVR ONE!(broken and Atmel won't fix)
JTAGICE3 (only works with AS6)
AVRISP II
So far - '88 '2560
Sometimes my own RTOS
|
| |
|
|
|
|
|
Posted: Apr 20, 2012 - 01:11 AM |
|

Joined: Jun 21, 2005
Posts: 882
Location: Chicago area, USA
|
|
|
SprinterSB wrote:
Never (as in NEVER!) include C files!
As someone who pretty much ALWAYS includes C files, I'll bite. Never? Is it better to put everything into one single file?
(Again, I am not saying that everyone should forget about linking and never learn what a linker is. If someone includes C files just because he/she does not know any better - that is bad and it should be pointed out. But to never include? I say never say never.) |
|
|
| |
|
|
|
|
|
Posted: Apr 20, 2012 - 01:50 AM |
|


Joined: May 08, 2011
Posts: 228
Location: Tooele/Lake Point/Erda, Utah
|
|
I have multiple C files, but I don't use include. I just tell the IDE/project whatever it is called there are multiple source files. I have one (or more) header files with all function declarations and global variable declarations. But the C files don't have to be included.
Not sure the danger in including c files, but with the IDE/project essentially wrapping it all together in a project for you, there is no need.
I think I am missing SprinterSBs main point. |
_________________ I use:
AS6 (under duress)
WinAvr 20100110
Windows 7 & XP
STK 600
AVR ONE!(broken and Atmel won't fix)
JTAGICE3 (only works with AS6)
AVRISP II
So far - '88 '2560
Sometimes my own RTOS
|
| |
|
|
|
|
|
Posted: Apr 20, 2012 - 09:16 AM |
|


Joined: Jul 18, 2005
Posts: 62324
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
|
Quote:
I think I am missing SprinterSBs main point.
Ignore it for now - as Stefan told you your post triggered Georg-Johann to read/reply to the original post - nothing to do with what you were asking. Anyway just to confirm what Stefan said. If I take the example code I posted to this thread:
Code:
typedef struct {
int n;
char c;
} my_data_type;
void init_data(my_data_type * p) {
p->n = 12345;
p->c = 'A';
}
int main(void) {
my_data_type mydata;
init_data(mydata);
if (mydata.n == 12345) {
UART_send(mydata.c);
}
}
and compile that I get:
Code:
avr-gcc -c -mmcu=atmega16 -I. -gdwarf-2 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort
-enums -Wall -Wstrict-prototypes --save-temps -fverbose-asm -Wa,-adhlns=./test.lst -std=gnu99 -MMD -MP -MF .dep/test.o.
d test.c -o test.o
test.c: In function 'main':
test.c:14: error: incompatible type for argument 1 of 'init_data'
test.c:16: warning: implicit declaration of function 'UART_send'
The reason for that is that I missed the & as the function invocation was supposed to pass a POINTER to the struct, not the struct itself (we just fell foul of something like this in real code the other day when a 250K struct instead of a pointer to it was being passed and crashing the stack in a DSP RTOS - that was actually because of C++'s pass by reference mechanism which makes it easier to make this error). The code should have read:
Code:
init_data(&mydata);
in which case you only get the warning:
Code:
test.c: In function 'main':
test.c:16: warning: implicit declaration of function 'UART_send'
and that's simply because this is an incomplete test program.
In case you missed it the whole point of typedef'ing a struct and avoiding the use of a tag is for the very reason that you don't then have to sprinkle you code with the word 'struct' all over the place. |
_________________
|
| |
|
|
|
|
|