Hello,
I,m using s12zvml31 for capture square wave's frequency and duty。Simultaneously, output square wave with the same frequency and specific duty(5% for example). The input frequency is between 10Hz and 1000Hz.
S12zvml31 only have a Timer0 and my main interrupt cycle is 100us, what can I do to solve this problem? The main iterrupt cycle has the highest priority.
My timer's frequency is 625K now.
Hi,
entire code is attached, minimum measured frequency is defined only maximum number of overflows.
It worked, however, I have not seen it for, really will not lie, for years.
Yes, it is for different MCU but principle....
The code only measures frequency without measuring duty cycle.
1)
* Detailed Description:
* - It mesure frequency at PT1 by means of ECT module.
* - The measaurement is sensitive on rising edges so duty cycle has no affect
to the measurement
* - Constants:
BUSCLOCK
MAX_OVERFLOWS
TIMER_PRESCALLER
must be defined
* - MAX_OVERFLOWS determines minimum mesurable frequency.
It is max. allowed number of overflows. When overflows counter reaches
this value it the flag FREQUENCY_TOO_LOW is set. The message
PERIOD BETWEEN TWO EDGES IS TO WIDE is then sent sent to the PC through
SCI0. This value gives time interval:
T = TIMER_PRESCALER * MAX_OVERFLOWS * 65536 / BUSCLOCK
For example:
- TIMER_PRESCALER = 1
- MAX_OVERFLOWS = 1000
- BUSCLOCK = 8000000Hz
T = 1 * 1000 * 65536 / 8000000 = 8,192s => f=0.122Hz
* - TIMER_PRESCALER = { 1,2,4,8,16,32,64,128} - smaller values give more
precise values but it generates timer overflow more frequently
... for example....
2) The issue I see is duty cycle measurement for small a large duty cycles in the first method. Because of this I would try to solve second method.
3) Another possibility and approach is to connect input signal to two different timer inputs and calculate period from rising edges from one channel including duty provided by interrupt on different channel for falling edge. However, it also requires study and tests.
incomming signal |^^^^^^^^^^^^^^^|_____________________________________________|^^^^^^^^^^^^^^^|____
ICx (rising edges) |<----period measured by ICx, P= f(TCx_old, TCx_new,ovfs)------------->|<----period-----
ICy (falling edges) |- event which stores TCy and num. of ovfs to be able to calc. duty |- again
4) Your task is really not simple and will require a lot of test and modifications. Probably there is also much simpler solution but not going to my mind now.
Best regrads,
Ladislav
Thanks,lama
I understand the method.
Hi,
I was thinking about your task and I am not sure whether you need the value of the incoming signal. If yes then OK but if you do not need it then I think easier solution is monostable flip flop circuit to generate the same frequency with the given constant duty. It looks to be easier and faster solution. Moreover it removes issues with higher range of measured frequencies considering timer prescaler setup and SW (calculation) issues...and it removes issues with creating outgoing signal.
For this purpose, if I decide to use MCU for solution, I would use S12XE MCU with integrated XGATE and use the XGATE (Risc core integrated on the chip and connected also to a CPU) as a parallel processor (interrupt driven) for processes which I do not want to influence CPU. Wery good especially in the case of processing signals and fast direct responses while CPU calculates more complicated tasks.
Best regards,
Ladislav
Hi,lama
I have a idea for this problem. I use the interrupt of Timer0 IOC0 and IOC3. IOC3 is for input capture and IOC0 for output compare. The timer base frequency is 200K. If I add the compare value at IOC0 interrupt , then I can generate a 10us interrupt. I will deal with the output compare using the period interrupt(10us) for 10hz~1000Hz. The problem is when I set the different priority it will meet some problem. If I set the same priority it works well. You can see the problem below:
I want to set the priority of IOC0 is higher than IOC3, what can I do?
Thanks, lama
I use the LIN as the input signal and I can't change the MCU.
Fast thinking for left aligned incoming pulses…using my old code (for another MCU) for frequency measurement adding additional code. Timer channel 1 is set for both edges interrupt and main timer is set for overflows. The code is just presenting approach. Probably it is correct, I am sorry topically can't see mistake....it requires some time for thinking....I know.....
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|___________|^^^^^^^^^^^^^^^^^ incomming signal
Irising edge |falling edge |rising edge
|<---------period or duty or Globalperiod_1--------------->|<----period--->|<----period-----
|<-----------------------------------------Globalperiod----------->|<---------------------Globalperiod-----
// Count overflows
//*********************************
#pragma CODE_SEG NON_BANKED
interrupt XX void ECT_OvfIsr(void) // count overflows
{
ch1ovfCnt++; // count overflows
if(ch1ovfCnt>MAX_OVERFLOWS)
{
ch1ovfCnt = 0;
FREQUENCY_TOO_LOW = TRUE;
SCI0_SendValue(); // send message to the PC
}
else
{ FREQUENCY_TOO_LOW = FALSE;
}
ECT_TFLG2 = 0B10000000; // clear interrupt flag of main timer
}
#pragma CODE_SEG DEFAULT
//*********************************
//Service interrupt for rising and falling edge
// calculate topical length of the finished level and length/globalperiod of invcoming signal:
//*********************************
#pragma CODE_SEG NON_BANKED
interrupt XX void ECT_Ch1Isr(void)
{
unsigned int ovfs;
//------
timerNewValue = ECT_TC1; // read new captured value and clear flag
ovfs = ch1ovfCnt; // save amount of ovfs to temporary variable
ch1ovfCnt = 0; // clear number of overflows
ECT_TFLG1 = 0B00000010; // clear interrupt flag from PT1
//----- Ch1 period calculation, calculate lengt of currently finished level of incoming signal ---------
if(!ovfs) // Did edges appear within one timer period?
{
period = (ULONG)(timerNewValue - timerOldValue); // per. of given level
}
else // some number of overflows has appeared between two edges
{
// time given by overflows period=....
period = (ULONG)( ~timerOldValue+1 ); // time in the first period
period+= (ULONG)( timerNewValue); // time in the last period
period+= (ULONG)((ULONG)((ovfs-1)) * (ULONG)(65536));
}
timerOldValue = timerNewValue; // prepare new old value
//------------- calculate period and duty of incomming signal
if(rising edge)
{
Globalperiod = Globalperiod_1 + period; // period of incoming signal
Data_prepared = TRUE;
// now you have entire period and duty cycle of the Globalperiod which
// has now gone. This value you can use for PWM
}
else
{
Globalperiod_1 = period; // also it is duty of a new Globalperiod
}
}
#pragma CODE_SEG DEFAULT
Note; if you set prescaler of main timer to be sure there is only one overflow between rising and falling edge then formulas and code could be simplified. This is general approach for pulse of long length with maximum lengt of MAX_OVERFLOWS.
Best regards,
Ladislav
Thanks, lama.
It does't work. Because the max frequency of Timer1 is 50M, the overflow time is 65535/50M = 1.31ms .It's too long for checking square wave with 1K Hz frequency.
any other ideas?