51单片机+红外发射模块(38k+NEC),这代码对不对?有详细注释!

shaoxiaojing5193 2013-03-12 03:52:12
哪位大神帮小弟看一下这段代码,是网上载的,我大概修改了一下几个数值,因为我觉得原来的错的,结果红外发射模块发射不了,用原来载下来的数值执行起来也是不行,小弟这里没示波器,这份代码小弟很详细的给它添加了很多注释,只求有心的前辈帮一下小弟,帮忙看一下哪里不对。。。。 38k + NEC协议。。。。作者没有使用循环去发送 用户码 用户反码 键码 键反码,所以代码看起来比较多,其实是很少的。。。
捣鼓了我好几天了一直不知道为什么不行,啊啊啊啊啊啊 拜托前辈了!帮了小弟这个忙,什么都好说



//#include <AT89X51.h> 
#include <reg51.h>

static bit OP; //红外发射管的亮灭控制位
static unsigned int count; //延时计数器
static unsigned int endcount; //终止延时计数
static unsigned char flag; //红外发送标志
sbit P3_4=P3^4;
char iraddr1; //十六位地址的第一个字节
char iraddr2; //十六位地址的第二个字节
void SendIRdata(char p_irdata);//发送子函数
void delay();


void main(void)
{
count = 0;
flag = 0; //无载波
OP = 0; //不亮
P3_4 = 0; //在后面会发现用OP赋值的
EA = 1; //允许CPU中断
TMOD = 0x11; //设定时器0和1为16位模式1
ET0 = 1; //定时器0中断允许
TH0 = 0xFF;
TL0 = 0xE6; //设定时值0为38K 也就是每隔26us中断一次
TR0 = 1; //开始计数
iraddr1=3; //自定义的一个地址
iraddr2=252; //地址反码

do
{
delay(); //延时
SendIRdata(221); //发送数据

}while(1);
}

//定时器0中断处理
void timeint(void) interrupt 1
{
TH0=0xFF;
TL0=0xE6; //设定时值为38K 也就是每隔26us中断一次
count++;

if (flag==1) //如果是待发送的有效数据flag=1,就在此产生载波(亮灭交变)
{
OP=~OP; //产生方波其实就是调制后的高电平哈
}
else
{
OP = 0; //发送低电平
}

P3_4 = OP; //往发射模块的 IO口发送出去哈
}

void SendIRdata(char p_irdata) //发送数据子函数
{
int i;
char irdata=p_irdata;

/***************************************************************/

//发送9ms的起始码
//引导码是9ms的高电平,9000us/26us = 346
endcount = 346;
flag=1; //载波模式有效
count=0;
while(count<endcount); //等待中断,在中断中发送载波,总时间为9ms


//发送4.5ms的结果码,并是载波模式无效,也就是发送4.5ms的低电平
//结果码是 4500us/26us = 173
endcount = 173;
flag=0;
count=0;
while(count<endcount);

/***************************************************************/
//发送十六位地址的前八位,iraddr存的是地址码
irdata=iraddr1;
for(i=0;i<8;i++)
{
//一个周期里规定先以高电平开始,在以低电平结束。先发送0.56ms的38KHZ“1”的红外波(即编码中0.56ms的高电平)
endcount = 21; //560us/26us = 21
flag=1;
count=0;
while(count<endcount); //等待中断


if(irdata-(irdata/2)*2) //判断二进制数个位为1还是0
{
endcount=64; //如果是 1,修改 endcount = 64, 64*26us = 1680us
}
else
{
endcount=21;//如果是0,则低电平 21*26us = 560us;
}
flag=0; //因为发送的 0,所以调制后就是一连串连续的低电平,所以 flag=0,载波模式无效
count=0;

while(count<endcount); //等待中断发送

irdata=irdata>>1;//依次取位

}

//发送十六位地址的后八位


irdata=iraddr2; //此处已经是地址的反码
for(i=0;i<8;i++)
{
endcount = 21;
flag=1;
count=0;

while(count<endcount);

if(irdata-(irdata/2)*2)
{
endcount = 64;

}
else
{
endcount = 21;
}

flag=0;
count=0;

while(count<endcount);

irdata=irdata>>1;
}/***************************************************************/
//发送八位数据

irdata=p_irdata;

for(i=0;i<8;i++)
{
endcount = 21;
flag=1;
count=0;

while(count<endcount);

if(irdata-(irdata/2)*2)
{
endcount=64;;

}
else
{
endcount = 21;
}

flag=0;
count=0;

while(count<endcount);

irdata=irdata>>1;
}

//发送八位数据的反码
irdata=~p_irdata; //要将数据位取反

for(i=0;i<8;i++)
{
endcount = 21;
flag=1;
count=0;

while(count<endcount);

if(irdata-(irdata/2)*2)
{
endcount = 64;
}
else
{
endcount = 21;
}

flag=0;
count=0;

while(count<endcount);

irdata=irdata>>1;
}

//到这边一帧的数据已经按照 38K + NEC发送出去了
}


void delay()
{
int i,j;

for(i=0;i<400;i++)
{
for(j=0;j<100;j++)
{
}
}
}


...全文
1257 3 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
am540 2014-10-21
  • 打赏
  • 举报
回复
while(count<endcount); 有问题 没有count++
shaoxiaojing5193 2013-03-12
  • 打赏
  • 举报
回复
引用 1 楼 duojinian 的回复:
1.注意硬件电路需要匹配合适的晶体,如果是外部晶体的话。 2.内部晶体需要注意匹配发送速率。
硬件方面很简单阿,我是用 51的核心板,然后网上买的红外发射模块,有 GND,GCC,OUT 三个引脚,直接就接51的IO口了,所以硬件方面应该不会有问题吧。。。至于38k,NEC,都是用51的定时器实现的。。。还请前辈花点心思帮忙看下代码啊,这问题实在是困扰小弟多日了。。。。
DISINHUI 2013-03-12
  • 打赏
  • 举报
回复
1.注意硬件电路需要匹配合适的晶体,如果是外部晶体的话。 2.内部晶体需要注意匹配发送速率。

27,517

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