作者共发了5篇帖子。 内容转换:不转换▼
 
点击 回复
746 4
【原创】两片S52单片机使用2个IO口进行通信
一派护法 十九级
1楼 发表于:2013-8-29 17:06

这两份程序本人花了好几天才成功!
本程序适合于一个单片机不停地发数据,一个单片机不停地收。

 

1.两片单片机使用同一个电源。
2.发送者的P2.6接接收者的P3.3口(外中断1)
3.发送者的P2.7接接收者的P1.6口
4.接收方的P2口接共阳数码管的位选,其中左边第一个数码管为P2.0,P0口接数码管段选
5.两个单片机都用11.0592M晶振。
我主要用在我的电子时钟上。该电子时钟时刻不停地往外发送时间和温度信息,供其他单片机读取利用。这两个I/O口已
用排针引出。
实验效果:接收方的数码管上从17497300显示到17497399
本方法不需要接收方对发送方进行任何I/O口操作就能收到数据,特别适合多个单片机接收一个单片机发出来的数据。

一派护法 十九级
2楼 发表于:2013-8-29 17:06
//晶振:11.0592MHz
//发数据
#include <AT89X52.h>
sbit TSCLK=P2^6;
sbit TSDAT=P2^7;
//延迟n毫秒
void delay(unsigned int n)
{
 while (n--)
 {
  TH2=0xfc;
  TL2=0x66; //11.0592MHz
  TF2=0;
  TR2=1;
  while (TF2==0);
  TF2=0;
 }
}
void superdelay(unsigned char h, unsigned char l)
{
 TH2=h;
 TL2=l;
 TF2=0;
 TR2=1;
 while (TF2==0);
 TR2=0;
}
//延迟半毫秒
void delay500us()
{
 superdelay(0xfe,0x33);
}

