stm32f103: Force DMA transfer complete interrupt - arm

I'm trying to implement communication between stm32f103 and SIM900A using FreeRTOS (mutexes and stream buffers), DMA and USART3.
I've enabled USART_IT_IDLE USART3 interrupt to be able to detect end of SIM900 transmittion and make force firing of DMA transmission complete interrupt to copy data from memory into FreeRtos's streamBuffer.
This article said that this is possible.
/**
* \brief Global interrupt handler for USART2
*/
void USART2_IRQHandler(void) {
/* Check for IDLE flag */
if (USART2->SR & USART_FLAG_IDLE) { /* We want IDLE flag only */
/* This part is important */
/* Clear IDLE flag by reading status register first */
/* And follow by reading data register */
volatile uint32_t tmp; /* Must be volatile to prevent optimizations */
tmp = USART2->SR; /* Read status register */
tmp = USART2->DR; /* Read data register */
(void)tmp; /* Prevent compiler warnings */
DMA1_Stream5->CR &= ~DMA_SxCR_EN; /* Disabling DMA will force transfer complete interrupt if enabled */
}
}
But my debugger says: no
Here is my code:
#define BUFF_SIZE 16
uint8_t RX_BUFFER[BUFF_SIZE] = {"\0"};
uint8_t TX_BUFFER[BUFF_SIZE] = {"\0"};
....
// USART TX channel
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(USART3->DR);
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&TX_BUFFER[0];
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStruct.DMA_BufferSize = sizeof(TX_BUFFER);
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
DMA_InitStruct.DMA_Priority = DMA_Priority_Low;
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel2, &DMA_InitStruct);
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&RX_BUFFER[0];
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStruct.DMA_BufferSize = sizeof(RX_BUFFER);
DMA_Init(DMA1_Channel3, &DMA_InitStruct);
// USART RX channel
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&RX_BUFFER[0];
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStruct.DMA_BufferSize = sizeof(RX_BUFFER);
DMA_Init(DMA1_Channel3, &DMA_InitStruct);
// Interrupts
USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);
USART_DMACmd(USART3, USART_DMAReq_Tx | USART_DMAReq_Rx, ENABLE);
USART_Cmd(USART3, ENABLE);
DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA1_Channel3, ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY + 10;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_Init(&NVIC_InitStructure);
....
void USART3_IRQHandler() {
if (USART_GetITStatus(USART3, USART_IT_IDLE) == SET) {
volatile uint32_t tmp = USART3->SR;
tmp = USART3->DR;
(void) tmp;
// HERE interrupt should be fired!
DMA1_Channel3->CCR &= (uint16_t)(~DMA_CCR1_EN);
USART_ClearITPendingBit(USART3, USART_IT_IDLE);
}
}
void DMA1_Channel3_IRQHandler(void) {
if (DMA_GetITStatus(DMA1_IT_TC3) == SET) {
uint8_t len = BUFF_SIZE - DMA1_Channel3->CNDTR;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xStreamBufferSendFromISR(xUSART3ReceiveStreamBuffer, &RX_BUFFER, len, &xHigherPriorityTaskWoken);
for (uint8_t i = 0; i < len; i++) {
RX_BUFFER[i] = '\0';
}
DMA1_Channel3->CNDTR = BUFF_SIZE;
DMA_Cmd(DMA1_Channel3, ENABLE);
DMA_ClearITPendingBit(DMA1_IT_TC3);
}
}
Why I can't force DMA1_IT_TC3 interrupt? Or can it be forced on STM32F103?

Related

There is a problem with TIM2_CH1 on stm32f103c8t6

