找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 6145|回復(fù): 3
收起左側(cè)

基于Matlab GUI的單片機(jī)串口與PC的通信 附源碼

[復(fù)制鏈接]
ID:436521 發(fā)表于 2018-11-30 14:38 | 顯示全部樓層 |閱讀模式
我也是最近學(xué)習(xí)單片機(jī)和MATLAB的小白平時(shí)在看學(xué)習(xí)的時(shí)候 下載了一些有價(jià)值的參考文獻(xiàn)
概述
  • 采用51單片機(jī),atmelSTC89C52RC芯片,主要用到的是七段數(shù)碼管用來做一個(gè)時(shí)鐘,程序編寫軟件為keil,燒錄軟件為STC-ISP 4.88,串口調(diào)試軟件用的是sscom42。
  • 運(yùn)用MatlabGUI工具編輯一個(gè)可視化界面,用以跟單片機(jī)進(jìn)行串口通信

實(shí)現(xiàn)功能
  • 運(yùn)用keil編寫時(shí)鐘程序,燒錄到單片機(jī)中,時(shí)鐘程序?qū)崿F(xiàn)的功能是實(shí)現(xiàn)時(shí)鐘的顯示,并且能用開發(fā)板上的三個(gè)按鈕進(jìn)行時(shí)鐘的修改,一個(gè)按鈕進(jìn)入修改模式,另兩個(gè)實(shí)現(xiàn)時(shí)間的增減。
  • 編輯GUI界面,實(shí)現(xiàn)對(duì)單片機(jī)的控制,其中,GUI界面通過串口能不斷的采樣開發(fā)板上時(shí)鐘的數(shù)值,并在GUI界面上進(jìn)行顯示。同樣的,可以通過GUI界面實(shí)現(xiàn)對(duì)開發(fā)板上時(shí)鐘的修改。
具體實(shí)現(xiàn)
  • 開發(fā)板部分:

B)  Matlab GUI界面的編輯
效果圖如下,操作說明:START點(diǎn)擊開始,采集單片機(jī)時(shí)鐘時(shí)間,ADJUST點(diǎn)擊進(jìn)入修改模式,同時(shí)單片機(jī)開發(fā)板亦會(huì)進(jìn)入修改模式,EXIT點(diǎn)擊關(guān)串口,退出界面,GET點(diǎn)擊獲取當(dāng)前值,另外一些輔助按鈕,滑塊按鈕都有各自功能,易于理解。
其中:
  • 添加控件,具體略
  • 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));
  • 調(diào)整時(shí)鐘 調(diào)整分鐘 調(diào)整秒鐘 都添加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. 開發(fā)板上的按鈕修改時(shí)鐘顯示

2. 開發(fā)板上時(shí)鐘顯示


3. START前的開發(fā)板以及GUI界面,此時(shí)GUI界面的時(shí)鐘無顯示
4. START點(diǎn)擊后GUI有了顯示,與開發(fā)板顯示一致

5. ADJUST點(diǎn)擊后進(jìn)入修改模式,開發(fā)板同步進(jìn)入修改模式,同時(shí)GUI保留當(dāng)前時(shí)間quondam time,隨后分別調(diào)整秒鐘 時(shí)鐘 分鐘,可以用編輯框,也可以用滑塊.
6. 點(diǎn)擊調(diào)整時(shí)鐘后,顯示調(diào)整結(jié)束。
7. 同時(shí),也可以用單片機(jī)上的按鈕調(diào)整時(shí)鐘,同時(shí)GUI會(huì)實(shí)時(shí)返回設(shè)置值



