AnsweredAssumed Answered

NEC Infrared Remote Not Working With Timer+DMA+UART

Question asked by Suyog Buradkar on Aug 29, 2017
Latest reply on Aug 30, 2017 by waclawek.jan

Hello Everyone, I am trying to implement NEC IR Remote with STM32F103C8T6. I programmed Timer 1 on channel 1 and transmitting data over UART1. Data from Timer and UART taking in DMA. I am using existing code from github (GitHub - petoknm/STM32_NEC_Decode: A library for decoding NEC IR protocol with STM32 ). I am unble to get what wrong with the code. anybody guess what is the real problem with code.#

 

#include "main.h"
#include "stm32f1xx_hal.h"
#include <string.h>

typedef enum {
NEC_NOT_EXTENDED, NEC_EXTENDED
} NEC_TYPE;

typedef enum {
NEC_INIT, NEC_AGC_OK, NEC_AGC_FAIL, NEC_FAIL, NEC_OK
} NEC_STATE;

typedef struct {
int rawTimerData[32];
uint8_t decoded[4];

NEC_STATE state;

TIM_HandleTypeDef *timerHandle;

uint32_t timerChannel;
HAL_TIM_ActiveChannel timerChannelActive;

uint16_t timingBitBoundary;
uint16_t timingAgcBoundary;
NEC_TYPE type;

void (*NEC_DecodedCallback)(uint16_t, uint8_t);
void (*NEC_ErrorCallback)();
void (*NEC_RepeatCallback)();
} NEC;


NEC nec;

TIM_HandleTypeDef htim1;
DMA_HandleTypeDef hdma_tim1_ch1;
UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_tx;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_TIM1_Init(void);
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);


void NEC_TIM_IC_CaptureCallback(NEC* handle) {

if (handle->state == NEC_INIT) {

HAL_TIM_IC_Stop_DMA(handle->timerHandle, handle->timerChannel);

if (handle->rawTimerData[1] < handle->timingAgcBoundary) {
handle->state = NEC_OK;
handle->NEC_RepeatCallback();
} else {
handle->state = NEC_AGC_OK;
HAL_TIM_IC_Start_DMA(handle->timerHandle, handle->timerChannel,
(uint32_t*) handle->rawTimerData, 32);
}

} else if (handle->state == NEC_AGC_OK) {

HAL_TIM_IC_Stop_DMA(handle->timerHandle, handle->timerChannel);

for (int pos = 0; pos < 32; pos++) {
int time = handle->rawTimerData[pos];
if (time > handle->timingBitBoundary) {
handle->decoded[pos / 8] |= 1 << (pos % 8);
} else {
handle->decoded[pos / 8] &= ~(1 << (pos % 8));
}
}

uint8_t valid = 1;

uint8_t naddr = ~handle->decoded[0];
uint8_t ncmd = ~handle->decoded[2];

if (handle->type == NEC_NOT_EXTENDED && handle->decoded[1] != naddr)
valid = 0;
if (handle->decoded[3] != ncmd)
valid = 0;

handle->state = NEC_OK;

if (valid)
handle->NEC_DecodedCallback(handle->decoded[0], handle->decoded[2]);
else
handle->NEC_ErrorCallback();
}
}

void NEC_Read(NEC* handle) {
handle->state = NEC_INIT;
HAL_TIM_IC_Start_DMA(handle->timerHandle, handle->timerChannel,
(uint32_t*) handle->rawTimerData, 2);
}

void myNecDecodedCallback(uint16_t address, uint8_t cmd) {
char buff[100];
snprintf(buff, 100, "A:%d\tC:%d\n", address, cmd);
HAL_UART_Transmit_DMA(&huart1, (uint8_t*) buff, strlen(buff));
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
HAL_Delay(10);
NEC_Read(&nec);
}

void myNecErrorCallback() {
char* msg = "Error!\n";
HAL_UART_Transmit_DMA(&huart1, (uint8_t*) msg, strlen(msg));
HAL_Delay(10);
NEC_Read(&nec);
}

void myNecRepeatCallback() {
char* msg = "Repeat!\n";
HAL_UART_Transmit_DMA(&huart1, (uint8_t*) msg, strlen(msg));
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
HAL_Delay(10);
NEC_Read(&nec);
}

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
if (htim == &htim1) {
NEC_TIM_IC_CaptureCallback(&nec);
}
}


int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
MX_TIM1_Init();
nec.timerHandle = &htim1;
nec.timerChannel = TIM_CHANNEL_1;
nec.timerChannelActive = HAL_TIM_ACTIVE_CHANNEL_1;
nec.timingBitBoundary = 1680;
nec.timingAgcBoundary = 12500;
nec.type = NEC_NOT_EXTENDED;
nec.NEC_DecodedCallback = myNecDecodedCallback;
nec.NEC_ErrorCallback = myNecErrorCallback;
nec.NEC_RepeatCallback = myNecRepeatCallback;

NEC_Read(&nec);
char *msg="Toggle LED\n";
while (1)
{
HAL_UART_Transmit_DMA(&huart1, (uint8_t*) msg, strlen(msg));
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
HAL_Delay(100);
HAL_GPIO_TogglePin(DEBUG_GPIO_Port, DEBUG_Pin);
HAL_Delay(100);
}

}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;

/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

/**Configure the Systick interrupt time
*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

/**Configure the Systick
*/
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* TIM1 init function */
static void MX_TIM1_Init(void)
{

TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_SlaveConfigTypeDef sSlaveConfig;
TIM_MasterConfigTypeDef sMasterConfig;
TIM_IC_InitTypeDef sConfigIC;

htim1.Instance = TIM1;
htim1.Init.Prescaler = 83;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 0xffffffff;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&htim1);

sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig);

HAL_TIM_IC_Init(&htim1);

sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;
sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;
sSlaveConfig.TriggerPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
sSlaveConfig.TriggerFilter = 4;
HAL_TIM_SlaveConfigSynchronization(&htim1, &sSlaveConfig);

sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);

sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 4;
HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_1);

HAL_TIM_MspPostInit(&htim1);

}

/* USART1 init function */
static void MX_USART1_UART_Init(void)
{

huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_HalfDuplex_Init(&huart1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

}

/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();

/* DMA interrupt init */
/* DMA1_Channel2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
/* DMA1_Channel4_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 4, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);

}

/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
static void MX_GPIO_Init(void)
{

GPIO_InitTypeDef GPIO_InitStruct;

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, LED_Pin|DEBUG_Pin, GPIO_PIN_RESET);

/*Configure GPIO pins : LED_Pin DEBUG_Pin */
GPIO_InitStruct.Pin = LED_Pin|DEBUG_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}


void _Error_Handler(char * file, int line)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
while(1)
{
}
/* USER CODE END Error_Handler_Debug */
}

#ifdef USE_FULL_ASSERT

void assert_failed(uint8_t* file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */

}

Outcomes