void send_0()
{
 //数据0:0.5ms低电平和0.5ms高电平
 TSDAT=0;
 delay500us();
 TSDAT=1;
 delay500us();
 TSDAT=0; //把数据线拉低,免得程序卡在最后一个字节的高电平计时while循环里导致读错误
}
void send_1()
{
 //数据1:0.5ms低电平和1.5ms高电平
 TSDAT=0;
 delay500us();
 TSDAT=1;
 delay500us();
 delay500us();
 delay500us();
 TSDAT=0;
}
void sendbyte(unsigned char value)
{
 unsigned char i;
 for (i=0;i<8;i++)
 {
  if (value&0x80)
   send_1();
  else
   send_0();
  value<<=1; //从高位发到低位
 }
}
//数据输出
unsigned char i=0;
void output()
{
 //发送引导码
 TSCLK=0; //时钟线为低电平时表示正在发数据
 TSDAT=0; //数据线1ms低电平和2.5ms高电平
 delay(1);
 TSDAT=1;
 delay(2);
 delay500us();
 //发送4个数字
 sendbyte(17);
 sendbyte(49);
 sendbyte(73);
 sendbyte(i); //最后一个数字是不断变化的
 i+=1;
 if (i>99)
  i=0;
 TSCLK=1; //拉高时钟线,表示发送数据完毕
 TSDAT=1; //释放数据线
 delay(4); //使高电平保持一段时间
}
void main()
{
 T2MOD=0x01; //定时器2工作于16位查询工作方式
 TR2=0;
 while (1)
 {
  output();
  delay(1000);
 }
}
一派护法 十九级
3楼 发表于:2013-8-29 17:06
//晶振:11.0592MHz
//收数据
#include <AT89X52.h>
sbit TSCLK=P3^3;
sbit TSDAT=P1^6;
sbit LED1=P2^0;
sbit LED2=P2^1;
sbit LED3=P2^2;
sbit LED4=P2^3;
sbit LED5=P2^4;
sbit LED6=P2^5;
sbit LED7=P2^6;
sbit LED8=P2^7;
sbit fmq=P3^6; //这是蜂鸣器
unsigned char num[4]={0,0,0,0};
unsigned char code DIS_SEG7[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
unsigned int lowtime,hightime;
//延迟n毫秒
void delay(unsigned int n)
{
 while (n--)
 {
  TH0=0xfc;
  TL0=0x66; //11.0592MHz
  TF0=0;
  TR0=1;
  while (TF0==0);
  TF0=0;
 }
}
void superdelay(unsigned char h, unsigned char l)
{
 TH0=h;
 TL0=l;
 TF0=0;
 TR0=1;
 while (TF0==0);
 TR0=0;
}
//延迟半毫秒
void delay500us()
{
 superdelay(0xfe,0x33);
}
//蜂鸣器
void beep()
{
 unsigned char i;
 for (i=0;i<150;i++)
 {
   fmq=0;
  delay500us();
  fmq=1;
  delay500us();
 }
}
void receivebyte(unsigned char* Data)
{
 unsigned char i;
 unsigned int time;
 for (i=0;i<8;i++)
 {
  *Data<<=1; //不应该在for循环的最后执行此操作,否则第一位会丢失
  TH0=TL0=0;
  while (TSDAT==0); //跳过低电平
  TR0=1;
  while (TSDAT==1 && TF0==0); //根据高电平长度判断是0还是1
  TR0=0;
  time=TH0*256+TL0;
  if (time>950)
   *Data|=0x01; //读1
  else
   *Data&=0xfe; //读0
 }
}
void Display()
{
 P0=0xff;
 LED1=0;
 P0=DIS_SEG7[num[0]/10];
 delay(1);
 LED1=1;
 P0=0xff;
 LED2=0;
 P0=DIS_SEG7[num[0]%10];
 delay(1);
 LED2=1;
 P0=0xff;
 LED3=0;
 P0=DIS_SEG7[num[1]/10];
 delay(1);
 LED3=1;
 P0=0xff;
 LED4=0;
 P0=DIS_SEG7[num[1]%10];
 delay(1);
 LED4=1;
 P0=0xff;
 LED5=0;
 P0=DIS_SEG7[num[2]/10];
 delay(1);
 LED5=1;
 P0=0xff;
 LED6=0;
 P0=DIS_SEG7[num[2]%10];
 delay(1);
 LED6=1;
 P0=0xff;
 LED7=0;
 P0=DIS_SEG7[num[3]/10];
 delay(1);
 LED7=1;
 P0=0xff;
 LED8=0;
 P0=DIS_SEG7[num[3]%10];
 delay(1);
 LED8=1;
}
void main()
{
 TMOD=0x01; //定时器2工作于16位查询工作方式
 TR0=0;
 EA=1;
 EX1=1;
 IT1=1;
 while (1)
 {
  P1_7=0;
  Display();
  P1_7=1;
 }
}
void int1() interrupt 2
{
 EX1=0;
 //检测引导码
 //数据线1ms低电平和2.5ms高电平
 TH0=TL0=0;
 TR0=1;
 while (TSDAT==0);
 TR0=0;
 lowtime=TH0*256+TL0;
 TH0=TL0=0;
 TR0=1;
 while (TSDAT==1);
 TR0=0;
 hightime=TH0*256+TL0;
 //对于低电平:1000us/1.085=921,实际值通常为934
 //对于高电平:2500/1.085=2304,实际值通常为2365或2367
 if (lowtime>880 && lowtime<980 && hightime>2300 && hightime<2400)
 {
  receivebyte(&num[0]);
  receivebyte(&num[1]);
  receivebyte(&num[2]);
  receivebyte(&num[3]);
  delay500us(); //全部数据接收完毕后,等待时钟线拉高,防止再次进入本中断
 }
 else
  beep(); //引导码不合法
 EX1=1;
}
一派护法 十九级
4楼 发表于:2013-8-29 17:08
接收方主函数里的P1_7=0;可以去掉,是为了测试用的
一派护法 十九级
5楼 发表于:2013-8-29 17:11

笔者在做本实验的时候,

接收方使用的开发板是:http://item.taobao.com/item.htm?spm=0.0.0.0.EKjqH3&id=4165387534

发送方使用的开发板是:http://item.taobao.com/item.htm?spm=0.0.0.0.Etd8wa&id=6820665303

 

回复帖子

内容:
用户名: 您目前是匿名发表
验证码:
(快捷键:Ctrl+Enter)
 

本帖信息

点击数:746 回复数:4
评论数: ?
作者:巨大八爪鱼
最后回复:巨大八爪鱼
最后回复时间:2013-8-29 17:11
 
©2010-2024 Arslanbar Ver2.0
除非另有声明,本站采用知识共享署名-相同方式共享 3.0 Unported许可协议进行许可。