時(shí)鐘顯示程序如下(并且加入了串口接收部分)

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];                                //顯示緩沖區(qū)
unsigned char Second;                                            
unsigned char Minute;
unsigned char Hour;            
unsigned char count;            
bit Timer1sFlg;            
//函數(shù)聲明
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);  //動(dòng)態(tài)顯示
unsigned char GetKey(void);
/*——————————————————————————————主函數(shù)————————————————————————————————————————————
————————————————————————————————————————————————————————————————————————————————*/
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);                                                        
              }            
}
/*——————————————————————————————配置函數(shù)————————————————————————————————————————————
————————————————————————————————————————————————————————————————————————————————*/
void AT89S51Config(void)
{               TMOD|=0x20;                 //串口配置————————————————————————————————————————
    PCON&=0x7f;
    TH1=TL1=0xfd;
    TR1=1;
    SCON=0x50;                 //串口配置————————————————————————————————————————
              RCAP2H=0x0F;//T2定時(shí)器初值
    RCAP2L=0x00;
    ET2=1;//允許T2定時(shí)器中斷
    TR2=1;//啟動(dòng)T2定時(shí)器
    EA=1;//開總中斷
}
/*——————————————————————————————變量初始化————————————————————————————————————————————
————————————————————————————————————————————————————————————————————————————————*/
void VariableInitial(void)
{
              ShowState = 0;
              Second = 0;                                            
              Minute = 0;
              Hour   = 0;
              Timer1sFlg = 0;            
              count=0;
}               
/*——————————————————————————————延時(shí)函數(shù)————————————————————————————————————————————
————————————————————————————————————————————————————————————————————————————————*/
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)   //——————————給串口送數(shù)據(jù),  既給 matlab 送數(shù)據(jù)———————————————————————————
                  {                                                                               //———————————————————————————————————————————————————————           
                    SBUF=LEDBuffer[5-i];
                              while (!TI );                                                                                         //操作對(duì)象是TI
          TI=0 ;
                  }
                }                           
              }
              LEDBuffer[0] = Second % 10;                            //秒個(gè)位送顯示緩沖區(qū)
              LEDBuffer[1] = Second / 10;                            //秒十位送顯示緩沖區(qū)
              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;
                 }            
}
/*——————————————————————————————秒鐘調(diào)整————————————————————————————————————————————
————————————————————————————————————————————————————————————————————————————————*/
void ShowSecondAdj(void)
{              unsigned char i;
              TYPEDEF_KEY key;
              LEDBuffer[0] = Second % 10;                            //秒個(gè)位送顯示緩沖區(qū)
              LEDBuffer[1] = Second / 10;                            //秒十位送顯示緩沖區(qū)
              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)   //——————————給串口送數(shù)據(jù),  既給 matlab 送數(shù)據(jù)———————————————————————————
                  {                                                                               //———————————————————————————————————————————————————————           
                    SBUF=LEDBuffer[5-i];
                              while (!TI );                                                                                         //操作對(duì)象是TI
          TI=0 ;
                  }
                }
              if(RI==1)
              { RI=0;
                Second=SBUF;
      TI=0;
                LEDBuffer[0] = Second % 10;                            //秒個(gè)位送顯示緩沖區(qū)
                LEDBuffer[1] = Second / 10;                            //秒十位送顯示緩沖區(qū)
                ShowState = SHOW_MIN_ADJ;
                for(i=0;i<100;i++)
                {Display(LEDBuffer,6);}
                 }                                                      
}
/*——————————————————————————————分鐘調(diào)整————————————————————————————————————————————
————————————————————————————————————————————————————————————————————————————————*/
void ShowMinuteAdj(void)
{                           
    unsigned char i;

              TYPEDEF_KEY key;
              LEDBuffer[0] = LED_GOOUT;              //熄滅
              LEDBuffer[1] = LED_GOOUT;              //熄滅
              LEDBuffer[2] = Minute % 10;                            //分個(gè)位送顯示緩沖區(qū)
              LEDBuffer[3] = Minute / 10;                            //分十位送顯示緩沖區(qū)
              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;                            //秒個(gè)位送顯示緩沖區(qū)
                  LEDBuffer[1] = Second / 10;                            //秒十位送顯示緩沖區(qū)
                            LEDBuffer[4]=0;
                            LEDBuffer[5]=0;
                  if(TI==0)   //——————————給串口送數(shù)據(jù),  既給 matlab 送數(shù)據(jù)———————————————————————————
                  {                                                                               //———————————————————————————————————————————————————————           
                    SBUF=LEDBuffer[5-i];
                              while (!TI );                                                                                         //操作對(duì)象是TI
          TI=0 ;
                  }
                }
              if(RI==1)
              { RI=0;
                Minute=SBUF;
                LEDBuffer[2] = Minute % 10;                            //分個(gè)位送顯示緩沖區(qū)
                LEDBuffer[3] = Minute / 10;                            //分十位送顯示緩沖區(qū)
      TI=0;
                Display(LEDBuffer,6);            
            
              ShowState = SHOW_HOUR_ADJ;
              for(i=0;i<100;i++)
              {Display(LEDBuffer,6);
              }
                 }                                         
}
/*——————————————————————————————時(shí)鐘調(diào)整————————————————————————————————————————————
————————————————————————————————————————————————————————————————————————————————*/
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;                            //小時(shí)個(gè)位送顯示緩沖區(qū)
              LEDBuffer[5] = Hour / 10;                            //小時(shí)十位送顯示緩沖區(qū)
              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;                            //秒個(gè)位送顯示緩沖區(qū)
                  LEDBuffer[1] = Second / 10;                            //秒十位送顯示緩沖區(qū)
                  LEDBuffer[2] = Minute % 10;
                  LEDBuffer[3] = Minute / 10;
                  if(TI==0)   //——————————給串口送數(shù)據(jù),  既給 matlab 送數(shù)據(jù)———————————————————————————
                  {                                                                 //———————————————————————————————————————————————————————           
                    SBUF=LEDBuffer[5-i];
                              while (!TI );                                                                                         //操作對(duì)象是TI
          TI=0 ;
                  }
                }
              if(RI==1)
              { RI=0;
                Hour=SBUF;
      TI=0;
                LEDBuffer[4] = Hour % 10;                            //小時(shí)個(gè)位送顯示緩沖區(qū)
                LEDBuffer[5] = Hour / 10;                            //小時(shí)十位送顯示緩沖區(qū)
                             
                ShowState = SHOW_NORMAL;
                for(i=0;i<100;i++)
              {Display(LEDBuffer,6);;}
              }                                         
}
/*——————————————————————————————顯示函數(shù)————————————————————————————————————————————
————————————————————————————————————————————————————————————————————————————————*/
void Display(unsigned char * buf, unsigned char number)
{
              unsigned char i;
              for (i = 0; i < number; i++)
              {
                            LED_SELECT = 0x00;                                                        //關(guān)所有LED (防止出現(xiàn)閃爍現(xiàn)象)
                            LED_DATA = LEDMAP[*(buf + i)];              //送數(shù)據(jù)            
                            LED_SELECT = ~(1<<light[ i]);                                                         //顯示某1位數(shù)碼管,其余關(guān)閉            
                            Delay(90);                                                                                    // 延時(shí)約1ms,參數(shù)與晶振大小有關(guān)
              }
}
/*——————————————————————————————定時(shí)器五————————————————————————————————————————————
————————————————————————————————————————————————————————————————————————————————*/
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);                                          //去抖動(dòng)                                         
                            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單片機(jī)串口PC的通信.doc (5.82 MB, 下載次數(shù): 65)


評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:496651 發(fā)表于 2020-2-18 15:39 來自手機(jī) | 顯示全部樓層
謝謝分享!
回復(fù)

使用道具 舉報(bào)

ID:813351 發(fā)表于 2020-8-11 21:35 | 顯示全部樓層
你好,樓主,你的GUI里的text沒有28個(gè)吧,17個(gè)text,7個(gè)Pushbutton,1個(gè)edit?
回復(fù)

使用道具 舉報(bào)

ID:813351 發(fā)表于 2020-8-11 21:44 | 顯示全部樓層
說錯(cuò)了,20個(gè)text吧?
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表