实验3 串口通信
1. 以2400bps从计算机发送任一字节数据,当单片机收到该数据后,将其送到数码管显示,在此数据前加上一序号然后连同此数据一起发送至计算机,当序号超过255时归零。
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
/**
题目要求:以2400bps从计算机发送任一字节数据,当单片机收到该数据后,将其送到数码管显示,在此数据前加上一序号然后连同此数据一起发送至计算机,当序号超过255时归零。
**/
/**
步骤
接线方式:
1、P0接数码管J12,实现段选
2、译码器和数码管位选输入短接,J15+J16
3、P2用来控制译码器的输入
4、P1是串口接收中断的指示,P1+JP1
5、本实验使用的晶振是11.0592
**/
//=========全局变量区============================================
sbit high=P2^4;
sbit mid=P2^3;
sbit low=P2^2;
uint code NumTable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//数字的编码
uint Received_Flag=0;//用来标志是否接收到信号
uchar ReceiveCount,Data_Received=0;//ReceiveCount是接受的条数,接收到的数据
uchar code table[]="index ";
//=========全局变量区结束========================================
//========函数区开始============================================
/**
延时
**/
void delay_1ms(uint x){
uint i=x;
uint j;
for(;i>0;--i){
for(j=110;j>0;--j);
}
}
/**
在数码管上显示对应的值
**/
void display(uchar Num)
{
P0=NumTable[Num];
delay_1ms(1);
P0=0; //送完段选信号后,进行消影的处理
}
/**
控制数码管显示后3位,并分解计数值
**/
void DisplayNumByOrder(uint Value){
low=0; mid=0; high=0; display(0);
low=1; mid=0; high=0; display(0);
low=0; mid=1; high=0; display(0);
low=1; mid=1; high=0; display(0);
low=0; mid=0; high=1; display(0);
low=1; mid=0; high=1; display(Value%1000/100);
low=0; mid=1; high=1; display(Value%100/10);
low=1; mid=1; high=1; display(Value%10);
}
void init(){ //初始化定时器T1和串口
SCON =0x50; //设置串口工作方式1,并打开接收中断
TMOD =0x20; //设置T1工作方式2
PCON =0x00; //设置SMOD为串口工作方式1
TL1 =0xf4;
TH1 =0xf4; //2400bps(12MHZ的晶振)
TR1 =1; //开启时钟
ES =1; //开启串口中断允许
EA =1; //开启中断总允许
}
/**
发送数据
**/
void SendData(uchar value){
SBUF=value;
while(!TI);
TI=0;
}
/**
处理接收到的数据
**/
void ProcessData(){
int i=0;
for(i=0;i<6;i++){
SendData(table[i]);
}
SendData(ReceiveCount);
SendData(':');
SendData(Data_Received);
}
int main(){
init();//初始化数据
while(1){
if(1==Received_Flag){//当单片机收到该数据后,将其送到数码管显示
ES=0;//将串口接收总中断关闭,因为发送数据的时候,往缓冲区内写数据也会引发串口接收中断。
ProcessData();
ES=1;
Received_Flag=0;
}
//在此数据前加上一序号然后连同此数据一起发送至计算机,当序号超过255时归零。
DisplayNumByOrder(Data_Received); //在数码管上显示
}
return0;
}
//========函数区结束============================================
//========中断函数区============================================
/**
串口接收中断
**/
void ser_received() interrupt 4
{
RI=0;//RI=1代表缓冲区内有数据,清零以便等待下次数据到来
Data_Received=(uchar)SBUF; //从缓冲区内读取数据
Received_Flag=1; //设置已经接收到数据
P1=~P1;
ReceiveCount++;
}
//========中断函数区结束==========================================
2. 以16进制发送一个0-65536之间的任一数,当单片机收到后在数码管上动态显示出来,波特率自定。
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
/**
题目要求: 以16进制发送一个0-65536之间的任一数,当单片机收到后在数码管上动态显示出来,波特率自定。
**/
/**
步骤
接线方式:
1、P0接数码管J12,实现段选
2、译码器和数码管位选输入短接,J15+J16
3、P2用来控制译码器的输入
4、P1是串口接收中断的指示,P1+JP1
5、本实验使用的晶振是11.0592
**/
//=========全局变量区============================================
sbit high=P2^4;
sbit mid=P2^3;
sbit low=P2^2;
uint code NumTable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//数字的编码
uint Received_Flag=0;//用来标志是否接收到信号
uchar ReceiveCount,DecodeCount,Data_Received=0;//ReceiveCount是已经接收的条数,DecodeCount是已经解析的数目,Data_Received是接收到的数据
ulong NumToDisplay=0;
//=========全局变量区结束========================================
//========函数区开始============================================
/**
延时
**/
void delay_1ms(uint x){
uint i=x;
uint j;
for(;i>0;--i){
for(j=110;j>0;--j);
}
}
/**
在数码管上显示对应的值
**/
void display(uchar Num)
{
P0=NumTable[Num];
delay_1ms(1);
P0=0; //送完段选信号后,进行消影的处理
}
/**
控制数码管显示后3位,并分解计数值
**/
void DisplayNumByOrder(ulong Value){
low=0; mid=0; high=0; display(0);
low=1; mid=0; high=0; display(0);
low=0; mid=1; high=0; display(0);
low=1; mid=1; high=0; display(Value%100000/10000);
low=0; mid=0; high=1; display(Value%10000/1000);
low=1; mid=0; high=1; display(Value%1000/100);
low=0; mid=1; high=1; display(Value%100/10);
low=1; mid=1; high=1; display(Value%10);
}
void init(){ //初始化定时器T1和串口
SCON =0x50; //设置串口工作方式1,并打开接收中断
TMOD =0x20; //设置T1工作方式2
PCON =0x00; //设置SMOD为串口工作方式1
TL1 =0xf4;
TH1 =0xf4; //2400bps(11.0592MHZ的晶振)
TR1 =1; //开启时钟
ES =1; //开启串口中断允许
EA =1; //开启中断总允许
}
/**
发送数据
**/
void SendData(uchar value){
SBUF=value;
while(!TI);
TI=0;
}
int main(){
init();//初始化数据
while(1){
if(1==Received_Flag){//当单片机收到该数据后,将其送到数码管显示
ES=0;//将串口接收总中断关闭,因为发送数据的时候,往缓冲区内写数据也会引发串口接收中断。
//ProcessData();
ES=1;
Received_Flag=0;
}
//在此数据前加上一序号然后连同此数据一起发送至计算机,当序号超过255时归零。
DisplayNumByOrder(NumToDisplay); //在数码管上显示
}
return0;
}
//========函数区结束============================================
//========中断函数区============================================
/**
串口接收中断
**/
void ser_received() interrupt 4
{
if(RI ==1){//接收到触发中断
RI=0;//RI=1代表缓冲区内有数据,清零以便等待下次数据到来
Data_Received=(uchar)SBUF; //从缓冲区内读取数据
Received_Flag=1; //设置已经接收到数据
if(DecodeCount==0){
NumToDisplay=Data_Received;
++DecodeCount;
}else{
NumToDisplay =(NumToDisplay <<8)| Data_Received;//相当于原来的数乘以8,然后+现在的数
DecodeCount++;
if(DecodeCount ==3) //0..65536要接收6位的16进制
DecodeCount =0;
}
P1=~P1;
ReceiveCount++;
}
}
//========中断函数区结束==========================================
扩展题目:
1. 实现单片机双机通信,实现单片机甲发送一个信息给单片机乙,同时在数码管上显示出来,单片机乙收到信息后,回复OK给单片机甲。
//甲机
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
/**
题目要求:以2400bps从计算机发送任一字节数据,当单片机收到该数据后,将其送到数码管显示,在此数据前加上一序号然后连同此数据一起发送至计算机,当序号超过255时归零。
**/
/**
步骤
接线方式:
1、P0接数码管J12,实现段选
2、译码器和数码管位选输入短接,J15+J16
3、P2用来控制译码器的输入
4、P1是串口接收中断的指示,P1+JP1
5、本实验使用的晶振是11.0592
**/
//=========全局变量区============================================
sbit high=P2^4;
sbit mid=P2^3;
sbit low=P2^2;
uint code NumTable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//数字的编码
uint Received_Flag=0;//用来标志是否接收到信号
uchar ReceiveCount,Data_Received=0;//ReceiveCount是接受的条数,接收到的数据
uchar code table[]="index ";
//=========全局变量区结束========================================
//========函数区开始============================================
/**
延时
**/
void delay_1ms(uint x){
uint i=x;
uint j;
for(;i>0;--i){
for(j=110;j>0;--j);
}
}
/**
在数码管上显示对应的值
**/
void display(uchar Num)
{
P0=NumTable[Num];
delay_1ms(1);
P0=0; //送完段选信号后,进行消影的处理
}
/**
控制数码管显示后3位,并分解计数值
**/
void DisplayNumByOrder(uint Value){
low=0; mid=0; high=0; display(0);
low=1; mid=0; high=0; display(0);
low=0; mid=1; high=0; display(0);
low=1; mid=1; high=0; display(0);
low=0; mid=0; high=1; display(0);
low=1; mid=0; high=1; display(Value%1000/100);
low=0; mid=1; high=1; display(Value%100/10);
low=1; mid=1; high=1; display(Value%10);
}
void init(){ //初始化定时器T1和串口
SCON =0x50; //设置串口工作方式1,并打开接收中断
TMOD =0x20; //设置T1工作方式2
PCON =0x00; //设置SMOD为串口工作方式1
TL1 =0xf4;
TH1 =0xf4; //2400bps(11.0592MHZ的晶振)
TR1 =1; //开启时钟
ES =1; //开启串口中断允许
EA =1; //开启中断总允许
}
/**
发送数据
**/
void SendData(uchar value){
SBUF=value;
while(!TI);
TI=0;
}
int main(){
init();//初始化数据
SendData(0x00);//发送数据
SendData(0x01);
SendData(0x01);
while(1){
if(1==Received_Flag){//当单片机收到该数据后,将其送到数码管显示
ES=0;//将串口接收总中断关闭,因为发送数据的时候,往缓冲区内写数据也会引发串口接收中断。
ES=1;
Received_Flag=0;
}
//在此数据前加上一序号然后连同此数据一起发送至计算机,当序号超过255时归零。
DisplayNumByOrder(Data_Received); //在数码管上显示
}
return0;
}
//========函数区结束============================================
//========中断函数区============================================
/**
串口接收中断
**/
void ser_received() interrupt 4
{
RI=0;//RI=1代表缓冲区内有数据,清零以便等待下次数据到来
Data_Received=(uchar)SBUF; //从缓冲区内读取数据
Received_Flag=1; //设置已经接收到数据
P1=~P1;
ReceiveCount++;
}
//========中断函数区结束==========================================
//乙机
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
/**
题目要求: 以16进制发送一个0-65536之间的任一数,当单片机收到后在数码管上动态显示出来,波特率自定。
**/
/**
步骤
接线方式:
1、P0接数码管J12,实现段选
2、译码器和数码管位选输入短接,J15+J16
3、P2用来控制译码器的输入
4、P1是串口接收中断的指示,P1+JP1
5、本实验使用的晶振是11.0592
**/
//=========全局变量区============================================
sbit high=P2^4;
sbit mid=P2^3;
sbit low=P2^2;
uint code NumTable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//数字的编码
uint Received_Flag=0;//用来标志是否接收到信号
uchar ReceiveCount,DecodeCount,Data_Received=0;//ReceiveCount是已经接收的条数,DecodeCount是已经解析的数目,Data_Received是接收到的数据
ulong NumToDisplay=0;
//=========全局变量区结束========================================
//========函数区开始============================================
/**
延时
**/
void delay_1ms(uint x){
uint i=x;
uint j;
for(;i>0;--i){
for(j=110;j>0;--j);
}
}
/**
在数码管上显示对应的值
**/
void display(uchar Num)
{
P0=NumTable[Num];
delay_1ms(1);
P0=0; //送完段选信号后,进行消影的处理
}
/**
控制数码管显示后3位,并分解计数值
**/
void DisplayNumByOrder(ulong Value){
low=0; mid=0; high=0; display(0);
low=1; mid=0; high=0; display(0);
low=0; mid=1; high=0; display(0);
low=1; mid=1; high=0; display(Value%100000/10000);
low=0; mid=0; high=1; display(Value%10000/1000);
low=1; mid=0; high=1; display(Value%1000/100);
low=0; mid=1; high=1; display(Value%100/10);
low=1; mid=1; high=1; display(Value%10);
}
void init(){ //初始化定时器T1和串口
SCON =0x50; //设置串口工作方式1,并打开接收中断
TMOD =0x20; //设置T1工作方式2
PCON =0x00; //设置SMOD为串口工作方式1
TL1 =0xf4;
TH1 =0xf4; //2400bps(11.0592MHZ的晶振)
TR1 =1; //开启时钟
ES =1; //开启串口中断允许
EA =1; //开启中断总允许
}
/**
发送数据
**/
void SendData(uchar value){
SBUF=value;
while(!TI);
TI=0;
}
int main(){
init();//初始化数据
while(1){
if(1==Received_Flag){//当单片机收到该数据后,将其送到数码管显示
ES=0;//将串口接收总中断关闭,因为发送数据的时候,往缓冲区内写数据也会引发串口接收中断。
SendData(‘o’);
SendData(‘k’);
ES=1;
Received_Flag=0;
}
//在此数据前加上一序号然后连同此数据一起发送至计算机,当序号超过255时归零。
DisplayNumByOrder(NumToDisplay); //在数码管上显示
}
return0;
}
//========函数区结束============================================
//========中断函数区============================================
/**
串口接收中断
**/
void ser_received() interrupt 4
{
if(RI ==1){//接收到触发中断
RI=0;//RI=1代表缓冲区内有数据,清零以便等待下次数据到来
Data_Received=(uchar)SBUF; //从缓冲区内读取数据
Received_Flag=1; //设置已经接收到数据
if(DecodeCount==0){
NumToDisplay=Data_Received;
++DecodeCount;
}else{
NumToDisplay =(NumToDisplay <<8)| Data_Received;//相当于原来的数乘以8,然后+现在的数
DecodeCount++;
if(DecodeCount ==3) //0..65536要接收6位的16进制
DecodeCount =0;
}
P1=~P1;
ReceiveCount++;
}
}
//========中断函数区结束==========================================
作者:kissazi2
出处:http://www.cnblogs.com/kissazi2/
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。