I am using Keil, C51 Compiler with Infineon XC886 8-bit micro....
I have a simple application that acquires rising and falling edges at P3.0 and then calculates the Period and Pulse Width in ticks of T12.
Then the program "based on these values" stretches the pulse using a 2D lookup table and generates a PWM output on P3.7 (it is inverted).
The lookup table returns a value from 0 to 1000.... a value of 300 means add 30% to the actual pulse width (NOT duty cycle which is %).
Everything seems to work except the output pulse width is incorrect.
I have (by process of elimintation) worked out the portion of code that is causing problems, but I think that it is actually the compiler.
The name of the function is "modifyDutyCycle"..
Step 1: First I disabled all interrupts then cut and paste the contents of the function into main. Since the calculation was quite involved I created a number of temporary variables to see the step by step results....
for (periodTemp = 3500; periodTemp < 31000; periodTemp += 200) { for(pulseTemp = 150; pulseTemp < 4000; pulseTemp += 50) { //Checking the lookUpTable function here in the for loop.... works! //index1 = lookUpTable(periodTemp, pulseTemp); //delay(10); //Extended version of the calculation from the "modifyDutyCycle" function //adjustVal = (uword)(((ulong)dutyCycle[0])*((ulong)(lookUpTable(period[0], dutyCycle[0])))/1000); //index2 = (uword)(((ulong)pulseTemp)*((ulong)(lookUpTable(periodTemp, pulseTemp)))/1000); index2 = lookUpTable(periodTemp, pulseTemp); //index2 = uword index3 = (ulong)index2; //index3 = ulong index4 = (ulong)pulseTemp; //index4 = ulong index5 = index3*index4; //index5 = ulong index5 /= 1000; //Attempt #1 //index6 = (uword)index5; //index6 = uword //Attempt #2 //blah = index5; //blah = uword //Attempt #3 index6 = index5; } }
Inititally "Attempt #1 failed to give the correct value" Then I just added yet another variable "blah" - which generated the correct value. Then I tried with no type cast with success
Step 2: I returned to the original function and tried to get it to work - still using temporary variables. When I simulate I get the following results...
1. There is no green/grey block on the side of the window (where you normally blace a breakpoint) at the "adjustVal = index4;" line
2. When I put the variable in the "watch" window however it seems to update the value of adjustVal
void modifyDutyCycle(void) { //sam uword index1; ulong index2; ulong index3; ulong index4; uword adjustVal; //sam #ifdef debug programStatus = 0x40; #endif dutyCycleNew[3] = dutyCycleNew[2]; dutyCycleNew[2] = dutyCycleNew[1]; dutyCycleNew[1] = dutyCycleNew[0]; //Calculate the extra number of timer ticks to be added to the output pulse //Stretch based on pulse width (off-time) not on total period //adjustVal = (uword)(((ulong)dutyCycle[0])*((ulong)(lookUpTable(period[0], dutyCycle[0])))/1000); index1 = lookUpTable(period[0], dutyCycle[0]); index2 = (ulong)index1; index3 = (ulong)dutyCycle[0]; index4 = index2*index3; index4 /= 1000; //adjustVal = (uword)index4; //typecast.. automatic?? adjustVal = index4; //index1 = index4; //dutyCycleNew[0] = dutyCycle[0]; // //Check that the new duty cycle is <100% if ((dutyCycle[0] + adjustVal) < (period[0] - 10)) { //Return new updated duty cycle dutyCycleNew[0] = dutyCycle[0] + adjustVal; } else //Error has occurred.... { dutyCycleNew[0] = period[0] - 10; //Make the pulse width to approx. 100% } }
3. When I try it on my hardware, I have a pulse output but the width is incorrect - which looks very similar to the first time I tried the funtion in main "Attempt #1"
My problem is something to do with a type cast or a memory addressing issue I think. But my results are inconsistent.
Any help on this oune would be much appreciated!!
Thanks, bye!!
"which it (hopefully) is not within an organization"
That depends a lot on what projects that organisation is busy with.
Would you rename all data types used by the Windows API just to normalize them with the data type names used by the own organisation for own projects?
So what do you do when you have one set of projects where WORD is a 16-bit integer, and another set of projects where WORD is the size of the target platforms registers? What happens when developers from one set of projects jumps to the other set of projects?
Microsoft themselves have had huge problems with their own code because of their data type uses. What should they do when all developers declared the variables as WORD - according to the API documentation - and the 16-bit API moved to a 32-bit and later a 64-bit target where the parameter in question needed to change accordingly? While other uses of the same WORD did not relate to the int size or the size needed to span the memory system.
Many, many real-world examples can be shown, where the use of "word" have resulted in large costs in rework or because of bugs because of the ambiguous meaning of the term. It's just that lots of projects survives far longer than originally planned, and gets moved to new platforms in a way not intended.
Code really should separate data types used when size is important and where it isn't important. stdint.h have data types like uint16_t, uint_fast16_t and uint_least16_t just to give developers the tools to tell other developers and the compilers what is important. And if we need to store an address as an integer data type instead of a pointer data type, we have intptr_t or uintptr_t.
If we have the tools, we should make use of them.
If we have seen common and well-documented problems with a specific data type naming, we should try to avoid that type of naming.