初级会员
- 积分
- 176
- 金钱
- 176
- 注册时间
- 2017-12-7
- 在线时间
- 20 小时
|
1金钱
用T0解码红外键码一切正常,用T2单独软件模拟PWM输出也是正常(用两个按键控制占空大小也是正常的),但是将两段代码结合后PWM输出就没有变化了,红外解码一切正常,请教高手
完整代码如下:
#include<reg51.h> //包含单片机寄存器的头文件
//#define byte unsigned char
//#define word unsigned int
#define MAIN_Fosc 24000000UL //定义主时钟
#define PWM_DUTY 6000 //定义PWM的周期,数值为时钟周期数,假如使用24.576MHZ的主频,则PWM频率为6000HZ。
#define PWM_HIGH_MIN 32 //限制PWM输出的最小占空比。用户请勿修改。
#define PWM_HIGH_MAX (PWM_DUTY-PWM_HIGH_MIN) //限制PWM输出的最大占空比。用户请勿修改。
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
sfr TL2 = 0xD7;
sfr TH2 = 0xD6;
sfr IE2 = 0xAF; //STC12C5A60S2系列
sfr P3M1 = 0xB1; //P3M1.n,P3M0.n =00--->Standard, 01--->push-pull
sfr P3M0 = 0xB2; // =10--->pure input, 11--->open drain
sfr AUXR = 0x8E;
sfr INT_CLKO = 0x8F;
sbit P_PWM = P3^0; //定义PWM输出引脚。
sbit IR=P3^2; //将IR 位定义为 P3.2引脚
//sbit P30=P3^0;
sbit P33=P3^3;
sbit P31=P3^1;
sbit P34=P3^4;
sbit P35=P3^5;
bit k1,k2;
u8 a[4]; //储存用户码、用户反码与键数据码、键数据反码
u16 LowTime,HighTime; //储存高、低电平的宽度
u16 pwm; //定义PWM输出高电平的时间的变量。用户操作PWM的变量。
u16 PWM_high,PWM_low; //中间变量,用户请勿修改。
void delay_ms(u8 ms);
void LoadPWM(u16 i);
/************************************************************
函数功能:reset
*************************************************************/
void reset(void)
{
P33=1;
P31=1;
P34=1;
P35=1;
}
/************************************************************
函数功能:delay
*************************************************************/
void delay(u8 n)
{
u16 x;
while (n--)
{
x = 0;
while (++x);
}
}
/************************************************************
函数功能:对 4个字节的用户码和键数据码进行解码
说明:解码正确,返回 1,否则返回 0
出口参数:dat
*************************************************************/
bit DeCode(void)
{
u8 i,j;
u8 temp; //储存解码出的数据
for(i=0;i<4;i++) //连续读取4 个用户码和键数据码
{
for(j=0;j<8;j++) //每个码有 8 位数字
{
temp=temp>>1; //temp 中的各数据位右移一位,因为先读出的是高位数据
TH0=0; //定时器清 0
TL0=0; //定时器清 0
TR0=1; //开启定时器 T0
while(IR==0) //如果是低电平就等待
; //低电平计时
TR0=0; //关闭定时器 T0
LowTime=TH0*256+TL0; //保存低电平宽度
TH0=0; //定时器清 0
TL0=0; //定时器清 0
TR0=1; //开启定时器 T0
while(IR==1) //如果是高电平就等待
;
TR0=0; //关闭定时器 T0
HighTime=TH0*256+TL0; //保存高电平宽度
if((LowTime<370)||(LowTime>640))
return 0; //如果低电平长度不在合理范围,则认为出错,停止解码
if((HighTime>420)&&(HighTime<620)) //如果高电平时间在560微秒左右,即计数560/1次
temp=temp&0x7f; //(520-100=420, 520+100=620),则该位是 0
if((HighTime>1300)&&(HighTime<1800)) //如果高电平时间在 1680微秒左右,即计数 1680 1.085=1548 次
temp=temp|0x80; //(1550-250=1300,1550+250=1800),则该位是 1
}
a[i]=temp; //将解码出的字节值储存在 a[i]
}
if(a[2]=~a[3]) //验证键数据码和其反码是否相等,一般情况下不必验证用户码
return 1; //解码正确,返回 1
}
/************************************************************
函数功能:执行遥控功能
*************************************************************/
void Function(void)
{
//EA=0;
if(a[2]==0xEE)
{
//k1=0;
//delay(15);
//while(pwm < (PWM_HIGH_MAX-8)&&k1==0)
//{
pwm += 16; //PWM逐渐加到最大
LoadPWM(pwm);
delay_ms(2);
//}
// k1=1;
}
if(a[2]==0x99)
{
//k2=0;
//delay(15);
// while(pwm > (PWM_HIGH_MAX-8)&&k2==0)
//{
pwm -= 16; //PWM逐渐减到最小
LoadPWM(pwm);
delay_ms(2);
// }
// k2=1;
}
if(a[2]==0xAA)
{
delay(2);
P33=0;
P31=1;
P34=0;
P35=1;
delay(15);
reset();
}
if(a[2]==0xCC)
{
delay(2);
P33=1;
P31=0;
P34=0;
P35=1;
delay(3);
reset();
}
if(a[2]==0x22)
{
delay(2);
P33=0;
P31=1;
P34=1;
P35=0;
delay(3);
reset();
}
if(a[2]==0x66)
{
delay(2);
P33=1;
P31=0;
P34=1;
P35=0;
delay(15);
reset();
}
//EA=1;
}
/************************************************************
函数功能:主函数
*************************************************************/
void main()
{
EA=1; //开启总中断
EX0=1; //开外中断 0
ET0=1; //定时器 T0中断允许
IT0=1; //外中断的下降沿触发
TMOD=0x01; //使用定时器 T0的模式 1
TR0=0; //定时器T0 关闭
P_PWM = 1;
P3M1 &= ~1; //P3.0 设置为推挽输出
P3M0 |= 1;
AUXR &= ~(1<<4); //停止计数
IE2 |= (1<<2); //允许中断
AUXR |= (1<<2); //1T
AUXR &= ~(1<<3); //定时
INT_CLKO |= 0x04; //输出时钟
TH2 = 0;
TL2 = 0;
AUXR |= (1<<4); //开始运行
pwm = PWM_DUTY / 10; //给PWM一个初值,这里为10%占空比
//pwm = 32;
LoadPWM(pwm); //计算PWM重装值
while(1) //等待红外信号产生的中断
;
}
//========================================================================
// 函数: void delay_ms(u8 ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注:
//========================================================================
void delay_ms(u8 ms)
{
unsigned int i;
do{
i = MAIN_Fosc / 13000;
while(--i) ;
}while(--ms);
}
/**************** 计算PWM重装值函数 *******************/
void LoadPWM(u16 i)
{
u16 j;
if(i > PWM_HIGH_MAX) i = PWM_HIGH_MAX; //如果写入大于最大占空比数据,则强制为最大占空比。
if(i < PWM_HIGH_MIN) i = PWM_HIGH_MIN; //如果写入小于最小占空比数据,则强制为最小占空比。
j = 65536UL - PWM_DUTY + i; //计算PWM低电平时间
i = 65536UL - i; //计算PWM高电平时间
EA = 0;
PWM_high = i; //装载PWM高电平时间
PWM_low = j; //装载PWM低电平时间
EA = 1;
}
/************************************************************
函数功能:红外线触发的外中断处理函数
*************************************************************/
void Int0(void) interrupt 0 using 0
{
EX0=0; //关闭外中断 0,不再接收二次红外信号的中断,只解码当前红外信号
TH0=0; //定时器T0 的高 8位清 0
TL0=0; //定时器T0 的低 8位清 0
TR0=1; //开启定时器 T0
while(IR==0) //如果是低电平就等待,给引导码低电平计时
;
TR0=0; //关闭定时器T0
LowTime=TH0*256+TL0; //保存低电平时间
TH0=0; //定时器T0 的高 8位清 0
TL0=0; //定时器T0 的低 8位清 0
TR0=1; //开启定时器 T0
while(IR==1) //如果是高电平就等待,给引导码高电平计时
;
TR0=0; //关闭定时器 T0
HighTime=TH0*256+TL0; //保存引导码的高电平长度
if((LowTime>7800)&&(LowTime<8800)&&(HighTime>3600)&&(HighTime<4700))
{
//如果是引导码,就开始解码,否则放弃,引导码的低电平计时
//次数=9000us/1.085=8294, 判断区间:8300-500=7800,8300+500=8800.
if(DeCode()==1)
Function(); //如果满足条件,执行遥控功能
//EA=0;
}
EX0=1; //开启外中断 EX0
}
/********************* Timer2中断函数************************/
void timer2_int (void) interrupt 12
{
if(P_PWM)
{
//P34=P_PWM ;
TH2 = (u8)(PWM_low >> 8); //如果是输出高电平,则装载低电平时间。
TL2 = (u8)PWM_low;
}
else
{
//P34=P_PWM;
TH2 = (u8)(PWM_high >> 8); //如果是输出低电平,则装载高电平时间。
TL2 = (u8)PWM_high;
}
}
|
最佳答案
查看完整内容[请看2#楼]
中断程序里面死等 高低电平,
你这是独占CPU资源的方式编程
只适合单任务教学使用.
实践中,不可取.
只可以完成解码任务,只他的事情都做不了.
|