如何让c51产生38khz的频率信号,用于做红外收发器

我用定时器每13us产生一个溢出,就是TH0=0xff, TL0=0xf3,为什么最后输出信号只有19khz左右?

把你的程序发过来才好分析,不然只言片语真的很难发现问题所在。

还有你的单片机是 STC89C52RC 的话,可以用“定时器2可编程时钟输出”产生38khz的频率信号,STC89C52RC一共有3个定时器(定时器0、1、2),其中定时器2功能最多,可编程时钟输出就是其中之一。定时器2可编程时钟输出是独立的硬件,单片机只需控制 开和关,不占用CPU时间。

void TT2(uint i) // i 赫兹
{
TR2=0;
RCAP2H=(65536-12000000/4/i)>>8;
RCAP2L=(65536-12000000/4/i);
}

void main(void)
{
T2MOD=0x02; //0000, 0010 允许 定时器2 可编程时钟输出(由 P1.0 输出)
TT2(38000); //设置38KHz

while(1)
{
……
}
}

此时只要启动定时器2(TR2=1; ),P1.0 就会输出占空比为50%的38KHz方波,
关闭只需加2个语句:
TR2=0;
P1^0=1; //使用PNP三极管驱动发射管,关闭时 PNP三极管基极 应为高电平

缺点:占空比=50%不可调,发射引脚只能是P1.0。

“软程序”产生38khz的频率信号。
优点:
①可以随意调节38khz载波的占空比,可以实现低功耗高峰值电流发射,提高发射接收距离。
②发射引脚任意定义。
以下是实例:
/***************************************************************
作品:红外线发射
单片机:STC89C52RC
晶振:12M
编译环境:Keil uVision4 V9.00
***************************************************************/
//
// 发射引脚(接PNP三极管b极)
// PNP三极管e极接2Ω电阻,c极接红外发射管

#include <REG51.h>
#include <intrins.h>

#define uchar unsigned char
#define uint unsigned int

#define SBM 0x80 //识别码

#define m9 (65536-9000) //约9mS
#define m4_5 (65536-4500) //约4.5mS
#define m1_6 (65536-1630) //约1.65mS
#define m_65 (65536-580) //约0.65mS
#define m_56 (65536-560) //约0.56mS
#define m40 (65536-40000) //约40mS
#define m30_5 (65536-30500) //约30.5mS
#define m2_2 (65536-2250) //约2.25mS

sbit IR = P2^0; //定义发射引脚(接PNP三极管基极)

sbit K1=P3^2; //按键1
sbit K2=P3^3; //按键2

void ZZ(uchar x);
void Z0(uchar temp);
void TT0(bit BT,uint x);

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数功能:主函数
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void main(void)
{

TMOD = 0x01; //T0 16位工作方式
IR=1; //发射端口常态为高电平

while(1)
{
if(!K1)
{
while(!K1);
ZZ(0x12); //启动红外发射主程序,发送操作码0x12
}

if(!K2)
{
while(!K2);
ZZ(0x62); //启动红外发射主程序,发送操作码0x62
}
}
}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数功能:红外发射主程序
入口参数:操作码
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void ZZ(uchar x)
{
TT0(1,m9); //38KHz,延时9mS
TT0(0,m4_5); //无38KHz,延时4.5mS

/*┈ 发送4帧数据 ┈*/
Z0(SBM); //发射识别码
Z0(~SBM); //发射识别码反码
Z0(x); //发射操作码
Z0(~x); //发射操作码反码

/*┈┈ 结束码 ┈┈*/
TT0(1,m_65);
TT0(0,m40);

/*┈┈ 重复码 ┈┈*/

while(!K1 || !K2)
{
TT0(1,m9);
TT0(0,m2_2);

TT0(1,m_56);
TT0(0,m30_5);
}

}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数功能:单帧发送程序
入口参数:1帧数据
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void Z0(uchar temp)
{
uchar v;
for (v=0;v<8;v++) //循环8次移位
{
TT0(1,m_65); //高电平0.65mS
if(temp&0x01) TT0(0,m1_6); //发送最低位
else TT0(0,m_56);
temp >>= 1; //右移一位
}
}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数功能:38KHz脉冲发射 + 延时程序
入口参数:(是否发射脉冲,延时约 x (uS))
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void TT0(bit BT,uint x)
{
TH0 = x>>8; //输入T0初始值
TL0 = x;
TF0=0; //清0
TR0=1; //启动定时器0
if(BT == 0) while(!TF0); //BT=0时不发射38KHz脉冲只延时;BT=1发射38KHz脉冲且延时;
else while(1) //38KHz脉冲,占空比5:26
{
IR = 0;
if(TF0)break;
if(TF0)break;
IR = 1;
if(TF0)break;
if(TF0)break;
if(TF0)break;
if(TF0)break;
if(TF0)break;
if(TF0)break;
if(TF0)break;
if(TF0)break;
if(TF0)break;
if(TF0)break;
}
TR0=0; //关闭定时器0
TF0=0; //标志位溢出则清0

IR =1; //脉冲停止后,发射端口常态为高电平
}
温馨提示:答案为网友推荐,仅供参考
相似回答