I capture input PWM signal from AURORA9x using 3 timers (TIM4_CH1, TIM3_CH1, TIM2_CH1). All works great except TIM2_CH1. I can't to fix that issue for 3 days. May be some of You came across to this problem.
Here code for three timers. Configuration for all timers are same, but TIM2 doesn't work
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "can.h"
#include "main.h"
void TIM4_Config(void);
void TIM3_Config(void);
void TIM2_Config(void);
uint32_t DataCapture_TIM4=0,
DataCapture_TIM3=0,
DataCapture_TIM2=0;
Timer Configuration for capturing mode for TIM4_CH1
void TIM4_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_Time_user;
GPIO_InitTypeDef port;
TIM_ICInitTypeDef TIM_ICInit_user;
NVIC_InitTypeDef NVIC_InitStructure2;
// TIM4 clock enable
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
// GPIOB clock enable
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// TIM4 channel_1 configuration : PB6
port.GPIO_Pin = GPIO_Pin_6;
port.GPIO_Mode = GPIO_Mode_IN_FLOATING;
port.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOB, &port);
// Connect TIM pin to AF2
// Enable the TIM4 global Ymtirrupt
NVIC_InitStructure2.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure2.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure2.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure2.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure2);
// Time base configuration
TIM_Time_user.TIM_Period = PERIOD;
TIM_Time_user.TIM_Prescaler = PRESCALER;
TIM_Time_user.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_Time_user.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_Time_user);
//Capture configuration
TIM_ICInit_user.TIM_Channel = TIM_Channel_1;
TIM_ICInit_user.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInit_user.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInit_user.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInit_user.TIM_ICFilter = 0x0;
//Inicialize our structure for capture signal
TIM_PWMIConfig(TIM4, &TIM_ICInit_user);
//input trigger
TIM_SelectInputTrigger(TIM4, TIM_TS_TI1FP1);
TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset);
// Select the slave Mode: Reset Mode
TIM_SelectMasterSlaveMode(TIM4,TIM_MasterSlaveMode_Enable);
// Enable the TIM4 Counter
TIM4->CR1 |= TIM_CR1_CEN;
// Enable the CC1 Interrupt request
TIM4->DIER |= TIM_IT_CC1;
}
Interrupt handler for TIM4_CH1
void TIM4_IRQHandler(void)
{
if (TIM4->SR & TIM_SR_CC1IF )
{
DataCapture_TIM4 = TIM4->CCR2;
}
}
Capture mode for TIM3_Ch1
void TIM3_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_Time_user;
GPIO_InitTypeDef port;
TIM_ICInitTypeDef TIM_ICInit_user1;
NVIC_InitTypeDef NVIC_InitStructure1;
// TIM4 clock enable
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
// GPIOB clock enable
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// TIM channel1 confikurotion : PA6
port.GPIO_Pin = GPIO_Pin_6;
port.GPIO_Mode = GPIO_Mode_IN_FLOATING;///////////////////////////////
port.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &port);
// Enable the TIM3 global interrupt
NVIC_InitStructure1.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure1.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure1.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure1.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure1);
// Time base configuration
TIM_Time_user.TIM_Period = PERIOD;
TIM_Time_user.TIM_Prescaler = PRESCALER;
TIM_Time_user.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_Time_user.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_Time_user);
//
TIM_ICInit_user1.TIM_Channel = TIM_Channel_1;
TIM_ICInit_user1.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInit_user1.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInit_user1.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInit_user1.TIM_ICFilter = 0x0;
//
TIM_PWMIConfig(TIM3, &TIM_ICInit_user1);
//input trigger
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
// Select the slave Mode: Reset Mode
TIM_SelectMasterSlaveMode(TIM3,TIM_MasterSlaveMode_Enable);
// Enable the TIM3 Counter
TIM3->CR1 |= TIM_CR1_CEN;
// Enable the CC1 Intirrupt Request
TIM3->DIER |= TIM_IT_CC1;
}
Interrupt handler for TIM3_CH1
void TIM3_IRQHandler(void)
{
if (TIM3->SR & TIM_SR_CC1IF )
{
DataCapture_TIM3 = TIM3->CCR2;
}
}
A problem is HERE for Capturing mode for TIM2_Ch1
void TIM2_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_Time_user;
GPIO_InitTypeDef port;
TIM_ICInitTypeDef TIM_ICInit_user;
NVIC_InitTypeDef NVIC_InitStructure2;
// TIM4 clock enable
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// GPIOB clock enable
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// TIM2 channel_1 configuration : PA0
port.GPIO_Pin = GPIO_Pin_0;
port.GPIO_Mode = GPIO_Mode_IN_FLOATING;
port.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &port);
// Enable the TIM2 global Interrupt
NVIC_InitStructure2.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure2.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure2.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure2.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure2);
// Time base configuration
TIM_Time_user.TIM_Period = PERIOD;
TIM_Time_user.TIM_Prescaler = PRESCALER;
TIM_Time_user.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_Time_user.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_Time_user);
//
TIM_ICInit_user.TIM_Channel = TIM_Channel_1;
TIM_ICInit_user.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInit_user.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInit_user.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInit_user.TIM_ICFilter = 0x0;
//
TIM_PWMIConfig(TIM2, &TIM_ICInit_user);
//input trigger
TIM_SelectInputTrigger(TIM2, TIM_TS_TI1FP1);
TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);
// Select the slave Mode: Reset Mode
TIM_SelectMasterSlaveMode(TIM2,TIM_MasterSlaveMode_Enable);
// Enable the TIM2 Counter
TIM2->CR1 |= TIM_CR1_CEN;
// Enable the CC1 Interrupt Request
TIM2->DIER |= TIM_IT_CC1;
}
Interrupt handler for TIM2_CH1
void TIM2_IRQHandler(void)
{
if (TIM2->SR & TIM_SR_CC1IF )
{
DataCapture_TIM2 = TIM2->CCR2;
}
}
Sorry I cann't add comment.You can check your setting register values in debug mode and check different between your work and CubeMx setting to find problem
As an alternative answer, I recommend you to try CubeMX.
It's a code generator for STM32 that can help you quickly write STM32 low level driver.

