PC与51单片机串口通信.docx
- 文档编号:26611502
- 上传时间:2023-06-20
- 格式:DOCX
- 页数:29
- 大小:384.92KB
PC与51单片机串口通信.docx
《PC与51单片机串口通信.docx》由会员分享,可在线阅读,更多相关《PC与51单片机串口通信.docx(29页珍藏版)》请在冰豆网上搜索。
PC与51单片机串口通信
PC与51单片机串口通信
串行通信是计算机和外设进行通讯、对外设进行监控并获取由外设采集到的监测数据的一个非常重要的手段。
由于其所用的传输线少,成本低,实现起来方便易行,因而得到广泛的应用。
STC89C52RC有一个可编程的全双工串行通信接口,可以方便的实现PC机与其之间的串行通信。
一、总体方案
系统中采用STC89C52RC/STC89C54RD+单片机作为下位机,PC机为上位机,二者通过CH340将PC的USB口转成RS232的串行口接收或上传数据。
单片机部分的程序采用C语言编程,用KeiluVision4编译后产生HEX文件下载到单片机内,从而实现数据收发。
PC端采用一个串口调试助手(sscom4.2)或MATLABGUI实现数据的收发。
二、具体方案
1、简单通信测试程序
本程序为了测试通信方式是否合适,以便于下一步增加程序的内容。
(1)利用STC提供STC-ISP-V4.83软件检查MCU选项
MCUTypeis:
STC89C54RD+
MCUFirmwareVersion:
3.2C
Chinese:
MCU固件版本号:
3.2C
Doublespeed/双倍速:
12T/单倍速
振荡放大器增益:
fullgain
下次下载时P1.0/P1.1与下载无关
内部扩展AUX-RAM:
允许访问(强烈推荐)
下次下载用户应用程序时将数据Flash区擦除:
NO
用户软件启动内部看门狗后:
复位关看门狗
ALEpin仍为ALE
内部时钟频率:
11.061806M
外部时钟频率:
11.061806M
(2)串行口初始参数设定
串行口工作方式为方式1(10位异步收发),波特率为9600bps,用定时器1作波特率发生器,选用定时器模式2,其它详见程序及说明。
(3)程序功能说明
通过串口调试助手,向单片机发送字符,发送字符的末尾需加“!
”,让单片机识别数据接收完毕,返回“Waitcommand!
”字符串。
当单片机接收一个字符时,发光二极管端引脚取反一次,所以其亮、灭的状态改变一次。
例如:
初始状态为灭。
当发送“12!
”时,取反三次,发光二极管变亮,返回“Waitcommand!
”字符串(如图
(1)所示);当发送“123!
”时,取反四次,发光二极管状态不变,但返回“Waitcommand!
”字符串(如图
(2)所示)。
图
(1)a图
(1)b
图
(2)a图
(2)b
(4)单片机内运行的程序
#include
sbitP1_2=P1^2;//接发光二极管
bitflag;//单片机数据发送标志位
bitflag_inter;//单片机数据接收完标志位
unsignedchara;
voidSendData(chardat);//发送字符
voidSendString(char*s);//发送字符串
voidmain()
{
SCON=0x50;//串行通信方式1,接收允许
PCON=0x00;//单倍频
TMOD=0x20;//设置定时器T1为模式2,定时方式
TH1=TL1=0xFD;//波特率为9600,晶振11.0594MHz
TR1=1;//定时器T1开始计数
EA=1;//中断允许
ES=1;//串行口中断开放
while
(1)
{
if(flag_inter==1)
{
flag_inter=0;//标志位清0
SendString("Waitcommand!
\n");
}
}
}
//串口接收发送中断
voidUart_Isr()interrupt4using1
{
if(RI)
{
RI=0;//接收中断标志
a=SBUF;
P1_2=!
P1_2;//数据送到P0口
if(a=='!
')
{
flag_inter=1;//数据接收完毕,置1
}
}
if(TI)
{
TI=0;//发送中断标志
flag=0;//标志位清0
}
}
//向串口发送字符
voidSendData(chardat)
{
while(flag);//等待数据发送
ACC=dat;
flag=1;//标志位置1
SBUF=ACC;//数据装入SBUF
}
//向串口发送字符串
voidSendString(char*s)
{
while(*s)//字符串发送完否
{
SendData(*s++);//发送字符,并指针指向下一字符
}
}
2、利用串口调试助手实现串行口数据收发
本程序可以实现PC机与单片机之间数据双向传输、互发
(注:
由CH37X451电路板原理图可知CH452数码管驱动及键盘控制芯片为四线接口,CH452_DCLK=P1^7,CH452_DIN=P1^6,CH452_LOAD=P1^5,CH452_DOUT=P3^3。
)
(1)利用STC提供STC-ISP-V4.83软件检查MCU选项
MCUTypeis:
STC89C52RC
MCUFirmwareVersion:
3.2C
Chinese:
MCU固件版本号:
3.2C
Doublespeed/双倍速:
12T/单倍速
振荡放大器增益:
fullgain
下次下载时P1.0/P1.1与下载无关
内部扩展AUX-RAM:
允许访问(强烈推荐)
下次下载用户应用程序时将数据Flash区擦除:
NO
用户软件启动内部看门狗后:
复位关看门狗
ALEpin仍为ALE
内部时钟频率:
24.011256M.
外部时钟频率:
24.011256M.
(2)串行口初始参数设定
串行口工作方式为方式1(10位异步收发),波特率为4800bps,用定时器1作波特率发生器,选用定时器模式2,其它详见程序及说明。
(3)程序功能说明
通过串口调试助手,向单片机发送字符,发送字符的末尾需加“!
”,让单片机识别数据接收完毕。
当单片机接收到PC机发来的数据时,先存入数组,当检测到结束标志“!
”时,调用显示函数,从左至右,两个LED数码管表示一位字符的ASCII码(注:
为了显示出特殊字符,所以用ASCII码表示)。
一次最多只能表示四个字符,当超过四个时,延时一段时间,再显示下面的字符。
数码管显示结束后,返回“Waitcommand!
”字符串。
当按下按键时,将按键对应的键值返回给PC机。
例如:
当在串口调试助手中发送“a=1,b=3,b>a!
”时,数码管将依次显示对应的十六进制ASCII码如下:
61H(a)、3dH(=)、31H
(1)、2cH(,)、62H(b)、3dH(=)、33H(3)、2cH(,)、62H(b)、3EH(>)、61H(a)、21H(!
),具体见图(3)。
当从左至右,从上到下依次按下键盘上的三行按键时,返回键值到PC机,具体见图(4)。
图(3)a图(3)b
图(3)c图(3)d
图(4)a图(4)b
(4)单片机内运行的程序
主程序如下:
#include
#include
#include
#include
bitflag;//标志位
bitflag_inter;//PC机发送信息结束标志位
unsignedcharm=0;//数组testdata[a]
unsignedchartestdata[20]={0};//存放PC机发送到单片机的信息
//输出命令子程序,定义一无符号整型变量存储12字节的命令字。
voidCH452_Write(unsignedintcmd)
{
unsignedchari;
#ifdefUSE_KEY
DISABLE_INTERRUPT;//禁止键盘中断,防止传输过程中被CH452中断
//进入中断服务程序中再次传输
#endif
CH452_LOAD_CLR;//命令开始,LOAD=0
for(i=0;i!
=12;i++)//送入12位数据,低位在前
{
if(cmd&1){CH452_DIN_SET;}
else{CH452_DIN_CLR;}//输出位数据
CH452_DCLK_CLR;
cmd>>=1;
CH452_DCLK_SET;//上升沿有效
}
CH452_LOAD_SET;//加载数据,LOAD上升沿
DELAY_1US;//命令数据加载周期不小于6US
DELAY_1US;
DELAY_1US;
DELAY_1US;
DELAY_1US;
DELAY_1US;
#ifdefUSE_KEY
ENABLE_INTERRUPT;
#endif
}
//输入命令子程序,MCU从CH452读一个字节
unsignedcharCH452_Read()
{
unsignedchari;
unsignedcharcmd,keycode;//定义命令字,和数据存储器
#ifdefUSE_KEY
DISABLE_INTERRUPT;//禁止键盘中断,防止传输过程中被CH452中断
//进入中断服务程序中再次传输
#endif
cmd=0x07;//输入读451命令字
CH452_LOAD_CLR;
for(i=0;i!
=4;i++)
{
if(cmd&1){CH452_DIN_SET;}
else{CH452_DIN_CLR;}//输出位数据
CH452_DCLK_CLR;
cmd>>=1;//往右移一位
CH452_DCLK_SET;//产生时钟上升沿锁通知CH451输入位数据
}
CH452_LOAD_SET;//产生加载上升沿通知CH451处理命令数据
keycode=0;//清除keycode
for(i=0;i!
=7;i++)
{
keycode<<=1;//数据移入keycode,高位在前,低位在后
keycode|=CH452_DOUT;//从高到低读入451的数据
CH452_DCLK_CLR;//产生时钟下升沿通知CH451输出下一位
CH452_DCLK_SET;
}
CLEAR_INTER_FLAG;//清中断标志
#ifdefUSE_KEY
ENABLE_INTERRUPT;
#endif
return(keycode);//反回键值
}
//延时函数
voiddelayms(unsignedchari)
{unsignedintj;
do{for(j=0;j!
=1000;j++)
{;}
}while(--i);
}
//串行通信初始设置子函数
voidinit(void)
{
SCON=0x50;//串行通信方式1,接收允许
PCON=0x00;//单倍频
TMOD=0x20;//设置定时器T1为模式2,定时方式
TH1=TL1=0xf3;//波特率为4800,晶振24MHz
TR1=1;//定时器T1开始计数
EA=1;//中断允许
ES=1;//串行口中断开放
}
//LED显示函数
voidDisplay(void)
{
unsignedcharn=0;
unsignedcharp;
unsignedchartestdata1;
unsignedchartestdata2;
unsignedchartestdata3;
unsignedchartestdata4;
unsignedchartestdata5;
unsignedchartestdata6;
unsignedchartestdata7;
unsignedchartestdata8;
CH452_Write(CH452_SYSON2);//两线制方式,如果SDA用做按键中断输出,//那么命令应该为(0x04,0x23)
CH452_Write(CH452_BCD);//BCD译码,8个数码管
while((4*n)<(m+1))
{
testdata1=testdata[0+4*n]%16;
testdata2=testdata[0+4*n]/16;
testdata3=testdata[1+4*n]%16;
testdata4=testdata[1+4*n]/16;
testdata5=testdata[2+4*n]%16;
testdata6=testdata[2+4*n]/16;
testdata7=testdata[3+4*n]%16;
testdata8=testdata[3+4*n]/16;
CH452_Write(CH452_DIG0|testdata7);//显示接收字符的ASCII码
CH452_Write(CH452_DIG1|testdata8);
CH452_Write(CH452_DIG2|testdata5);
CH452_Write(CH452_DIG3|testdata6);
CH452_Write(CH452_DIG4|testdata3);
CH452_Write(CH452_DIG5|testdata4);
CH452_Write(CH452_DIG6|testdata1);
CH452_Write(CH452_DIG7|testdata2);
delayms(1000);//延时
delayms(1000);
delayms(1000);
delayms(1000);
n++;
}
for(p=0;p<21;p++)//数组清零
{
testdata[p]=0;
}
m=0;
}
//串口接收发送中断
voidUart_Isr()interrupt4using1
{
if(RI)
{
RI=0;//接收中断标志
testdata[m]=SBUF;
if(testdata[m]=='!
')
{
Display();
flag_inter=1;
}
else
{
m++;
}
}
if(TI)
{
TI=0;//发送中断标志
flag=0;//标志位清零
}
}
//向串口发送字符
voidSendData(chardata0)
{
while(flag);//等待数据发送
ACC=data0;
flag=1;//标志位置1
SBUF=ACC;//数据装入SBUF
}
//向串口发送字符串
voidSendString(char*s)
{
while(*s)//字符串发送完否
{
SendData(*s++);//发送字符,并指针指向下一字符
}
}
//INT1中断服务程序
voidint1()interrupt2//using1
{
TI=0;
SBUF=CH452_Read();//将按键值通过串口发给PC机检查
while(!
TI);
TI=0;
}
voidmain()
{
delayms(10);//延时
init();//串口初始化函数
//设置CH452按键中断
IE1=0;//外部中断1中断请求标志
EX1=1;//外部中断1中断允许
while
(1)
{
if(flag_inter==1)
{
flag_inter=0;
SendString("Waitcommand!
\n");
}
}
}
附外加头文件:
(1)CH452CMD.h
#defineCH452_NOP0x0000//空操作
#defineCH452_RESET0x0201//复位
#defineCH452_LEVEL0x0100//加载光柱值
#defineCH452_CLR_BIT0x0180//段位清0
#defineCH452_SET_BIT0x01C0//段位置1
#defineCH452_SLEEP0x0202//进入睡眠状态
#defineCH452_LEFTMOV0x0300//设置移动方式-左移
#defineCH452_LEFTCYC0x0301//设置移动方式-左循
#defineCH452_RIGHTMOV0x0302//设置移动方式-右移
#defineCH452_RIGHTCYC0x0303//设置移动方式-右循
#defineCH452_SELF_BCD0x0380//自定义BCD码
#defineCH452_SYSOFF0x0400//关显示、键盘
#defineCH452_SYSON10x0401//开显示
#defineCH452_SYSON20x0403//开显示、键盘
#defineCH452_SYSON2W0x0423//开显示、键盘,真正2线接口
#defineCH452_DSP0x0500//设置默认显示方式
#defineCH452_BCD0x0580//设置BCD译码方式
#defineCH452_TWINKLE0x0600//设置闪烁控制
#defineCH452_GET_KEY0x0700//获取按键
#defineCH452_DIG00x0800//数码管位0显示
#defineCH452_DIG10x0900//数码管位1显示
#defineCH452_DIG20x0a00//数码管位2显示
#defineCH452_DIG30x0b00//数码管位3显示
#defineCH452_DIG40x0c00//数码管位4显示
#defineCH452_DIG50x0d00//数码管位5显示
#defineCH452_DIG60x0e00//数码管位6显示
#defineCH452_DIG70x0f00//数码管位7显示
(2)pin.h
/*延时1uS子程序,主要用于2线接口,与单片机速度有关*/
#defineDELAY_1US{_nop_();_nop_();}//MCS51<=30MHz
/*4线接口的连接,与实际电路有关*/
sbitCH452_DCLK=P1^7;//串行数据时钟上升延激活
sbitCH452_DIN=P1^6;//串行数据输出,接CH452的数据输入
sbitCH452_LOAD=P1^5;//串行命令加载,上升延激活
sbitCH452_DOUT=P3^3;//INT1,键盘中断和键值输入,接CH452的数据输出
/*4线接口的位操作,与单片机有关*/
#defineCH452_DCLK_SET{CH452_DCLK=1;}
#defineCH452_DCLK_CLR{CH452_DCLK=0;}
#defineCH452_DIN_SET{CH452_DIN=1;}
#defineCH452_DIN_CLR{CH452_DIN=0;}
#defineCH452_LOAD_SET{CH452_LOAD=1;}
#defineCH452_LOAD_CLR{CH452_LOAD=0;}
/*与单片机有关,与中断连接方式有关*/
#defineDISABLE_INTERRUPT{EX1=0;}
#defineENABLE_INTERRUPT{EX1=1;}
#defineCLEAR_INTER_FLAG{IE1=0;}
3、MATLAB控制数据收发
(1)利用STC提供STC-ISP-V4.83软件检查MCU选项(同2)
(2)串行口初始参数设定(同2)
(3)单片机内运行的程序(同2)
以上部分皆与“2、利用串口调试助手实现串行口数据收发”内容相同只是用MATLAB替代串口调试助手的功能。
(4)MATLAB数据收发功能实现简述
先用MATLABGUI画出所需窗口(如图(5)所示),并在系统生成的程序中设置串口通信参数及相关函数。
(注:
由于刚学MATLAB没几天,窗口设置较简单。
接收数据窗口,只能显示接收到字符的ASCII码;发送数据窗口会在数据前自动加控制字符“LF”,ASCII码为0AH。
这些不足都有待于进一步学习。
)
图(5)
当要发送数据时,在数据发送窗口输入所要发送的数据,点击发送。
同样,需在所要发送数据末尾加上“!
”,让单片机识别数据接收完,调用LED数码管显示程序,显示发送数据的ASCII码,然后返回“Waitcommand!
”字符串(PC机数据接收窗口显示其ASCII码),表示数据已接收且显示。
当单片机按下按键时,返回键值(PC机数据接收窗口显示键值的ASCII码)。
点击MATLAB收发窗口的关闭按钮,可以关闭此窗口。
例如:
MATLAB数据发送窗口输入“6789ABCD!
”,LED数码管依次显示
0AH(LF控制符)、36H(6)、37H(7)、38H(8)、39H(9)、20H(空格)、41H(A)、42H(B)、43H(C)、44H(D)、21H(!
),详见图(6)。
当按下最左侧的三个键@、H、x时,数据接收窗口依次显示40H(@)、48H(H)、78H(x),详见图(7)。
图(6)a图(6)b
图(6)c图(6)d
图(7)a图(7)b
图(7)c图(7)d
(5)MATLAB相关程序
functionvarargout=chuankoutongxingmatlab(varargin)
gui_Singleton=1;
gui_State=struct('gui_Name',mfilename,...
'gui_Singleton',gui_Singleton,...
'gui_OpeningFcn',...
@chuankoutongxingm
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- PC 51 单片机 串口 通信