Pour le centre spatial de liège, je doit représenter un signal via PWM envoyé depuis l'uart d'un microcontroleur MSP430FR6989.
Ps: J'ai utilisé ma class fifo pour la gestion des threads
Ce programme n'est pas tout à fait terminé mais on peut déjà voir le signal.

Main
Code : Tout sélectionner
; --------------------------------------------------------
; PROJECT : Uart communication
; AUTHOR : Bielen Pierre
; DATE : 2020-11-10
; PROCESS : Read information between a microcontroller
; MSP430FR6989 through a UART protocol.
; NOTE : the message will have this structure
; DxxFx
; D00 -> duty cycle of 0 %
; D01 -> duty cycle of 10 %
; D02 -> duty cycle of 20 %
; D03 -> duty cycle of 30 %
; D04 -> duty cycle of 40 %
; D05 -> duty cycle of 50 %
; D06 -> duty cycle of 60 %
; D07 -> duty cycle of 70 %
; D08 -> duty cycle of 80 %
; D09 -> duty cycle of 90 %
; D10 -> duty cycle of 100 %
; F0 -> frequency of 50 HZ
; F1 -> frequency of 100 HZ
; F2 -> frequency of 500 HZ
; F3 -> frequency of 1 KHZ
; F4 -> frequency of 2 KHZ
; F5 -> frequency of 5 KHZ
; F6 -> frequency of 10 KHZ
; F7 -> frequency of 20 KHZ
; --------------------------------------------------------
EnableExplicit
;-- LIBARY INCLUSION
XIncludeFile "include/fifo.pbi"
;-- GLOBAL VARIABLES
Global THR_D,THR_R
Global fifo = FIFO::new(20)
Global com,i
Global serial_port.s
Global runed.b = #False
Global current_duty_cycle,current_frequency
;-- STRUCTURE
Structure _data
duty.i
frequency.i
EndStructure
;-- ENUMERATION
Enumeration
#MAIN_FORM
#CB_COM
#BT_RUN
#CANVAS
EndEnumeration
#BUFFER_LENGHT = 1024
;-- FUNCTIONS INCLUSION
XIncludeFile "include/prototype.pbi"
XIncludeFile "include/function.pbi"
;-- INITIATION
open_main_form()
;-- MAIN LOOP
Repeat
WaitWindowEvent()
ForEver
End
Code : Tout sélectionner
; --------------------------------------------------------
; PROJECT : Uart communication
; AUTHOR : Bielen Pierre
; DATE : 2020-11-10
; PROCESS : prototypes of function
; --------------------------------------------------------
; FUNCTION NAME : THR_read
; PARAMETER : fifo.FIFO::object
; (a instance of fifo object)
; RETURNED VALUE : VOID
; PROCESS : THREAD read informations from
; the UART protocol
; NOTE :
; -----------------------------------------------
Declare THR_read(fifo.FIFO::object)
; -----------------------------------------------
; FUNCTION NAME : THR_display
; PARAMETER : fifo.FIFO::object
; (a instance of fifo object)
; RETURNED VALUE : VOID
; PROCESS : THREAD read information from
; the fifo object and draw run
; a function for draw the signal
; NOTE :
; -----------------------------------------------
Declare THR_display(fifo.FIFO::object)
; -----------------------------------------------
; FUNCTION NAME : exit
; PARAMETER : VOID
; RETURNED VALUE : VOID
; PROCESS : callback (close window and application)
; NOTE :
; -----------------------------------------------
Declare exit()
; -----------------------------------------------
; FUNCTION NAME : open_serial_port
; PARAMETER : VOID
; RETURNED VALUE : VOID
; PROCESS : open a serial port of communication
; NOTE :
; -----------------------------------------------
Declare open_serial_port()
; -----------------------------------------------
; FUNCTION NAME : ev_cb_com
; PARAMETER : VOID
; RETURNED VALUE : VOID
; PROCESS : callback (change the current port)
; NOTE :
; -----------------------------------------------
Declare ev_cb_com()
; -----------------------------------------------
; FUNCTION NAME : ev_run_button
; PARAMETER : VOID
; RETURNED VALUE : VOID
; PROCESS : callback (run or stop connection)
; NOTE :
; -----------------------------------------------
Declare ev_run_button()
; -----------------------------------------------
; FUNCTION NAME : open_main_form
; PARAMETER : VOID
; RETURNED VALUE : VOID
; PROCESS : open the main window
; NOTE :
; -----------------------------------------------
Declare open_main_form()
; -----------------------------------------------
; FUNCTION NAME : draw_grid
; PARAMETER : unity (unity of in µs)
; RETURNED VALUE : VOID
; PROCESS : draw a grid depending on the frequency
; NOTE :
; -----------------------------------------------
Declare draw_grid()
; -----------------------------------------------
; FUNCTION NAME : draw_signal
; PARAMETER : VOID
; RETURNED VALUE : VOID
; PROCESS : draw the signal
; NOTE :
; -----------------------------------------------
Declare draw_signal()
; -----------------------------------------------
; FUNCTION NAME : draw_period
; PARAMETER : unity (unity in µs)
; period (unity in µs)
; RETURNED VALUE : VOID
; PROCESS : draw the signal
; NOTE :
; -----------------------------------------------
Declare draw_period(unity,period)
Code : Tout sélectionner
; --------------------------------------------------------
; PROJECT : Uart communication
; AUTHOR : Bielen Pierre
; DATE : 2020-11-10
; PROCESS : functions
; --------------------------------------------------------
; -----------------------------------------------
; FUNCTION NAME : THR_read
; PARAMETER : fifo.FIFO::object
; (a instance of fifo object)
; RETURNED VALUE : VOID
; PROCESS : THREAD read informations from
; the UART protocol
; NOTE :
; -----------------------------------------------
Procedure THR_read(fifo.FIFO::object)
Protected myData.l,myString.s,begining.b,n,*ds._data
Repeat
; -- clear data structure
myString = ""
; -- for wait first letter of data
begining = #False
; -- we have data available
While AvailableSerialPortInput(com)
; -- we read data
ReadSerialPortData(com,@myData,1)
; -- if on the first letter or into the data structure
If(PeekS(@myData) = "D" Or begining)
; -- we construct the data string
myString + PeekS(@myData)
; -- we say we have into the data
begining = #True
; -- if we have on the end of data from the microcontroller
If(Len(myString) >= 5)
;Debug myString
; -- extract date from string
*ds = AllocateStructure(_data)
*ds\duty = Val(Mid(myString,2,2))
*ds\frequency = Val(Right(myString,1))
; -- push data into the fifo
fifo\push(*ds)
; -- exit on the read loop
Break
EndIf
EndIf
Wend
; -- we want to leave some time at CPU to be breath
; without this delay, this will take lot resource
Delay(1)
Until runed = #False
; -- say we have stoping
fifo\push(-1)
; -- we kill the thread
If IsThread(THR_R)
KillThread(THR_R)
EndIf
EndProcedure
; -----------------------------------------------
; FUNCTION NAME : THR_display
; PARAMETER : fifo.FIFO::object
; (a instance of fifo object)
; RETURNED VALUE : VOID
; PROCESS : THREAD read information from
; the fifo object and draw run
; a function for draw the signal
; NOTE :
; -----------------------------------------------
Procedure THR_display(fifo.FIFO::object)
Protected *d._data
Repeat
; -- read data from fifo list
*d = fifo\pop()
If *d <> -1
current_duty_cycle = *d\duty
current_frequency = *d\frequency
FreeStructure(*d)
;Debug current_duty_cycle
;Debug current_frequency
EndIf
; -- we want to leave some time at CPU to be breath
; without this delay, this will take lot resource
Delay(1)
draw_signal()
Until runed = #False
; -- we free the fifo object
fifo\free()
; -- we kill the thread
If IsThread(THR_D)
KillThread(THR_D)
EndIf
EndProcedure
; -----------------------------------------------
; FUNCTION NAME : exit
; PARAMETER : VOID
; RETURNED VALUE : VOID
; PROCESS : callback (close window and application)
; NOTE :
; -----------------------------------------------
Procedure exit()
; -- close the main window
CloseWindow(#MAIN_FORM)
End
EndProcedure
; -----------------------------------------------
; FUNCTION NAME : open_serial_port
; PARAMETER : VOID
; RETURNED VALUE : VOID
; PROCESS : open a serial port of communication
; NOTE :
; -----------------------------------------------
Procedure open_serial_port()
com = OpenSerialPort(#PB_Any,"COM3",115200,#PB_SerialPort_NoParity,8,1,#PB_SerialPort_NoHandshake,5,5)
ProcedureReturn com
EndProcedure
; -----------------------------------------------
; FUNCTION NAME : ev_cb_com
; PARAMETER : VOID
; RETURNED VALUE : VOID
; PROCESS : callback (change the current port)
; NOTE :
; -----------------------------------------------
Procedure ev_cb_com()
Protected i = GetGadgetState(#CB_COM)+1
; -- change the current serial port
serial_port = "COM"+i
EndProcedure
; -----------------------------------------------
; FUNCTION NAME : ev_run_button
; PARAMETER : VOID
; RETURNED VALUE : VOID
; PROCESS : callback (run or stop connection)
; NOTE :
; -----------------------------------------------
Procedure ev_run_button()
; -- change the current serial port from the combo box
ev_cb_com()
If(runed)
; -- change title of button
SetGadgetText(#BT_RUN,"Connect")
; -- change the runed flag
runed = #False
; -- stop all threads
runed = #False
; -- close connection
If IsSerialPort(com)
CloseSerialPort(com)
EndIf
com = 0
Else
; -- try to open serial connection
If Not open_serial_port()
MessageRequester("Serial connection error","The serial connection has failled!",#PB_MessageRequester_Error)
; -- stop the code here
ProcedureReturn #False
EndIf
; -- change title of button
SetGadgetText(#BT_RUN,"Disconnect")
; -- change the runed flag
runed = #True
; -- create instance of the fifo object
fifo = FIFO::new(#BUFFER_LENGHT)
; -- start all threads
THR_R = CreateThread(@THR_read(),fifo)
THR_D = CreateThread(@THR_display(),fifo)
EndIf
EndProcedure
; -----------------------------------------------
; FUNCTION NAME : open_main_form
; PARAMETER : VOID
; RETURNED VALUE : VOID
; PROCESS : open the main window
; NOTE :
; -----------------------------------------------
Procedure open_main_form()
; -- we start with a left and up margin to 5 px
Protected x = 5,y = 5 ,i,W = 550,H = 600
; -- open the window
OpenWindow(#MAIN_FORM,0,0,W,H,"Uart communication",#PB_Window_ScreenCentered|
#PB_Window_SystemMenu)
; -- Combo box with serial ports to chose
TextGadget(#PB_Any,x,y,200,30,"Serial port")
; -- y position of combo box
y+15
ComboBoxGadget(#CB_COM,X,Y,200,30)
; -- fill the combo box
For i = 1 To 16
AddGadgetItem(#CB_COM,-1,"COM "+Str(i))
Next
; -- y position for the button run
y = 20
; -- x position for the button run
x + 205
; -- button run/stop
ButtonGadget(#bt_run,x,y,200,30,"Connect")
; -- the canvas where the signal will be drawn
; ---- position x of the canvas
x = 10
; ---- position y of the canvas
Y + 40
CanvasGadget(#CANVAS,x,y,H - (y+10),H - (y+10))
; -- draw the canvas (only the background)
draw_signal()
; -- place here yours event listeners
; ---- when the user clicks on the exit cross
BindEvent(#PB_Event_CloseWindow,@exit(),#MAIN_FORM)
; ---- when the user clicks on the run button
BindGadgetEvent(#BT_RUN,@ev_run_button())
; ---- when the user selects an item from the combo box
BindGadgetEvent(#CB_COM,@ev_cb_com())
EndProcedure
; -----------------------------------------------
; FUNCTION NAME : draw_grid
; PARAMETER : unity (unity of in µs)
; RETURNED VALUE : VOID
; PROCESS : draw a grid depending on the frequency
; NOTE :
; -----------------------------------------------
Procedure draw_grid()
Protected w = GadgetWidth(#CANVAS)
Protected unity = w / 10
Protected x,y
ResetCoordinates(#PB_Coordinate_User)
; -- draw time grid (vertical)
While(x <= w-unity)
x + unity
MovePathCursor(x,0)
AddPathLine(x,w)
Wend
; -- draw volt grid (horizontal)
While(y <= w-unity)
y + unity
MovePathCursor(0,y)
AddPathLine(w,y)
Wend
VectorSourceColor($31DBDBDB)
DotPath(1,3)
EndProcedure
; -----------------------------------------------
; FUNCTION NAME : draw_signal
; PARAMETER : VOID
; RETURNED VALUE : VOID
; PROCESS : draw the signal
; NOTE :
; -----------------------------------------------
Procedure draw_signal()
Protected unity,period
Select current_frequency
Case 0 ; 50 HZ period = 20 ms
unity = 5000 ; 5000 µs
period = 20000
Case 1 ; 100 HZ period = 10 ms
unity = 5000 ; 2500 µs
period = 10000
Case 2 ; 500 HZ period = 2 ms
unity = 1000 ; 1000 µs
period = 2000
Case 3 ; 1 KHZ period = 1 ms
unity = 250 ; 250 µs
period = 1000
Case 4 ; 2 KHZ period = 500 µs
unity = 250 ; 250 µs
period = 500
Case 5 ; 5 KHZ period = 200 µs
unity = 100 ; 100 µs
period = 200
Case 6 ; 10 KHZ period = 100 µs
unity = 25 ; 25 µs
period = 100
Case 7 ; 20 KHZ period = 50 µs
unity = 10 ; 10 µs
period = 50
EndSelect
StartVectorDrawing(CanvasVectorOutput(#CANVAS))
; -- grey color
VectorSourceColor($FF474747)
; -- eraze the canvas
FillVectorOutput()
; -- draw the grid
draw_grid()
If runed
draw_period(unity,period)
EndIf
StopVectorDrawing()
EndProcedure
; -----------------------------------------------
; FUNCTION NAME : draw_period
; PARAMETER : unity (unity in µs)
; period (unity in µs)
; RETURNED VALUE : VOID
; PROCESS : draw the signal
; NOTE :
; -----------------------------------------------
Procedure draw_period(unity,period)
Protected w.d = GadgetWidth(#CANVAS)
Protected pxl_unity.d = w / 10 ; unity of grid
Protected x.d = pxl_unity ; we start at one unity
Protected n_unity = period / unity
Protected low.d = pxl_unity * 5 ; y when the signal is low
Protected hight.d = low - (pxl_unity * 3); y when the signal is hight
Protected duty.d
Select current_duty_cycle
Case 1 ; 10 %
duty = pxl_unity * (n_unity * 0.1)
Case 2 ; 20 %
duty = pxl_unity * (n_unity * 0.2)
Case 3 ; 30 %
duty = pxl_unity * (n_unity * 0.3)
Case 4 ; 40 %
duty = pxl_unity * (n_unity * 0.4)
Case 5 ; 50 %
duty = pxl_unity * (n_unity * 0.5)
Case 6 ; 60 %
duty = pxl_unity * (n_unity * 0.6)
Case 7 ; 70 %
duty = pxl_unity * (n_unity * 0.7)
Case 8 ; 80 %
duty = pxl_unity * (n_unity * 0.8)
Case 9 ; 90 %
duty = pxl_unity * (n_unity * 0.9)
EndSelect
If current_duty_cycle >0 And current_duty_cycle <10
; -- draw volt line
; --- starting line
MovePathCursor(0,low)
AddPathLine(pxl_unity,low)
While x <= w-pxl_unity
; -- draw time line
; ---- starting period
MovePathCursor(x,hight)
AddPathLine(x,low)
; --- duty cycle
MovePathCursor(x + duty,hight)
AddPathLine(x + duty,low)
; --- hight volt signal
MovePathCursor(x,hight)
AddPathLine(x + duty,hight)
; --- low volt signal
MovePathCursor(x + duty,low)
AddPathLine(x + (n_unity * pxl_unity),low)
; --- end period
x + (n_unity * pxl_unity)
MovePathCursor(x,hight)
AddPathLine(x,low)
Wend
ElseIf current_duty_cycle =0
MovePathCursor(0,low)
AddPathLine(w,low)
Else
MovePathCursor(0,hight)
AddPathLine(w,hight)
EndIf
VectorSourceColor($FFFF901E)
StrokePath(4)
EndProcedure
Code : Tout sélectionner
; -----------------------------------------------------------------------------
; MODULE : fifo
; PROCESS : manage a fifo list
; VERSION : 1.0
; -----------------------------------------------------------------------------
DeclareModule FIFO
Interface object
; ---------------------------------------------------------------------------
; PUBLIC METHOD : push
; PROCESS : push a data into the fifo list
; ARGUMENTS : *item -> adresse to item
; RETURN : VOID
; ---------------------------------------------------------------------------
push(item)
; ---------------------------------------------------------------------------
; PUBLIC METHOD : pop
; PROCESS : pop a data from the fifo list
; ARGUMENTS : VOID
; RETURN : pointer of data adresse
; ---------------------------------------------------------------------------
pop()
; ---------------------------------------------------------------------------
; PUBLIC METHOD : free
; PROCESS : free fifo list
; ARGUMENTS : VOID
; RETURN : VOID
; ---------------------------------------------------------------------------
free()
EndInterface
; ---------------------------------------------------------------------------
; CONSTRUCTOR : new
; ARGUMENTS : buffer_length.i -> length of buffer minimum 1
; RETURN : instance of fifo
; ---------------------------------------------------------------------------
Declare new(buffer_length.i)
EndDeclareModule
XIncludeFile "../lib/_fifo.pbi"
Code : Tout sélectionner
; -----------------------------------------------------------------------------
; MODULE : fifo
; PROCESS : manage a fifo list
; VERSION : 1.0
; -----------------------------------------------------------------------------
Module FIFO
EnableExplicit
Structure _FIFO
*methods
Array *buffer(0) ; you can change this buffer with any variable type
buffer_length.i
input.i
output.i
items.i
spaces.i
mutex.i
EndStructure
; ---------------------------------------------------------------------------
; CONSTRUCTOR : new
; ARGUMENTS : buffer_length.i -> length of buffer minimum 1
; RETURN : instance of fifo
; ---------------------------------------------------------------------------
Procedure new(buffer_length.i)
Protected *this._FIFO = AllocateStructure(_FIFO)
With *this
\methods = ?S_MTH
\input = 0
\output = 0
\buffer_length = buffer_length
; initiation of semaphores and mutex
\items = CreateSemaphore(0)
\spaces = CreateSemaphore(buffer_length)
\mutex = CreateMutex()
ReDim \buffer(buffer_length)
ProcedureReturn *this
EndWith
EndProcedure
; ---------------------------------------------------------------------------
; PUBLIC METHOD : push
; PROCESS : push a data into the fifo list
; ARGUMENTS : *item -> adresse to item
; RETURN : VOID
; ---------------------------------------------------------------------------
Procedure push(*this._FIFO,item)
With *this
WaitSemaphore(\spaces) ; wait for space into the buffer
LockMutex(\mutex) ; mutual exclusion
\buffer(\input) = item ; push into the list
\input +1 ; next list position
; manage circular list
If \input >= \buffer_length ; uper to bufer length
\input = 0
EndIf
UnlockMutex(\mutex) ; end of mutual exclusion
SignalSemaphore(\items) ; tel data available
EndWith
EndProcedure
; ---------------------------------------------------------------------------
; PUBLIC METHOD : pop
; PROCESS : pop a data from the fifo list
; ARGUMENTS : VOID
; RETURN : pointer of data adresse
; ---------------------------------------------------------------------------
Procedure pop(*this._FIFO)
With *this
Protected returned_value = 0
WaitSemaphore(\items) ; wait for data available
LockMutex(\mutex) ; mutual exclusion
returned_value = \buffer(\output) ; load from the List
\output +1 ; next list position
; manage circular list
If \output >= \buffer_length ; uper to bufer length
\output = 0
EndIf
UnlockMutex(\mutex) ; End of mutual exclusion
SignalSemaphore(\spaces) ; tel space available
ProcedureReturn returned_value
EndWith
EndProcedure
; ---------------------------------------------------------------------------
; PUBLIC METHOD : free
; PROCESS : free fifo list
; ARGUMENTS : VOID
; RETURN : VOID
; ---------------------------------------------------------------------------
Procedure free(*this._FIFO)
With *this
FreeSemaphore(\spaces)
FreeSemaphore(\items)
FreeMutex(\mutex)
FreeStructure(*this)
EndWith
EndProcedure
DataSection
S_MTH:
Data.i @push()
Data.i @pop()
Data.i @free()
E_MTH:
EndDataSection
EndModule