STM32 Blinking LEDs with a Timer

I'm trying to blink 4 LEDs with a Timer Interrupt, at different frequencies.
I came up with this code
/*********** Includes ****************/
#include "stm32f4xx.h"
#include "stm32f4_discovery.h"
/*********** Defines *****************/
#define TIM3_CK_CNT 50000
/*********** Declarations *************/
/*------ Function prototypes ---------*/
void TimerConfiguration(void);
/* ----- Global variables ----------- */
volatile uint16_t CCR1_Val = 50000;
volatile uint16_t CCR2_Val = 40000;
volatile uint16_t CCR3_Val = 30000;
volatile uint16_t CCR4_Val = 20000;
/************ Main *********************/
int main(void)
{
// LED initialization
STM_EVAL_LEDInit(LED3); // Orange
STM_EVAL_LEDInit(LED4); // Green
STM_EVAL_LEDInit(LED5); // Red
STM_EVAL_LEDInit(LED6); // Blue
/* TIM3 Configuration */
TimerConfiguration();
while (1);
}
/*********** Functions *****************/
/**
* #brief Configure the TIM3 TIMER.
* #param None
* #retval None
*/
void TimerConfiguration(void)
{
uint16_t PrescalerValue = 0;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* TIM3 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 65535;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* Prescaler configuration */
PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / TIM3_CK_CNT) - 1;
TIM_PrescalerConfig(TIM3, PrescalerValue, TIM_PSCReloadMode_Immediate);
/* Output Compare Timing Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable);
/*Channel2 */
TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
/*Channel3 */
TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
TIM_OC3Init(TIM3, &TIM_OCInitStructure);
/*Channel4 */
TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
TIM_OC4Init(TIM3, &TIM_OCInitStructure);
/* Configure the TIM3 gloabal Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* TIM Interrupts enable */
TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE);
TIM_ITConfig(TIM3, TIM_IT_CC3, ENABLE);
TIM_ITConfig(TIM3, TIM_IT_CC4, ENABLE);
/* TIM3 counter enable */
TIM_Cmd(TIM3, ENABLE);
}
int LedCount6 = 0;
int LedCount5 = 0;
int LedCount4 = 0;
int LedCount3 = 0;
/************ Interrupt Handlers *************/
/**
* #brief This function handles TIM3 global interrupt request.
* #param None
* #retval None
*/
void TIM3_IRQHandler(void)
{
uint16_t capture = 0;
LedCount6++;
LedCount5++;
LedCount4++;
LedCount3++;
if ((TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET) && (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET) && (TIM_GetITStatus(TIM3, TIM_IT_CC3) != RESET) && (TIM_GetITStatus(TIM3, TIM_IT_CC4) != RESET))
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);
TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);
int val6 = 100000;
int val5 = 70000;
int val4 = 60000;
int val3 = 50000;
if (LedCount6 >= val6 ) {
/* LED6 toggling */
STM_EVAL_LEDToggle(LED6);
LedCount6 = 0;
/* Update CH1 OCR */
capture = TIM_GetCapture1(TIM3);
TIM_SetCompare1(TIM3, capture + CCR1_Val);}
if (LedCount5 >= val5) {
/* LED5 toggling */
STM_EVAL_LEDToggle(LED5);
LedCount5 = 0;
/* Update CH2 OCR */
capture = TIM_GetCapture2(TIM3);
TIM_SetCompare2(TIM3, capture + CCR2_Val);}
if (LedCount4 >= val4) {
/* LED4 toggling */
STM_EVAL_LEDToggle(LED4);
LedCount4 = 0;
/* Update CH3 OCR */
capture = TIM_GetCapture3(TIM3);
TIM_SetCompare3(TIM3, capture + CCR3_Val);}
if (LedCount3 >= val3 ) {
/* LED3 toggling */
STM_EVAL_LEDToggle(LED3);
LedCount3 = 0;
/* Update CH4 OCR */
capture = TIM_GetCapture4(TIM3);
TIM_SetCompare4(TIM3, capture + CCR4_Val);}
}
}
Now, all the code that blinks the 4 leds is inside the interrupt handler (void TIM3_IRQHandler(void)).
The 4 LEDs blink, but blink all at the same time, how can i change their frequencies to be all different?
Changing the TIM3_CK_CNT value will change the frequency of all 4, but because it's a define i cannot manipulate it through the code to change for each led.
The TIMER (TIM3) has 4 channels which all can cause an interrupt, but the interrupt handler will be the same one for all channels.
Replace your IRQ handler like this (Change the LED toggle as you wish):
void TIM3_IRQHandler(void)
{
uint16_t capture = 0;
if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
/* LED6 toggling */
STM_EVAL_LEDToggle(LED6);
/* Update CH1 OCR */
capture = TIM_GetCapture1(TIM3);
TIM_SetCompare1(TIM3, capture + CCR1_Val);
}
else if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
/* LED5 toggling */
STM_EVAL_LEDToggle(LED5);
/* Update CH2 OCR */
capture = TIM_GetCapture2(TIM3);
TIM_SetCompare2(TIM3, capture + CCR2_Val);
}
else if (TIM_GetITStatus(TIM3, TIM_IT_CC3) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);
/* LED4 toggling */
STM_EVAL_LEDToggle(LED4);
/* Update CH3 OCR */
capture = TIM_GetCapture3(TIM3);
TIM_SetCompare3(TIM3, capture + CCR3_Val);
}
else if (TIM_GetITStatus(TIM3, TIM_IT_CC4) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);
/* LED3 toggling */
STM_EVAL_LEDToggle(LED3);
/* Update CH4 OCR */
capture = TIM_GetCapture4(TIM3);
TIM_SetCompare4(TIM3, capture + CCR4_Val);
}
}
With this change, LED will toggle with respect to each channel interrupt. i.e Only one LED blinks at each interrupt. In order to Blink with different frequencies, you need to check the datasheet, how configure different frequency for different LED channel.
The code is too large to place it here.
Here is my solution:
https://www.diymat.co.uk/arm-blinking-led-driver/
Any number of LEDs, any frequencies (off and on time can be different) any number of blinks (+continous) and the callbacks at the end of the sequence.

