数字信号处理2012电子信息工程专业答辩报告姓名杨全任伟学号********* *********成绩Matlab与51单片机的串口通信一、简介从Matlab6.0版本开始,Mathworks公司在软件中增加了设备控制箱(instrument control toolbox),提供了对RS-232/RS-485通信标准串口(九针串口)通信正式支持(本实验采用USB转串口)利用该工具箱serial类及instrcallback()回调函数,能可靠地进行实时串地通信。
Matlab支持面向对象技术,用一个对象将计算机串口封装起来,只要创建串口对象,对串口对象操作就是对串口操作,非常方便。
使用serial函数就可创建串口对象,通过定义串口对象的属性,能定义串口的通信模式,从串口对象属性也能了解串口的状态,即可以通过MATLAB的串口通讯函数读写数据。
二、 Matlab串口函数serial 创建一个串口对象,格式:s = serial('coml' )fopen 打开串口对象,格式:fopen(s)fwrite 其他程序能对该串口进行读写操作fwrite(s,’’)fread 读取串口数据,格式: fread(s)fclose 关闭串口对象,格式:fclose(s)free 解除Matlab对串口对象的控制,使delete 删除对象s,格式:delete(s)clear 从工作空间中删除对象s,格式:clear(s)三、实现功能利用MATLAB串口通信函数,读写51单片机(STC89C52R+)数据,运用keil编写时钟程序,烧录到单片机中,时钟程序实现的功能是实现时钟的显示,并且能用开发板上的三个按钮进行时钟的修改,一个按钮进入修改模式(复位),另两个实现时间的增减。
编辑MATLAB程序,实现对单片机的控制。
读写串口操作。
初始化并打开串口调协对象之后,现在可以对串口设备对象进行读写操作,串口读写操作支持二进制和文本(ASCII)两种方式。
当Matlab通信数据采用西方(ASCII)方式时,读写串口设备命令分别是fscanf、fpritf;当Matlab通信数据采用二进制方式时,读写串口设备命令分别是fread、fwrite。
四、具体实现4.1开发板4.2 实现流程先创建创建串口设备对象,配置串口初始化的对象属性,连接窗口物理设备(开发板),写发送通信握手信号;进行读写操作(串口发送接收数据)。
4.3 时钟程序见附录(添加串口接收部分)4.4 Matlab的操作如下%%%%%%默认COM4属性设置%%%%%s=serial('com4')%开启串口COM4的函数并设置属性Serial Port Object : Serial-COM4Communication SettingsPort: COM4BaudRate: 9600Terminator: 'LF'Communication StateStatus: closedRecordStatus: offRead/Write StateTransferStatus: idleBytesAvailable: 0ValuesReceived: 0ValuesSent: 0>> fopen(s);%打开s(COM4串口)>> fwrite(s,'00000000')>> fwrite(s,'00000000')%显示清零;及时拍下数码管显示如下图fwrite(s,'00 0C FE')%数码管显示00010及时拍下数码管显示如下图>> fwrite(s,'00 0C FE')%写入数据>> v=fread(s,30); %读取前30个数据>> dec2hex(v) %转换成16进制输出ans =8080A0888080A889808008808080MATLAB串口输出的数据与串口输出的数据作比较可以发现读取的数据一样,由于时钟程序反馈的数是变化的所以不能够比较准确的将它们一个不差的比较出来。
五、总结:用MATLAB的串口功能与一般的串口调试助手的功能是一样的,都能准确的读写数据,可以接受和发送一般十六进制的数。
总的来说本实验还有一些要改的地方比如说,在51程序的设计方面有些地方编写的不太好(基本功能:波特率9600,发出十六进制的数据,触发串口中断,接收十六进制数完成功能调试),用MATLAB串口和超级串口来接收和发送数据的时候不太理想,会出现一些误差使得反馈值计算错误,由于MATLAB的GUI(图形用户界面)的设计上知识的不足没能完成,如果编写好回调函数,使用MA TLAB的GUI 做一个电子时钟显示就更好了。
六、附录51程序(添加串口发送和接收功能可以进行MATLAB的GUI设计)#include <REGX52.H>#define LED_SELECT P2// 数码管位选#define LED_DATA P0// 数码管段选#define KEY_PIN P3// 定义按键接口//变量定义和单片机引脚unsigned char light[]={1,2,3,4,5,6,7,8};//数码管位选static unsigned char count_1s=0 ;typedef enum{NULL, KEY_ENTER, KEY_UP, KEY_DOWN}TYPEDEF_KEY;enum SHOW_STATE{SHOW_NORMAL, SHOW_SEC_ADJ, SHOW_MIN_ADJ,SHOW_HOUR_ADJ,}ShowState;unsigned char code LEDMAP[] = //共阴极数码管显示段选代码{/*0xc0, 0xf9, 0xa4, 0xb0, 0x99,0x92, 0x82, 0xf8, 0x80, 0x90,*/0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0xff, //熄灭};enum{LED_GOOUT = 10,};unsigned char LEDBuffer[6]; //显示缓冲区unsigned char Second;unsigned char Minute;unsigned char Hour;unsigned char count;bit Timer1sFlg;/*--------------------函数声明----------------*/void AT89S51Config(void);void VariableInitial(void);void ShowNormal(void);void ShowSecondAdj(void);void ShowMinuteAdj(void);void ShowHourAdj(void);void Delay(unsigned int t);void Display(unsigned char * buf, unsigned char number); //动态显示unsigned char GetKey(void);/*------------------------------主函数-----------*/main(void){AT89S51Config(); //AT89S51配置VariableInitial(); //变量初始化while(1){switch(ShowState){case SHOW_NORMAL:ShowNormal();break;case SHOW_SEC_ADJ:ShowSecondAdj();break;case SHOW_MIN_ADJ:ShowMinuteAdj();break;case SHOW_HOUR_ADJ:ShowHourAdj();break;default:break;}Display(LEDBuffer,6);}}/*---------------------------配置函数---------*/ void AT89S51Config(void){ TMOD|=0x20; //串口配置PCON&=0x7f;TH1=TL1=0xfd;TR1=1;SCON=0x50; //串口配置RCAP2H=0x0F; //T2定时器初值RCAP2L=0x00;ET2=1;//允许T2定时器中断TR2=1;//启动T2定时器EA=1;//开总中断}/*------------------------------变量初始化----------*/ void VariableInitial(void){ShowState = 0;Second = 0;Minute = 0;Hour = 0;Timer1sFlg = 0;count=0;}/*------------------------------延时函数-----------*/ void Delay(unsigned int t){for (t; t>0; t--) ;}/*------------------------正常显示界面-----------*/ void ShowNormal(void){ unsigned char i;TYPEDEF_KEY key;//1秒钟到,显示值更新if(Timer1sFlg){Timer1sFlg = 0;Second++;if(Second >= 60){Second = 0;Minute ++;if(Minute >= 60){Minute = 0;Hour ++;if(Hour >= 24){Hour = 0;}}}for(i=0;i<6;i++){if(TI==0) //--给串口送数据,给 matlab发送数据 {SBUF=LEDBuffer[5-i];while (!TI ); //操作对象是TITI=0 ;}}}LEDBuffer[0] = Second % 10; //秒个位送显示缓冲区LEDBuffer[1] = Second / 10; //秒十位送显示缓冲区LEDBuffer[2] = Minute % 10;LEDBuffer[3] = Minute / 10;LEDBuffer[4] = Hour % 10;LEDBuffer[5] = Hour / 10;key = GetKey();if(key == KEY_ENTER){ShowState = SHOW_SEC_ADJ;}if(RI==1){RI=0;TI=0;ShowState = SHOW_SEC_ADJ;}}/*------------------------------秒钟调整-----------*/ void ShowSecondAdj(void){ unsigned char i;TYPEDEF_KEY key;LEDBuffer[0] = Second % 10; //秒个位送显示缓冲区LEDBuffer[1] = Second / 10; //秒十位送显示缓冲区LEDBuffer[2] = LED_GOOUT; //熄灭LEDBuffer[3] = LED_GOOUT; //熄灭LEDBuffer[4] = LED_GOOUT; //熄灭LEDBuffer[5] = LED_GOOUT; //熄灭Display(LEDBuffer,6);key = GetKey();switch(key){case KEY_ENTER:ShowState = SHOW_MIN_ADJ;break;case KEY_UP:Second++;if(60 == Second){Second = 0;}break;case KEY_DOWN:if(0 == Second){Second = 59;}else{Second--;}break;}for(i=0;i<6;i++){LEDBuffer[2]=0;LEDBuffer[3]=0;LEDBuffer[4]=0;LEDBuffer[5]=0;if(TI==0) //----------给串口送数据,给 matlab发送数据 {SBUF=LEDBuffer[5-i];while (!TI ); //操作对象是TITI=0 ;}}if(RI==1){ RI=0;Second=SBUF;TI=0;LEDBuffer[0] = Second % 10; //秒个位送显示缓冲区 LEDBuffer[1] = Second / 10; //秒十位送显示缓冲区 ShowState = SHOW_MIN_ADJ;for(i=0;i<100;i++){Display(LEDBuffer,6);}}}/*------------------------------分钟调整-----------*/void ShowMinuteAdj(void){unsigned char i;TYPEDEF_KEY key;LEDBuffer[0] = LED_GOOUT; //熄灭LEDBuffer[1] = LED_GOOUT; //熄灭LEDBuffer[2] = Minute % 10; //分个位送显示缓冲区LEDBuffer[3] = Minute / 10; //分十位送显示缓冲区LEDBuffer[4] = LED_GOOUT; //熄灭LEDBuffer[5] = LED_GOOUT; //熄灭Display(LEDBuffer,6);key = GetKey();switch(key){case KEY_ENTER:ShowState = SHOW_HOUR_ADJ;break;case KEY_UP:Minute++;if(60 == Minute){Minute = 0;}break;case KEY_DOWN:if(0 == Minute){Minute = 59;}else{Minute--;}break;}for(i=0;i<6;i++){LEDBuffer[0] = Second % 10; //秒个位送显示缓冲区LEDBuffer[1] = Second / 10; //秒十位送显示缓冲区LEDBuffer[4]=0;LEDBuffer[5]=0;if(TI==0) //----------给串口送数据,给 matlab发送数据{SBUF=LEDBuffer[5-i];while (!TI ); //操作对象是TI TI=0 ;}}if(RI==1){ RI=0;Minute=SBUF;LEDBuffer[2] = Minute % 10; //分个位送显示缓冲区 LEDBuffer[3] = Minute / 10; //分十位送显示缓冲区 TI=0;Display(LEDBuffer,6);ShowState = SHOW_HOUR_ADJ;for(i=0;i<100;i++){Display(LEDBuffer,6);}}}/*------------------------------时钟调整-----------*/void ShowHourAdj(void){ unsigned char i;TYPEDEF_KEY key;LEDBuffer[0] = LED_GOOUT; //熄灭LEDBuffer[1] = LED_GOOUT; //熄灭LEDBuffer[2] = LED_GOOUT; //熄灭LEDBuffer[3] = LED_GOOUT; //熄灭LEDBuffer[4] = Hour % 10; //小时个位送显示缓冲区Display(LEDBuffer,6);key = GetKey();switch(key){case KEY_ENTER:ShowState = SHOW_NORMAL;break;case KEY_UP:Hour++;if(24 == Hour){Hour = 0;}break;case KEY_DOWN:if(0 == Hour){Hour = 23;}else{Hour--;}break;}for(i=0;i<6;i++){LEDBuffer[0] = Second % 10; //秒个位送显示缓冲区LEDBuffer[2] = Minute % 10;LEDBuffer[3] = Minute / 10;if(TI==0) //----------给串口送数据,给 matlab 发送数据 {SBUF=LEDBuffer[5-i];while (!TI ); //操作对象是TITI=0 ;}}if(RI==1){RI=0;Hour=SBUF;TI=0;LEDBuffer[4] = Hour % 10; //小时个位送显示缓冲区LEDBuffer[5] = Hour / 10; //小时十位送显示缓冲区ShowState = SHOW_NORMAL;for(i=0;i<100;i++){Display(LEDBuffer,6);;}}}/*------------------------------显示函数-----------*/void Display(unsigned char * buf, unsigned char number){unsigned char i;for (i = 0; i < number; i++){LED_SELECT = 0x00; //关所有LED (防止出现闪烁现象)LED_DATA = LEDMAP[*(buf + i)]; //送数据LED_SELECT = ~(1<<light[i]); //显示某1位数码管,其余关闭Delay(90); // 延时约1ms,参数与晶振大小有关}}/*------------------------------定时器五-----------*/Timer2_server(void) interrupt 5{TF2=0;count_1s++;if(20 == count_1s){Timer1sFlg = 1;count_1s =0;}}/*------------------------------得到按键值-----------*/TYPEDEF_KEY GetKey(void){TYPEDEF_KEY key = NULL;if( ~KEY_PIN & 0x1c) //有键按下{Delay(1000); //去抖动if(~KEY_PIN & 0X04){key = KEY_ENTER;}else if(~KEY_PIN & 0X08){key = KEY_UP;}else if(~KEY_PIN & 0X10){key = KEY_DOWN;}else{return(NULL);}while(KEY_PIN != 0XFF) //等待键抬起{Delay(2);}return(key);}return(NULL);}数字信号处理课程报告答辩记录。