📄 main.c
字号:
/****************************************************************************
* 文 件 名:main.c
* 功 能:使用外部中断3进行B1的控制,每当有一次中断时,即取反B1控制口,以便指示中断输入。
* 使用非向量中断方式。
* 说 明:将跳线器JP2 JP4短接,JP7断开,然后反复按下与释放KEY1。
****************************************************************************/
#include "config.h"
#define LEDCON 0Xf0000000
#define BEEPCON 1<<7 // P0.7引脚控制B1,低电平蜂鸣,1<<7 等价于 0x80
#define IRIN (1<<20) //P0.20为红外接收器数据线
uint8 Time_Count=0; //IR接收基准计数
uint8 DisPlay_Flag=0; //显示标志
uint8 rcv_stat; //当前接收状态(00--06)
uint8 Arrayj,Arrayk=0; //数据接收寄存器的J与K
uint8 IrCount=0; //IR每位接收时间计数
uint8 IRCOM[]={0xff,0xff,0xff,0xff,0x10,0x10}; //数据接收寄存器
void DelayNS(uint32 dly);
void DelayMS(uint8 ms);
void Display(void);
void F_ServiceIRDecode(void);
/****************************************************************************
* 名称:IRQ_Time0()
* 功能:定时器0中断服务程序,取反LEDCON控制口。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void __irq IRQ_Time0(void)
{
if(Time_Count<255)
{
Time_Count++;}
else
{
Time_Count=0;}
F_ServiceIRDecode();
T0IR = 0x01<<1; // 清除中断标志
VICVectAddr = 0x00; // 通知VIC中断处理结束
}
/****************************************************************************
* 名 称:IRQ_Eint3()
* 功 能:外部中断EINT3服务函数,取反B1控制口。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void __irq IRQ_Eint3(void)
{
EXTINT = 1<<3; // 清除EINT3中断标志
if(rcv_stat==0)
{
Time_Count=0;
rcv_stat=01;
Arrayj=0;
Arrayk=0;
IrCount=0;
}
VICVectAddr = 0x00;
}
/****************************************************************************
* 名称:DelayNS()
* 功能:长软件延时
* 入口参数:dly 延时参数,值越大,延时越久
* 出口参数:无
****************************************************************************/
void DelayNS(uint32 dly)
{ uint32 i;
for(; dly>0; dly--)
for(i=0; i<50000; i++);
}
/****************************************************************************
* 名称:DelayMS()
* 功能:Timer0延时
* 入口参数:dly 延时参数,值越大,延时越久
* 出口参数:无
****************************************************************************/
void DelayMS(uint8 ms)
{ Time_Count=0;
while(Time_Count<ms);
}
/****************************************************************************
* 名称:Time0Init()
* 功能:初始化定时器0,定时时间为0.5S,并打开中断。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void Time0Init(void)
{ /* 初始化定时器0,实现0.14MS定时
Fcclk = Fosc*4 = 11.0592MHz*4 = 44.2368MHz
Fpclk = Fcclk/4 = 44.2368MHz/4 = 11.0592MHz
*/
T0PR = 99; // 设置定时器0分频为100分频,得110592Hz
T0MCR = 0x03<<3; // 匹配通道1匹配中断并复位T0TC
T0MR1 = 16; // 设置MR1比较值(0.14MS定时值)
T0TCR = 0x03; // 启动并复位T0TC
T0TCR = 0x01;
}
/*******************************************************************
显示码值函数
*******************************************************************/
void Display(void)
{
IO2SET=0xffffffff;
IO2CLR =(IRCOM[4]&0x0000000f)<<28;
DelayNS(1);
}
/*******************************************************************
红外解码函数
*******************************************************************/
void F_ServiceIRDecode(void)
{
switch(rcv_stat)
{
case 00:break;
case 01:if(Time_Count>=15)
{if (!(IRIN&IO0PIN)==0)
{ rcv_stat=00;
return;
}
rcv_stat=02;
}
break;
case 02: if (IRIN&IO0PIN) //等IR变为高电平,跳过9ms的前导低电平信号。
{ rcv_stat=03;
}
break;
case 03: if (!(IRIN&IO0PIN)) //等 IR 变为低电平,跳过4.5ms的前导高电平信号。
{ rcv_stat=04;
}
break;
case 04:if (IRIN&IO0PIN) //等 IR 变为高电平
{ IrCount=0;
rcv_stat=05;
}
break;
default:break;
}
if(rcv_stat==05)
{
if(IRIN&IO0PIN) //测量高电平时间
{ IrCount++;
if (IrCount>=30)
{rcv_stat=00;
} //0.14ms计数过长自动离开。
return;
}
else //高电平计数完毕
{
if(Arrayj<4) //收集四组数据
{IRCOM[Arrayj]=IRCOM[Arrayj] >> 1; //数据最高位补“0”
if (IrCount>=8) {IRCOM[Arrayj] = IRCOM[Arrayj] | 0x80;} //数据最高位补“1”
Arrayk++;
if (Arrayk>=8) {Arrayk=0; Arrayj++; } //每组数据有8位
}
if(Arrayj>=4) //接收数据完成
{rcv_stat=06;
IrCount=0;
if (IRCOM[2]!=((~IRCOM[3])&0xff)) //接收时间是否正确
{
rcv_stat=00;
IrCount=0;
return;
}
if(IRCOM[0]!=0x00) //比较用户码
{
rcv_stat=00;
IrCount=0;
return;
}
IRCOM[4]=IRCOM[2] & 0x0F; //取键码的低四位
IRCOM[5]=IRCOM[2] >> 4; //右移4次,高四位变为低四位
rcv_stat=00; //准备下次接收
DisPlay_Flag=01;
return;
}
rcv_stat=03;
IrCount=0;
return;
}
}
}
/****************************************************************************
* 名 称:main()
* 功 能:初始化外部中断3(EINT3)为非向量中断,并设置为电平触发模式,然后等待外部中断。
* 说 明:在STARTUP.S文件中使能IRQ中断(清零CPSR中的I位)。
****************************************************************************/
int main(void)
{
IO2DIR = LEDCON;
PINSEL1 = 3<<8; // 设置管脚连接,P0.20设置为EINT3
// 3<<8 等价于 0x00000180
//IO0SET = IRIN; I/O口初始化
EXTMODE = 0x0F; // 设置EINT3中断为边沿触发方式
EXTPOLAR= 0x00; // 设置EINT3中断为下降沿触发
VICIntSelect = 0x00; // 所有中断通道设置为IRQ中断
/* 设置定时器0*/
Time0Init(); // 定时器0初始化
VICVectCntl0 = 0x20|04; // 定时器0中断通道分配最高优先级(向量控制器0)
VICVectAddr0 = (uint32)IRQ_Time0;// 设置中断服务程序地址向量
/* 打开EINT3中断(使用向量IRQ) */
VICVectCntl1 = 0x20|17; // 分配EINT3中断到向量中断0
VICVectAddr1 = (int)IRQ_Eint3; // 设置中断服务程序地址
EXTINT = 1<<3; // 清除EINT3中断标志
VICIntEnable = (1<<4)|(1<<17); // 使能定时器、EINT3中断
while(1) // 等待中断
{
if(DisPlay_Flag==0x01)
{
Display();
DisPlay_Flag=00;
}
}
return(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -