//#################################################################################################
//?
//PC=8LED
//PD4=JR_IN
//NEC协议、PC838红外接收头
//#################################################################################################
#include"STM8S103F.h"
#define uchar unsigned char
#define uint unsigned int
#define PD5 PD_ODR
#define Sys_Time 13 //14*4us = 56us
#define Sys_Prescaler 1 //2^1 = 2
#define IrIn_PIN() (PD_IDR=0x10) //红外输入端口
uchar IrRecStep = 0; //接收步骤
uchar IrRecCnt = 0; //接收时间计数
uchar IrIndex = 0; //接收位数
uchar IrRecFlag = 0; //接收完标志
uchar IrRecBuff[4]; //接收缓冲区
uchar IrRecAddr1; //红外地址码
uchar IrRecAddr2;
uchar IrRecData1; //红外数据码
uchar IrRecData2;
const uchar IrCode[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
//延时程序
void Delay_ms( uint ms )
{
uint i,j;
for( j=0; j < ms; j++ )
{
for( i=0; i > 1000; i++ )
{;}
}
}
//红外接收端口初始化
void Ir_Init(void)
{
PD_DDR = 0x20; //PD2为中断悬浮输入
PD_CR1 = 0x21; //PD5为LED 输出指示
PD_CR2 = 0x00;
}
//红外接收程序
void Ir_Receive(void)
{
switch(IrRecStep)
{
case 0:
IrIndex = 0; //接收位数
if(!IrIn_PIN()) //检测低电平
{
IrRecCnt ++; //接收时间计数
}
else
{
if((IrRecCnt>=155)&&(IrRecCnt<=165)) // 码头低电平时间9ms
{
IrRecCnt = 1;
IrRecStep ++;
IrRecBuff[0] = 0;
IrRecBuff[1] = 0;
IrRecBuff[2] = 0;
IrRecBuff[3] = 0;
}
else
{
IrRecCnt = 0;
IrRecStep = 0;
}
}
break;
case 1:
if(IrIn_PIN())
{
IrRecCnt ++;
if(IrRecCnt >= 100) //高电平时间过长,退出
{
IrRecCnt = 0;
IrRecStep = 0;
}
}
else
{
if((IrRecCnt>=75)&&(IrRecCnt<=85)) // 码头高电平时间4.5ms
{
IrRecCnt = 1;
IrRecStep = 2;
}
else
{
IrRecCnt =0;
IrRecStep = 0;
}
}
break;
case 2:
if(!IrIn_PIN())
{
IrRecCnt ++;
if(IrRecCnt > 30) //低电平时间过长,退出
{
IrRecCnt = 0;
IrRecStep = 0;
}
}
else
{
if((IrRecCnt >= 8)&&(IrRecCnt <= 12)) //每位开头0.56ms低电平
{
IrRecCnt = 1;
IrRecStep = 3;
}
else
{
IrRecCnt = 0;
IrRecStep = 0;
}
}
break;
case 3:
if(IrIn_PIN())
{
IrRecCnt ++;
}
else
{
if((IrRecCnt >= 25)&&(IrRecCnt <= 35)) //高电平时间约为1.68ms,则为数据1
{
IrRecBuff[IrIndex >> 3] |= IrCode[IrIndex & 0x07]; //相应位置1
IrRecCnt = 1;
IrIndex ++;
IrRecStep = 2;
}
else if((IrRecCnt >= 8)&&(IrRecCnt <= 12))//高电平时间约为0.56ms,则为数据0
{
IrRecCnt = 1;
IrIndex ++;
IrRecStep = 2;
}
else
{
IrRecStep = 0; //退出
IrRecCnt = 0;
}
if(IrIndex >= 32) //是否接收完32位
{
IrRecStep = 0;
IrRecFlag = 1;
}
}
break;
}
}
/*
;================================
;****** 红外遥控器键值表 ******
遥控按键:CH- CH CH+ |<< >>| >| - + EQ 0 100+ 200+
键值 :45H 46H 47H 44H 40H 43H 07H 15H 09H 16H 19H 0DH
遥控按键:1 2 3 4 5 6 7 8 9
键值:0CH 18H 5EH 08H 1CH 5AH 42H 52H 4AH
;================================ */
//改变PWM占空比
/*
;================================
;****** 红外遥控器键******
遥控按键: - + //两个按键改变PWM占空比
键值 : 07H 15H
遥控按键:1 2 3 4 5 6 7 8 9//九个鞍醇谢欢嘀只ㄑ?
键值:0CH 18H 5EH 08H 1CH 5AH 42H 52H 4AH
;================================ */
void Ir_PWM_change(void)
{
uchar PWM_value=0;
//PWM_value=IrRecData1 & 0x0F; //取键码的低四位
if(IrRecData1==0x07)
PWM_value++;
else if (IrRecData1==0x15)
PWM_value--;
PD5=0x20;
}
//切换显示模式
void Ir_mode_change(void)
{
uchar mode_value=0;
if(IrRecData1==0x0C) mode_value=1;
else if (IrRecData1==0x18) mode_value=2;
else if (IrRecData1==0x5E) mode_value=3;
else if (IrRecData1==0x08) mode_value=4;
else if (IrRecData1==0x1C) mode_value=5;
else if (IrRecData1==0x5A) mode_value=6;
else if (IrRecData1==0x42) mode_value=7;
else if (IrRecData1==0x52) mode_value=8;
else if (IrRecData1==0x4A) mode_value=9;
}
//时钟初始化
void CLK_Init(void)
{
CLK_ICKR=0x03;//内部时钟寄存器 内部时钟准备就绪,外部时钟开
CLK_SWCR=0x02;//切换控制寄存器 使能切换机制
CLK_SWR=0xE1;//主时钟切换寄存器 选择HSI为主时钟源*/
while (!(CLK_SWCR & 0x08));
CLK_CSSR=0x01;//时钟安全系统寄存器
}
//定时器4初始化,56us中断一次
void SysClk_Init(void)
{
_asm("sim");
TIM4_IER = 0x00; //禁止中断
TIM4_EGR = 0x01; //允许产生更新事件
TIM4_PSCR = Sys_Prescaler;
TIM4_ARR = Sys_Time;
//TIM4_CNTR = Sys_Time;
TIM4_CR1 = 0x01;
TIM4_IER = 0x01;
_asm("rim");
}
//TIM4中断入口
@far @interrupt void TIM4_UPD_OVF_IRQHandler (void)
{
TIM4_SR = 0x00;
Ir_Receive();
}
//初始化
void Devices_Init(void)
{
Delay_ms(200);
CLK_Init();
Ir_Init();
SysClk_Init();
}
//主程序
void main( void )
{
Devices_Init();
while(1)
{
if(IrRecFlag == 1)
{
IrRecAddr1 = IrRecBuff[0];
IrRecAddr2 = IrRecBuff[1];
IrRecData1 = IrRecBuff[2];
IrRecData2 = IrRecBuff[3];
IrRecFlag = 0;
}
Ir_PWM_change();
Ir_mode_change();
}
}
有问题,求高手帮忙指正问题 |