Showing results for 
Search instead for 
Did you mean: 

Cannot get CC1 on TIM15 to go low using CCMR1 register

Senior III

Using a Nucleo-F072RB.  I am trying to get the output of CC1 to go low after the CPU does something.  Everything is working as expected except I cannot get the line to go low.  I have tried both variants of the CC1P bit and neither seems to work.  I place a breakpoint at the first line where I touch CCMR1 register and single step.  I see that the bits are as I believe they should be but for the life of me I cannot force the output line low (line 3 below --- monitoring with scope).  Can someone tell me what I am missing?



	htim15.Instance->CCMR1 = TIM_OCMODE_TIMING;
	htim15.Instance->CCMR1 = TIM_OCMODE_TIMING;
	htim15.Instance->CCMR1 = TIM_OCMODE_ACTIVE;




> If I change GPIO->MODER to AF my signal (yellow scope trace) completely disappears. 

How do you generate that signal at the first place?

Show some code, CubeMX setting, whatever.


Here are the main.c, main.h and .ioc files....

I am using the 3 gpio lines to measure things and make sure I am shutting down hardware, etc. when not using as I don't trust the HAL libraries always doing the correct thing.

A synopsis of the current code:

The code is using TIM1 to trigger TIM15 which in turn is used to capture 6 a/d using DMA....I shut down things and send data over the UART.  This repeats every 4 seconds....As mentioned the only caveat I can't seem to resolve here is getting the YELLOW Gpio line to go low after the DMA is complete.  In the ISR I disable TIM15 and force line low then reset it to go active when count reaches CCR.  AND as you will see I don't enable that counter until the next 4 second period.  Note just before while(1) you will find a commented out line you requested I try that didn't work for me.


OK so you are *not* using TOGGLE mode of TIM15_CH1 at all. You set PB14=YELLOW_Pin as GPIO Out and then toggle it using HAL_GPIO_TogglePin() in HAL_TIM_OC_DelayElapsedCallback().

So what don't you simply set that pin to the desired level using HAL_GPIO_WritePin() when done, i.e. after disabling the interrupt in HAL_ADC_ConvCpltCallback()?


Because I am using the GPIO to indicate activity of the counter / timer and I want to see that it powers down, stops counting, etc. forcing the GPIO of course will take it low but it doesn't tell me that the peripheral is doing what I expect it to do, hence I would like to see the commanding of the peripheral cause the event on the GPIO

> I would like to see the commanding of the peripheral cause the event on the GPIO

You mean, the timer should drive the pin directly.

Then you have to set the pin to AF, and its AFR to TIM15_CH1.

And you have to enable given channel in TIMx_CCER and globally by TIMx_BDTR.MOE.



So let me ask you this:

I have the CCR ISR (OC_DelayElapsedCallback) where I am allowing the GPIO to toggle each time which 'sort' of indicates to me the #A/D samples are being taken correctly (it's my way of visualizing that the DMA and Update Event are clocking off the correct # samples). I am going to this detail because I would eventually like to familiarize myself with low power (wake, sleep, etc.) on these processors and these are clearly not MSP430 (STM32s are way more complicated).  GPIOs are a great way to monitor and trigger current measurments. 

Now when DMA expires I opt to use the "FORCE_ACTIVE' etc. mechanism in CCMR1....Are you saying that I should pick either GPIO path or AF path and that I am mixing the two which is not allowed?

The reason I chose GPIO over AF was because the AF (in CubeMX) wanted to use one pins that I already had set aside for functionality.


ADDITION HERE:  Also using AF didn't appear to be working for me (I probably was doing something wrong here) as the DMA was taking samples at 7.5 clocks + 12.5 clocks for conversion all at 14MHz a/d sampling.  So I set my timer update event for mentioned it was grabbing samples and displaying them just fine but when I tried to introduce the monitor (CCR1 toggling) to see a very close approximation of the a/ds getting sampled then the code did not want to work hence it lead me down this rabbit hole

> mixing the two which is not allowed

It's not "not allowed". You either have the pin set in GPIO_MODER to Out, when its state is controlled by GPIO_ODR; or to AF, when it's state is controlled by whichever peripheral is chosen via GPIO_AFRx.

That's either-or, there's no hardware which would allow you to have both in some way.

> I have the CCR ISR (OC_DelayElapsedCallback) where I am allowing the GPIO to toggle each time which 'sort' of indicates [...]

If you set the pin to AF/TIM15_CH1 and enable that channel as I've said both in TIM15_CCER and TIM15_BDTR, and that channel is set to Toggle mode, you will see the same toggling on the pin.

JW firstly (THANK YOU for your patience!!!)....I took CubeMX and set Channel 1 as Output Compare AF bit gets set now...It seems the code does not touch the CCER / BDTR registers so I did this manually in the 4 second ISR.  It does not toggle (notice I removed the toggling code out of the ISR as I believe it should automatically toggle here without doing anything???).  I have attached my new code along with a scope shot showing what the yellow NOW looks like.  It toggles but stays high (what should my CCxP bit be and should I be using 'FORCE_ACTIVE' or FORCE_INACTIVE here?)


+ it looks a little strange on the tail end...any comments there?


I don't want to muddy the waters here but recall I said 7.5clks + 12.5clks at 14MHZ which means I should be able to trigger the dma with the scope shows this toggling using your method and this is what I have been seeing using the never stops toggling and you notice the green line never goes low (I am collecting only 6 samples) ...everything breaks here


ADDITION:  I find that if I remove trying to track the A/D samples that timing looks pretty reasonable on the DMA (GREEN) time but when you add monitoring of the A/D sampling I get more toggling than samples and it won't even work (DMA never comes out of ISR to trigger the data to the UART) if I take the sampling below 15us (which is waaaaay longer than 20/14mhz needed per sample)...this translates to wasted energy

Sorry, but I failed to follow.

Maybe it's simpler if you revert to the GPIO based solution, since you are familiar with how it works.


Thank you very much for all the help!  After taking your information and going back a few steps then rebuilding from scratch up I got something that works pretty well.

Your MOE and CC1E bits were important.

Clock frequency played a role as when I moved the clock up to 48MHz from 20MHz things seemed to get better.

Finally I used HAL_TIM_BASE_Start instead of HAL_TIM_BASE_Start_IT for the CCR1 output and a/d sampling.....

With that said here is a pic of my final signals....I guess it seems reasonable to think that there is a 'front' and 'back' porch for DMA as the total time for 6 samples at 5us measures about 60us instead of the theoretical 30us (5*6).  I set CCR1 to go off at 0 and toggle every 5us....As you can see there are 11 toggles (the last one going high to low does not count as this is forced active here, where active is defined as low)...

It consistently seems to do this so I think all is good here now.  YELLOW is CCR1 going off every 5us, GREEN is measuring the DMA length and PINK just represents a toggling 2 second waveform where sampling is done.

Once again thanks for the insight!