STM32F4 PWM and interrupt with the same timer

I have a STM32F407x. Is it possible to have a PWM Signal on a Pin and at the same time getting a timer interrupt if the UPPER value is reached? I tried the following code, but I only get once an interrupt (count stays at 1 forever if I use the debugger), but the PWM Signal is still available at PB6:
volatile int count=0;
void TM_LEDS_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct;
/* Clock for GPIOB */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
/* Alternating functions for pins */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_TIM4);
/* Set pins */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void TM_TIMER_Init(void) {
TIM_TimeBaseInitTypeDef TIM_BaseStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_BaseStruct.TIM_Prescaler = 100;
TIM_BaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_BaseStruct.TIM_Period = 256;
TIM_BaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_BaseStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4, &TIM_BaseStruct);
}
void TM_PWM_Init(void) {
TIM_OCInitTypeDef TIM_OCStruct;
TIM_OCStruct.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCStruct.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCStruct.TIM_Pulse = 150; /* 25% duty cycle */
TIM_OC1Init(TIM4, &TIM_OCStruct);
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);
/* Clear Interrupt */
for(int i=0; i<3; i++)
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
/* Enable Interrupt */
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM4, ENABLE);
}
void configNVIC(void)
{
NVIC_InitTypeDef initNVICStruct;
/* Enable the TIM2 global Interrupt */
initNVICStruct.NVIC_IRQChannel = TIM4_IRQn;
initNVICStruct.NVIC_IRQChannelPreemptionPriority = 1;
initNVICStruct.NVIC_IRQChannelSubPriority = 3;
initNVICStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&initNVICStruct);
}
void TIM4_IRQHandler(void) //This Interrupt changes changes state from x to x+-1
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
count++;
}
}
int main(void) {
/* Initialize system */
SystemInit();
configNVIC();
/* Init leds */
TM_LEDS_Init();
/* Init timer */
TM_TIMER_Init();
/* Init PWM */
TM_PWM_Init();
int i=0;
while (1) {
i=count;
}
}
If you're trying to count pulses or stop at a certain pulse this post may help
Stop PWM output after N steps

