這一篇文章是我前一篇文章的續集,主要是爲了彌補 CCS無法實時捕捉數據至上位機的缺陷(可能CCS有,但是我卻沒找到,如果有讀者知道具體答案,請留言告訴我。)。當然串口傳輸來的數據也有不足的地方,就是這些數據只能讓我們感性的觀看,如果想做數據分析,如FFT等,可能數據的採樣精度就不夠了。所以這也是一個不足的地方,希望日後能有解決的辦法。下面開始正文部分吧!
廢話不多說,先來張效果圖:
圖1是DSP_demo板加Lcd12864的顯示。顯示的比較粗糙,026.56就是26.56℃,一些細節沒有做好,主要是功能的實現。
圖2是使用Matlab2017b的AppDesigner製作的串口通信上位機軟件,具體功能有:發送(TX)、接收(RX)、實時繪圖、數據實時保存等。其中COM口和波特率需要設置,其他的如:數據位、校驗位、停止位等等,已經在代碼中默認設置了,因爲只是這個小設計的定製版本,也沒有高興將所有功能都全部放置在界面上。
圖像中,出現了34℃,那是我用手拿住了 Ds18b20。目前是6月底,江蘇黃梅天,今天室溫就是27℃左右。
圖3是採集到的數據。只是展示了部分,剛開機的時候是沒有打開文本存儲按鈕的,因此第一個數據與圖2中接收數據框中前幾個數據不是對應的。
圖1 圖2 圖3
效果展示完了,那麼接下來就是代碼部分:
/*
* 功能:1.DS18B20進行溫度採集,並使用12864進行顯示
* 2.將採集到的溫度 通過SCIA傳輸,因爲SCIB的9口被12864佔用,所以不能用SCIB
* 3.SCIA使用CpuTimer0中斷,1s傳輸一次溫度數據給PC,未使用FIFO中斷
* 波特率:9600 8位數據位,1位停止位,無校驗位
*/
#include "DSP2833x_Project.h"
#include "math.h"
#include "lcd12864.h"
#include "ds18b20_para.h"
#define uchar unsigned char
void init_port(void);
uchar Init_DS18B20();
uchar ReadOneChar(void);
void WriteOneChar(uchar dat);
float ReadTemperature();
void lcd_init(void);
void lcd_write_cmd(uchar cmd);
void lcd_write_dat(uchar dat);
void LCD12864SetAddress_f( uchar x, uchar y ); //地址轉換
void show(uchar x, uchar y, uchar * data);
void scia_init(void);
void GPIO_init();
interrupt void Timer0_ISR(void);
uchar table[7];
int main(void)
{
float tt;
int tt1;
InitSysCtrl();
init_port(); //ds18b20 & 12864 端口初始化
DINT;
InitPieCtrl(); //初始化中斷控制
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();//初始化中斷矢量表
GPIO_init(); //配置端口爲SCI
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.TINT0 = &Timer0_ISR;//將定時器0中斷服務函數入口放入中斷向量表
EDIS; // This is needed to disable write to EALLOW protected registers
InitCpuTimers();
ConfigCpuTimer(&CpuTimer0, 150, 1000000); //定時器0定時時間爲 1s
scia_init(); //SCIA端口初始化
lcd_init();
PieCtrlRegs.PIECTRL.bit.ENPIE = 1; // Enable the PIE block
PieCtrlRegs.PIEIER1.bit.INTx7=1; // PIE Group 1, INT7
IER = 0x001;
EINT;
CpuTimer0Regs.TCR.bit.TSS = 0; // 啓動定時器0
while (1)
{
tt=ReadTemperature();
tt1=tt*100+0.5;
//留兩個小數點就*100,+0.5是四捨五入,因爲C語言浮點數轉換爲整型的時候把小數點
//後面的數自動去掉,不管是否大於0.5,而+0.5之後大於0.5的就是進1了,小於0.5的就
//算加上0.5,還是在小數點後面。
table[0]=tt1/10000+0x30; //百位
table[1]=tt1%10000/1000+0x30;//十位
table[2]=tt1%1000/100+0x30;//個位
table[3]='.';
table[4]=tt1%100/10+0x30;//十分位;
table[5]=tt1%10+0x30;//百分位;
table[6]='\0'; //用來中止一組顯示數據
show(0,0,table);
}
}
//----------------------
//--- 12864 及 DS18B20 的初始化
//----------------------
void init_port(void)
{
EALLOW;
GpioCtrlRegs.GPBPUD.bit.GPIO40 = 0; // 使能GPIO10 引腳內部上拉
GpioCtrlRegs.GPBMUX1.bit.GPIO40 =0; // 配置GPIO10爲通用I/O口
GpioCtrlRegs.GPBQSEL1.bit.GPIO40 = 0; // GPIO40與系統時鐘SYSCLKOUT 同步
//lcd12864 use
GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0; // 使能GPIO0 引腳內部上拉
GpioCtrlRegs.GPAPUD.bit.GPIO1 = 1; // 禁止GPIO1 引腳內部上拉
GpioCtrlRegs.GPAQSEL1.all = 0x0000; // GPIO0-GPIO15與系統時鐘SYSCLKOUT 同步
GpioCtrlRegs.GPADIR.all = 0x003FF;// 配置GPIO0-GPIO9爲輸出引腳
//輸出數據LCD_RW和LCD_EN清零
GpioDataRegs.GPADAT.bit.GPIO0 = 1;
GpioDataRegs.GPADAT.bit.GPIO1 = 0;
EDIS;
}
//----------------------
//---SCI的初始化
//----------------------
void GPIO_init()
{
EALLOW;
GpioCtrlRegs.GPBPUD.bit.GPIO35 = 0; // Enable pull-up for GPIO35 (SCITXDA)
GpioCtrlRegs.GPBMUX1.bit.GPIO35 = 1; // GPIO35 for SCITXDA operation
GpioCtrlRegs.GPBPUD.bit.GPIO36 = 0; // Enable pull-up for GPIO36 (SCIRXDA)
GpioCtrlRegs.GPBQSEL1.bit.GPIO36 = 3; // Asynch input GPIO36 (SCIRXDA)
GpioCtrlRegs.GPBMUX1.bit.GPIO36 = 1; // GPIO36 for SCIRXDA operation
EDIS;
}
void scia_init(void)
{
SciaRegs.SCICCR.all =0x0007; // 1 stop bit,
// No parity,8 char bits,
// async mode, idle-line protocol
SciaRegs.SCICTL1.all =0x0003; // enable TX, RX, internal SCICLK,
// Disable RX ERR, SLEEP, TXWAKE
SciaRegs.SCIHBAUD =0x0001;
SciaRegs.SCILBAUD =0x00E7; //構成 0x01e7=487 波特率計算爲 37.5M/[(487+1)*8]=9605 近似等於9600
SciaRegs.SCICTL1.bit.SWRESET=1;//Relinquish SCI from Reset
}
interrupt void Timer0_ISR(void)
{
int i=0;
while(table[i] != '\0') //不斷髮送,直到1組溫度數據發送完畢
{
SciaRegs.SCITXBUF=table[i]; //發送數據
DELAY_US(1000); //若不加,會出現數據丟失
i++;
}
SciaRegs.SCITXBUF='\n'; //每接收一組數據後,換行
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;//PIE組1應答
}
以上是DSP上的代碼。接下來是上位機代碼,供大家學習。這其中的一部分代碼,我也是從網上尋找來的,因此在此要感謝那位哥們開放的串口軟件。Appdesigner比較新,界面也不錯,如果大家喜歡,可以自己做出修改,但是我希望大家在我這個版本基礎上修改後,能在留言處開源自己的內容,讓大家一起進步。首先將app的鏈接給出:
鏈接:https://pan.baidu.com/s/1NEqKQJX87mv86V9ENZ2kkA
提取碼:x3y0
或 https://download.csdn.net/download/wx_simba/11259531
以下是代碼,有Matlab的朋友可以直接用 Appdesigner打開查看。注意,至少需要 2016a版本才具有Appdesigner功能。
***這是回頭打的字,插入代碼居然沒有Matlab的m語言格式。。。還有下面代碼看着多,其實估計80%都是系統生成的,我們是無法修改的,實現功能的代碼其實不多。
classdef app2 < matlab.apps.AppBase
% Properties that correspond to app components
properties (Access = public)
UIFigure matlab.ui.Figure
pbOpenSerial matlab.ui.control.StateButton
RXLabel matlab.ui.control.Label
TXLabel matlab.ui.control.Label
Label_RX matlab.ui.control.Label
Label_TX matlab.ui.control.Label
ReceiveView matlab.ui.control.TextArea
Button_Send matlab.ui.control.Button
transmitView matlab.ui.control.TextArea
Button_Clear matlab.ui.control.Button
DropDownLabel matlab.ui.control.Label
ppCOM matlab.ui.control.DropDown
Label matlab.ui.control.Label
Label_2 matlab.ui.control.Label
Lamp matlab.ui.control.Lamp
Label_3 matlab.ui.control.Label
ppCOM_2 matlab.ui.control.DropDown
Panel matlab.ui.container.Panel
Label_5 matlab.ui.control.Label
txtStoreSwich matlab.ui.control.Switch
Label_6 matlab.ui.control.Label
txtStoreFlag matlab.ui.control.Lamp
UIAxes matlab.ui.control.UIAxes
UartsEditFieldLabel matlab.ui.control.Label
UartsEditField matlab.ui.control.NumericEditField
end
properties (Access = public)
COM; % 端口號
Baud_Rate; %波特率
s ; %端口設置句柄
RX_num; %接收統計
TX_num; %發送統計
RX_once;%一次接收的數據
RX_Date;%接收的所有數據
is_open;%是否打開串口標誌位
Flag_i %繪圖橫座標的點
end
methods (Access = public)
function EveBytesAvailableFcn(app, src, event)
n = src.BytesAvailable;%獲取接收到的字符個數
if n>0%n>0才繼續執行,因爲0也會觸發中斷
app.RX_num=app.RX_num+n;
app.Label_RX.Text=num2str(app.RX_num);%將數字轉化爲字符串輸出
app.RX_once=fread(src,n,'uchar');%讀取函數,讀取後矩陣爲一列
app.RX_Date =strcat(app.RX_Date, app.RX_once');%字符串拼接,需要轉置化爲一行
app.ReceiveView.Value= app.RX_Date;%textarea的設置格式爲cell,或單行字符串
app.Flag_i=app.Flag_i+1;
t=app.Flag_i*app.UartsEditField.Value;
y=str2double(char(app.RX_once'));
plot(app.UIAxes,t,y,'marker','+','linewidth',5,'linestyle','--');
hold(app.UIAxes,'on');
if strcmp(app.txtStoreSwich.Value,'On')
app.txtStoreFlag.Color=[0 1 0];
name_ref=['wx',datestr(now,29),'.txt']; % name_ref=['wx',datestr(now,29),'.xls'];
fid = fopen(name_ref,'a'); %fid = fopen('c.xls','a');
fprintf(fid,'%s\r\n',app.RX_once'); %需要轉置,進行換行處理,txt換行 要\r\n..xls只\n就可以換行
fclose(fid);
else
app.txtStoreFlag.Color=[0 0 0];
end
end
end
end
methods (Access = private)
% Code that executes after component creation
function startupFcn(app)
app.RX_num=0;
app.TX_num=0;
app.is_open=0;
app.Flag_i=0;
scoms = instrfind;%獲取佔用的串口號
if scoms ~= 0%如果存在則關閉,否則不能打開
stopasync(scoms);
fclose(scoms);
delete(scoms);
end
end
% Button pushed function: Button_Send
function Button_SendPushed(app, event)
val=app.transmitView.Value;
if length(val{1})>0%textarea控件是cell格式,獲取需要用{1}
app.TX_num=app.TX_num+length(val{1});
app.Label_TX.Text=num2str(app.TX_num);
fwrite(app.s, char(val), 'uint8', 'async');%需要將val轉化爲char
end
end
% Value changed function: pbOpenSerial
function pbOpenSerialValueChanged2(app, event)
app.COM=get(app.ppCOM,'Value');
app.Baud_Rate=get(app.ppCOM_2,'Value');
if strcmp(get(app.pbOpenSerial,'Text'),'打開串口')
try
app.s=serial(app.COM);
app.s.BaudRate=str2double(app.Baud_Rate);%設置波特率,str2double 很重要
app.s.DataBits=8;%設置數據長度
app.s.StopBits=1;%設置停止位長度
app.s.InputBufferSize=1024000;%設置輸入緩衝區大小爲1M
app.s.BytesAvailableFcnMode='byte'; %串口事件回調設置
% app.s.Terminator='CR/LF';
app.s.BytesAvailableFcnCount=1; %輸入緩衝區存在10個字節觸發回調函數
app.s.BytesAvailableFcn={@app.EveBytesAvailableFcn};%回調函數的指定
fopen(app.s);%打開串口
app.is_open=1;
app.pbOpenSerial.Text='關閉串口';
app.Lamp.Color=[0 1 0];
catch err
msgbox('打開失敗');
end
else
try
fclose(app.s);
app.pbOpenSerial.Text='打開串口';
app.Lamp.Color=[0.15 0.15 0.15];
catch err
msgbox('關閉失敗');
end
delete(app.s);
app.is_open=0;
end
end
% Close request function: UIFigure
function UIFigureCloseRequest(app, event)
delete(app)
end
% Button pushed function: Button_Clear
function Button_ClearPushed(app, event)
app.RX_Date ='';
app.ReceiveView.Value= app.RX_Date;
app.TX_num=0;
app.RX_num=0;
app.Label_TX.Text=num2str(app.TX_num);
app.Label_RX.Text=num2str(app.RX_num);
cla(app.UIAxes,'reset');
end
% Value changed function: txtStoreSwich
function txtStoreSwichValueChanged(app, event)
value = app.txtStoreSwich.Value;
if strcmp(value,'On')
app.txtStoreFlag.Color=[0 1 0];
else
app.txtStoreFlag.Color=[0 0 0];
end
end
end
% App initialization and construction
methods (Access = private)
% Create UIFigure and components
function createComponents(app)
% Create UIFigure
app.UIFigure = uifigure;
app.UIFigure.Position = [500 300 895 521];
app.UIFigure.Name = 'UI Figure';
app.UIFigure.CloseRequestFcn = createCallbackFcn(app, @UIFigureCloseRequest, true);
% Create pbOpenSerial
app.pbOpenSerial = uibutton(app.UIFigure, 'state');
app.pbOpenSerial.ValueChangedFcn = createCallbackFcn(app, @pbOpenSerialValueChanged2, true);
app.pbOpenSerial.Text = '打開串口';
app.pbOpenSerial.FontSize = 16;
app.pbOpenSerial.FontWeight = 'bold';
app.pbOpenSerial.Position = [740 311 81 27];
% Create RXLabel
app.RXLabel = uilabel(app.UIFigure);
app.RXLabel.Position = [42 60 25 15];
app.RXLabel.Text = 'RX:';
% Create TXLabel
app.TXLabel = uilabel(app.UIFigure);
app.TXLabel.Position = [102 60 25 15];
app.TXLabel.Text = 'TX:';
% Create Label_RX
app.Label_RX = uilabel(app.UIFigure);
app.Label_RX.Position = [66 60 37 15];
app.Label_RX.Text = '0';
% Create Label_TX
app.Label_TX = uilabel(app.UIFigure);
app.Label_TX.Position = [126 60 82 15];
app.Label_TX.Text = '0';
% Create ReceiveView
app.ReceiveView = uitextarea(app.UIFigure);
app.ReceiveView.Position = [25 192 161 270];
% Create Button_Send
app.Button_Send = uibutton(app.UIFigure, 'push');
app.Button_Send.ButtonPushedFcn = createCallbackFcn(app, @Button_SendPushed, true);
app.Button_Send.FontSize = 16;
app.Button_Send.FontWeight = 'bold';
app.Button_Send.Position = [716 96 100 27];
app.Button_Send.Text = '發送';
% Create transmitView
app.transmitView = uitextarea(app.UIFigure);
app.transmitView.Position = [27 88 159 60];
% Create Button_Clear
app.Button_Clear = uibutton(app.UIFigure, 'push');
app.Button_Clear.ButtonPushedFcn = createCallbackFcn(app, @Button_ClearPushed, true);
app.Button_Clear.FontSize = 16;
app.Button_Clear.FontWeight = 'bold';
app.Button_Clear.Position = [716 49 100 27];
app.Button_Clear.Text = '清空';
% Create DropDownLabel
app.DropDownLabel = uilabel(app.UIFigure);
app.DropDownLabel.HorizontalAlignment = 'right';
app.DropDownLabel.FontName = 'Calibri';
app.DropDownLabel.FontSize = 18;
app.DropDownLabel.Position = [684 422 41 24];
app.DropDownLabel.Text = '串口';
% Create ppCOM
app.ppCOM = uidropdown(app.UIFigure);
app.ppCOM.Items = {'COM1', 'COM2', 'COM3', 'COM4'};
app.ppCOM.FontName = 'Calibri';
app.ppCOM.FontSize = 18;
app.ppCOM.Position = [740 424 76 25];
app.ppCOM.Value = 'COM1';
% Create Label
app.Label = uilabel(app.UIFigure);
app.Label.FontSize = 18;
app.Label.FontWeight = 'bold';
app.Label.Position = [39 475 42 23];
app.Label.Text = '接收';
% Create Label_2
app.Label_2 = uilabel(app.UIFigure);
app.Label_2.FontSize = 18;
app.Label_2.FontWeight = 'bold';
app.Label_2.Position = [39 151 42 23];
app.Label_2.Text = '發送';
% Create Lamp
app.Lamp = uilamp(app.UIFigure);
app.Lamp.Position = [695 317 20 20];
app.Lamp.Color = [0.149 0.149 0.149];
% Create Label_3
app.Label_3 = uilabel(app.UIFigure);
app.Label_3.HorizontalAlignment = 'right';
app.Label_3.FontName = 'Calibri';
app.Label_3.FontSize = 18;
app.Label_3.Position = [682 373 59 24];
app.Label_3.Text = '波特率';
% Create ppCOM_2
app.ppCOM_2 = uidropdown(app.UIFigure);
app.ppCOM_2.Items = {'300', '600', '1200', '2400', '4800', '9600', '19200', '38400', '115200'};
app.ppCOM_2.FontName = 'Calibri';
app.ppCOM_2.FontSize = 18;
app.ppCOM_2.Position = [756 375 60 25];
app.ppCOM_2.Value = '9600';
% Create Panel
app.Panel = uipanel(app.UIFigure);
app.Panel.Position = [655 173 231 87];
% Create Label_5
app.Label_5 = uilabel(app.Panel);
app.Label_5.HorizontalAlignment = 'center';
app.Label_5.Position = [136 24 77 15];
app.Label_5.Text = '文本存儲按鈕';
% Create txtStoreSwich
app.txtStoreSwich = uiswitch(app.Panel, 'slider');
app.txtStoreSwich.ValueChangedFcn = createCallbackFcn(app, @txtStoreSwichValueChanged, true);
app.txtStoreSwich.Position = [151 54 45 20];
% Create Label_6
app.Label_6 = uilabel(app.Panel);
app.Label_6.HorizontalAlignment = 'right';
app.Label_6.Position = [26 24 77 15];
app.Label_6.Text = '文本存儲指示';
% Create txtStoreFlag
app.txtStoreFlag = uilamp(app.Panel);
app.txtStoreFlag.Position = [52 45 29 29];
app.txtStoreFlag.Color = [0 0 0];
% Create UIAxes
app.UIAxes = uiaxes(app.UIFigure);
title(app.UIAxes, 'Figure')
xlabel(app.UIAxes, 'time')
ylabel(app.UIAxes, 'Y')
app.UIAxes.LineStyleOrder = {'- '};
app.UIAxes.NextPlot = 'add';
app.UIAxes.Position = [197 46 445 438];
% Create UartsEditFieldLabel
app.UartsEditFieldLabel = uilabel(app.UIFigure);
app.UartsEditFieldLabel.HorizontalAlignment = 'right';
app.UartsEditFieldLabel.Position = [262 18 121 15];
app.UartsEditFieldLabel.Text = 'Uart發送數據的週期/s';
% Create UartsEditField
app.UartsEditField = uieditfield(app.UIFigure, 'numeric');
app.UartsEditField.Limits = [0 Inf];
app.UartsEditField.Position = [398 14 49 22];
app.UartsEditField.Value = 1;
end
end
methods (Access = public)
% Construct app
function app = app2
% Create and configure components
createComponents(app)
% Register the app with App Designer
registerApp(app, app.UIFigure)
% Execute the startup function
runStartupFcn(app, @startupFcn)
if nargout == 0
clear app
end
end
% Code that executes before app deletion
function delete(app)
% Delete UIFigure when app is deleted
delete(app.UIFigure)
end
end
end