INTERFACING
MENGGUNAKAN VB .NET 2005
(Update Buku Teknik Interfacing Komputer dan Mikrokontroler)
a. Port Paralel /Port
ISA
Berikut contoh program C untuk mengontrol
8 buah alat melalui penekanan tombol keyboard :
Program pengontrol menggunakan port parallel (Kontrolpar.c)
/*
Program
untuk mengontrol peralatan menggunakan port paralel .
Alat dikontrol dengan menekan tombol 1-8 di keyboard.
*/
#include<dos.h>
#include<stdio.h>
#include<conio.h>
#define PORT 0x378 /* alamat port paralel */
main()
{
char val=0,key=0;
char str1[]="ON ";
char str2[]="OFF";
char *str;
clrscr();
printf("Tekan key yang sesuai untuk
menghidupkan /mematikan alat \n\n");
printf("Alat
ke 1 terhubung ke D0 port paralel , begitu seterusnya \n\n");
printf("Tekan \"x\" untuk keluar\n\n");
gotoxy(1,8);
printf("Device1:OFF Device2:OFF Device3:OFF
Device4:OFF\n");
printf("Device5:OFF Device6:OFF Device7:OFF
Device8:OFF");
while(key!='x' && key!='X') //Jika yang
ditekan bukan X
{
gotoxy(1,12);
printf("Nilai dalam format hex telah dikirim
ke port:");
key=getch();
switch(key){
case '1': //jika kita menekan 1 di keyboard
gotoxy(9,8);
val=(val&0x01)?(val&(~0x01)):val|0x01;
str=(val&0x01)?str1:str2;
printf("%s",str);
outportb(PORT,val);
gotoxy(1,13);
printf("%x",val);
break;
case '2':
gotoxy(21,8);
val=(val&0x02)?(val&(~0x02)):val|0x02;
str=(val&0x02)?str1:str2;
printf("%s",str);
outportb(PORT,val);
gotoxy(1,13);
printf("%x",val);
break;
case '3':
gotoxy(33,8);
val=(val&0x04)?(val&(~0x04)):val|0x04;
str=(val&0x04)?str1:str2;
printf("%s",str);
outportb(PORT,val);
gotoxy(1,13);
printf("%x",val);
break;
case '4':
gotoxy(45,8);
val=(val&0x08)?(val&(~0x08)):val|0x08;
str=(val&0x08)?str1:str2;
printf("%s",str);
outportb(PORT,val);
gotoxy(1,13);
printf("%x",val);
break;
case '5':
gotoxy(9,9);
val=(val&0x10)?(val&(~0x10)):val|0x10;
str=(val&0x10)?str1:str2;
printf("%s",str);
outportb(PORT,val);
gotoxy(1,13);
printf("%x",val);
break;
case '6':
gotoxy(21,9);
val=(val&0x20)?(val&(~0x20)):val|0x20;
str=(val&0x20)?str1:str2;
printf("%s",str);
outportb(PORT,val);
gotoxy(1,13);
printf("%x",val);
break;
case '7':
gotoxy(33,9);
val=(val&0x40)?(val&(~0x40)):val|0x40;
str=(val&0x40)?str1:str2;
printf("%s",str);
outportb(PORT,val);
gotoxy(1,13);
printf("%x",val);
break;
case '8':
gotoxy(45,9);
val=(val&0x80)?(val&(~0x80)):val|0x80;
str=(val&0x80)?str1:str2;
printf("%s",str);
outportb(PORT,val);
gotoxy(1,13);
printf("%x",(unsigned char)val);
break;
}
}
}
Program diatas segera akan mengeluarkan
data ke port paralel ketika user menekan tombol keyboard menggunakan fungsi case, dan
menggunakan fungsi outportb untuk
mengendalikan port . Fungsi gotoxy untuk menempatkan string pada posisi x dan y
yang telah ditentukan, serta fungsi break untuk berhenti, berikut potongoan kodenya :
case '1': //jika kita menekan 1 di keyboard
gotoxy(9,8);
val=(val&0x01)?(val&(~0x01)):val|0x01;
str=(val&0x01)?str1:str2;
printf("%s",str);
outportb(PORT,val);
gotoxy(1,13);
printf("%x",val);
break;
Untuk mendeteksi alamat port printer apa saja yang
telah diset pada port parallel, gunakan perintah debug sebagai berikut :

Gambar
Menggunakan perintah debug untuk melihat alamat LPT1
Dari gambar diatas
terlihat LPT1 diset dialamat 378H dan ada alamat lainnya yang telah diset juga.
Contoh aplikasi berikut akan
mengukur suhu melalui port parallel dan sensor DS1722. Pin SERMODE ialah Serial
interface mode, sedangkan CE ialah Chip Enable seperti penjelasan pada Tabel
Tabel No Pin dan Fungsi DS1722
|
No. Pin |
Nama Pin |
Keterangan |
|
7 |
SERMODE |
Serial Interface Mode |
|
2 |
CE |
Chip Enable |
|
3 |
SCLK |
Serial Clock |
|
5 |
SDO |
Serial Data Out |
|
6 |
SDI |
Serial Data In |
|
8 |
VDDA |
Analog supply voltage |

Gambar
Rangkaian sensor temperatur
Terlihat pada gambar, yang
dibutuhkan hanya sinyal SCK, SDI dan SD0 untuk mengirim data ke port parallel. An3315.pdf merupakan tutorial menulis program bahasa
C untuk 2 wire di port parallel.
Program Sensor Temperatur DS1722 (Ds1722.c)
// Sensor berbasis DS1722 di
port Paralel
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#include <process.h>
#include <alloc.h>
#define VDD_ON 0x01 /* power to PIC through VDD_ON on pin 2 (D0)
*/
#define SCK 0x02 /* serial clock for SPI provided by
PC */
#define PCSDO 0x04 /* serial data out from PC on Data bit
2 */
#define PCSDI 0x20 /* note this is on Status register
(bit 1) */
#define SSOUT 0x40 /* =CE, active high, not low as for
PIC SPI */
#define MCLR_HI 0x80 /* MCLR* on pin
9 (Data bit 7) normally high */
#define OPERATE VDD_ON |
MCLR_HI /* normal
operation of DS1722 */
/* adjust these to match the
CPU speed */
#define DELTIME 10000 /* settling time after transfers
*/
#define SECDELA 10000000 /* to get about 1 s sampling */
void dodelay(long);
void outportd(unsigned char);
int dport,sport;
void main(void)
{
unsigned char LSB,transfer(unsigned char,unsigned char);
char MSB; /* note this is signed */
void outportd(unsigned char outbyte);
int i,j,it;
float T;
/* LPT1 port addresses */
if(!(dport = peek(0x40,0x08)))
{ printf("\n\n\nLPT1
not available... aborting\n\n\n"); exit(1); }
sport = dport + 1; /*
status port address */
/* Initialize the
/* includes putting SCK in
the neutral 0 position: ~ is bitwise negation */
outportd(OPERATE&~SSOUT);
printf("hit key to stop list\n");
transfer(0x80,0xE8); /*
initialize DS1722 */
for(j=0;j<20;j++)
{ if(kbhit()) break;
printf("
config %X: ",transfer(00,0));
dodelay(SECDELA);
printf(" LSB
%X: ",LSB=transfer(0x01,0)); dodelay(SECDELA);
printf(" MSB
%X: ",MSB=transfer(0x02,0)); dodelay(SECDELA);
printf("T=%10.4f\n",T=MSB+(float)LSB/256.);
} /* for loop */
}
unsigned char transfer(unsigned char outbyte,unsigned char
outdata)
{ /* output address byte on Data2, data byte, getting
inbyte on Status5 */
unsigned char
outmask,inbyte,statusmask;
int ibit;
inbyte=0x00;
/* raise SSOUT for 2 byte
transfer, SCK also in lowered neutral position */
outportd(OPERATE|SSOUT);
for(ibit=0;ibit<8;ibit++)
{ outportd(OPERATE|SCK|SSOUT);
outmask=outbyte&0x80;
outbyte=outbyte<<1;
if(outmask)outportd(OPERATE|SCK|PCSDO|SSOUT);
/* output of 1 or */
else outportd(OPERATE|SCK|SSOUT); /* of 0 on PCSDO */
if(outmask)outportd(OPERATE|PCSDO|SSOUT); /* lower clock SCK */
else outportd(OPERATE|SSOUT); /* retaining data */
}
for(ibit=0;ibit<8;ibit++) /* output
outdata */
{ /* & input inbyte */
outportd(OPERATE|SCK|SSOUT); /* raise clock SCK */
outmask=outdata&0x80;
outdata=outdata<<1;
if(outmask)outportd(OPERATE|SCK|PCSDO|SSOUT);
/* output of 1 or */
else outportd(OPERATE|SCK|SSOUT); /* of 0 on PCSDO */
if(outmask)outportd(OPERATE|PCSDO|SSOUT); /*
lower clock SCK */
else
outportd(OPERATE|SSOUT);
/* retaining data */
statusmask=inportb(sport); /* read status port*/
statusmask=statusmask&PCSDI; /* mask input line */
inbyte=inbyte<<1;
inbyte=inbyte&0xFE; inbyte|=statusmask>>5;
}
/* lower SSOUT at end of 2
byte transfer, lower SCK to neutral position */
outportd(OPERATE&~SSOUT);
return inbyte;
}
void outportd(unsigned char outbyte)
{ dodelay(DELTIME); outportb(dport,outbyte); dodelay(DELTIME); }
void dodelay(long deltime)
{ long i; for(i=0; i<deltime; i++) ; }
Pada program diatas, program melakukan pendeteksian Port LPT1, lalu
melakukan inisialisasi DS1722 untuk membaca temperatur dan dikirim ke port
LPTI1 dengan delay tertentu.
Contoh berikut dapat dicoba.
/* File LED_FLSH.C
**
** Illustrates simple use of printer port. When switch is
** depressed LED flashes. When switch is not depressed, LED is
** turned off.
**
** P.H. Anderson,
*/
#include <stdio.h>
#include <dos.h>
/* required for delay function */
#define DATA 0x03bc
#define STATUS DATA+1
#define CONTROL DATA+2
void main(void)
{
int
in;
while(1)
{
in = inportb(STATUS);
if (((in^0x80)&0x80)==0)
/* if BUSY bit is
at 0 (sw closed) */
{
outportb(DATA,0x00);
/* turn LED on */
delay(100);
outportb(DATA, 0x01);
/* turn it off */
delay(100);
}
else
{
outportb(DATA,0x01);
/* if PB not depressed, turn LED off
*/
}
}
}

Program dibawah ini dapat mengendalikan port parallel, atau port ISA sesuai alamat port yang diset (378H atau 300H).
Langkah-langkahnya :
1. buat menu utama di VB .NET 2005

2. Buat form input vb, tambahkan kode sebagai berikut :

Public Class Input
Inherits
System.Windows.Forms.Form
Private Declare Function inp Lib "inpout32.dll"
Alias "Inp32"
(ByVal portaddress As
Integer) As Integer
Private Declare Sub out Lib "inpout32.dll"
Alias "Out32"
(ByVal portaddress As
Integer, ByVal
value As Integer)
……
Private Sub Button1_Click(ByVal
sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim
data As Integer
data = inp(&H378)
TextBox1.Text = data
End Sub

Private Sub Button1_Click(ByVal
sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
out(&H378, txtin.Text)
txtout.Text = txtin.Text
End Sub
B. Port Serial
Anda juga dapat memprogram
komunikasi serial antara 2 PC menggunakan C dengan lebih mudah . Berikut program komunikasi data
serial menggunakan fungsi BIOSCOM.
Program
Komunikasi serial menggunakan C (SerialC.c)
//Program komunikasi serial
menggunakan fungsi bioscom
//Dibuat oleh Widodo
Budiharto
//nilai port 0 untuk COM1, 1 untuk COM2 dan
seterusnya.
//8 bit teratas dari return
value ialah untuk status
//8 bit terendeah tergantung
pada perintah yang telah ditentukan
//perintah dapat berisi :
// 0
|Sets the communications parameters to the value in abyte.
// 1 |
Sends the character in abyte out over the communications line
// 2 |
Receives a character from the communications line.
// 3 |
Returns the current status of the communications port.
//abyte ialah kombinasi dari bit berikut
// 0x02 | 7 data bits 0x00
110 baud
// 0x03 | 8 data bits 0x20
150 baud
// 0x40
300 baud
// 0x00 | 1 stop bit 0x60
600 baud
// 0x04 | 2 stop bits 0x80
1200 baud
// 0x00 | No parity 0xA0
2400 baud
// 0x08 | Odd parity 0xC0
4800 baud
// 0x18 | Even parity 0xE0
9600 baud
//Sebagai contoh, 0xEB
//(0xE0|0x08|0x00|0x03)
untuk abyte akan menset
//port komunikasi ke 9600
baud, odd parity,1 stop bit, dan 8 bit data
//bioscom menggunakan BIOS 0x14 interrupt.
//Menyertakan header file yang dibutuhkan
#include <bios.h>
#include <conio.h>
//definisi port
#define COM1 0
#define DATA_READY 0x100
#define TRUE 1
#define FALSE 0
//definisi settings
#define SETTINGS ( 0x80 | 0x02 | 0x00 | 0x00)
int main(void)
{
int in, out,
status, DONE = FALSE;
bioscom(0,
SETTINGS, COM1);//3 parameter dari bioscom
cprintf("Komunikasi
serial menggunakan BIOSCOM, tekan [ESC] untuk keluar \n");
while (!DONE)
{
status =
bioscom(3, 0, COM1);
if (status &
DATA_READY)
if ((out =
bioscom(2, 0, COM1) & 0x7F) != 0)
putch(out);
if (kbhit())
{
if ((in =
getch()) == '\x1B')
DONE = TRUE;
bioscom(1,
in, COM1);
}
}
return 0;
}
Jika Anda ingin membuat aplikasi menggunakan bahasa Visual Basic .NET, menggunakan kelas Rs232, berikut contohnya : ‘ Program Inisialisasi dan membuka port komunikasi
Private Sub btnOpenCom_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnOpenCom.Click
moRS232
= New Rs232() ‘buat ojek serial
Try
'// setup parameter koneksi
With moRS232
.Port = miComPort
.BaudRate
= CInt(txtBaudrate.Text)
.DataBit
= 8
.StopBit
= Rs232.DataStopBit.StopBit_1
.Parity
= Rs232.DataParity.Parity_None
.Timeout = CInt(txtTimeout.Text)
.WorkingMode = CType(IIf(chkOl.Checked, Rs232.Mode.Overlapped,
Rs232.Mode.NonOverlapped), Rs232.Mode)
btnAsyncTx.Enabled =
(.WorkingMode = Rs232.Mode.Overlapped)
btnAsync.Enabled = (.WorkingMode
= Rs232.Mode.Overlapped)
chkOl.Enabled = False
End With
'// inisialisasi
port serial
moRS232.Open()
'// Set state of RTS / DTS
moRS232.Dtr = (chkDTR.CheckState
= CheckState.Checked)
moRS232.Rts = (chkRTS.CheckState
= CheckState.Checked)
Catch Ex As Exception
MessageBox.Show(Ex.Message,
"Error koneksi ", MessageBoxButtons.OK)
Finally
btnCloseCom.Enabled
= moRS232.IsOpen
btnOpenCom.Enabled
= Not moRS232.IsOpen
btnTx.Enabled =
moRS232.IsOpen
btnRx.Enabled =
moRS232.IsOpen
btnCheck.Enabled
= moRS232.IsOpen
End Try
End Sub
Untuk menulis data, gunakan
fungsi-fungsi berikut ini :
Private Sub Kirim_Click_1(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnTx.Click
‘gunakan fungsi write()
moRS232.Write(txtTx.Text)
'moRS232.Write(Chr()
& Chr(3) & Chr(0) & Chr(0) & Chr(0) & Chr(16) & Chr(68)
& Chr(83))
' Bersihkan textbox
txtRx.Text =
String.Empty
txtRx.Refresh()
lbHex.Items.Clear()
If
chkAutorx.Checked Then Button1_Click(Nothing, Nothing)
End Sub
Untuk membaca data gunakan fungsi-fungsi Read dan InputStreamString seperti berikut
:
Try
‘gunakan fungsi Read()
moRS232.Read(CInt(txtBytes2Read.Text))
txtRx.Text =
moRS232.InputStreamString
txtRx.ForeColor = Color.Black
txtRx.BackColor = Color.White
'// Fills listbox with hex
values
Dim aBytes As Byte()
= moRS232.InputStream
Dim iPnt As Int32
For iPnt = 0 To
aBytes.Length - 1
lbHex.Items.Add(iPnt.ToString
& ControlChars.Tab & String.Format("0x{0}",
aBytes(iPnt).ToString("X")))
Next
Catch Ex
As Exception
txtRx.BackColor = Color.Red
txtRx.ForeColor = Color.White
txtRx.Text = "Terjadi error " & Ex.Message & " data fetched: " &
moRS232.InputStreamString
End Try

Gambar Program Komunikasi Serial VB
.NET
Kita juga dapat
menggunakan komponen yang sudah dibuat oleh suatu perusahaan, misalnya PortController.Net
yang terdapat pada CD Program, sehingga pemrograman menjadi lebih mudah seperti
contoh mebuka dan menulis ke suatu port serial
berikut :
Private Sub
Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
myPortController.Open("COM1")
End Sub
Private Sub
SendButton_Click(ByVal sender As System.Object, ByVal
e As System.EventArgs) Handles SendButton.Click
myPortController.Write(SendText.Text)
SendText.Clear()
End Sub
Private Sub
myPortController_OnDataReceived(ByVal sender As
Object, ByVal e As System.EventArgs) Handles myPortController.OnDataReceived
ReceiveText.AppendText(myPortController.Read())
End Sub
Jika
hanya menggunakan bahasa Visual Basic 6, tempelkan kontrol MSComm1, dan
masukkan kode untuk menset MSComm1 dimana memperoleh input dari suatu combobox
berikut :
MsComm1.commPort=cmbPort.ListIndex
+1
MsComm1.Settings=cmbbitspersecond.text
MSComm1.Handshaking=cmbFlowControl.LinstIndex
Berikut program mengirim string ke COM1 menggunakan VB .NET 2005
‘Program mengirim String
Sub SendSerialData(ByVal data
As String)
' Send strings to a serial port.
Using com1 As
IO.Ports.SerialPort = _
My.Computer.Ports.OpenSerialPort("COM1")
com1.WriteLine(data)
End Using
End Sub
‘Program Menerima String di VB .Net 2005
Function ReceiveSerialData()
As String
' Receive strings from a serial port.
Dim returnStr
As String = ""
Using com1 As
IO.Ports.SerialPort = _
My.Computer.Ports.OpenSerialPort("COM1")
Do
Dim
Incoming As String = com1.ReadLine()
If
Incoming Is Nothing Then
Exit Do
Else
returnStr &= Incoming & vbCrLf
End
If
End Using
Return
returnStr
End Function
‘Menampilkan port yang tersedia
Sub GetSerialPortNames()
' Show all available COM ports.
For Each sp As String In My.Computer.Ports.SerialPortNames
ListBox1.Items.Add(sp)
Next
End Sub

Private Sub Button1_Click(ByVal sender
As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
SendSerialData("hello")
End Sub
Sub SendSerialData(ByVal data As
String)
' Send strings to a serial port.
Using com1 As IO.Ports.SerialPort = _
My.Computer.Ports.OpenSerialPort("COM1")
com1.WriteLine(data)
Label1.Text = data
End Using
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button2.Click
Label2.Text = ReceiveSerialData()
End Sub
Function ReceiveSerialData() As String
' Receive strings from a serial port.
Dim returnStr As String = ""
Using com1 As IO.Ports.SerialPort = _
My.Computer.Ports.OpenSerialPort("COM1")
Do
Dim Incoming As String =
com1.ReadLine()
If Incoming Is Nothing Then
Exit Do
Else
returnStr &= Incoming
& vbCrLf
End If
End Using
End Function
Private Sub Serial_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
GetSerialPortNames()
End Sub
Sub GetSerialPortNames()
' Show all available COM ports.
For Each sp As String In My.Computer.Ports.SerialPortNames
ListBox1.Items.Add(sp)
Next
End Sub
Jika anda
ingin interfacing ke keyboard, pelajari dulu modelpengiriman data sebagai
berikut :

Dimana koneksi keboard dengan CHIP sebagai berikut:

Berikut contoh konkesi Wireless menggunakan port RS232
Tiny Planet: a planet-wide, wireless I/O
port
Penerapan
Fig. 1
Fig. 2

PC Thermometer berbasis catu daya USB

PC TERMOMETER


Private Sub Timer1_Timer()
Dim t As Double
Dim unit As String
If check_farenheit Then
unit = "°F"
Else
unit = "°C"
End If
t = temperature(0)
If t = ERROR_TEMPERATURE_NOT_READ Then
MsgBox "Unable to read internal temperature", vbOKOnly, "Error"
Timer1.Enabled = False
label_temperature_indoor.Caption = "--.-" + unit
Else
If check_farenheit Then
t = farenheit(t)
End If
label_temperature_indoor.Caption = Format(t, "#0.0" + unit)
End If
If option_double Then
t = temperature(1)
If t = ERROR_TEMPERATURE_NOT_READ Then
MsgBox "Unable to read external temperature", vbOKOnly, "Error"
Timer1.Enabled = False
label_temperature_outside.Caption = "--.-" + unit
Else
If check_farenheit Then
t = farenheit(t)
End If
label_temperature_outside.Caption = Format(t, "#0.0" + unit)
End If
Else
label_temperature_outside.Caption = "--.-" + unit
End If
If option_double Then
frm_thermometer.Caption = label_temperature_indoor.Caption + " ( out " + label_temperature_outside.Caption + " )"
Else
frm_thermometer.Caption = label_temperature_indoor.Caption
End If
log_to_file
End Sub
Private Function temperature(address As Integer) As Double
Dim temperature_int As Long
Dim temperature_frac As Long
address = address * 2
On Error GoTo errors
open_iic_bus MSComm1.object
'/*resettiamo bene il chip*/
IIC_stop
'/**/
IIC_start
IIC_tx_byte &H90 + address
IIC_tx_byte &HAC
IIC_tx_byte &H2
IIC_start
IIC_tx_byte &H90 + address
IIC_tx_byte &HEE
IIC_stop
IIC_start
IIC_tx_byte &H90 + address
IIC_tx_byte &HAA
IIC_start
IIC_tx_byte &H91 + address
temperature_int = IIC_rx_byte(1)
temperature_frac = IIC_rx_byte(0)
temperature = (temperature_int * 256 + temperature_frac) / 128 * 5 / 10
If temperature_int >= 128 Then
temperature = temperature - 256
End If
IIC_stop
Exit Function
errors:
temperature = ERROR_TEMPERATURE_NOT_READ
End Function
Private Function update_sample_rate()
If option_1_sec Then
Timer1.Interval = 1000
ElseIf option_5_sec Then
Timer1.Interval = 5000
ElseIf option_30_sec Then
Timer1.Interval = 30000
ElseIf option_1_min Then
Timer1.Interval = 60000
Else
Timer1.Interval = 1000
End If
End Function
Private Function update_com_port()
If MSComm1.PortOpen Then
MSComm1.PortOpen = False
End If
If option_com1 Then
MSComm1.CommPort = 1
Timer1.Enabled = True
ElseIf option_com2 Then
MSComm1.CommPort = 2
Timer1.Enabled = True
ElseIf option_com3 Then
MSComm1.CommPort = 3
Timer1.Enabled = True
ElseIf option_com4 Then
MSComm1.CommPort = 4
Timer1.Enabled = True
Else
MSComm1.CommPort = 1
Timer1.Enabled = False
End If
End Function
Private Function farenheit(t As Double)
farenheit = 32 + 9 / 5 * t
End Function
Private Function log_to_file()
If check_log_to_file Then
Open "pc_thermometer.txt" For Append As #1
Print #1, Date$, Time$, label_temperature_outside.Caption, label_temperature_indoor.Caption
Close #1
End If
End Function

SILAHKAN DOWNLOAD KODE di bagian downloads kode buku”Teknik InterfacingKomputer dan Mikrokontroler” di widodo.com
Anda dapat mengikuti workshop 1 hari PC interfacing dengan biaya Rp 300.000
Hubungi Mr.WIDODO,HP:08569887384