STM32F4 Discovery and CAN programming

I am trying to start learning programming and I am trying to get this code to work: https://github.com/espruino/Espruino/blob/master/targetlibs/stm32f4/lib/stm32f4xx_can.c
I am using Atollic TruStudio Lite.
I did the basic LED blinking code with Discovery, but other than that. I have no clue how to do this.
I don't get how am i supposed to simulate CAN message (and other things) via STM32.
I am a total beginner, so please, don't rip my throat out.
Thanks
Here's an example of a CAN loopback you can try. It's a CAN loopback test. It's in the stm32f4 examples that you can download from the STM website. This is for an STM32439 eval board but it should work on a discovery. (Both are STM32F4 chips).
#define USE_CAN1
/* Uncomment the line below if you will use the CAN 2 peripheral */
/* #define USE_CAN2 */
#ifdef USE_CAN1
#define CANx CAN1
#define CAN_CLK RCC_APB1Periph_CAN1
#else /* USE_CAN2 */
#define CANx CAN2
#define CAN_CLK (RCC_APB1Periph_CAN1 | RCC_APB1Periph_CAN2)
#endif /* USE_CAN1 */
typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;
__IO uint32_t ret = 0; /* for return of the interrupt handling */
volatile TestStatus TestRx;
TestStatus CAN_Polling(void);
int main(void) {
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
files (startup_stm32f40_41xxx.s/startup_stm32f427_437xx.s/startup_stm32f429_439xx.s)
before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f4xx.c file
*/
/* CANx Periph clock enable */
RCC_APB1PeriphClockCmd(CAN_CLK, ENABLE);
/* Initialize LEDs mounted on EVAL board */
STM_EVAL_LEDInit(LED1);
STM_EVAL_LEDInit(LED2);
/* CAN transmit at 125Kb/s and receive by polling in loopback mode */
TestRx = CAN_Polling();
if (TestRx != FAILED) { /* OK */
/* Turn on LED1 */
STM_EVAL_LEDOn(LED1);
} else { /* KO */
/* Turn on LED2 */
STM_EVAL_LEDOn(LED2);
}
/* Infinite loop */
while (1) { }
}
/**
* #brief Configures the CAN, transmit and receive by polling
* #param None
* #retval PASSED if the reception is well done, FAILED in other case
*/
TestStatus CAN_Polling(void) {
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CanTxMsg TxMessage;
CanRxMsg RxMessage;
uint32_t uwCounter = 0;
uint8_t TransmitMailbox = 0;
/* CAN register init */
CAN_DeInit(CANx);
/* CAN cell init */
CAN_InitStructure.CAN_TTCM = DISABLE;
CAN_InitStructure.CAN_ABOM = DISABLE;
CAN_InitStructure.CAN_AWUM = DISABLE;
CAN_InitStructure.CAN_NART = DISABLE;
CAN_InitStructure.CAN_RFLM = DISABLE;
CAN_InitStructure.CAN_TXFP = DISABLE;
CAN_InitStructure.CAN_Mode = CAN_Mode_LoopBack;
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
/* CAN Baudrate = 175kbps (CAN clocked at 42 MHz) */
CAN_InitStructure.CAN_BS1 = CAN_BS1_6tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq;
CAN_InitStructure.CAN_Prescaler = 16;
CAN_Init(CANx, &CAN_InitStructure);
/* CAN filter init */
#ifdef USE_CAN1
CAN_FilterInitStructure.CAN_FilterNumber = 0;
#else /* USE_CAN2 */
CAN_FilterInitStructure.CAN_FilterNumber = 14;
#endif /* USE_CAN1 */
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
/* transmit */
TxMessage.StdId = 0x11;
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.IDE = CAN_ID_STD;
TxMessage.DLC = 2;
TxMessage.Data[0] = 0xCA;
TxMessage.Data[1] = 0xFE;
TransmitMailbox = CAN_Transmit(CANx, &TxMessage);
uwCounter = 0;
while((CAN_TransmitStatus(CANx, TransmitMailbox) != CANTXOK) && (uwCounter != 0xFFFF)) {
uwCounter++;
}
uwCounter = 0;
while((CAN_MessagePending(CANx, CAN_FIFO0) < 1) && (uwCounter != 0xFFFF)) {
uwCounter++;
}
/* receive */
RxMessage.StdId = 0x00;
RxMessage.IDE = CAN_ID_STD;
RxMessage.DLC = 0;
RxMessage.Data[0] = 0x00;
RxMessage.Data[1] = 0x00;
CAN_Receive(CANx, CAN_FIFO0, &RxMessage);
if (RxMessage.StdId != 0x11) {
return FAILED;
}
if (RxMessage.IDE != CAN_ID_STD) {
return FAILED;
}
if (RxMessage.DLC != 2) {
return FAILED;
}
if ((RxMessage.Data[0]<<8|RxMessage.Data[1]) != 0xCAFE) {
return FAILED;
}
return PASSED; /* Test Passed */
}

