【DigiKey创意大赛】基于STM32H7B3I-DK的智能家居助手+任意红外调制信号产生与测试
[复制链接]
三.任意波形调制信号产生
原理
定义输出状态数据结构,即对应的输出状态和保持时间
typedef struct iostate
{
uint8_t level;
uint32_t holdtime;
}iostate_t;
定义对应缓冲区,如下定义了2个序列,每个序列有40个状态,以0xFF状态作为结束标志。
iostate_t s_iostate[2][40]=
{
{
{0,3000}, /* 0 - 3mS 1000 25uS*/
{1,3000}, /* 1 - 3ms */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
...
{0Xff,0}
},
{
{0,3000}, /* 0 - 3mS 1000 25uS*/
{1,3000}, /* 1 - 3ms */
{0,500}, /* 0- 500uS */
...
{0Xff,0}
}
};
查询输出缓冲区,输出第一个引脚状态,并设置定时器周期为对应的保持时间。在定时器回调中,查询下一状态需要保持的时间,设置对应的周期,并设置对应引脚状态。以上直到输出所有的状态。
引脚
使用引脚PI10输出
驱动代码
Ir.h
#ifndef IR_H
#define IR_H
#ifdef __cplusplus
extern "C" {
#endif
void ir_init(void);
void ir_send(uint8_t num);
uint8_t ir_isdone(void);
#ifdef __cplusplus
}
#endif
#endif
Ir.c
#include <stdint.h>
#include "main.h"
#define TIMx TIM7
#define CLK 1000000ul
#define ir_outh() HAL_GPIO_WritePin(GPIOI, GPIO_PIN_10, GPIO_PIN_SET)
#define ir_outl() HAL_GPIO_WritePin(GPIOI, GPIO_PIN_10, GPIO_PIN_RESET)
static void ir_handle(void);
static TIM_HandleTypeDef TimHandle;
void time_init(uint32_t period)
{
RCC_ClkInitTypeDef clkconfig;
uint32_t uwTimclock, uwAPB1Prescaler;
uint32_t uwPrescalerValue;
uint32_t pFLatency;
__HAL_RCC_TIM7_FORCE_RESET();
__HAL_RCC_TIM7_RELEASE_RESET();
__HAL_RCC_TIM7_CLK_DISABLE();
/*Configure the TIMx IRQ priority */
HAL_NVIC_SetPriority(TIM7_IRQn, 5 ,0U);
/* Enable the TIMx global Interrupt */
HAL_NVIC_EnableIRQ(TIM7_IRQn);
/* Enable TIM7 clock */
__HAL_RCC_TIM7_CLK_ENABLE();
/* Get clock configuration */
HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
/* Get APB1 prescaler */
uwAPB1Prescaler = clkconfig.APB1CLKDivider;
/* Compute TIM7 clock */
if (uwAPB1Prescaler == RCC_HCLK_DIV1)
{
uwTimclock = HAL_RCC_GetPCLK1Freq();
}
else
{
uwTimclock = 2UL * HAL_RCC_GetPCLK1Freq();
}
/* Compute the prescaler value to have TIM7 counter clock equal to 1MHz */
uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000U) - 1U);
/* Initialize TIM7 */
TimHandle.Instance = TIMx;
/* Initialize TIMx peripheral as follow:
+ Period = [(TIM7CLK/1000) - 1]. to have a (1/1000) s time base.
+ Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock.
+ ClockDivision = 0
+ Counter direction = Up
*/
TimHandle.Init.Period = period - 1U;
TimHandle.Init.Prescaler = uwPrescalerValue;
TimHandle.Init.ClockDivision = 0;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
TimHandle.Init.RepetitionCounter = 0;
TimHandle.Init.AutoReloadPreload = 0;
__HAL_TIM_URS_ENABLE(&TimHandle);
if(HAL_TIM_Base_Init(&TimHandle) == HAL_OK)
{
/* Start the TIM time Base generation in interrupt mode */
HAL_TIM_Base_Start_IT(&TimHandle);
}
}
void TIM7_IRQHandler(void)
{
//static uint32_t freq=1000;
ir_handle();
//time_init(freq+=1000);
if (__HAL_TIM_GET_FLAG(&TimHandle, TIM_FLAG_UPDATE) != RESET)
{
if (__HAL_TIM_GET_IT_SOURCE(&TimHandle, TIM_IT_UPDATE) != RESET)
{
__HAL_TIM_CLEAR_IT(&TimHandle, TIM_IT_UPDATE);
}
}
///HAL_GPIO_TogglePin(GPIOI, GPIO_PIN_10);
}
void time_stop()
{
HAL_TIM_Base_Stop_IT(&TimHandle);
}
void ir_init(void)
{
GPIO_InitTypeDef gpio_init_structure;
__HAL_RCC_GPIOI_CLK_ENABLE();
/* Configure the GPIO_LED pin */
gpio_init_structure.Mode = GPIO_MODE_OUTPUT_PP;
gpio_init_structure.Pull = GPIO_PULLUP;
gpio_init_structure.Speed = GPIO_SPEED_FREQ_HIGH;
gpio_init_structure.Pin = GPIO_PIN_10;
HAL_GPIO_Init(GPIOI, &gpio_init_structure);
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_10, GPIO_PIN_RESET);
}
typedef struct iostate
{
uint8_t level;
uint32_t holdtime;
}iostate_t;
iostate_t s_iostate[2][40]=
{
{
{0,3000}, /* 0 - 3mS 1000 25uS*/
{1,3000}, /* 1 - 3ms */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,2500}, /* 1 -2,5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,2500}, /* 1 -2.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,2500}, /* 1 -2.5mS */
{0,500}, /* 0- 500uS */
{1,2500}, /* 1 -2.5mS */
{0,500}, /* 0- 500uS */
{1,4000}, /* 1 -4mS */
{0,500}, /* 0- 500uS */
{1,60000}, /* 1 -1000mS */
{0Xff,0}
},
{
{0,3000}, /* 0 - 3mS 1000 25uS*/
{1,3000}, /* 1 - 3ms */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,2500}, /* 1 -2,5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,2500}, /* 1 -2.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,2500}, /* 1 -2.5mS */
{0,500}, /* 0- 500uS */
{1,2500}, /* 1 -2.5mS */
{0,500}, /* 0- 500uS */
{1,4000}, /* 1 -4mS */
{0,500}, /* 0- 500uS */
{1,22500}, /* 1 -22.5mS */
{0Xff,0}
}
};
static uint32_t s_ir_index = 0;
static uint32_t s_ir_done = 1;
static uint32_t s_ir_num = 0;
static void ir_handle(void)
{
if(s_ir_index < sizeof(s_iostate[0])/sizeof(s_iostate[0][0]))
{
if(s_iostate[s_ir_num][s_ir_index].level != 0xFF)
{
if(s_iostate[s_ir_num][s_ir_index].level == 0)
{
ir_outl();
}
else
{
ir_outh();
}
time_init(s_iostate[s_ir_num][s_ir_index].holdtime);
}
else
{
time_stop();
s_ir_done = 1;
}
}
else
{
s_ir_done = 1;
time_stop();
}
s_ir_index++;
}
void ir_send(uint8_t num)
{
s_ir_index = 0;
s_ir_done = 0;
s_ir_num = num;
if(s_iostate[s_ir_num][s_ir_index].level == 0)
{
ir_outl();
}
else
{
ir_outh();
}
time_init(s_iostate[s_ir_num][s_ir_index].holdtime);
s_ir_index++;
}
uint8_t ir_isdone(void)
{
return s_ir_done;
}
任意波形输出测试
测试可以看到和缓冲区数据定义完全一致
{
{0,3000}, /* 0 - 3mS 1000 25uS*/
{1,3000}, /* 1 - 3ms */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,2500}, /* 1 -2,5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,2500}, /* 1 -2.5mS */
{0,500}, /* 0- 500uS */
{1,1500}, /* 1 -1.5mS */
{0,500}, /* 0- 500uS */
{1,2500}, /* 1 -2.5mS */
{0,500}, /* 0- 500uS */
{1,2500}, /* 1 -2.5mS */
{0,500}, /* 0- 500uS */
{1,4000}, /* 1 -4mS */
{0,500}, /* 0- 500uS */
{1,60000}, /* 1 -1000mS */
{0Xff,0}
},
注意事项
配置URS为1
__HAL_TIM_URS_ENABLE(&TimHandle);
这样只有溢出时才会产生中断,否则如下初始化时会手动产生一次更新事件而进入中断。与我们需要的到了周期再中断需求不符。
|