PC与51单片机串口通信
更新时间:2023-08-09 23:43:01 阅读量: 工程科技 文档下载
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
PC与51单片机串口通信
串行通信是计算机和外设进行通讯、对外设进行监控并获取由外设采集到的监测数据的一个非常重要的手段。由于其所用的传输线少,成本低,实现起来方便易行,因而得到广泛的应用。STC89C52RC有一个可编程的全双工串行通信接口,可以方便的实现PC机与其之间的串行通信。
一、总体方案
系统中采用STC89C52RC/STC89C54RD+单片机作为下位机,PC机为上位机,二者通过CH340将PC的USB口转成RS232的串行口接收或上传数据。单片机部分的程序采用C语言编程,用Keil uVision4编译后产生HEX文件下载到单片机内,从而实现数据收发。PC端采用一个串口调试助手(sscom4.2)或MATLAB GUI实现数据的收发。
二、具体方案
1、简单通信测试程序
本程序为了测试通信方式是否合适,以便于下一步增加程序的内容。
(1)利用STC提供STC-ISP-V4.83软件检查MCU选项
MCU Type is: STC89C54RD+ MCU Firmware Version: 3.2C Chinese:MCU 固件版本号: 3.2C
Double speed / 双倍速: 12T/单倍速 振荡放大器增益: full gain 下次下载时 P1.0/P1.1 与下载无关
内部扩展AUX-RAM: 允许访问(强烈推荐) 下次下载用户应用程序时将数据Flash区擦除: NO 用户软件启动内部看门狗后: 复位关看门狗 ALE pin 仍为 ALE
内部时钟频率:11.061806M 外部时钟频率:11.061806M
(2)串行口初始参数设定
串行口工作方式为方式1(10位异步收发),波特率为9600bps,用定时器1作波特率发生器,选用定时器模式2,其它详见程序及说明。
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
(3)程序功能说明
通过串口调试助手,向单片机发送字符,发送字符的末尾需加“!”,让单片机识别数据接收完毕,返回“Wait command!”字符串。当单片机接收一个字符时,发光二极管端引脚取反一次,所以其亮、灭的状态改变一次。
例如:初始状态为灭。当发送“12!”时,取反三次,发光二极管变亮,返回“Wait command!”字符串(如图(1)所示);当发送“123!”时,取反四次,发光二极管状态不变,但返回“Wait command!”字符串(如图(2)所示)。
图(1)a 图(1)b
图(2)a 图(2)
b
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
(4)单片机内运行的程序
#include <reg51.h>
sbit P1_2=P1^2; //接发光二极管
bit flag; //单片机数据发送标志位 bit flag_inter; //单片机数据接收完标志位 unsigned char a;
void SendData(char dat);//发送字符 void SendString(char *s);//发送字符串
void main() {
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("Wait command!\n"); } } }
//串口接收发送中断
void Uart_Isr() interrupt 4 using 1 {
if (RI) {
RI=0; //接收中断标志 a=SBUF;
P1_2=!P1_2; //数据送到P0口 if(a=='!') {
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
flag_inter=1; //数据接收完毕,置1 } } if(TI) {
TI=0; //发送中断标志 flag=0; //标志位清0 } }
//向串口发送字符
void SendData(char dat) {
while(flag); ACC=dat;
flag=1; SBUF=ACC; }
//向串口发送字符串 void SendString(char *s) {
while(*s) {
SendData(*s++); } } //等待数据发送 //标志位置1 //数据装入SBUF //字符串发送完否 //发送字符,并指针指向下一字符
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
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选项
MCU Type is: STC89C52RC
MCU Firmware Version: 3.2C Chinese:MCU 固件版本号: 3.2C
Double speed / 双倍速: 12T/单倍速 振荡放大器增益: full gain 下次下载时 P1.0/P1.1 与下载无关
内部扩展AUX-RAM: 允许访问(强烈推荐) 下次下载用户应用程序时将数据Flash区擦除: NO 用户软件启动内部看门狗后: 复位关看门狗 ALE pin 仍为 ALE
内部时钟频率:24.011256M. 外部时钟频率:24.011256M.
(2)串行口初始参数设定
串行口工作方式为方式1(10位异步收发),波特率为4800bps,用定时器1作波特率发生器,选用定时器模式2,其它详见程序及说明。
(3)程序功能说明
通过串口调试助手,向单片机发送字符,发送字符的末尾需加“!”,让单片机识别数据接收完毕。当单片机接收到PC机发来的数据时,先存入数组,当检测到结束标志“!”时,调用显示函数,从左至右,两个LED数码管表示一位字符的ASCII码(注:为了显示出特殊字符,所以用ASCII码表示)。一次最多只能表示四个字符,当超过四个时,延时一段时间,再显示下面的字符。数码管显示结束后,返回“Wait command!”字符串。当按下按键时,将按键对应的键值返回给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)。
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
图(3)a 图(3)b
图(3)c 图(3)d
图(4)a 图(4)b
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
(4)单片机内运行的程序
主程序如下:
#include <reg51.h> #include <intrins.h>
#include <CH452CMD.h> #include <pin.h>
bit flag; //标志位
bit flag_inter; //PC机发送信息结束标志位
unsigned char m=0; //数组testdata[a]
unsigned char testdata[20]={0}; //存放PC机发送到单片机的信息
//输出命令子程序,定义一无符号整型变量存储12字节的命令字。 void CH452_Write(unsigned int cmd) { unsigned char i; #ifdef USE_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; #ifdef USE_KEY
ENABLE_INTERRUPT; #endif }
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
//输入命令子程序,MCU从CH452读一个字节 unsigned char CH452_Read() { unsigned char i;
unsigned char cmd,keycode; //定义命令字,和数据存储器 #ifdef USE_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; //清中断标志 #ifdef USE_KEY
ENABLE_INTERRUPT; #endif
return(keycode); //反回键值 }
//延时函数
void delayms(unsigned char i) { unsigned int j; do{ for(j=0;j!=1000;j++) {;} }while(--i); }
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
//串行通信初始设置子函数 void init(void) {
SCON=0x50; //串行通信方式1,接收允许 PCON=0x00; //单倍频
TMOD = 0x20; //设置定时器T1为模式2,定时方式 TH1=TL1=0xf3; //波特率为4800,晶振24MHz TR1=1; //定时器T1开始计数 EA=1; //中断允许
ES=1; //串行口中断开放 }
//LED显示函数 void Display(void) {
unsigned char n=0; unsigned char p;
unsigned char testdata1; unsigned char testdata2; unsigned char testdata3; unsigned char testdata4; unsigned char testdata5; unsigned char testdata6; unsigned char testdata7; unsigned char testdata8;
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;
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
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; }
//串口接收发送中断
void Uart_Isr() interrupt 4 using 1 {
if(RI) { RI=0; testdata[m]=SBUF; if(testdata[m]=='!') { Display(); flag_inter=1; } else { m++; } } if(TI)
//延时 //数组清零 //接收中断标志
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
{
TI=0; //发送中断标志 flag=0; //标志位清零 } }
//向串口发送字符
void SendData(char data0) {
while(flag); ACC=data0;
flag=1; SBUF=ACC; }
//向串口发送字符串 void SendString(char *s) {
while(*s) {
SendData(*s++); } }
// INT1中断服务程序
void int1() interrupt 2 //using 1 {
TI=0;
SBUF=CH452_Read(); while(!TI); TI=0; }
void main() { delayms(10); init(); //等待数据发送 //标志位置1 //数据装入SBUF //字符串发送完否 //发送字符,并指针指向下一字符 //将按键值通过串口发给PC机检查 //延时 //串口初始化函数
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
// 设置CH452按键中断
IE1=0; //外部中断1 中断请求标志 EX1=1; //外部中断1中断允许 while(1) { if(flag_inter==1) { flag_inter=0; SendString("Wait command!\n"); } } }
附外加头文件: (1)CH452CMD.h
#define CH452_NOP 0x0000 #define CH452_RESET 0x0201 #define CH452_LEVEL 0x0100 #define CH452_CLR_BIT 0x0180 #define CH452_SET_BIT 0x01C0 #define CH452_SLEEP 0x0202 #define CH452_LEFTMOV 0x0300 #define CH452_LEFTCYC 0x0301 #define CH452_RIGHTMOV 0x0302 #define CH452_RIGHTCYC 0x0303 #define CH452_SELF_BCD 0x0380 #define CH452_SYSOFF 0x0400 #define CH452_SYSON1 0x0401 #define CH452_SYSON2 0x0403 #define CH452_SYSON2W 0x0423 #define CH452_DSP 0x0500 #define CH452_BCD 0x0580 #define CH452_TWINKLE 0x0600 #define CH452_GET_KEY 0x0700 #define CH452_DIG0 0x0800 #define CH452_DIG1 0x0900 #define CH452_DIG2 0x0a00 #define CH452_DIG3 0x0b00 #define CH452_DIG4 0x0c00 #define CH452_DIG5 0x0d00 #define CH452_DIG6 0x0e00 #define CH452_DIG7 0x0f00
// 空操作 // 复位 // 加载光柱值 // 段位清0 // 段位置1 // 进入睡眠状态 //设置移动方式-左移 //设置移动方式-左循 //设置移动方式-右移 //设置移动方式-右循 //自定义BCD码 //关显示、键盘 //开显示 //开显示、键盘 //开显示、键盘, 真正2线接口 //设置默认显示方式 //设置BCD译码方式 //设置闪烁控制 // 获取按键 //数码管位0显示 //数码管位1显示 //数码管位2显示 //数码管位3显示 //数码管位4显示 //数码管位5显示 //数码管位6显示 //数码管位7显示
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
(2)pin.h
/* 延时1uS子程序,主要用于2线接口,与单片机速度有关 */ #define DELAY_1US {_nop_();_nop_();} // MCS51<=30MHz
/* 4线接口的连接,与实际电路有关 */
sbit CH452_DCLK=P1^7; // 串行数据时钟上升延激活 sbit CH452_DIN=P1^6; // 串行数据输出,接CH452的数据输入 sbit CH452_LOAD=P1^5; // 串行命令加载,上升延激活
sbit CH452_DOUT=P3^3; // INT1,键盘中断和键值输入,接CH452的数据输出
/* 4线接口的位操作,与单片机有关 */ #define CH452_DCLK_SET {CH452_DCLK=1;} #define CH452_DCLK_CLR {CH452_DCLK=0;} #define CH452_DIN_SET {CH452_DIN=1;} #define CH452_DIN_CLR {CH452_DIN=0;} #define CH452_LOAD_SET {CH452_LOAD=1;} #define CH452_LOAD_CLR {CH452_LOAD=0;}
/* 与单片机有关,与中断连接方式有关 */ #define DISABLE_INTERRUPT {EX1=0;} #define ENABLE_INTERRUPT {EX1=1;} #define CLEAR_INTER_FLAG {IE1=0;}
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
3、MATLAB控制数据收发
(1)利用STC提供STC-ISP-V4.83软件检查MCU选项(同2) (2)串行口初始参数设定(同2) (3)单片机内运行的程序(同2)
以上部分皆与“2、利用串口调试助手实现串行口数据收发”内容相同只是用MATLAB替代串口调试助手的功能。
(4)MATLAB数据收发功能实现简述
先用MATLAB GUI画出所需窗口(如图(5)所示),并在系统生成的程序中设置串口通信参数及相关函数。
(注:由于刚学MATLAB没几天,窗口设置较简单。接收数据窗口,只能显示接收到字符的ASCII码;发送数据窗口会在数据前自动加控制字符“LF,”ASCII码为0AH。这些不足都有待于进一步学习。)
图(5)
当要发送数据时,在数据发送窗口输入所要发送的数据,点击发送。同样,需在所要发送数据末尾加上“!”,让单片机识别数据接收完,调用LED数码管显示程序,显示发送数据的ASCII码,然后返回“Wait command!”字符串(PC机数据接收窗口显示其ASCII码),表示数据已接收且显示。当单片机按下按键时,返回键值(PC机数据接收窗口显示键值的ASCII码)。点击MATLAB
收发窗口的
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
关闭按钮,可以关闭此窗口。
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
例如:MATLAB数据发送窗口输入“6789 ABCD!”,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
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
图(7)a 图(7)b
图(7)c 图(7)d
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
(5)MATLAB相关程序
function varargout = chuankoutongxingmatlab(varargin) gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ... 'gui_OpeningFcn', ...
@chuankoutongxingmatlab_OpeningFcn, ...
'gui_OutputFcn', ...
@chuankoutongxingmatlab_OutputFcn, ...
'gui_LayoutFcn', [] , ... 'gui_Callback', []); if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1}); end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); else
gui_mainfcn(gui_State, varargin{:}); end
% --- Executes just before chuankoutongxingmatlab is made visible.
function chuankoutongxingmatlab_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject; global data; global port; try
%设置串口 handles.s=serial('COM7','BaudRate',4800,'Parity','none',...
'DataBits',8,'StopBits',1);%建立串口对象
port=handles.s;
set(handles.s,'OutputBufferSize',512);%设置输出缓冲区大小 set(handles.s,'InputBufferSize',1024);%设置输入缓冲区大小
set(handles.s,'BytesAvailableFcnMode','byte');%设置BytesAvailableFcnMode属性 set(handles.s,'BytesAvailableFcnCount',1);
set(handles.s,'BytesAvailableFcn',{@mycallback,handles});
%定义Bytes-Available事件回调函数
fopen(handles.s); catch
%进行出错处理 errmsg = lasterr;
errordlg(['不能打开串口: COM7',char(10),...
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
'请检查串口连接或串口已打开'],'串口打开错误');
rethrow(lasterror); end
guidata(hObject, handles);
% --- Outputs from this function are returned to the command line. function varargout = chuankoutongxingmatlab_OutputFcn...
(hObject, eventdata, handles)
varargout{1} = handles.output;
% --- Executes on button press in pushbutton2.
function pushbutton2_Callback(hObject, eventdata, handles) delete(handles.figure1);%关闭对话框
% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles) global port; global data;
data=get(handles.edit2,'string'); fprintf(port,data);
function edit2_Callback(hObject, eventdata, handles)
% --- Executes during object creation, after setting all properties. function edit2_CreateFcn(hObject, eventdata, handles) if ispc && isequal(get(hObject,'BackgroundColor'),...
get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white'); end
function edit1_Callback(hObject, eventdata, handles)
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
% --- Executes during object creation, after setting all properties. function edit1_CreateFcn(hObject, eventdata, handles) if ispc && isequal(get(hObject,'BackgroundColor'),...
get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white'); end
function mycallback(obj,event,handles)%接收事件回调函数 global rcv; global str;
if handles.s.BytesAvailable>0
rcv=fread(handles.s, handles.s.BytesAvailable,'uint8');%数据读取 str=sprintf('%3X',rcv);%以大写十六进制ASCII码显示,每个占三位 set(handles.edit1,'String',str); end
% --- Executes during object deletion, before destroying properties. function figure1_DeleteFcn(hObject, eventdata, handles) fclose(handles.s);%关闭串口连接 delete(handles.s);%删除串口对象 clear all;%清除所有
PC与51单片机串口通信。包括单片机内运行的程序,及MATLAB调试助手简易程序等!
三、小结
PC与单片机间的串口通信的科研训练,要求实验时能实现简单的通信工作,对于从未具体操作过相关实物的我来说收获很大。
首先,对51系列单片机的通用部分及具体不同的产品差异有了一定了解。通过查阅具体单片机产品手册,可得知其中通用及差异部分,为实现目的可以有不同的方法,不同单片机也存在着自己独有的优势。
由于对MATLAB有了一点接触,感到其功能十分强大,对许多问题实现和解决较为便捷。短短几天的了解,为我进一步学习打下了基础。同时,也进一步熟悉Keil uVision4的部分功能。
本次训练中收获许多对实际问题解决方法,发现程序编译没有问题到能真正实现所要功能还有很长一段路。期间,需要不断调试,一点一点找出错误。而且,需要对不同情况进行测试,直到没有问题位置。所以这次的对具体问题的训练,让我获益匪浅,会让我以后的学习简单很多。接下来我会继续学习相关知识,为毕业设计做好准备。
最后,感谢杨老师在此次科研训练中给予我的巨大帮助!
正在阅读:
PC与51单片机串口通信08-09
“动-定序贯八法”与中医临床思维-广东省中医院(范冠杰)-洛阳09-06
建筑制图与识图教案绪论09-03
预制梁场建设方案(完成版)09-21
员工忠诚度与执行力系统解决方案 - 图文07-01
第一次比赛作文500字06-24
钢铁冶金(炼铁部分)重点 - 图文11-12
中科院-中科大1998试卷及答案10-24
自动扶梯和自动人行道试题11111-16
性格特征及自我评价02-24
- 尿酸偏高的原因
- 七上记叙文知识能力侧重点
- 计算机专业的职业生涯规划书范文
- 12 司马迁发愤写《史记》
- 马克西姆音乐会网络宣传策划案
- 山东丝绸纺织职业学院
- ch 8空间解析几何与向量代数
- 数据库系统概论期末试题及答案(重点知识)
- 基于PLC的电梯控制系统文献
- 新概念英语考试第一册期末试卷
- 浅谈高效课堂中的讲练结合
- 高二化学烃的衍生物知识总结
- 公路工程路基路面雨季施工技术探讨
- 诗歌朗诵技巧
- 三相交流系统短路电流计算
- 计算机科学与技术导论论文
- 经营副总岗位职责
- 5G、半导体等行业用关键材料,最急迫的国产替代领域!20亿小市值却是最纯正的技术突破先锋,产品已批量供货中芯国际;机构龙虎榜疯狂扫货,此板块是6月唯一一场主升浪!——0605脱水研报
- 用列举法解决问题(2)
- shRNA详细原理及引物设计