STM32F4Discovery: Receiving CAN message

I am lost on how to receive CAN message on STM32F4Discovery. I have it in Silent_Loopback mode, meaning all sent messages should arrive in CAN controller itself. I get Transmit_OK status when I send the message, however, nothing appears in the FIFO mailbox. I have skipped CAN filter configuration in order to receive all messages and not to filter any of them out. What am I doing wrong?
/* Includes */
#include "stm32f4xx.h"
#include "stm32f4_discovery.h"
void Delay(__IO uint32_t nCount) {
while(nCount--) {
}
}
void RCC_Configuration(void) {
/* ENABLE CLOCKS */
/* GPIOB clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
/* USART3 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
/* CAN1 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
/* CAN2 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE);
}
void GPIO_Configuration(void) {
GPIO_InitTypeDef GPIO_InitStructureUSART;
GPIO_InitTypeDef GPIO_InitStructureCAN_RX;
GPIO_InitTypeDef GPIO_InitStructureCAN_TX;
/* GPIO USART Configuration */
GPIO_InitStructureUSART.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructureUSART.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructureUSART.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructureUSART.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructureUSART.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructureUSART);
/* Connect USART to AF */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3); //USART_TX = PB10
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3); //USART_RX = PB11
/* GPIO CAN_RX Configuration */
GPIO_InitStructureCAN_RX.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructureCAN_RX.GPIO_Mode = GPIO_Mode_AF;
//GPIO_InitStructureCAN_TX.GPIO_OType = GPIO_OType_PP;
//GPIO_InitStructureCAN_TX.GPIO_PuPd = GPIO_PuPd_NOPULL;
//GPIO_InitStructureCAN_TX.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructureCAN_RX);
/* GPIO CAN_TX Configuration */
GPIO_InitStructureCAN_TX.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructureCAN_TX.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructureCAN_TX.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructureCAN_TX.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructureCAN_TX.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructureCAN_TX);
/* Connect CAN_RX & CAN_TX to AF9 */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_CAN2); //CAN_RX = PB12
GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_CAN2); //CAN_TX = PB13
}
void USART_Configuration(void) {
USART_InitTypeDef USART_InitStructure;
/* USART3 configuration */
/* 256000 baud, window 8 data bits, one stop bit, no parity, no hardware flow control, rx/tx enabled */
USART_InitStructure.USART_BaudRate = 256000;
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_Init(USART3, &USART_InitStructure);
USART_Cmd(USART3, ENABLE);
}
void CAN_Configuration(void) {
CAN_InitTypeDef CAN_InitStructure;
/* CAN2 reset */
CAN_DeInit(CAN2);
/* CAN2 configuration */
CAN_InitStructure.CAN_TTCM = DISABLE; // Time-triggered communication mode = DISABLED
CAN_InitStructure.CAN_ABOM = DISABLE; // Automatic bus-off management mode = DISABLED
CAN_InitStructure.CAN_AWUM = DISABLE; // Automatic wake-up mode = DISABLED
CAN_InitStructure.CAN_NART = DISABLE; // Non-automatic retransmission mode = DISABLED
CAN_InitStructure.CAN_RFLM = DISABLE; // Receive FIFO locked mode = DISABLED
CAN_InitStructure.CAN_TXFP = DISABLE; // Transmit FIFO priority = DISABLED
CAN_InitStructure.CAN_Mode = CAN_Mode_Silent_LoopBack; // Normal CAN mode
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq; // Synchronization jump width = 1
CAN_InitStructure.CAN_BS1 = CAN_BS1_14tq; //14
CAN_InitStructure.CAN_BS2 = CAN_BS2_6tq; //6
CAN_InitStructure.CAN_Prescaler = 4; // Baudrate 500 kbps
//CAN_InitStructure.CAN_Prescaler = 16; // Baudrate 125 kbps
if (CAN_Init(CAN2, &CAN_InitStructure)) { // Initialize CAN
STM_EVAL_LEDInit(LED6); // Initialize and
STM_EVAL_LEDOn(LED6); // Turn ON blue LED if CAN initialization is successful
}
}
void CAN_FilterConfiguration(void) {
CAN_FilterInitTypeDef CAN_FilterInitStructure;
/* CAN2 filter configuration */
CAN_FilterInitStructure.CAN_FilterNumber = 0; // Filter number = 0 (0<=x<=13)
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask; // Filter mode = identifier mask based filtering
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_16bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0300 << 5; //0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x03FF << 5;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0; // FIFO = 0
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
}
void CAN_TxMessage(void) {
CanTxMsg TxMessage;
/* CAN message to send */
TxMessage.StdId = 0x321;
TxMessage.ExtId = 0x01;
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.IDE = CAN_ID_STD;
TxMessage.DLC = 8;
TxMessage.Data[0] = 0x04;
TxMessage.Data[1] = 0x01;
TxMessage.Data[2] = 0x00;
TxMessage.Data[3] = 0x00;
TxMessage.Data[4] = 0x00;
TxMessage.Data[5] = 0x00;
TxMessage.Data[6] = 0x00;
TxMessage.Data[7] = 0x00;
//while (1) {
CAN_TransmitStatus(CAN2, 0);
CAN_Transmit(CAN2, &TxMessage);
if(CAN_TransmitStatus(CAN2, 0)){
STM_EVAL_LEDInit(LED4); // Initialize and
STM_EVAL_LEDOn(LED4); // turn ON green LED if transmit was successful
}
//}
}
void CAN_OBDII_RequestCurrentData(int PIDNumber) {
CanTxMsg TxMessage;
TxMessage.StdId = 0x7DF; // PID request identifier
TxMessage.ExtId = 0x7DF;
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.IDE = CAN_ID_STD;
TxMessage.DLC = 8;
TxMessage.Data[0] = 0x02; // Number of additional bytes = 2
TxMessage.Data[1] = 0x01; // Show current data = 1
TxMessage.Data[2] = PIDNumber; // PID code number
TxMessage.Data[3] = 0x00;
TxMessage.Data[4] = 0x00;
TxMessage.Data[5] = 0x00;
TxMessage.Data[6] = 0x00;
TxMessage.Data[7] = 0x00;
CAN_Transmit(CAN2, &TxMessage); // Transmit OBDII PID request via CAN2/mailbox0
}
void CAN_RxMessage(void) {
CanRxMsg RxMessage;
int d0=0;
while(1) {
CAN_Receive(CAN2,CAN_FIFO0,&RxMessage);
d0 = RxMessage.Data[0];
d0 = RxMessage.Data[1];
d0 = RxMessage.Data[2];
d0 = RxMessage.Data[3];
d0 = RxMessage.Data[4];
d0 = RxMessage.Data[5];
d0 = RxMessage.Data[6];
d0 = RxMessage.Data[7];
}
}
int main(void)
{
/* Initialize Clocks */
RCC_Configuration();
/* Initialize GPIO */
GPIO_Configuration();
/* Initialize USART */
USART_Configuration();
/* Initialize CAN */
CAN_Configuration();
/* Initialize CAN Reception Filter */
//CAN_FilterConfiguration();
/* Transfer CAN message */
CAN_TxMessage();
/* Receive CAN message */
CAN_RxMessage();
You have to configure filter to accept all messages (if you don't have any filter, no message will be accepted). But in your example you use CAN2, so FilterNumber must be 14 or higher.
#define CAN_FIFO_ID 0
#define CAN_FIFO CAN_FIFO0
#define CAN_FIFO_IN CAN_IT_FMP0
/**
* #brief Default filter - accept all to CAN_FIFO
*/
void CAN_SetFilter()
{
/* Default filter - accept all to CAN_FIFO*/
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CAN_FilterInitStructure.CAN_FilterNumber = 14; // 0..13 for CAN1, 14..27 for CAN2
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_16bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO_ID;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
}
The number of filters assigned to CAN1 and CAN2 is defined in the CAN_FMR register which by default is set to 14 which is the start of the CAN2 filters.
This can be set to 28 which would mean no filters to CAN2 and all 28 to CAN1 or if set to 0 all 28 filters are assigned to CAN2.
Normally (if you have a valid Filter Number) in mask mode any mask = zero will let everything through.

Resources