STM32F4 multiple SPI_I2S_GetFlagStatus crashes the program - c

I'm trying to implement a simple http server on my stm32F411RE nucleo board from here, but of course I've run into some problems - so far, I managed to narrow the current one to the fact, that after about 20 calls to
SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE); My program crashes. By crash, I mean goes to the Infinite Loop defined in the startup file, reason being "Program received signal SIGINT, Interrupt."
My spi is initialised like that:
void SPI1_Init(void){
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable SPI1 and GPIOA clocks */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
//SCK, MISO, MOSI
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//CS
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//CS down
GPIO_SetBits(GPIOA, GPIO_Pin_2);
SPI_InitTypeDef SPI_InitStructure;
/* SPI1 configuration */
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
/* Enable SPI1 */
SPI_Cmd(SPI1, ENABLE);
}
after the initialization, I do this:
for(tmpCnt = 0; tmpCnt < 100; tmpCnt++){
SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE);
}
and it crashes after about 20 iterations. I am using the standard peripheral library, and System Workbench with all stock settings of compiler and everything else. At the moment nothing is connected to the SPI pins, could that be the problem?
calling
(SPI1->SR) instead of SPI_I2S_GetFlagStatus
has the same effect so I guess that the problem lies withing reading the register. Why could that be? I'm really stuck at the moment, so any help would be appreciated.
EDIT:
Ok, it turns out that I missed a bit of code that seems to cause this behaviour - before the SPi1->SR calls, I also had this function called:
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
SysTick->LOAD = ticks - 1; /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */
SysTick->VAL = 0; /* Load the SysTick Counter Value */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
return (0); /* Function successful */
}
why does it break the SPI1->SR access? could there be anything else wrong? My main function:
int main(void)
{
int tmpCnt = 0;
int rev = 0;
//uint16_t writedat = 22;
RCC_Init();
SPI1_Init();
//SysTick_Config(1000);
for(tmpCnt = 0; tmpCnt < 50; tmpCnt++){
SPI1->SR ;
}
enc28j60Init((unsigned char *)enc28j60_MAC);
//simple_server();
rev = enc28j60getrev();
return rev;
}
RCC_Init does not seem to change anything in the behaviour of the SPI1->SR.
As before, any advice would be welcome.

Related

program freezes when calling I2C write function

