找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5444|回复: 3
收起左侧

基于Matlab GUI的单片机串口与PC的通信 附源码

[复制链接]
ID:436521 发表于 2018-11-30 14:38 | 显示全部楼层 |阅读模式
我也是最近学习单片机和MATLAB的小白平时在看学习的时候 下载了一些有价值的参考文献
概述
  • 采用51单片机,atmelSTC89C52RC芯片,主要用到的是七段数码管用来做一个时钟,程序编写软件为keil,烧录软件为STC-ISP 4.88,串口调试软件用的是sscom42
  • 运用MatlabGUI工具编辑一个可视化界面,用以跟单片机进行串口通信

实现功能
  • 运用keil编写时钟程序,烧录到单片机中,时钟程序实现的功能是实现时钟的显示,并且能用开发板上的三个按钮进行时钟的修改,一个按钮进入修改模式,另两个实现时间的增减。
  • 编辑GUI界面,实现对单片机的控制,其中,GUI界面通过串口能不断的采样开发板上时钟的数值,并在GUI界面上进行显示。同样的,可以通过GUI界面实现对开发板上时钟的修改。
具体实现
  • 开发板部分:

B)  Matlab GUI界面的编辑
效果图如下,操作说明:START点击开始,采集单片机时钟时间,ADJUST点击进入修改模式,同时单片机开发板亦会进入修改模式,EXIT点击关串口,退出界面,GET点击获取当前值,另外一些辅助按钮,滑块按钮都有各自功能,易于理解。
其中:
  • 添加控件,具体略
  • START添加callback
   global s
   s=serial('COM10');
   fopen(s);
   handles.timer = timer('TimerFcn',{@mycallback,handles},    'Period',0.01,'ExecutionMode','FixedRate');
   start(handles.timer);

  • ADJUST添加callback
a=get(handles.text8,'String');
set(handles.text28,'String',a);
a=get(handles.text10,'String');
set(handles.text27,'String',a);
a=get(handles.text13,'String');
set(handles.text25,'String',a);
a=get(handles.text14,'String');
set(handles.text24,'String',a);
a=get(handles.text15,'String');
set(handles.text22,'String',a);
a=get(handles.text16,'String');
set(handles.text21,'String',a);
global s
fwrite(s,0);
  • EXIT添加callback
global s
fclose(s);
close;
  • GET添加callback
global s
a=fread(s,6);
set(handles.text8,'String',a(6));
set(handles.text10,'String',a(5));
set(handles.text13,'String',a(4));
set(handles.text14,'String',a(3));
set(handles.text15,'String',a(2));
set(handles.text16,'String',a(1));
  • 调整时钟 调整分钟 调整秒钟 都添加callback
global s
a=str2num(get(handles.edit1,'String'));
fwrite(s,a);
  • SLIDER1添加callback
a=get(handles.slider1,'value');
set(handles.edit1,'String',a);

C)操作说明
1. 开发板上的按钮修改时钟显示

2. 开发板上时钟显示


3. START前的开发板以及GUI界面,此时GUI界面的时钟无显示
4. START点击后GUI有了显示,与开发板显示一致

5. ADJUST点击后进入修改模式,开发板同步进入修改模式,同时GUI保留当前时间quondam time,随后分别调整秒钟 时钟 分钟,可以用编辑框,也可以用滑块.
6. 点击调整时钟后,显示调整结束。
7. 同时,也可以用单片机上的按钮调整时钟,同时GUI会实时返回设置值



时钟显示程序如下(并且加入了串口接收部分)

Main.c
#include <REGX52.H>
#define LED_SELECT P2                           
#define LED_DATA   P0
#define KEY_PIN    P3
//变量定义
unsigned char light[]={3,2,0,7,5,4,1,6};
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,            
              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 );                                                                                         //操作对象是TI
          TI=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 );                                                                                         //操作对象是TI
          TI=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;                            //小时个位送显示缓冲区
              LEDBuffer[5] = 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[1] = Second / 10;                            //秒十位送显示缓冲区
                  LEDBuffer[2] = Minute % 10;
                  LEDBuffer[3] = Minute / 10;
                  if(TI==0)   //——————————给串口送数据,  既给 matlab 送数据———————————————————————————
                  {                                                                 //———————————————————————————————————————————————————————           
                    SBUF=LEDBuffer[5-i];
                              while (!TI );                                                                                         //操作对象是TI
          TI=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);            
}

完整的Word格式文档51黑下载地址:
Matlab的GUI单片机串口PC的通信.doc (5.82 MB, 下载次数: 65)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:496651 发表于 2020-2-18 15:39 来自手机 | 显示全部楼层
谢谢分享!
回复

使用道具 举报

ID:813351 发表于 2020-8-11 21:35 | 显示全部楼层
你好,楼主,你的GUI里的text没有28个吧,17个text,7个Pushbutton,1个edit?
回复

使用道具 举报

ID:813351 发表于 2020-8-11 21:44 | 显示全部楼层
说错了,20个text吧?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表