1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Windows; 7 using System.Windows.Controls; 8 using System.Windows.Data; 9 using System.Windows.Documents; 10 using System.Windows.Input; 11 using System.Windows.Media; 12 using System.Windows.Media.Imaging; 13 using System.Windows.Navigation; 14 using System.Windows.Shapes; 15 16 //引用串口类库 17 using System.IO.Ports; 18 19 namespace Demo_5 20 { 21 /// <summary> 22 /// MainWindow.xaml 的交互逻辑 23 /// </summary> 24 public partial class MainWindow : Window 25 { 26 public delegate void showReceiveDelegate(string text); //当采用响应模式,应申明一个委托,实现不同线程的控件实验 27 28 SerialPort com = new SerialPort(); 29 public MainWindow() 30 { 31 InitializeComponent(); 32 this.Loaded += MainWindow_Loaded; 33 } 34 35 /// <summary> 36 /// 窗体加载事件 37 /// </summary> 38 /// <param name="sender"></param> 39 /// <param name="e"></param> 40 void MainWindow_Loaded(object sender, RoutedEventArgs e) 41 { 42 //获取本机所有串口的名字 43 string[] strPortName = SerialPort.GetPortNames(); 44 //将本机所有串口名称赋值给cmbPort控件 45 cmbPort.ItemsSource = strPortName; 46 47 //下拉框初始化 48 //如果本机串口数量不为0,则将cmbPort的Item第一个索引 49 if (strPortName.Length > 0) cmbPort.SelectedIndex = 0; 50 //将波特率下拉框cmbBaudRate的Item第一个索引 51 cmbBaudRate.SelectedIndex = 0; 52 //将数据位下拉框cmbDataBits的Item第一个索引 53 cmbDataBits.SelectedIndex = 0; 54 //将停止位下拉框cmbStopBits的Item第一个索引 55 cmbStopBits.SelectedIndex = 0; 56 //将奇偶校验下拉框cmbParity的Item第一个索引 57 cmbParity.SelectedIndex = 0; 58 //接收模式初始化(设置为响应模式) 59 rbResponse.IsChecked = true; 60 } 61 62 /// <summary> 63 /// 打开按钮点击事件 64 /// </summary> 65 /// <param name="sender"></param> 66 /// <param name="e"></param> 67 private void btnOpen_Click_1(object sender, RoutedEventArgs e) 68 { 69 //如果按钮内容是“打开串口”则进行打开串口否则进行关闭串口操作 70 if (btnOpen.Content.ToString() == "打开串口") 71 { 72 //尝试执行串口打开,出错则在界面进行提示 73 try 74 { 75 //判断串口是否已经打开 76 if (!com.IsOpen) 77 { 78 //设置串口参数**************************************开始 79 com.PortName = cmbPort.Text;//串口号 80 com.BaudRate = int.Parse(cmbBaudRate.Text);//波特率 81 com.DataBits = int.Parse(cmbDataBits.Text);//数据位 82 switch (cmbStopBits.SelectedIndex)//停止位 83 { 84 case 0: 85 com.StopBits = StopBits.One; break; 86 case 1: 87 com.StopBits = StopBits.Two; break; 88 case 2: 89 com.StopBits = StopBits.OnePointFive; break; 90 case 3: 91 com.StopBits = StopBits.None; break; 92 } 93 switch (cmbParity.SelectedIndex)//奇偶校验 94 { 95 case 0: com.Parity = Parity.None; break; 96 case 1: com.Parity = Parity.Odd; break; 97 case 2: com.Parity = Parity.Even; break; 98 } 99 //设置串口参数**************************************结束 100 com.Open();//打开串口 101 } 102 //设置按钮内容为关闭串口 103 btnOpen.Content = "关闭串口"; 104 //界面显示信息“串口已打开!” 105 txtStatus.Text = "串口已打开!"; 106 //启用发送按钮 107 btnSend.IsEnabled = true; 108 //如果界面选择应答模式,则启用接收按钮 109 if ((bool)rbAck.IsChecked) 110 btnReceive.IsEnabled = true; //应答模式,接收按钮有效 111 } 112 catch 113 { txtStatus.Text = "串口打开错误或串口不存在!"; } 114 } 115 else //关闭串口 116 117 try 118 { 119 if (com.IsOpen) 120 com.Close(); //关闭串口 121 btnOpen.Content = "打开串口"; 122 txtStatus.Text = "串口已关闭!"; 123 btnSend.IsEnabled = false; 124 if ((bool)rbAck.IsChecked) 125 btnReceive.IsEnabled = false; //应答模式,接收按钮无效 126 } 127 catch 128 { txtStatus.Text = "串口关闭错误或串口不存在!"; } 129 } 130 /// <summary> 131 /// 发送按钮点击事件 132 /// </summary> 133 /// <param name="sender"></param> 134 /// <param name="e"></param> 135 private void btnSend_Click_1(object sender, RoutedEventArgs e) 136 { 137 try 138 { 139 //发送的数据 140 byte[] data = null; 141 //是否16进制发送 142 if ((bool)chkSendHex.IsChecked) 143 data = getBytesFromString(txtSend.Text);//将数据转为16进制字符串 144 else 145 data = Encoding.Default.GetBytes(txtSend.Text);//将数据转为字符串 146 //向串口写入数据 147 com.Write(data, 0, data.Length); 148 } 149 catch (Exception err) 150 { txtStatus.Text = err.ToString(); } 151 } 152 /// <summary> 153 /// 接收按钮点击事件 154 /// </summary> 155 /// <param name="sender"></param> 156 /// <param name="e"></param> 157 private void btnReceive_Click_1(object sender, RoutedEventArgs e) 158 { 159 try 160 { 161 //应答模式 162 //获取串口缓冲区字节数 163 int count = com.BytesToRead; 164 //实例化接收串口数据的数组 165 byte[] readBuffer = new byte[count]; 166 //从串口缓冲区读取数据 167 com.Read(readBuffer, 0, count); 168 169 if ((bool)chkRecHex.IsChecked) 170 txtReceive.Text = getStringFromBytes(readBuffer); //转十六进制 171 else 172 txtReceive.Text = Encoding.Default.GetString(readBuffer); //字母、数字、汉字转换为字符串 173 174 } 175 catch (Exception err) 176 { txtStatus.Text = err.ToString(); } 177 } 178 179 /// <summary> 180 /// 响应模式 181 /// </summary> 182 /// <param name="sender"></param> 183 /// <param name="e"></param> 184 private void rbResponse_Checked_1(object sender, RoutedEventArgs e) 185 { 186 try 187 { 188 //设置接收按钮的启用属性 189 btnReceive.IsEnabled = (bool)rbAck.IsChecked; 190 if ((bool)rbResponse.IsChecked) 191 com.DataReceived += new SerialDataReceivedEventHandler(com_DataReceived); //加载接收事件 192 } 193 catch (Exception err) 194 { txtStatus.Text = err.ToString(); } 195 } 196 /// <summary> 197 /// 应答模式 198 /// </summary> 199 /// <param name="sender"></param> 200 /// <param name="e"></param> 201 private void rbAck_Checked_1(object sender, RoutedEventArgs e) 202 { 203 try 204 { 205 btnReceive.IsEnabled = (bool)rbAck.IsChecked; 206 if ((bool)rbAck.IsChecked) 207 com.DataReceived -= new SerialDataReceivedEventHandler(com_DataReceived); //移除接收事件 208 } 209 catch (Exception err) 210 { txtStatus.Text = err.ToString(); } 211 } 212 /// <summary> 213 /// 响应模式时,串口接收数据事件 214 /// </summary> 215 /// <param name="sender"></param> 216 /// <param name="e"></param> 217 private void com_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) 218 { 219 try 220 { 221 bool RecHex = false; 222 Dispatcher.Invoke(new Action(() => 223 { 224 //获取界面控件复选框是否以16进制显示 225 RecHex = (bool)chkRecHex.IsChecked; 226 })); 227 //获取串口缓冲区字节数 228 int count = com.BytesToRead; 229 //实例化接收串口数据的数组 230 byte[] readBuffer = new byte[count]; 231 //从串口缓冲区读取数据 232 com.Read(readBuffer, 0, count); 233 string strReceive = ""; 234 if (RecHex) 235 strReceive = getStringFromBytes(readBuffer); //转十六进制 236 else 237 strReceive = Encoding.Default.GetString(readBuffer); //字母、数字、汉字转换为字符串 238 239 240 Dispatcher.Invoke(new Action(() => 241 { 242 txtReceive.Text = strReceive; 243 })); 244 245 } 246 catch (Exception err) 247 { 248 Dispatcher.Invoke(new Action(() => 249 { 250 txtStatus.Text = err.ToString(); 251 })); 252 } 253 254 } 255 /// <summary> 256 /// 以十六进制数据发送转换时,显示转换对应数据 257 /// </summary> 258 /// <param name="sender"></param> 259 /// <param name="e"></param> 260 private void chkSendHex_CheckedChanged(object sender, EventArgs e) 261 { 262 try 263 { 264 if ((bool)chkSendHex.IsChecked) 265 txtSend.Text = getStringFromBytes(Encoding.Default.GetBytes(txtSend.Text)); 266 else 267 txtSend.Text = Encoding.Default.GetString(getBytesFromString(txtSend.Text)); 268 } 269 catch 270 { txtStatus.Text = "数据转换出错,请输入正确的数据格式"; } 271 } 272 /// <summary> 273 /// 以十六进制数据显示接收数据时,显示对应数据 274 /// </summary> 275 /// <param name="sender"></param> 276 /// <param name="e"></param> 277 private void chkRecHex_CheckedChanged(object sender, EventArgs e) 278 { 279 try 280 { 281 if ((bool)chkRecHex.IsChecked) 282 txtReceive.Text = getStringFromBytes(Encoding.Default.GetBytes(txtReceive.Text)); 283 else 284 txtReceive.Text = Encoding.Default.GetString(getBytesFromString(txtReceive.Text)); 285 } 286 catch 287 { txtStatus.Text = "数据转换出错,请输入正确的数据格式"; } 288 } 289 290 /// <summary> 291 /// 把十六进制格式的字符串转换成字节数组。 292 /// </summary> 293 /// <param name="pString">要转换的十六进制格式的字符串</param> 294 /// <returns>返回字节数组。</returns> 295 public static byte[] getBytesFromString(string pString) 296 { 297 string[] str = pString.Split(' '); //把十六进制格式的字符串按空格转换为字符串数组。 298 byte[] bytes = new byte[str.Length]; //定义字节数组并初始化,长度为字符串数组的长度。 299 for (int i = 0; i < str.Length; i++) //遍历字符串数组,把每个字符串转换成字节类型赋值给每个字节变量。 300 bytes[i] = Convert.ToByte(Convert.ToInt32(str[i], 16)); 301 return bytes; //返回字节数组。 302 } 303 304 /// <summary> 305 /// 把字节数组转换为十六进制格式的字符串。 306 /// </summary> 307 /// <param name="pByte">要转换的字节数组。</param> 308 /// <returns>返回十六进制格式的字符串。</returns> 309 public static string getStringFromBytes(byte[] pByte) 310 { 311 string str = ""; //定义字符串类型临时变量。 312 //遍历字节数组,把每个字节转换成十六进制字符串,不足两位前面添“0”,以空格分隔累加到字符串变量里。 313 for (int i = 0; i < pByte.Length; i++) 314 str += (pByte[i].ToString("X").PadLeft(2, '0') + " "); 315 str = str.TrimEnd(' '); //去掉字符串末尾的空格。 316 return str; //返回字符串临时变量。 317 } 318 } 319 }
1 package com.example.fandemonew; 2 3 import com.example.demo.library.SerialPort; 4 import com.example.demo.library.ShareData; 5 import com.example.demo.library.ZigBeeService; 6 import com.newland.jni.Linuxc; 7 8 import android.os.Bundle; 9 import android.app.Activity; 10 import android.content.Intent; 11 import android.view.Menu; 12 import android.view.View; 13 import android.view.View.OnClickListener; 14 import android.widget.AdapterView; 15 import android.widget.AdapterView.OnItemSelectedListener; 16 import android.widget.ArrayAdapter; 17 import android.widget.Spinner; 18 import android.widget.Toast; 19 20 public class MainActivity extends Activity { 21 22 //风扇1命令 23 private char[] fanOpenCommand= {0xFF,0xF5,0x05,0x02,0x34,0x12,0x00,0x01,0x00}; 24 private char[] fanCloseCommand= {0xFF,0xF5,0x05,0x02,0x34,0x12,0x00,0x02,0x00}; 25 //风扇2命令 26 private char[] fan2OpenCommand= {0xFF,0xF5,0x05,0x02,0x01,0x00,0x00,0x01,0x03}; 27 private char[] fan2CloseCommand= {0xFF,0xF5,0x05,0x02,0x01,0x00,0x00,0x02,0x02}; 28 //控制对象 29 private String mControlName; 30 31 @Override 32 protected void onCreate(Bundle savedInstanceState) { 33 super.onCreate(savedInstanceState); 34 setContentView(R.layout.activity_main); 35 //打开串口 36 OpenZigBee(); 37 //初始化UI 38 initView(); 39 } 40 41 //打开串口 42 private void OpenZigBee() { 43 //判断串门是否打开,如果打开则关闭 44 if (ShareData.com_fdZigBee > 0) 45 SerialPort.closePort(ShareData.com_fdZigBee); 46 // 读取串口设置值,无线传感网默认值为0 47 ShareData.com_fdZigBee = SerialPort.openPort(1, 0, 5); 48 if (ShareData.com_fdZigBee == -1) { 49 Toast.makeText(this, "串口打开失败", Toast.LENGTH_LONG).show(); 50 } 51 //开启硬件交互服务 52 Intent intent = new Intent(this, ZigBeeService.class); 53 this.startService(intent); 54 } 55 56 //初始化UI 57 private void initView(){ 58 //初始化下拉框,及填充下拉框的值 59 String[] strs = {"请选择","风扇1","风扇2"}; 60 Spinner sp = (Spinner) findViewById(R.id.sp); 61 ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, strs); 62 sp.setAdapter(adapter); 63 //下拉框项 64 sp.setOnItemSelectedListener(new OnItemSelectedListener() { 65 66 @Override 67 public void onItemSelected(AdapterView<?> parent, View arg1, 68 int position, long arg3) { 69 String itemName = parent.getItemAtPosition(position).toString(); 70 mControlName = itemName; 71 } 72 73 @Override 74 public void onNothingSelected(AdapterView<?> arg0) { 75 // TODO Auto-generated method stub 76 77 } 78 }); 79 //设置打开按钮监听 80 findViewById(R.id.open_btn).setOnClickListener(new OnClickListener() { 81 82 @Override 83 public void onClick(View arg0) { 84 if("风扇1".equals(mControlName)){ 85 sendCMD(fanOpenCommand); 86 }else if("风扇2".equals(mControlName)){ 87 sendCMD(fan2OpenCommand); 88 } 89 } 90 }); 91 //设置关闭按钮监听 92 findViewById(R.id.close_btn).setOnClickListener(new OnClickListener() { 93 94 @Override 95 public void onClick(View arg0) { 96 if("风扇1".equals(mControlName)){ 97 sendCMD(fanCloseCommand); 98 }else if("风扇2".equals(mControlName)){ 99 sendCMD(fan2CloseCommand); 100 } 101 } 102 }); 103 } 104 105 //发送命令 106 private static void sendCMD(char[] cmd) { 107 String strcmd = String.valueOf(cmd); 108 Linuxc.sendMsgUartHex(ShareData.com_fdZigBee, strcmd, strcmd.length()); 109 } 110 111 @Override 112 public boolean onCreateOptionsMenu(Menu menu) { 113 // Inflate the menu; this adds items to the action bar if it is present. 114 getMenuInflater().inflate(R.menu.main, menu); 115 return true; 116 } 117 118 }