Board : STM32F4 Discovery
I am having troubles initializing I2C, i think! When the program reaches I2C_write function it hangs! I am trying to communicate with a temp&hum sensor HDC1080 from TI. The hardware is ok, i've been testing it with cubeMX and HAL libraries and it works ok!
I have a saleae logic analyzer hooked up to PB8(SCL) and PB9(SDA) , there's no activity!
I removed the init_usart part thinking that maybe they are interffering because they share the same port (GPIOB).
void init_usart(void)
{
//enable AHB1 peripheral clock
RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOB, ENABLE);
//Init GPIOB
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);
//Enable USART peripheral clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
//Init usart
USART_InitTypeDef USART_InitStruct;
USART_InitStruct.USART_BaudRate = 57600;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No ;
USART_InitStruct.USART_Mode = USART_Mode_Tx;
USART_InitStruct.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
USART_Init(USART1, &USART_InitStruct);
USART_Cmd(USART1, ENABLE);
}
void InitializeI2C()
{
RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; // 8=SCL 9=SDA
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1);
/* enable APB1 peripheral clock for I2C1*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE);
I2C_InitTypeDef I2C_InitStruct;
I2C_InitStruct.I2C_ClockSpeed = 100000;
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStruct.I2C_OwnAddress1 = 0x01;
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStruct);
I2C_Cmd(I2C1, ENABLE);
}
void I2C_write( uint8_t HW_address, uint8_t addr, uint8_t data)
{
I2C_GenerateSTART(I2C1, ENABLE);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, HW_address, I2C_Direction_Transmitter);
while (!I2C_CheckEvent(I2C1,
I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData(I2C1, addr);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1, data);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(I2C1, ENABLE);
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
}
int main(void)
{
init_usart()
InitializeI2C();
while (1)
{
delay_div(50);
I2C_write( 0x40 << 1 , 0x01, 0x00); //here it stops!!!
}
One possible problem: You are using uninitialised data.
From your code:
I2C_InitTypeDef I2C_InitStruct;
I2C_InitStruct.I2C_ClockSpeed = 100000;
//I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStruct.I2C_OwnAddress1 = 0x01;
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStruct);
At least I2C_Mode is not initialised here, and you cannot assume the value to be 0. It will just be whatever is on the stack at that time.
You either want to memset the struct to 0, or implicitly initialise other members to zero when declaring:
I2C_InitTypeDef I2C_InitStruct = {
.I2C_ClockSpeed = 100000,
//.I2C_Mode = I2C_Mode_I2C,
.I2C_DutyCycle = I2C_DutyCycle_2,
.I2C_OwnAddress1 = 0x01,
.I2C_Ack = I2C_Ack_Enable,
.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit,
};
I2C_Init(I2C1, &I2C_InitStruct);
My temp & hum sensor is dead! I2C init is fine, tried it with an i2c oled display and i can see activity on the bus!
Just a short and final update!!! Bear with me, please!
My temp&hum sensor (HDC1080) was ok! After spending 40 minutes soldering wires to a new sensor (the pins are 0.4mm) i discovered that this was also not working.
Nothing changed in terms of hardware from my succesfull initial test that i did using the HAL library, breadboard with 2 x 10k (that's what i had) pull-up resistors, 3V power supply from stm32 discovery board.
It seems that for unknown reasons the HAL test was working with those two 10k pull-ups but the SP library wasn't. Since my SSD1306 oled display comes on a pcb with 4.7k resistors already mounted i was able to discover that i can communicate with both the temp&hum sensor and display.
Final conclusion , pull-up resistors was my problem in the end!

STM32F1 timer share for PWM and interrupt

i'm implementing a project using stm32f101cb microcontroller. I understand that this control have 3 timer in it. TIM2 and TIM4 had been set to encoder mode to capture 2 rotary encoder.
I'm now left me the only timer TIM3, I would to ask is there possible for me to set TIM3 to PWM mode and at the same time doing the normal timer interrupt? I could not find it in reference manual or programming manual.
Thanks!
It should be possible. I'm doing it for an STM32F091RC I've developed an application for where I'm controlling LED:s with PWM and generating a timer update interrupt (counter reset) with the same timer peripheral.
Here's some of my configuration code:
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
/* LED_TIM clock enable */
RCC_APB1PeriphClockCmd(TIM_LED_RCC, ENABLE);
/* LED_PORT Configuration: Channel 1, 2, 3 as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = LED_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(LED_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(LED_PORT, LED_PIN_SOURCE, LED_TIM_AF);
/* Enable the TIM global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = LED_TIM_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Time Base configuration */
TIM_TimeBaseStructure.TIM_Prescaler = LED_TIM_PSC;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 0xFFFF; // Max 0xFFFF
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* Channel 1 Configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_Pulse = LED_INIT_PULSE;
TIM_OC1Init(LED_TIM, &TIM_OCInitStructure); // Init Channel 1
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable);
/* TIM IT enable */
TIM_ITConfig(LED_TIM, TIM_IT_Update, ENABLE); // Enable interrupts for LED_TIM
/* LED_TIM counter enable */
TIM_Cmd(LED_TIM, ENABLE);
/* LED_TIM Main Output Enable */
TIM_CtrlPWMOutputs(LED_TIM, ENABLE);
Should be very similar for your device. If everything works correctly, you should be getting interrupts in your TIM3_IRQHandler ISR
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(LED_TIM, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(LED_TIM, TIM_IT_Update);
// Do ISR stuff here!
}
}

STM32F407 UART gives garbage on terminal

