cancel
Showing results for 
Search instead for 
Did you mean: 

One shot pulse

giuseppe
Associate II
Posted on March 04, 2014 at 09:40

Hi, I need to generate some pulses on a pin with a timer.

Pin is normally high, it have to stay low for a precise time, then high for at least another time.

I tried with one-pulse mode, but it works conversely: it wait, then it do pulse.

Someone has an idea? Please not with software timers...

Thanks
5 REPLIES 5
Posted on March 04, 2014 at 16:41

Well there's PWM mode, where the pulse width and period can be modified, and can be always ON or OFF. There's timers with N channels, and polarity settings?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
giuseppe
Associate II
Posted on March 04, 2014 at 17:14

I have to communicate with a DS2431, it's a 1-wire EEPROM.

It has strictly timings, I wrote code with software timing already, but sometimes it fails I think because of RTOS interrupts.

When I have to write a bit in, I have to send a pulse short or long respectively if 1 or 0, then to wait the end of the fixed time slot. This is the only condition must be respected.

STM32 timers' one pulse mode is the opposite: delay before and then pulse.

Is it possible to do it with a single timer or I have to cascade two of them?

Posted on March 04, 2014 at 17:23

If I were modifying a single parameter DMAing that from a table of sequences would work quite effectively. For two parameters, I'd probably opt for a similar arrangement but use the TIM Update interrupt to modify those parameters at each step.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
giuseppe
Associate II
Posted on March 26, 2014 at 11:31

I've found the solution: TIM3 generates pulses and at same time it measures pulse width on same pin.

TIM3 is controlled by TIM9 which starts and stops it when needed.

Both timers are initialized to be clocked at 8MHz.

The memory is connected to PC8, which is initialized as open drain, and with AF=3 that is TIM3_CH3.

PC8 has a 1,8kΩ resistor to VDD to let pin high when not asserted.

This is the function to check if a device is connected:

_bool OWConnected()

{

TIM9->ARR=7040;

TIM9->CNT=1;

TIM9->SMCR=0;

TIM9->CR1=TIM_OPMode_Single;

TIM9->CR2=TIM_TRGOSource_Enable;

TIM3->CCMR2=(TIM3->CCMR2&~(TIM_CCMR2_OC3M|TIM_CCMR2_CC3S|TIM_CCMR2_OC4M|TIM_CCMR2_CC4S))|TIM_OCMode_Timing|(TIM_OCMode_Timing<<8);

TIM3->ARR=7050; //higher than TIM9->ARR

TIM3->CNT=4479; //setting it at CCR3+1 pulse is generated immediately

TIM3->CCR3=4478;

TIM3->CR1=TIM_CounterMode_Down;

TIM3->SMCR=TIM_SlaveMode_Gated|TIM_TS_ITR0;

TIM3->CR2=0;

TIM3->CCMR2=(TIM3->CCMR2&~(TIM_CCMR2_OC3M|TIM_CCMR2_CC3S|TIM_CCMR2_IC4F|TIM_CCMR2_IC4PSC|TIM_CCMR2_OC4M|TIM_CCMR2_CC4S))|TIM_OCMode_PWM2|(TIM_ICSelection_IndirectTI<<8);

TIM3->CCER=(TIM3->CCER&~(TIM_CCER_CC3P|TIM_CCER_CC4P|TIM_CCER_CC4NP))|((TIM_OutputState_Enable|TIM_OCPolarity_High)<<8)|((TIM_CCx_Enable)<<12);

OWPORT->MODER=(OWPORT->MODER&~(3<<(OWPIN*2)))|(2<<(OWPIN*2));

  TIM3->SR&=~TIM_FLAG_Update;

TIM9->SR&=~TIM_FLAG_Update;

TIM3->CR1|=TIM_CR1_CEN;

TIM9->CR1|=TIM_CR1_CEN; //start both timers

while((TIM9->SR&TIM_FLAG_Update)==0); //wait finish

TIM3->CR1&=~TIM_CR1_CEN;

return (TIM3->CCR4<6421)?1:0; //if connected a device generate a pulse

}

