We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi there!
I have some problems with CAPCOM timer. It was configured: CPU clock - 40 MHz prescaler - module clock / 8 Timer0 overflow (usec) - 100 Timer 0 reload register - 0xFE0C
On digital oscilloscope I can see ~9.615 kHz, not 10 kHz.
Can anyone explain this problem?
Some info: _MCTC1 EQU 1 _RWDC1 EQU 0 _MTTC1 EQU 0
From what I can see you are stopping and starting T7 in your code without any compensation for the off time (again in the code).
Hi Chris!
May be you right. But:
It was done to prevent more than 2 comparations (mode 1 can do it) in one period of timer. I think it is reason of strange invert PWM signal. If you can - look at picture: rapidshare.com/.../sample.JPG.html
My be someone know why it is happens and how to solve it?
Hi,
1) I don't use ST devices only Infineon so maybe I can't help you very much.
2) I can't download your picture since my time limit has expired for the free use.
3) It appears to me you are using double compare mode and the 6 pins of P8 for your signals.
4) CAPCOM2 doesn't have any shadow registers for the channels so you need to be very care full when updating the compare values.
5) You have decided to update all the compare channels at the timer T7 interrupt and are trying to prevent any missing compare events by stopping T7. However you are not compensating for the time you shut down the timer nor are you really sure of the value of T7 when you stop it. So you still could have a problem here since you don't know what the real value is (most likely it is not zero due to interrupt latency and software execution time).
6) My suggestion would to have a combination of interrupts, T7 and on the channel compares and dynamically choose when to update the new value as to prevent any glitches. So when the channel is not changing state near the T7 overflow use this interrupt to calculate the next compare value for these channels. If the changing state is near the T7 overflow then you need to update the compare value for the channel at the channel compare event interrupt.
Hi again!
1) ST and infineon are quite similar but there are some mismatches.
2)You can look at picture at another site:
www.bestsharing.com/.../sample.JPG.html
I am still needed in any advises about situation. May be someone have solved similar problem.
3) Yes, you are right
4,5) Yep. It is really reason of my problem with timer. If I do not stop timer - I can see 10 kHz PWM on hardware, but it looks like as at picture - with PWM signal invertion at some places.
6) Thanks. I'll try it. Sounds like it can help. But I don't understand why 12 first "=" operations of interrupt can't be executed in proper minimum time when the changing state is near the T7 overflow. Are they really so time-consuming?
CC16 = CC16_image; F2303482 MOV CC16,DPP2:0x0234
With next string I made 15 value gap at both edges of timer period for 12 MOV commands.
temp1 = ((unsigned int) Tone.y1 + 0x8000) / 298 + 15;
Where is the program execution from (internal or external)? In your first post you tell me that MCTC1 = 1 which means one wait state but is this where your program is executing from (CS1)?
Given you are running at 40MHz this means you have a possible instruction cycle of 50nsec (without adding a wait state or if you are running from the external bus which has a path of 16-bit verses 32-bit internal).
So if you make a rough calculation for the response time to get to the T7 interrupt before you begin processing anything. The minimum interrupt response time is 5 states (250nsec). This requires program execution from the internal code memory, no external operand read requests and setting the interrupt request flag during the last state of an instruction cycle. When the interrupt request flag is set during the first state of an instruction cycle, the minimum interrupt response time under these conditions is 6 state times (300nsec). This is just for the interrupt instruction to be fetched now it needs to make it through the pipeline to know it has to jump again to your interrupt service routine. Then you need to account for the preample of the interrupt frame. Which may look something like…
89: static void timer0 (void) interrupt T7INT 0002006A ECEF PUSH MSW 0002006C EC2E PUSH MAL 0002006E EC2F PUSH MAH 00020070 C6ED0000 SCXT MRW,#0x0000 00020074 EC84 PUSH IDX0 00020076 C6030300 SCXT DPP3,#0x0003 0002007A C6871000 SCXT MDC,#0x0010 0002007E EC06 PUSH MDH 00020080 EC07 PUSH MDL 00020082 ECF4 PUSH R4 00020084 ECF5 PUSH R5 00020086 ECF6 PUSH R6 00020088 ECF7 PUSH R7 0002008A ECF8 PUSH R8 0002008C ECF9 PUSH R9 100: T78CON &= ~0x0040; 0002008E 6690BFFF AND T78CON,#0xFFBF 102: CC16 = CC16_image; 00020092 F2302082 MOV CC16,DPP2:0x0220 103: CC19 = CC16_image; 00020096 F2332082 MOV CC19,DPP2:0x0220 104: CC24 = CC24_image;
Also notice that you have 16-bit and 32-bit opcodes and it takes an extra bus access to get the whole instruction from external memory (hence the advantage of the internal program memory bus which is 32-bits wide).
Ok how many cycles do you have before you turn off the clock to T7?
My suggestions to you would be…
1) You cannot turn off T7 because as you stated you are making wave shaped signals based on a PWM value. 2) Figure out when to update either in the timer interrupt or on the channel interrupt. 3) Change "CoSHR #14" as the simulator doesn't like this but should work in the actual device. 4) At least minimize the ISR something like this...
while (1) { /* service here instead of in the T7 interrupt or make this a high * priority task in your system to know it will run as soon as the * T7 interrupt has finished */ if(updatePWM == 1) { Generate_Sine (&Tone); Generate_Sine (&Tone2); Generate_Sine (&Tone3); temp1 = ((unsigned int) Tone.y1 + 0x8000) / 298 + 15; temp12 = ((unsigned int) Tone2.y1 + 0x8000) / 298 + 15; temp13 = ((unsigned int) Tone3.y1 + 0x8000) / 298 + 15; CC16_image = 0xFE0C + temp1; CC24_image = 0xFFFF - temp1; CC17_image = 0xFE0C + temp12; CC25_image = 0xFFFF - temp12; CC18_image = 0xFE0C + temp13; CC26_image = 0xFFFF - temp13; updatePWM = 0; } };
This code for T7 ISR is greatly reduced…
102: static void timer0 (void) interrupt T7INT { 103: T78CON &= ~0x0040; 000204F2 6690BFFF AND T78CON,#0xFFBF 104: CC16 = CC16_image; 000204F6 F2301682 MOV CC16,DPP2:0x0216 105: CC19 = CC16_image; 000204FA F2331682 MOV CC19,DPP2:0x0216 106: CC24 = CC24_image; 000204FE F2381A82 MOV CC24,DPP2:0x021A 107: CC27 = CC24_image; 00020502 F23B1A82 MOV CC27,DPP2:0x021A 108: CC17 = CC17_image; 00020506 F2311282 MOV CC17,DPP2:0x0212 109: CC20 = CC17_image; 0002050A F2341282 MOV CC20,DPP2:0x0212 110: CC25 = CC25_image; 0002050E F2391882 MOV CC25,DPP2:0x0218 111: CC28 = CC25_image; 00020512 F23C1882 MOV CC28,DPP2:0x0218 112: CC18 = CC18_image; 00020516 F2321082 MOV CC18,DPP2:0x0210 113: CC21 = CC18_image; 0002051A F2351082 MOV CC21,DPP2:0x0210 114: CC26 = CC26_image; 0002051E F23A1482 MOV CC26,DPP2:0x0214 115: CC29 = CC26_image; 00020522 F23D1482 MOV CC29,DPP2:0x0214 116: T78CON |= 0x0040; 00020526 76904000 OR T78CON,#0x0040 117: updatePWM = 1; 0002052A 0F00 BSET 0xFD00.0 0002052C FB88 RETI
I've done as you said. It really works! Even without stopping CAPCOM timer!
You are most usefull man in this forum, thanks a lot.