View previous topic :: View next topic |
Author |
Message |
L.T.
Joined: 24 Jul 2020 Posts: 62
|
Using struct and union |
Posted: Fri Aug 14, 2020 7:22 am |
|
|
Hi there,
I wrote a code with struct/union. You can see below.
Code: |
typedef struct{
uint8 s_syncBYTE;
uint8 s_THRBW;
uint8 s_P1_THR_0;
uint8 s_P1_THR_1;
uint8 s_P1_THR_2;
uint8 s_P1_THR_3;
uint8 s_P1_THR_4;
uint8 s_P1_THR_5;
uint8 s_P1_THR_6;
uint8 s_P1_THR_7;
uint8 s_P1_THR_8;
uint8 s_P1_THR_9;
uint8 s_P1_THR_10;
uint8 s_P1_THR_11;
uint8 s_P1_THR_12;
uint8 s_P1_THR_13;
uint8 s_P1_THR_14;
uint8 s_P1_THR_15;
uint8 s_P2_THR_0;
uint8 s_P2_THR_1;
uint8 s_P2_THR_2;
uint8 s_P2_THR_3;
uint8 s_P2_THR_4;
uint8 s_P2_THR_5;
uint8 s_P2_THR_6;
uint8 s_P2_THR_7;
uint8 s_P2_THR_8;
uint8 s_P2_THR_9;
uint8 s_P2_THR_10;
uint8 s_P2_THR_11;
uint8 s_P2_THR_12;
uint8 s_P2_THR_13;
uint8 s_P2_THR_14;
uint8 s_P2_THR_15;
}pga_bufs16;
typedef union{
pga_bufs16 pgab16;
uint8 pga_bufdizi16[sizeof(pga_bufs16)];
}pga_bufu16;
void pga460_initThresholds(BYTE thr)
{
P1_THR_0 = 0x88;
P1_THR_1 = 0x88;
P1_THR_2 = 0x88;
P1_THR_3 = 0x88;
P1_THR_4 = 0x88;
P1_THR_5 = 0x88;
P1_THR_6 = 0x84;
P1_THR_7 = 0x21;
P1_THR_8 = 0x08;
P1_THR_9 = 0x42;
P1_THR_10 = 0x10;
P1_THR_11 = 0x80;
P1_THR_12 = 0x80;
P1_THR_13 = 0x80;
P1_THR_14 = 0x80;
P1_THR_15 = 0x00;
P2_THR_0 = 0x88;
P2_THR_1 = 0x88;
P2_THR_2 = 0x88;
P2_THR_3 = 0x88;
P2_THR_4 = 0x88;
P2_THR_5 = 0x88;
P2_THR_6 = 0x84;
P2_THR_7 = 0x21;
P2_THR_8 = 0x08;
P2_THR_9 = 0x42;
P2_THR_10 = 0x10;
P2_THR_11 = 0x80;
P2_THR_12 = 0x80;
P2_THR_13 = 0x80;
P2_THR_14 = 0x80;
P2_THR_15 = 0x00;
pga_bufu16 pgau16;
pgau16.pgab16.s_syncBYTE=syncBYTE;
pgau16.pgab16.s_THRBW=THRBW;
pgau16.pgab16.s_P1_THR_0=P1_THR_0;
pgau16.pgab16.s_P1_THR_1=P1_THR_1;
pgau16.pgab16.s_P1_THR_2=P1_THR_2;
pgau16.pgab16.s_P1_THR_3=P1_THR_3;
pgau16.pgab16.s_P1_THR_4=P1_THR_4;
pgau16.pgab16.s_P1_THR_5=P1_THR_5;
pgau16.pgab16.s_P1_THR_6=P1_THR_6;
pgau16.pgab16.s_P1_THR_7=P1_THR_7;
pgau16.pgab16.s_P1_THR_8=P1_THR_8;
pgau16.pgab16.s_P1_THR_9=P1_THR_9;
pgau16.pgab16.s_P1_THR_10=P1_THR_10;
pgau16.pgab16.s_P1_THR_11=P1_THR_11;
pgau16.pgab16.s_P1_THR_12=P1_THR_12;
pgau16.pgab16.s_P1_THR_13=P1_THR_13;
pgau16.pgab16.s_P1_THR_14=P1_THR_14;
pgau16.pgab16.s_P1_THR_15=P1_THR_15;
pgau16.pgab16.s_P2_THR_0=P2_THR_0;
pgau16.pgab16.s_P2_THR_1=P2_THR_1;
pgau16.pgab16.s_P2_THR_2=P2_THR_2;
pgau16.pgab16.s_P2_THR_3=P2_THR_3;
pgau16.pgab16.s_P2_THR_4=P2_THR_4;
pgau16.pgab16.s_P2_THR_5=P2_THR_5;
pgau16.pgab16.s_P2_THR_6=P2_THR_6;
pgau16.pgab16.s_P2_THR_7=P2_THR_7;
pgau16.pgab16.s_P2_THR_8=P2_THR_8;
pgau16.pgab16.s_P2_THR_9=P2_THR_9;
pgau16.pgab16.s_P2_THR_10=P2_THR_10;
pgau16.pgab16.s_P2_THR_11=P2_THR_11;
pgau16.pgab16.s_P2_THR_12=P2_THR_12;
pgau16.pgab16.s_P2_THR_13=P2_THR_13;
pgau16.pgab16.s_P2_THR_14=P2_THR_14;
pgau16.pgab16.s_P2_THR_15=P2_THR_15;
delay_us(100);
return;
}
|
I debugged the code but found that it doesn't write all the bytes. When I looked to "pgau16.pga_bufdizi16" array on watch, I saw this result.
Code: | "\x 55\x 10\x 88\x 88\x 88\x 88\x 88\x 88\x 84\x 21\x 8\x 0\x 88\x 88\x 88\x 88\x 88\x 88\x 0\x 85\x 21\x 0\x 84\x 21\x 8\x 42\x 0\x 0\x 0\x 75\x 1b\x 76\x 20\x 0\x 0" |
But it have to like this:
Code: | "\x 55\x 10\x 88\x 88\x 88\x 88\x 88\x 88\x 84\x 21\x 08\x 42\x 10\x 80\x 80\x 80\x 80\x 00\x 88\x 88\x 88\x 88\x 88\x 88\x 84\x 21\x 08\x 42\x 10\x 80\x 80\x 80\x 80\x 0" |
Where is the problem? Why does not it write all? Why is it only writing part of it? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19497
|
|
Posted: Fri Aug 14, 2020 1:11 pm |
|
|
You don't show any variables being defined called P1_THR_0 etc., but
write to these. If these are constant initialisations, why not #define
these?.
I'd actually print the values, rather than using watch. Unfortunately, the
debugger quite often seems to give 'issues' when dealing with larger objects.
As a general comment, it always seems to be more reliable, if you keep to
the original C requirement to declare variables at the start of the code
sections rather than mid code.
What chip?.
What compiler version?.
Then we can test and see if the problem is repeatable. |
|
|
L.T.
Joined: 24 Jul 2020 Posts: 62
|
|
Posted: Sun Aug 16, 2020 11:11 pm |
|
|
Actually, type of variables described above. I didn't write on my message, that is my fault.
Code: | BYTE P1_THR_0 = 0x88;
BYTE P1_THR_1 = 0x88;
BYTE P1_THR_2 = 0x88;
BYTE P1_THR_3 = 0x88;
BYTE P1_THR_4 = 0x88;
BYTE P1_THR_5 = 0x88;
BYTE P1_THR_6 = 0x84;
BYTE P1_THR_7 = 0x21;
BYTE P1_THR_8 = 0x08;
BYTE P1_THR_9 = 0x42;
BYTE P1_THR_10 = 0x10;
BYTE P1_THR_11 = 0x80;
BYTE P1_THR_12 = 0x80;
BYTE P1_THR_13 = 0x80;
BYTE P1_THR_14 = 0x80;
BYTE P1_THR_15 = 0x80;
BYTE P2_THR_0 = 0x88;
BYTE P2_THR_1 = 0x88;
BYTE P2_THR_2 = 0x88;
BYTE P2_THR_3 = 0x88;
BYTE P2_THR_4 = 0x88;
BYTE P2_THR_5 = 0x88;
BYTE P2_THR_6 = 0x84;
BYTE P2_THR_7 = 0x21;
BYTE P2_THR_8 = 0x08;
BYTE P2_THR_9 = 0x42;
BYTE P2_THR_10 = 0x10;
BYTE P2_THR_11 = 0x80;
BYTE P2_THR_12 = 0x80;
BYTE P2_THR_13 = 0x80;
BYTE P2_THR_14 = 0x80;
BYTE P2_THR_15 = 0x80;
|
I'm using PIC16F18346 and CCS C Compiler v5.076 and MPLABX IDE v5.05. And I dont know how can I print values to computer's screen? How do I connect the UART pins to the computer? I am using the PIC16F18346 microcontroller on the Microchip Curiosity test board. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19497
|
|
Posted: Mon Aug 17, 2020 2:32 am |
|
|
Right, several things here:
First, what you post is incredibly wasteful of memory space. You have fixed
initialisation values, that you copy into RAM, and then copy to the structure.
Why?. Just #define the initialisation values and then write them directly
to the structure. Saves 32 bytes of RAM straight away.
Then there is a big issue. You do realise that declaring pgau16 as you
do in the function, means it only 'exists' as a variable, while you are inside
the pga460_initThresholds subroutine. As soon as you exit this routine,
this variable ceases to exist, and the memory it uses can be re-used?.
So the bytes being 'wrong' outside this routine, will be totally correct.
If this variable needs to be re-accessed later, then it needs to be declared
as 'static' (which then means it will still exist after the function exits). If
it is to be used anywhere else, it needs to be globally declared.
The curiosity board has RX and TX on J34. For standard serial print, you
would need either a RS232 port on your PC, with suitable level translator
circuitry, or one of the little USB to TTL serial modules, and connect the
pins from this to these pins on the board.
However assuming you are using ICD, it may also be possible to print via
the ICD. This depends on what actual debugger you are using to connect
to the chip. |
|
|
L.T.
Joined: 24 Jul 2020 Posts: 62
|
|
Posted: Mon Aug 17, 2020 5:45 am |
|
|
PGA's register names is described as byte firstly. And default settings is loaded to registers at the same time. Then, I used these registers in different places. I have functions more than one and the same register can be used in more than one function. Different values can be loaded in each different function. When you think this way, do you still think I misidentified? Is the cause of the error due to this? Did it work when you experimented with the code I sent? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19497
|
|
Posted: Mon Aug 17, 2020 6:59 am |
|
|
If you want to use variables in multiple locations, they need to be globally
declared. As you currently show, they are not, which means the RAM they
contain can and will be re-used for other things as soon as you leave the
function. This will result in bytes containing the wrong values.
This almost certainly is what is causing the 'problem' you have.... |
|
|
L.T.
Joined: 24 Jul 2020 Posts: 62
|
|
Posted: Mon Aug 17, 2020 8:38 am |
|
|
Ttelmah wrote: | If you want to use variables in multiple locations, they need to be globally
declared. As you currently show, they are not, which means the RAM they
contain can and will be re-used for other things as soon as you leave the
function. This will result in bytes containing the wrong values.
This almost certainly is what is causing the 'problem' you have.... |
Could you please show me how to define it on my code as an example? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19497
|
|
Posted: Mon Aug 17, 2020 12:01 pm |
|
|
Read a basic C book:
Code: |
//processor setup
type name; //this variable is global
void function(someything)
{
type name; //this variable is local and only exists while the function
//exists
static type name; //this variable is also local, but exists all the time
}
|
|
|
|
L.T.
Joined: 24 Jul 2020 Posts: 62
|
|
Posted: Mon Aug 17, 2020 11:12 pm |
|
|
Ttelmah wrote: | Read a basic C book:
Code: |
//processor setup
type name; //this variable is global
void function(someything)
{
type name; //this variable is local and only exists while the function
//exists
static type name; //this variable is also local, but exists all the time
}
|
|
In the beginning, I defined all the registers globally in byte type. I wrote these definitions under processor setup.
Then, I changed it by reassigning values in functions. I think, it is local. Are you telling me to make the changes I made here as static? Do I get it right?
I don't understand what you want me to change. Can you show me where you mean on the codes I sent? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19497
|
|
Posted: Tue Aug 18, 2020 1:21 am |
|
|
The correct thing to do is:
1) All 'global' things (anything accessed in more than one location), should
be global.
2) Everything that is only used inside a single routine should be declared
locally to the routine.
3) Any 'local'' variables that need to maintain their contents between
successive calls to the routines, or values that are referenced (by pointer)
from outside the routine, should be declared as 'static'. |
|
|
|