中级会员
 
- 积分
- 472
- 金钱
- 472
- 注册时间
- 2016-2-22
- 在线时间
- 85 小时
|
正在做红外遥控解码分析的程序,想着把之前用延时等待方式的红外发送代码优化下,能做到开始发送后不用管,主程序能处理其它工作。
要满足这个要求就要先生成整个红外时间序列,以NEC为例IR数组为9000,4500,560,560,560,1690...(第一位高电平,第二位低电平以此类推), 然后由中断来按时间序列自动发送。
上面的数组时间是us单位,这样除了38k PWM定时器外还需要另一个定时器来处理时间,并且若时间大于65000us则超了16位会更烦。所以我这里不用时间单位而用脉冲数做单位,38k的时间周期是26us,9000us转到脉冲数是346,现在就能只用一个定时器产生PWM,并计算溢出次数是否大于346就能实现计时了。
完整代码如下,以NEC为例连续发送两个红外信号,在MDK中模拟的逻辑分析中看了波形没问题。这样改了后集中了编码处理,使结构非常清晰,要转成其它的编码也会很简单。
#include "stm32f10x.h"
#define NEC_HDR_MARK 9000
#define NEC_HDR_SPACE 4500
#define NEC_BIT_MARK 560
#define NEC_ONE_SPACE 1690
#define NEC_ZERO_SPACE 560
#define NEC_STOP_SPACE 40000
#define NEC_RPT_SPACE 2250
#define NEC_RPT_SPACE1 98000
#define NEC_38K_T 26 //38k周期=26us
#define LOW_BIT 0x0
#define HIGH_BIT 0x1
#define START_BIT 0x2
#define STOP_BIT 0x3
#define RPT_BIT 0x4
uint16_t ir_nec_date[200];
uint8_t offset =0;
uint8_t lenth =0;
int start=0;
int times=0;
//使用SetCompare修改ccr,脉冲计数方式定时
void pwm_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE );
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = 1895; //38K
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0; // 初始低电平,高电平为500,占空比=500/(1895-500)
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC4Init(TIM2, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_ARRPreloadConfig(TIM2, ENABLE);
TIM_ITConfig( TIM2,TIM_IT_Update,ENABLE);//允许更新中断
TIM_Cmd(TIM2, ENABLE); //使能定时器
}
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)
{
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
if(start)
{
if (offset%2==0)
TIM_SetCompare4(TIM2,500);
else
TIM_SetCompare4(TIM2,0);
times++;
if (times>=ir_nec_date[offset])
{
times=0;
offset++;
if(offset>lenth)
{
start=0; //发送完成,置标记,可以开始新的发送
TIM_SetCompare4(TIM2,0);
}
}
}
}
}
void ir_nec_get_bit(uint8_t ir_bit)
{
switch( ir_bit)
{
case START_BIT:
ir_nec_date[offset++]=NEC_HDR_MARK/NEC_38K_T;
ir_nec_date[offset++]=NEC_HDR_SPACE/NEC_38K_T;
break;
case STOP_BIT:
ir_nec_date[offset++]=NEC_BIT_MARK/NEC_38K_T;
ir_nec_date[offset++]=NEC_STOP_SPACE/NEC_38K_T;
break;
case HIGH_BIT:
ir_nec_date[offset++]=NEC_BIT_MARK/NEC_38K_T;
ir_nec_date[offset++]=NEC_ONE_SPACE/NEC_38K_T;
break;
case LOW_BIT:
ir_nec_date[offset++]=NEC_BIT_MARK/NEC_38K_T;
ir_nec_date[offset++]=NEC_ZERO_SPACE/NEC_38K_T;
break;
case RPT_BIT:
ir_nec_date[offset++]=NEC_HDR_MARK/NEC_38K_T;
ir_nec_date[offset++]=NEC_RPT_SPACE/NEC_38K_T;
ir_nec_date[offset++]=NEC_BIT_MARK/NEC_38K_T;
ir_nec_date[offset++]=NEC_RPT_SPACE1/NEC_38K_T;
break;
}
}
void ir_nec_get_data(uint8_t address,uint8_t command,uint8_t rpt) //参数:地址码,命令码,重复次数
{
int i;
offset =0;
ir_nec_get_bit(START_BIT);
for (i=0;i<8;i++)
ir_nec_get_bit(((address>>i)&0x01));
address=~address;
for (i=0;i<8;i++)
ir_nec_get_bit(((address>>i)&0x01));
for (i=0;i<8;i++)
ir_nec_get_bit(((command>>i)&0x01));
command=~command;
for (i=0;i<8;i++)
ir_nec_get_bit(((command>>i)&0x01));
ir_nec_get_bit(STOP_BIT);
for (i=0;i<rpt;i++)
ir_nec_get_bit(RPT_BIT);
lenth =offset;
offset=0;
times=0;
}
int main ()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
pwm_init();
ir_nec_get_data(0,0,1); //生成红外序列数组
start=1; //置标志位开始发送
while (start==1); //再次发送要生成数组前,需确认上次发送是否已完成
ir_nec_get_data(0x12,0x34,2);
start=1;
while (1)
{
}
}
|
|