I have just started my adventures with STM32f407 Discovery board. I'm using latest stable release of CoIDE and using up to date toolchain/libraries.
I managed to write the following code in order to use USART1 from the board
int main(void){
GPIO_InitTypeDef GPIO_InitStructure; // Definicja struktury do inicjalizacji PINOW
USART_InitTypeDef USART_InitStructure;
// Initialize pins as alternating function
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
// Modify USART_InitStructure for non -default values , e.g.
// USART_InitStructure.USART_BaudRate = 38400;
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;
USART_Init(USART1 ,&USART_InitStructure);
USART_Cmd(USART1 , ENABLE);
while(1)
{
while (USART_GetFlagStatus(USART1 , USART_FLAG_TXE) == RESET);
USART1 ->DR = (uint16_t)(45 & 0x01FF);
Delay(0x3FFFFF);
}
}
Also I have made sure clock is configured correctly by setting HSE and other clock details
#if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
And also
/************************* PLL Parameters *************************************/
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#define PLL_M 8
#define PLL_N 336
/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P 2
/* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */
#define PLL_Q 7
/******************************************************************************/
In console I just receive garbage and I have made the following to make sure the setup is correct :
- Checked USB-RS232 converter
- Switched between converter and STM32 board
- Switched converter
- Generated code using STM32CubeMX to compare it and it seems consistent (logic wise of course :) )
From my beginner perspective it is kinda "showstopper" :( I cannnot seem to find a root cause of this
Any help would be appreciated
UPDATE 1 : In order to find root cause I have decided to try one of the other USART modules. Below is my code for USART3 and this one WORKS OUT OF THE BOX which would lead me to incorrect init of USART1 in the initial question ?
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
/* Enable GPIO clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
/* Enable UART clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
/* Connect PXx to USARTx_Tx*/
GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3);
/* Connect PXx to USARTx_Rx*/
GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3);
/* Configure USART Tx as alternate function */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Configure USART Rx as alternate function */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_Init(GPIOC, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* USART configuration */
USART_Init(USART3, &USART_InitStructure);
/* Enable USART */
USART_Cmd(USART3, ENABLE);
SysTick_Config(SystemCoreClock / 1000);
while(1)
{
for (int var = 45; var < 128; var++)
{
USART_SendData(USART3, var);
Delay_SysTick(500); // 1 sek
}
}
}
Resolution: After a lot of digging and trying multiple things it appears that USART1 would collide with USB components and there is capacitor which collides with the transmission link to answer on ST forums
I wish I would have found this somewhere in documentation before.
Hope this helps someone and thanks everyone for your assistance
USART1 on this board (TX pin) has capacitor which collides with traffic. It is mentioned on ST forums.
Garbage on terminal often is caused when the sender has a different baudrate than the receiver.

Using STM32 Timer

