Hi:
i'm in trouble with the configuration of the TIM module of MC68HC908JK1 microcontroller. i wwant to use it as an PWM output to trigger a led in a IR reflective sensor. it seems that the sintaxis is good, but it doesn't work!!!!!
this is the program (section of the TIM configuration):
unsigned int Frecuencia=40;
unsigned int Dureza=4;
unsigned int Modulo;
unsigned int Duty;
void Emisor(void){
Modulo=2500/Frecuencia;
Duty=Dureza*Modulo/100;
TSC_TSTOP=1;
TSC_TRST=1;
TMOD=Modulo;
TCH0=Duty;
TSC0_MS0A=1;
TSC0_ELS0B=1;
TSC0_TOV0=1;
TSC_TRST=0;
TSC_TSTOP=0;
}
Thanks!
Added part number to subject.
Hello Mac,
Thank you very much for your reply.
In my application I happen to know that TMOD is less than 256, and originally chose 16-bit arithmetic for speed and because it was sufficient - and left a warning comment for myself that hopefully I would spot if I changed TMOD. I suppose my use of "TMOD" rather than "(word)TMODL" shows a lack of commitment!
I don't think I've had any strange results with the actual value - only that the two TCH1 byte-writes occur in the wrong order, which (unsurprisingly given the earlier result) also happens if I take your code snippet but do the cast before the shift: it seems to be torn between the knowledge that the expression really would fit in a byte but that it must be padded out to a word, and in so doing forgets that TCH1 is supposed to be written high byte first.
I'll take a fresh look at my application to see if there is any reason for not using a dword. I suppose if I do make the assumption that TMODH is zero, it would be logical to leave TCH1H alone (having once set it to zero) and just write TCH1L each time. Something for me to think about.
Thanks,
Jim
Hello Jim,
I did some further tests with the value of TMOD limited, as you described. I also checked the HCS08, in addition to the HC908, to see if there were any differences.
For the HC908, the following code was tested:
word c;
volatile byte scratch_byte = 0x40;
TMOD = 0x00F0;
// Case 1:
c = TMODL * scratch_byte / 256;
TCH1 = c;
// Case 2:
TCH1 = TMODL * scratch_byte / 256;
The compiler generated the following code to write to TCH1.
Case 1:
STX 0x29 ; High byte first
STA 0x2A
Case 2:
STHX 0x29 ; This should also be OK
The equivalent code for the HCS08:
volatile word scratch_byte = 0x40;
word c;
TPM1MOD = 0x00F0;
// Case 1:
c = TPM1MODL * scratch_byte / 256;
TPM1C1V = c;
// Case 2:
TPM1C1V = TPM1MODL * scratch_byte / 256;
The compiler generated the following code to write to TPM1C1V.
Case 1:
STHX 0x29 ; OK
Case 2:
STA 0x2A ; Low byte first - OK for HCS08
CLR 0x29 ; High byte
In all the above cases, the expected result of the calculation was obtained.
Regards,
Mac
Hello Mac,
Thank you very much for your continued efforts - naturally I tried out your code and had a play around to see what happened. Case 2 was a match, but case 1 also did an STHX for "c" in a __SHORT_SEG (MOV X+,0x29 etc otherwise), but in any case TCH1 was written correctly.
I eventually figured out why the code looked so different (the apparently non-optimised division (tired!) and the correct write-order): casting to a word optimised the division, and in case 1 the code worked as one would expect, however in case 2 the write-order problem came back.
I guess this is a fairly unlikely scenario - if I'd chosen to code properly for either a 16-bit TMOD/TCH1 or an 8-bit one everything would have been fine.
I've not yet done anything for HCS08 - I'm hoping to jump straight to its succesor!
Thanks again,
Jim
RELEASE NOTES CHC08 V5.0.18...List of new Features- Changed access order to objects declared with 'volatile', typically IO registers: volatile unsigned int TCNT; TCNT = 0x1234; gives now code that accesses the low address byte first: LDA #52 LDX #18 STX TCNT STA TCNT:1 previous compiler versions accessed all objects high address byte first.....
I thought I remembered that the compiler was supposed to take care of it, but I've just had problems with it:
TCH1 = TMOD * scratch_byte >> 8;
(or even TCH1 = TMOD >> 8
Compiler seems to get them the wrong way round - apparently because it knows the high byte is 0.
Is this right?
Jim
Hello Jim,
The operation TMOD * scratch_byte seems to be problematic. We are multiplying a 16-bit value with an 8-bit value, with the possible result of unsigned long value. The result always seems to be zero.
I obtained the expected result with the following code -
dword c;
c = TMOD;
c *= scratch_byte;
TCH1 = (word)(c >> 8);
The cast was required to eliminate a "possible loss of data" warning. Yet the following expression gave a zero result for c, and casts did not seem to help.
c = TMOD * scratch_byte;
Regards,
Mac