To write a byte is like Morse code: short and long pulses means respectively 1 and 0:

void OWWrite_bit(U8 v)

{

  TIM3->SR&=~TIM_FLAG_Update;

TIM9->SR&=~TIM_FLAG_Update;

if(v)

{

TIM3->CCR3=80;

TIM3->CNT=81;

}

else

{

TIM3->CNT=721;

TIM3->CCR3=720;

}

  TIM3->CR1|=TIM_CR1_CEN;

TIM9->CR1|=TIM_CR1_CEN;

while((TIM9->SR&TIM_FLAG_Update)==0);

}

void OWWrite(U8 v)

{

U8 bitMask;

TIM9->ARR=800;

TIM9->CNT=1;

TIM3->CCMR2=(TIM3->CCMR2&~(TIM_CCMR2_OC3M|TIM_CCMR2_CC3S))|TIM_OCMode_Timing;

TIM3->ARR=800;

TIM3->CNT=799;

TIM3->CCR3=0;

TIM3->CR1|=TIM_OPMode_Single|TIM_CounterMode_Down;

TIM3->CCMR2=(TIM3->CCMR2&~(TIM_CCMR2_OC3M|TIM_CCMR2_CC3S))|TIM_OCMode_PWM2;

TIM3->CCER=(TIM3->CCER&~TIM_CCER_CC3P)|((TIM_OutputState_Enable|TIM_OCPolarity_High)<<8);

for (bitMask = 0x01; bitMask; bitMask <<= 1) OWWrite_bit(bitMask & v);

}

To read, after a pulse, device replies not asserting pin if bit is 1, asserting it for a while if 0:

U8 OWRead_bit()

{

TIM3->CNT=79;

TIM3->CCR3=78;

  TIM3->SR&=~TIM_FLAG_Update;

TIM9->SR&=~TIM_FLAG_Update;

TIM3->CR1|=TIM_CR1_CEN;

TIM9->CR1|=TIM_CR1_CEN;

while((TIM9->SR&TIM_FLAG_Update)==0);

TIM3->CR1&=~TIM_CR1_CEN;

return (TIM3->CCR4>662)?1:0;

}

U8 OWRead()

{

U8 bitMask;

U8 r = 0;

TIM9->ARR=640;

TIM9->CNT=1;

TIM3->CCMR2=(TIM3->CCMR2&~(TIM_CCMR2_OC3M|TIM_CCMR2_CC3S|TIM_CCMR2_OC4M|TIM_CCMR2_CC4S))|TIM_OCMode_Timing|(TIM_OCMode_Timing<<8);

TIM3->ARR=800;

TIM3->CNT=79;

TIM3->CCR3=78;

TIM3->CR1=TIM_CounterMode_Down;

TIM3->CCMR2=(TIM3->CCMR2&~(TIM_CCMR2_OC3M|TIM_CCMR2_CC3S|TIM_CCMR2_IC4F|TIM_CCMR2_IC4PSC|TIM_CCMR2_OC4M|TIM_CCMR2_CC4S))|TIM_OCMode_PWM2|(TIM_ICSelection_IndirectTI<<8);

TIM3->CCER=(TIM3->CCER&~(TIM_CCER_CC3P|TIM_CCER_CC4P|TIM_CCER_CC4NP))|((TIM_OutputState_Enable|TIM_OCPolarity_High)<<8)|((TIM_CCx_Enable)<<12);

for (bitMask = 0x01; bitMask; bitMask <<= 1) if (OWRead_bit()) r |= bitMask;

return r;

}

That's all folks!

Posted on March 26, 2014 at 14:05

Just a note, you don't need to RMW on TIM->SR, so

TIM3->SR &= ~TIM_FLAG_Update;

Just needs to be, also removes a race condition

TIM3->SR = ~TIM_FLAG_Update;

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..