#include "reg51.h"
#define uchar unsigned char
#define uint unsigned int
//用单片机来模拟发送SAA3010数据码
//作者:全立波,quanlibo@126.com
uchar sendstart=3; //起始位2位+控制位1位+系统位6位=8位,其中起始两位为1,其它各为均为0
uchar senddatas=1; //数据位为6位,这里只用该字节的前6位
uchar count=0;
sbit P1_0=P1^0; //用来控制红外发光二极管来发送数据
bit sendflag=0; //发送数据的标志量
void Init();
void sendData();
uchar datas[28];
void main(void){
Init();
while(1){
if(sendflag==1){
//串口不允许中断
ET1=0;
TR1=0;
ES=0;
//一个周期是26.32us,那么一个周期的一半应该是13us,所有的错误全部都在这里(看来网上发
的文章也是一些理论没有真正实践过)
//12MHZ,38KHZ
//TH1=0xf3;
//TL1=0xf3;
//11.0592MHZ ,38KHZ
TH1=0xf4;
TL1=0xf4;
sendflag=0;
sendData();
}
};
}
//这里定义1位的时间为在1.651ms,那么半位的时间为1.651ms/2=0.8255ms=825.5us
//事先准备要发送的数
void sendData(){
uchar c=0;
uint b=0;//待发送的数据
uchar s=0;
sendstart=3;//起始码
for(c=0;c<8;c++){
if(senddatas-(senddatas/2)*2){
//为1
b=b|1;
}else{
//为0
b=b|0;
}
if(c<7){
b=b<<1;
}
senddatas=senddatas>>1;
}
b=b<<8>>2;
//做起来真是精细,还要搞掉后面没有被占掉的值,否则数据不准确,做学问真的是不容易啊
b=b |sendstart;
//下面代码用来装配发送数据
c=0;
//先发送起始位2位+控制位1位+系统位5位=8位,后面的6位是数据位,共14位
//用NPN三极管放大信号
do
{
if(b-(b/2)*2){
//发送1的前半位
datas[s++]=1;
}else{
//发送0的前半位
datas[s++]=0;
}
if(b-(b/2)*2){
//发送1的后半位
datas[s++]=0;
}else{
//发送0的后半位
datas[s++]=1;
}
//数据循环右移,发送下一位数据
b=b>>1;
}while(++c<14);
//开始发送数据
count=0;
//12MHZ,延时0.8255ms用
//TH0=0xfc;
//TL0=0xc6;
//11.0592MHZ,延时0.8255ms用
TH0=0xfd;
TL0=0x07;
ET0=1;
TR0=1;
}
void Init(){
//刚开始启动不发送
P1_0=0;
//我们这里利用定时器1的工作方式2(8位自动重载)来发送载波信号
TMOD=0x21;
EA=1;//总中断允许
ES=1;//允许串口中断
//串口工作于方式1,8位UART,波特率可变 ,允许串口接受数据,工作方式为1,无奇偶校验位。
SCON=0x50;
//波特率不加倍,也就是串口通信的波特率为9600
PCON=0x00;
//串口通信
TH1=0xfd; //装入初值, 以后是自动重载的8位计数器
TL1=0xfd;
ET1=0;
TR1=1;
}
void time0()interrupt 1
{
//12MHZ,延时0.8255ms用
//TH0=0xfc;
//TL0=0xc6;
//11.0592,延时0.8255ms用
TH0=0xfd;
TL0=0x07;
if(count==28){
//串口允许中断,用来接收新的发送数据
ES=1;
//数据发送完毕,退出发送
ET0=0;
TR0=0;
P1_0=0;
TH1=0xfd; //装入初值, 以后是自动重载的8位计数器
TL1=0xfd;
ET1=0; //串口模式定时器1不能产生中断,否则不正确
TR1=1;
return;
}
if(datas[count]==0){
//发送载波信号
ET1=1;
TR1=1;
}else{
//不发送载波信号
ET1=0;
TR1=0;
P1_0=0;
}
count++;
}
//人类之所以设计在一定载频下发送信号一是为了节能,如果一直发送将浪费大量能量;二是信号发送的更远
//红外线的载波发射,其实也不是很简单的,因为一般的载波为38K左右.周期只有26us,如果用50%占空比,
//那么13us单片机的IO口就需要高低切换一次,如果载波再高一点,那就更忙了的.
//所以一般的单片机在发送载波的时候根本就不能再处理其他的事情了.
void time1() interrupt 3
{
//周期为26us,38Khz,定时时间应该为周期的一半13us
P1_0=~P1_0;
}
void serial() interrupt 4 //串口中断是4
{
RI = 0; //清0接收中断标志
senddatas=SBUF; //用来测试电脑发送的数据正确与否
sendflag=1;//开始发送数据
}