51单片机与计算机通信
首先我们先来了解一下51单片机与计算机进行通信的实现方法。先来看一个实现这个功能的基本电路。
图中的P1就是仿真用的一个串口接口,这个仿真电路要实现与计算机通信功能需要用到其他两个软件,一个是虚拟串口驱动软件,另外一个是串口助手软件,这两个软件在网上都很容易找到。我使用的是Virtual Serial Port Driver和丁丁串口助手,你也可以使用自己熟悉的软件,如果找不到或使用,安装这两个软件有问题可以私信。
虚拟串口驱动软件安装后配置两个成对的虚拟串口一个对应仿真电路中的串口接口,一个对应在串口助手软件上,这样就相当于将两个软件通过虚拟串口连接在一起了,将他们配置成相同的串口参数之后,这时就可以实现相互发送信息了。
这里需要注意的一个问题,上一篇文章中最后部分列举了一个关于使用12MHz和11.0592MHz两种晶振配置特定波特率对应定时器数据寄存器的数据对应的表格,里面还包含各配置值对应的波特率精度,从图中可以看出使用12MHz晶振时误差率普遍比较大,而使用11.0592MHz时几乎没有误差,所以现在知道为啥你手上的单片机使用的晶振都是11.0592MHz的了吧!虽然使用12MHz的晶振进行通信计算机也能捕获到数据,但为了保险起见,若日后你使用51单片机开发项目需要使用到串口时要注意晶振的选择,当然如果使用其他单片机就要另说了,最简单的比如STC生产的1T型的51单片机(即一个机器周期等于一个时钟周期,它的执行效率理论上是传统单片机的12倍,实际因程序复杂程度不一会低一点),就需要参考对应说明了。
接下来我们要怎么验证单片机与计算机进行通信了呢?我们现在就编程实现计算机串口助手发送数据,单片机收到数据就做出回应将数据回传给计算机。
现在我们先来看看程序的具体实现过程。
/*
*这是一个串口通信应用程序
*目的是将串口助手发送过来的数据回传
*/
#include
#include
typedef unsigned char u8;
typedef unsigned int u16;
u8 data_L,data_H;
u8 T0_cnt = 0;
u8 T0_s = 0;
u8 T1_cnt = 0;
u8 crol = 0xfe;
u8 temp = 0;
u8 code num_codelist[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void delay(u8 ms);
void data_init(void);
//void Timer_init(void);
void display(void);
void uart_init(void);
void main(void)
{
// Timer_init();
uart_init();
while(1)
{
data_init();
display();
}
}
void delay(u8 ms)
{
u8 i,j;
for(i=0; i
}
void data_init(void)
{
data_L = T0_s%10;
data_H = T0_s/10;
}
void display(void)
{
P2 = 0xfe;
P0 = num_codelist[data_H];
delay(1);
P2 = 0xfd;
P0 = num_codelist[data_L];
delay(1);
}
void uart_init(void) //串口初始化
{
TMOD = 0x20;
SCON = 0x50;
TH1 = 0xFD; //9600
TL1 = TH1;
PCON = 0x00;
EA = 1;
ES = 1;
TR1 = 1;
}
void uart() interrupt 4 //串口中断
{
if(RI)
{
RI = 0;
temp=SBUF;
SBUF=temp;
while(TI==0);
TI=0;
}
}
现在来看一下程序的仿真效果:
可以看到串口助手发送的数据马上又被单片机传回来了。这个程序没有多少新的代码,主要就是void uart_init(void)和void uart() interrupt 4这两个函数,其中一个串口初始化函数,另一个是串口中断函数。void uart_init(void)这个函数里面设置串口模式,定时器计数值以及串口中断设置。void uart() interrupt 4串口中断函数里面非常简单,就是获取收到的数据然后将数据发送出去。
程序实现过程是非常简单吧,看到这里赶紧去试试看吧。
接下来
51单片机双机通信
在项目开发时我们用到串口更多是和其他芯片进行通信,所以这里我们再来实现一个单片机双机通信的例子,先来看看这个电路图。
现在来看看我们要实现双机通信的代码:
/*
*这是一个串口通信应用程序
*目的是实现单片机的双机通信
*/
#include
#include
typedef unsigned char u8;
typedef unsigned int u16;
sbit key1 = P3^0;
sbit key2 = P3^1;
sbit key3 = P3^2;
sbit key4 = P3^3;
u8 data_L,data_H;
u8 T0_cnt = 0;
u8 T0_s = 0;
u8 T1_cnt = 0;
u8 crol = 0xfe;
u8 temp = 0;
u8 temp_key = 0; //定义一个变量用来存放临时按键值
u8 key_num = 0;//定义一个数字,用来显示
u8 code num_codelist[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void delay(u8 ms);
void data_init(void);
//void Timer_init(void);
void display(void);
void key_init(void);
void uart_init(void);
void main(void)
{
// Timer_init();
key_init();
uart_init();
while(1)
{
data_init();
display();
}
}
void delay(u8 ms)
{
u8 i,j;
for(i=0; i
}
void data_init(void)
{
data_L = key_num%10;
data_H = key_num/10;
}
void display(void)
{
P2 = 0xfe;
P0 = num_codelist[data_H];
delay(1);
P2 = 0xfd;
P0 = num_codelist[data_L];
delay(1);
P1 = key_num; //P1端口LED显示
}
void key_init(void) //按键初始化
{
IT0=1; //外部中断0为下降沿触发
IT1=1; //外部中断1为下降沿触发
EX0=1; //开EX0中断
EX1=1; //开EX1中断
EA=1; //开总中断
}
void uart_init(void) //串口初始化
{
TMOD = 0x20;
SCON = 0x50;
TH1 = 0xFD; //9600
TL1 = TH1;
PCON = 0x00;
EA = 1;
ES = 1;
TR1 = 1;
}
//外部中断0服务例程
void P3_2_key_func(void) interrupt 0
{
//将外部中断0对应的按键K3设置为按键加功能
if(0 == key3)
{
delay(15);
if(0 == key3)
{
if(key_num < 100)
{
key_num++;
}
else
{
key_num = 0;
}
}
SBUF = key_num; //串口发送
while(TI==0);
TI=0;
}
}
//外部中断1服务例程
void P3_3_key_func(void) interrupt 2
{
//将外部中断0对应的按键K4设置为按键减功能
if(0 == key4)
{
delay(15);
if(0 == key4)
{
if(key_num > 0)
{
key_num--;
}
else
{
key_num = 100;
}
}
SBUF=key_num; //串口发送
while(TI==0);
TI=0;
}
}
void uart() interrupt 4
{
if(RI)
{
RI = 0;
key_num = SBUF; //串口接收
}
}
将这段代码同时下载到两个单片机中就实现两个单片机同步了,现在看看仿真结果:
这个程序中的大多数代码都是前面的文章中类似的,只做简单修改就可以,接下来的时间自己看这代码理一理逻辑