2019-12-06 01:20 AM
A while ago I received an STM32 discoveryboard as a gift, after I told some people on a fair that I'm a software engineer. Because I'm allready experienced in C/C++ but new to embedded software engineering, I ordered a course. Now I get stuck on the chapter on Timers, because the software I wrote just isn't working as it should. Here's my source file, I'm working with Atollic Truestudio.
#include "stm32f7xx.h"
int period;
float freq;
int main(void)
{
int last_value = 0;
int current_value = 0;
RCC->AHB1ENR |= 0x109; // GPIOA for PA5 blue led, GPIOD for TIM4, GPIOI for TIM5
GPIOD->MODER |= 0x2000000; // Select alternate function for PD12
GPIOD->AFR[1] |= 0x20000; // Alternate function 2 (TIM4_CH1) for PD12
RCC->APB1ENR |= 0x4; // Enable clock for TIM4
// This sets up a 1Hz Timer, TIM4_CH1 in output compare mode
TIM4->PSC = 1600-1; // Set the value for the prescaler
TIM4->ARR = 10000-1; // Set the value for the autoreloadregister
// Set the output to toggle on match
TIM4->CCMR1 |= 0x30; // Set the output to toggle on match
TIM4->CCR1 |= 0x0; // Set the match value
TIM4->CCER |= 0x1; // Set OC1 signal as output on PD12
TIM4->CNT = 0x0;
TIM4->CR1 = 0x1; // Counter Enable
// This sets up TIM5_CH4 in input capture mode
GPIOI->MODER |= 0x2; // Set alternate function for PI0
GPIOI->AFR[0] |= 0x2; // Alternate function 2 (TIM5_CH4) for PI0
RCC->APB1ENR |= 0x8; // Enable clock for TIM5
TIM5->PSC |= 16000-1;
TIM5->CCMR2 |= 0x4100; // Channel 4 is input, sampling every 6 ocurrences
TIM5->CCER |= 0xB000; // Enable capture, Capture rising and falling edge
TIM5->CR1 |= 0x1; // Counter enable
while (1)
{
while(!(TIM5->SR & 0x10)){} // Wait until edge is captured. HERE PROGRAM FLOW GETS STUCK
// The part below this comment never gets executed,
// except when I disconnect and reconnect the jumper wire between PD12 and PI0,
// then the while loop condition gets matched once.
current_value = TIM5->CCR4;
period = current_value - last_value;
last_value = current_value;
freq = 1000.0f / period;
}
}
According to what I learned from the course and what I found in the reference manual, https://www.st.com/content/ccc/resource/technical/document/reference_manual/group0/c8/6b/6e/ce/dd/f7/4b/97/DM00305990/files/DM00305990.pdf/jcr:content/translations/en.DM00305990.pdf , this should work.
However, I noticed something remarkable in the manual. In chapter '19.4.7 TIMx capture/compare mode register 1 (TIMx_CCMR1)(x = 2 to 5)', 'Bits 6:4 OC1M: Output compare 1 mode.'
OC1M is a three bit field in the register diagram, however the options provided in this chapter for setting up this register all consist out of four bits. This doesn't make sense to me. Anyways, following the instructions from chapter '19.3.8 Output compare mode' I set OC1M to '011' to toggle on match.
If I understood everything right, this should set the output on PD12 to high when it's low and to low when it's high, when the value in CNT matches the value in CR1. This should be the signal that goes trough the jumper wire and should get captured by TIM5 that I assume to be running in input capture mode.
I suppose that TIM5 indeed is capturing input, due to the fact that the while loop condition that I have marked in the source file's comments gets matched when I unplug and then replug the jumperwire.
I also have a different version of this program, where I commented out the part on setting up and enabling TIM4 and decided to use plain GPIO output from PD12, by setting up GPIOD in General purpose output mode and replacing the while (1) statement with the following code.
GPIOD->MODER = 0x100000;
GPIOD->ODR = 0;
while (1)
{
while(!(TIM5->SR & 0x10))
{
//GPIOI->BSRR = (GPIOI->BSRR & 0x1) ? 0x10000 : 0x1;
if(GPIOD->ODR&0x1000)
{
GPIOD->ODR=0;
}
else
{
GPIOD->ODR=0x1000;
}
delayMs(25);
} // Wait until edge is captured
current_value = TIM5->CCR4;
period = current_value - last_value;
last_value = current_value;
freq = 1000.0f / period;
}
If I'm right this should work more or less the same as the blinking led example that I got to work earlier in the same course, but now on the timer input.
I would appreciate it if anyone with more experience than me or with better equipment available as I got could take a closer look on this issue.
Thanks in advance, Ronnie van Aarle.
2019-12-06 02:12 AM
What course teaches you this style? I mean, it's nice to see register-level programming, but you should use more the symbols from the device header for the individual values, to make it more readable. Particular values used in above program appear to be OK, though.
Observe the TIM (and GPIO and RCC) registers' value in debugger. Observe the output pin using oscilloscope or LA.
> I also have a different version of this program,
And that one does work as expected?
JW
PS. Change your username to a normal nick
2019-12-06 02:31 AM
This is for historical reasons. You write 0 to them so that's OK.
JW
2019-12-06 09:40 PM
I've just looked at UM2140 and noticed, that PD12 is not brought out to any header/pin!
How exactly did you connect it?
(PI0 is brought out through an analog switch which is also suspicious, but it appears that by default it is switched to PI0 - but again, how exactly did you connect it?)
JW
2019-12-09 03:49 AM
The course that I'm working on is 'bare metal c programming' from udemy.com.
I don't have a logic analyser or osciloscope, someone I know promised me to bring a multimeter that can measure frequencies. That should be sufficient to see wether or not there is output on the pin.
No, the other version of the program where I replaced the timer output with basic gpio output also does not work.
2019-12-09 03:50 AM
Ah, now I see.
2019-12-09 04:04 AM
Well, I used the 'alternate function mapping' table from the 'STM32F722xx STM32F723xx product specification'. This combined with what's printed on the board itself.
To connect the ports together I put a jumper wire between the fifth connecter output on the bottom of the board, the arduino connector, the one that says PD12, to PI0 in the PMOD connector on top of the board.
Can you tell me where I should search in the User Manual and to what I should pay attention to find usable timer input and output pins?
What I need to know to find appropriate pins that I can use for timer output and timer input, so I can wire these together and see if I can get the program to work afterall?
Thanks allready.
2019-12-16 03:59 AM
Hello again,
I also took a look at UM2140 'Appendix A 32F723EDISCOVERY Discovery board I/O assignment'. I once again changed the program, this time I'm using PA15 TIM2_CH1 and PB0 TIM3_CH3. Here's the modified file.
#include "stm32f7xx.h"
int period;
float freq;
int main(void)
{
int last_value = 0;
int current_value = 0;
// TIM2_CH1->PA15 for output compare mode TIM3_CH3->PB0 for input capture
RCC->AHB1ENR |= 0x3; // GPIOA for TIM2_CH1, GPIOB for TIM3_CH3
GPIOA->MODER |= 0x80000000; // Select alternate function for PA15
GPIOA->AFR[1] |= 0x10000000; // Alternate function 2 (TIM2_CH1) for PA15
RCC->APB1ENR |= 0x1; // Enable clock for TIM2
// This sets up a 1Hz Timer, TIM2_CH1 in output compare mode
TIM2->PSC = 1600-1; // Set the value for the prescaler
TIM2->ARR = 10000-1; // Set the value for the autoreloadregister
// Set the output to toggle on match
TIM2->CCMR1 |= 0x30; // Set the output to toggle on match
TIM2->CCR1 |= 0x0; // Set the match value
TIM2->CCER |= 0x1; // Capture/Compare 1 output enable
TIM2->CNT = 0x0;
TIM2->CR1 = 0x1; // Counter Enable
// This sets up TIM3_CH4 in input capture mode
GPIOB->MODER |= 0x2; // Set alternate function for PI0
GPIOB->AFR[0] |= 0x2; // Alternate function 2 (TIM3_CH4) for PI0
RCC->APB1ENR |= 0x2; // Enable clock for TIM3
TIM3->PSC |= 16000-1;
TIM3->CCMR2 |= 0x41; // Channel 3 is input, sampling every 6 ocurrences
TIM3->CCER |= 0xB0; // Enable capture, Capture rising and falling edge
TIM3->CR1 |= 0x1; // Counter enable
while (1)
{
while(!(TIM3->SR & 0x8)) // Wait until edge is captured. HERE PROGRAM FLOW GETS STUCK
{
int i = 0 ? 1 : 0;
}
// The part below this comment never gets executed,
// except when I disconnect and reconnect the jumper wire between PD12 and PI0,
// then the while loop condition gets matched once.
current_value = TIM3->CCR3;
period = current_value - last_value;
last_value = current_value;
freq = 1000.0f / period;
}
}
Nevertheless, the result remains the same despite using different timers and pins. Also, according to the user manual, the gpio uses multiplexers on the different pins so the functions of the pins can be selected using the alternate function modes. Following what's written in the reference manual and the user manual, this means that my initial program should still be right. I'm using Reference Manual RM0431 and Datasheet https://static6.arrow.com/aropdfconversion/29737e50fc5e53cf3b25bd139bc2d144ac0a47a/179979946274536379.pdf
after searching for "STM32F722xx STM32F723xx" in google, st.com comes shows another datasheet belonging to another device, despite what the link in the search result says.
Anyways, when I connect PA15 and PB0 with the jumper wire, the same issue occurs.
I'll ad a screenshot of the debugger with TIM3 registers open. The only value that keeps changing while the program runs is CNT.
2019-12-16 04:04 AM
Well, I used the 'alternate function mapping' table from the 'STM32F722xx STM32F723xx product specification'. This combined with what's printed on the board itself.
To connect the ports together I put a jumper wire between the fifth connecter output on the bottom of the board, the arduino connector, the one that says PD12, to PI0 in the PMOD connector on top of the board.
Can you tell me where I should search in the User Manual and to what I should pay attention to find usable timer input and output pins?
What I need to know to find appropriate pins that I can use for timer output and timer input, so I can wire these together and see if I can get the program to work afterall?
Thanks allready.
2019-12-16 04:05 AM
I'm new to this messageboard, I sent answers where replies probably would have been more appropriate. My appologies.