I am working on the timer of STM32. I need two pulses like in the picture.
Frequency of CLK is 50 kHz and frequency of SI is 381.67 Hz. I need the SI to go low before the rising edge of next clock pulse but in the logic analyzer of Keil I saw the SI was in a different position relatively to CLK for each pulse, like shown on below picture. How can I fix it?
void Init_TIMER(void)
{
TIM_TimeBaseInitTypeDef TIM_BaseInitStructure2, TIM_BaseInitStructure3, TIM_BaseInitStructure4;
TIM_OCInitTypeDef TIM_OCInitStructure2, TIM_OCInitStructure3;
TIM_DeInit(TIM2);
TIM_DeInit(TIM3);
TIM_DeInit(TIM4);
TIM_InternalClockConfig(TIM2);
TIM_InternalClockConfig(TIM3);
TIM_InternalClockConfig(TIM4);
/************************************************/
/********TIMER2**********************************/
/************************************************/
TIM_BaseInitStructure2.TIM_Period = 180; //180/9000000=..ms 50KHZ
TIM_BaseInitStructure2.TIM_Prescaler = 7; //SYSCLK=72M, TIM1_CLK=72/8=9MHz
TIM_BaseInitStructure2.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_BaseInitStructure2.TIM_CounterMode = TIM_CounterMode_Up;
//TIM_BaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, & TIM_BaseInitStructure2);
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
TIM_OCInitStructure2.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure2.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure2.TIM_Pulse = 90;
TIM_OCInitStructure2.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC2Init(TIM2, & TIM_OCInitStructure2);
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);
/*****************************************************/
/********TIMER3***************************************/
/*****************************************************/
TIM_BaseInitStructure3.TIM_Period = 23580; //23580/9000000=... ms 381.67HZ 50KHZ/131=381.67HZ
TIM_BaseInitStructure3.TIM_Prescaler = 7; //SYSCLK=72M, TIM1_CLK=72/8=9MHz
TIM_BaseInitStructure3.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_BaseInitStructure3.TIM_CounterMode = TIM_CounterMode_Up;
//TIM_BaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, & TIM_BaseInitStructure3);
TIM_ClearFlag(TIM3, TIM_FLAG_Update);
TIM_OCInitStructure3.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure3.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure3.TIM_Pulse = 50;
TIM_OCInitStructure3.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC2Init(TIM3, & TIM_OCInitStructure3);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
/********************************************************/
/********TIMER4 to make sampling frequency **************/
/*******************************************************/
TIM_BaseInitStructure4.TIM_Period = 90; //90/9000000=0.01ms 100KHZ
TIM_BaseInitStructure4.TIM_Prescaler = 7; //SYSCLK=72M, TIM1_CLK=72/8=9MHz
TIM_BaseInitStructure4.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_BaseInitStructure4.TIM_CounterMode = TIM_CounterMode_Up;
//TIM_BaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4, & TIM_BaseInitStructure4);
TIM_ARRPreloadConfig(TIM4, DISABLE);
TIM_ClearFlag(TIM4, TIM_FLAG_Update);
/**********************************************/
TIM_ARRPreloadConfig(TIM2, ENABLE);
TIM_Cmd(TIM2, ENABLE);
TIM_ARRPreloadConfig(TIM3, ENABLE);
TIM_Cmd(TIM3, ENABLE);
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM4, ENABLE);
}
void GPIO_Configuration()
{
GPIO_InitTypeDef GPIO_InitStructure;
/*PA1 TIM2_CH2*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, & GPIO_InitStructure);
/*PA7 TIM3_CH2*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, & GPIO_InitStructure);
}
I had similar project where I had used taos TSL1402R matrix.
Instead of timer I used an SPI with circular DMA.
DMA buffer was 0x0, 0x0.....0x0, 0x1.
SI was connected to SPI MISO,
And CLK was connected to SPI_CLK.
Hope this will help.

STM32 Can't clear PWM interrupt flag

I'm trying to generate a 2MHz PWM with a duty-cycle of 50%. My problem is that I can't clear the interrupt flag. Here is my code:
#include "includes.h"
TIM_TimeBaseInitTypeDef TIM1_InitStruncture;
TIM_TimeBaseInitTypeDef TIM3_InitStruncture;
TIM_OCInitTypeDef TIM3_OCInitStructure;
SPI_InitTypeDef SPI_InitStructure;
void Timer3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3, TIM_IT_CC3) != RESET)
{
TIM_ClearFlag(TIM3, TIM_IT_CC3);
//dummy code
++StatusReg;
}
}
void CLK_init()
{
//activez HSI
RCC_HSICmd(ENABLE);
//astepst sa se activeze HSI
while( RCC_GetFlagStatus( RCC_FLAG_HSIRDY) == RESET );
//setez HSI ca sursa de clock
RCC_SYSCLKConfig( RCC_SYSCLKSource_HSI );
//activez HSE
RCC_HSEConfig( RCC_HSE_ON );
//astept sa se termine secventa de activare
while( RCC_GetFlagStatus( RCC_FLAG_HSERDY) == RESET );
//setez HSE (8MHz) ca input py PLL
//setez factotul de multiplicare 9
RCC_PLLConfig( RCC_PLLSource_HSE_Div1, RCC_PLLMul_9 );
//activez PLL-ul
RCC_PLLCmd(ENABLE);
//astept sa se termine secventa de activare
while( RCC_GetFlagStatus( RCC_FLAG_PLLRDY) == RESET );
#ifdef EMB_FLASH
// 5. Init Embedded Flash
// Zero wait state, if 0 < HCLK 24 MHz
// One wait state, if 24 MHz < HCLK 56 MHz
// Two wait states, if 56 MHz < HCLK 72 MHz
// Flash wait state
FLASH_SetLatency(FLASH_Latency_2);
// Half cycle access
FLASH_HalfCycleAccessCmd(FLASH_HalfCycleAccess_Disable);
// Prefetch buffer
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
#endif // EMB_FLASH
//setez iesirea de la PLL ca sursa de CLK
RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK );
}
void Port_C_Enable()
{
//GPIO_InitTypeDef GPIOC_InitStructure;
//resetez portul C (just in case)
RCC->APB2RSTR |= RCC_APB2RSTR_IOPCRST;
RCC->APB2RSTR &= ~RCC_APB2RSTR_IOPCRST;
//activez CLK-ul pentru portul C
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
/*
GPIOC_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIOC_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIOC_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIOC_InitStructure);
*/
}
void Timer3_Init()
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//reset Timer3 (just in case)
//RCC->APB1RSTR |= RCC_APB1RSTR_TIM3RST;
//RCC->APB1RSTR &= ~RCC_APB1RSTR_TIM3RST;
//give clock to Timer-ul 3
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
//frequency 2Mhz
TIM3_InitStruncture.TIM_Period = 36;
TIM3_InitStruncture.TIM_Prescaler = 0;
TIM3_InitStruncture.TIM_ClockDivision = 0;//TIM_CKD_DIV1;
TIM3_InitStruncture.TIM_CounterMode = TIM_CounterMode_CenterAligned3;
TIM_TimeBaseInit(TIM3, &TIM3_InitStruncture);
TIM_ITConfig(TIM3, TIM_IT_CC3, ENABLE);
TIM_Cmd(TIM3, ENABLE);
//dutycicle 50%
TIM3_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM3_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM3_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM3_OCInitStructure.TIM_Pulse = 18;
TIM_OC3Init(TIM3, &TIM3_OCInitStructure);
TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM3, ENABLE);
TIM_Cmd(TIM3, ENABLE);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*GPIOB Configuration: TIM3 channel1, 2, 3 and 4
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;*/
//GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);
/* GPIOA Configuration:TIM3 Channel1, 2, 3 and 4 as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void NVIC_init(void)
{
// NVIC init
#ifndef EMB_FLASH
/* Set the Vector Table base location at 0x20000000 */
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else /* VECT_TAB_FLASH */
/* Set the Vector Table base location at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
}
void SPI_init()
{
SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 0;
SPI_Init(SPI2, &SPI_InitStructure);
}
void main(void)
{
#ifdef DEBUG
debug();
#endif
// NVIC_SETPRIMASK();
CLK_init();
NVIC_init();
Port_C_Enable();
GPIO_Configuration();
//Timer1_Init();
Timer3_Init();
TIM_Cmd(TIM1, ENABLE);
unsigned int j=0;
while(1)
{
//dummy code
++j;
if(j == 0xff)
{
j=0;
}
}
}
Can anyone tell me why the CCR3 (Capture/Compare Register 3 Flag) stays high?
Thanks.
Pay attention to not mixing the following:
TIM_ClearFlag which shall be used together with TIM_FLAG_CC1
TIM_ClearITPendingBit which shall be used together with TIM_IT_CC1
as far as I understand. Otherwise you could have some masks which avoid to flag to be set.
Thanks aamxip for your answer.
I found the problem. It seems that the configuration is correct but i don't have enough time to execute the ISR(interrupt service routine). Once every 36 CLK's a new interrupt is generated and it takes me somewhere around 30 instructions or more only to enter in the ISR.
After more research i found out that i don't really need that frequency and i adopted a different approach, bit-banging.

Resources