View previous topic :: View next topic |
Author |
Message |
Woody
Joined: 11 Sep 2003 Posts: 83 Location: Warmenhuizen - NL
|
SMTrouble |
Posted: Tue Aug 31, 2021 10:03 am |
|
|
Hi,
I am getting some unexpected results with the SMT peripheral in an 18F27Q43.
The objective is to make a pulse that has an adjustable width between 1 and 30 us with as great a resolution as possible. 125ns is perfect. When generating this pulse nothing else needs to happen, so I hope to get away with a simple delay between raising and lowering the output pin.
I set out with above mentioned chip and this (simplified) code:
Code: |
#define PULSE_OUT PIN_C0
#use delay(internal=32000000)
#bit SMT1IF = 0x4AF.5
setup_smt1(SMT_ENABLED | SMT_MODE_TIMER | SMT_CLK_FOSC | SMT_DIV_BY_1);
smt1_reset_timer();
smt1_write(SMT_PERIOD_REG, 0x000001);
SMT1IF = 0;
smt1_start();
output_high(PULSE_OUT);
while(!SMT1IF);
output_low(PULSE_OUT);
smt1_stop();
|
This works and gives me a 500ns pulse on pin C0. What is unexpected is that as I change the SMT_PERIOD_REG value from 0x000001 to 0x000002, and 0x000003 the pulse width stays 500ns. When I change to 0x000004 the width becomes 870ns. Then it stays 870ns all the way up to 0x000010, when it becomes 1.245us. From 0x00001c onward the width becomes 1.620us and from 0x000028 it becomes 2us.
What I expected was an increase in time, 125ns for every step. What I am getting, I don't get. I see the pattern, but cannot explain why.
It could be the internal clock I'm using, it could be that I am not allowed to check SMT1IF the way I do, it could be that I completely misunderstood the SMT, I don't know. AFAICS the compiler generated code looks ok when compared with the datasheet, values end up where they should.
Anyway, staring at this for an afternoon did not make it work, so I hope someone can point me in the right direction.
Paul |
|
 |
gaugeguy
Joined: 05 Apr 2011 Posts: 318
|
|
Posted: Tue Aug 31, 2021 11:41 am |
|
|
I have not used that chip, but on others the SMT will have a step size, in your case it appears to be 375ns but will create pulse trains that are between steps by alternating between two different pulse widths. It might be 3 pulses at 1245ns and 1 pulse at 1620ns for an average over time of 1338ns. |
|
 |
Woody
Joined: 11 Sep 2003 Posts: 83 Location: Warmenhuizen - NL
|
|
Posted: Tue Aug 31, 2021 12:58 pm |
|
|
Thanks for you reaction, unfortunately I do not quite follow. The SMT has a 'step size', which is dependent on the clock. Its timer increases every clock cycle as shown in the DS page 428. With my 32MHz clock I would expect to see 125ns, and not 375ns.
If I understand the DS correctly the STM should work like this:
1) Enable and set the STM as a timer, select a clock (Fosc in my case, 32MHz) and a prescaler (1:1)
2) Clear (reset to 000000) the timer part of the STM
3) Set a value in the period register
4) Start the timer.
5) After a one-time sync the timer now increases every Fosc. When the timer equals the period register the SMT1IF bit is set
Now in my case 12 different values for the period register (e.g. 0x10..0x1b) lead to the same moment that the SMT1IF bit is set. I don't believe for a second that the STM module is malfunctioning and also the compiler seems to do fine here, so I suspect I either misunderstand something or made a silly mistake somewhere else.
Paul |
|
 |
gaugeguy
Joined: 05 Apr 2011 Posts: 318
|
|
Posted: Tue Aug 31, 2021 1:09 pm |
|
|
It could also be that your while(!SMT1IF); command takes 2-4 instruction cycles to loop through, thus limiting how fast you can respond depending on where in the loop the flag changes.
This will be a bit test loop made of several assembly commands, so is not a single cycle command. |
|
 |
Woody
Joined: 11 Sep 2003 Posts: 83 Location: Warmenhuizen - NL
|
|
Posted: Wed Sep 01, 2021 12:46 am |
|
|
Woke up this morning and I think I understand where I am going wrong.
It has most likely to do with the way I test for the change of SMT1IF. The problem is that this flag (according to the DS) stays 'up' for only one cycle.
This makes while(!SMT1IF) a bad idea to check it, as this takes 3 cycles itself.
Why it does work at all every 12 counts is a question for another time. First I am going to find an alternative for my programmable precise timer
Thanks for thinking along on this.
Paul |
|
 |
|