实例说明:
1、本实例是利用STM8单片机定时器TIM1的PWM输入捕获模式测量红外遥控码。
2、红外遥控码格式为NEC红外编码。
3、红外接收信号输入接PC1(TIM1输入通道1)。
4、采用外部晶振16M。
5、采用IAR FOR STM8开发环境。
6、程序代码如下:
//--------------------------------------------------------------------
#include "iostm8s105s4.h"
#define uchar unsigned char
#define uint unsigned int
uchar IrRecStep = 0; //接收步骤
uchar IrIndex = 0; //接收位数
uchar IrRecFlag = 0; //接收完标志
uchar IrRecBuff[4]; //接收缓冲区
uchar IrRecAddr1; //红外地址码
uchar IrRecAddr2;
uchar IrRecData1; //红外数据码
uchar IrRecData2;
uint IrCycle = 0; //红外周期
uint IrHigh = 0; //占空比
const uchar IrCode[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
//--------引导码低电平范围------------------
#define IrHeadLow_Max 2300 //2300*4 = 9200us
#define IrHeadLow_Min 2100 //2100*4 = 8400us
//--------引导码高电平范围------------------
#define IrHeadHigh_Max 1250 //1250*4 = 5000us
#define IrHeadHigh_Min 1050 //1050*4 = 4200us
//--------数据0的周期范围-------------------
#define IrData00_Max 300 //300*4 = 1200us
#define IrData00_Min 260 //260*4 = 1040us
//--------数据1的周期范围-------------------
#define IrData10_Max 580 //580*4 = 2320us
#define IrData10_Min 540 //540*4 = 2160us
//--------数据0的占空比(高电平)范围---------
#define IrData0_Max 160 //160*4 = 640us
#define IrData0_Min 120 //120*4 = 480us
//--------数据1的占空比(高电平)范围---------
#define IrData1_Max 440 //440*4 = 1760us
#define IrData1_Min 400 //400*4 = 1600us
//----------------------------------------------------------
#define REMOTE_CLK_DIV 63 //63+1=64----16Mh/64=4us
#define REMOTE_ICF_FILTER 0x30
//延时程序
void Delay_ms( uint ms )
{
uint i,j;
for( j=0; j {
for( i=0; i<1000; i++ )
{;}
}
}
//红外接收端口初始化
void Ir_Init(void)
{
PC_DDR_DDR1 = 0; //PC1为输入
PC_CR1_C11 = 1;
PC_CR2_C21 = 0;
}
//使用TIM1的PWM输入捕获
void Ir_PWM_Init(void)
{
TIM1_PSCRH = 0;
TIM1_PSCRL = REMOTE_CLK_DIV;
TIM1_CCER1 &= 0xee;//禁止输入捕获1,2
TIM1_CCMR1 |= (REMOTE_ICF_FILTER + 0x01);// ch1到ti1fp1
TIM1_CCER1 &= 0xec;//ch1 上升沿触发
TIM1_CCMR2 |= (REMOTE_ICF_FILTER + 0x02);// ch2选择 ti1fp2上
TIM1_CCER1 |= 0x20;//ch1 下降沿触发 ic2
TIM1_SMCR |= 0x54;//选源触发源和触发方式 复位
TIM1_CCER1 |= 0x11;//使能输入捕获1,2
TIM1_CR1 |= 0x05;
}
//红外接收程序
void Ir_Receive(void)
{
switch(IrRecStep)
{
case 0:
IrIndex = 0;
if ((TIM1_SR1_CC1IF == 1)&&(TIM1_SR1_CC2IF == 1))
{
IrHigh = (uint)(TIM1_CCR2H);
IrHigh = (IrHigh << 8) + TIM1_CCR2L; //IrHigh占空比
IrCycle = (uint)(TIM1_CCR1H);
IrCycle = (IrCycle << 8) + TIM1_CCR1L; //IrCycle周期
//是否在引导码低电平范围内
if (((IrCycle - IrHigh) < IrHeadLow_Max)&&((IrCycle - IrHigh) > IrHeadLow_Min))
{
IrRecStep = 1;
TIM1_SR1_CC1IF = 0;
TIM1_SR1_CC2IF = 0;
TIM1_SR2_CC1OF = 0;
TIM1_SR2_CC2OF = 0;
TIM1_SR1_UIF = 0;
IrRecBuff[0] = 0;
IrRecBuff[1] = 0;
IrRecBuff[2] = 0;
IrRecBuff[3] = 0;
}
}
break;
case 1:
if ((TIM1_SR2_CC1OF==1) || (TIM1_SR2_CC2OF==1) || (TIM1_SR1_UIF==1))
{
IrRecStep = 0;
}
else
{
if ((TIM1_SR1_CC1IF == 1)&&(TIM1_SR1_CC2IF == 1))
{
IrHigh = (uint)(TIM1_CCR2H);
IrHigh = (IrHigh << 8) + TIM1_CCR2L;
IrCycle = (uint)(TIM1_CCR1H);
IrCycle = (IrCycle << 8) + TIM1_CCR1L;
//是否在引导码高电平范围内
if ((IrHigh < IrHeadHigh_Max)&&(IrHigh > IrHeadHigh_Min))
{
IrRecStep = 2;
}
}
}
break;
case 2:
if ((TIM1_SR2_CC1OF==1) || (TIM1_SR2_CC2OF==1) || (TIM1_SR1_UIF==1))
{
IrRecStep = 0;
}
else
{
if ((TIM1_SR1_CC1IF == 1)&&(TIM1_SR1_CC2IF == 1))
{
IrHigh = (uint)(TIM1_CCR2H);
IrHigh = (IrHigh << 8) + TIM1_CCR2L;
IrCycle = (uint)(TIM1_CCR1H);
IrCycle = (IrCycle << 8) + TIM1_CCR1L;
//周期是否在数据0范围内
if ((IrCycle > IrData00_Min)&&(IrCycle < IrData00_Max))
{
//高电平是否在数据0范围内
if ((IrHigh > IrData0_Min)&&(IrHigh < IrData0_Max))
{
IrIndex++;
}
else
{
IrRecStep = 0;
}
}
//周期是否在数据1范围内
else if ((IrCycle > IrData10_Min)&&(IrCycle < IrData10_Max))
{
//高电平是否在数据1范围内
if ((IrHigh > IrData1_Min)&&(IrHigh < IrData1_Max))
{
IrRecBuff[IrIndex >> 3] |= IrCode[IrIndex & 0x07];
IrIndex++;
}
else
{
IrRecStep = 0;
}
}
else
{
IrRecStep = 0;
}
if(IrIndex >= 32)
{
IrRecStep = 0;
IrRecFlag = 1;
}
}
}
break;
}
}
//时钟初始化
void CLK_Init(void)
{
CLK_ECKR=0x03;//外部时钟寄存器 外部时钟准备就绪,外部时钟开
CLK_SWCR=0x02;//切换控制寄存器 使能切换机制
CLK_SWR=0xB4;//主时钟切换寄存器 选择HSE为主时钟源*/
while (!(CLK_SWCR & 0x08));
CLK_CSSR=0x01;//时钟安全系统寄存器
}
//初始化
void Devices_Init(void)
{
Delay_ms(200);
CLK_Init();
Ir_Init();
Ir_PWM_Init();
}
//主程序
void main( void )
{
Devices_Init();
while(1)
{
Ir_Receive();
if(IrRecFlag == 1)
{
IrRecAddr1 = IrRecBuff[0];
IrRecAddr2 = IrRecBuff[1];
IrRecData1 = IrRecBuff[2];
IrRecData2 = IrRecBuff[3];
IrRecFlag = 0;
}
}
}