首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

串口发送AT指令给短信猫没有返回值,该如何解决

2012-06-06 
串口发送AT指令给短信猫没有返回值各位,请教一个关于串口连接短信猫发短信的问题,我看这里也有很多贴子时

串口发送AT指令给短信猫没有返回值
各位,请教一个关于串口连接短信猫发短信的问题,我看这里也有很多贴子时关于这个问题的,可是我没有我的答案,我用C#写的,打开串口后,发送“AT\r”,返回“OK”正常,但是再发送其他AT指令的话就都没有返回值了。但奇怪的是,我用超级终端打开过串口后,再在程序里打开串口,发送其他AT指令就会有正常的返回值了(例如:“AT+CGMI\r”)。请问有人知道是怎么回事吗?

[解决办法]
串口通信是独占式的,你如果用超级终端打开串口后没有退出来,你的程序中再打开相同的串口,是不应该能够打开的。
在.NET中用Serialport组件来实现串口通信是非常方便的。设置好串口的参数并打开,向串口发送指令,利用SerialPort的DataReceived事件接收数据就可以了。请参考下面的技术要点。

技术要点: 
(1).首先,SerialPort的ReceivedBytesThreshold先设置成1,表示只要有1个字符送达端口时便触发DataReceived事件 
(2).当DataReceived触发时,先把ReceivedBytesThreshold设置成一个比较大的值,达到读取本次端口数据时,不再触发DataReceived. 
(3).循环读取端口中的数据,直至读完。 
(4).移除读取数据中的非法字符。 
(5).触发一个后台线程处理收到的数据。 
(6).在finally中把ReceivedBytesThreshold重置回1 

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) 

if (sender.GetType() != typeof(System.IO.Ports.SerialPort)) 

return; 

string strReceive = string.Empty; 
string strCollect = string.Empty; 
System.IO.Ports.SerialPort comPort = (System.IO.Ports.SerialPort)sender; 

try 

comPort.ReceivedBytesThreshold = comPort.ReadBufferSize; 
while (true) 

strReceive = comPort.ReadExisting(); 
if (string.Equals(strReceive, string.Empty)) 

break; 

else 

strCollect += strReceive; 
Application.DoEvents(); 
Thread.Sleep(100); 


strCollect = strCollect.Replace("\0", string.Empty); 
strCollect = strCollect.Replace("\r\n", string.Empty); 
strCollect = strCollect.Replace("\r", string.Empty); 
strCollect = strCollect.Replace("\n", string.Empty); 

if (!this.bIsHandleCom) 

this.bIsHandleCom = true; 
mReceiveData = strCollect; 
if (ReceiveDataParserEvent != null) 
ReceiveDataParserEvent(mReceiveData); 
if (ThreadReceiveParser != null && !ThreadReceiveParser.IsAlive) 

ThreadReceiveParser.Start(); 




catch (Exception ex) 

MessageBox.Show(this, ex.ToString(), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); 

finally 

comPort.ReceivedBytesThreshold = 1; 

}
[解决办法]
我也碰到过这种 问题 研究了很长时间才解决,发送完 号码时候 要发送个 特殊的内容,在超级终端里面是不用输入那个特殊的标志的
public class PortData
{
public event PortDataReceivedEventHandle Received; //接收事件
public event SerialErrorReceivedEventHandler Error; // 接收事件异常处理
private SerialPort port; //端口
private bool ReceiveEventFlag = false; //接收事件是否有效 false表示有效
private PDUdecoding PDU; //PDU 编码类
/// <summary>
/// 构造函数


/// </summary>
/// <param name="sPortName">端口名称 "com1,com2.... com255"</param>
/// <param name="baudrate">波特率</param>
/// <param name="parity">校验</param>
/// <param name="dataBits">数据位</param>
/// <param name="stopBits">停止位数</param>
/// <param name="RtimeOut">读端口时间超时</param>
/// <param name="WtimeOut">写端口时间超时</param>
public PortData(string sPortName, int baudrate,Parity parity , int dataBits,StopBits stopBits,int RtimeOut,int WtimeOut)
{
port = new SerialPort(sPortName, baudrate, parity, 8, stopBits);
this.PDU = new PDUdecoding();
port.RtsEnable = true;
port.ReadTimeout = RtimeOut;
port.WriteTimeout = WtimeOut;
port.DataReceived += new SerialDataReceivedEventHandler(DataReceived);
port.ErrorReceived += new SerialErrorReceivedEventHandler(ErrorEvent);
this.Open(); 
}
/// <summary>
/// 析构函数
/// </summary>
~PortData()
{
Close();
}
/// <summary>
/// 打开com口
/// </summary>
public void Open()
{
if (!port.IsOpen)
{
try
{
port.Open();
}
catch(Exception ex)
{
throw ex; 
}
}
}
/// <summary>
/// 关闭com口
/// </summary>
public void Close()
{
if (port.IsOpen)
{
try
{
port.Close();
}
catch(Exception ex)
{
throw ex;
}
}
}
//数据发送
/// <summary>
/// 暂无使用
/// </summary>
/// <param name="data"></param>
public void SendData(byte[] data)
{
if (port.IsOpen)
{
port.Write(data, 0, data.Length);
}
}
/// <summary>
/// 暂无使用
/// </summary>
/// <param name="data"></param>
/// <param name="offset"></param>
/// <param name="count"></param>
public void SendData(byte[] data,int offset,int count)
{
if (port.IsOpen)
{
port.Write(data, offset, count);
}
}
/// <summary>
/// 发送各种命令
/// </summary>
/// <param name="Sendcmd">命令正文</param>
/// <param name="ReceiveData">返回结果</param>
/// <param name="Overtime">发送超时</param>
/// <returns>发送标识</returns>
private int SendCommand(string Sendcmd, ref string ReceiveData,int Overtime)
{
if (!port.IsOpen)
{
this.Open(); 
}
if (port.IsOpen)
{
try
{
ReceiveEventFlag = true; //关闭接收事件
port.DiscardInBuffer(); //清空接收缓冲区
port.Write(Sendcmd); //写入命令
int num = 0, ret = 0;
while (num++ < Overtime)


{
System.Threading.Thread.Sleep(1000);
if (port.BytesToRead > 0) //存在需要读取的数据 
{
ret = port.BytesToRead;
break;
}
else
System.Threading.Thread.Sleep(1); //延时1毫秒 等待数据发送到端口上
}
if (ret > 0) //如果要读取的数据存在 读取数据 并且 打开接收
{
ReceiveData = port.ReadExisting(); //先读取再激活接收事件 ReadExecting()
ReceiveEventFlag = false; //打开事件
}
//如果是发送短信则休息3秒
if (ReceiveData.ToLower().Contains("cmgs:"))
System.Threading.Thread.Sleep(3000);
return ret;
}
catch (Exception ex)
{
throw ex;
}
}
return -1;
}
/// <summary>
/// 处理异常
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void ErrorEvent(object sender, SerialErrorReceivedEventArgs e)
{
if(Error != null) Error(sender, e);
}
/// <summary>
/// 接收短信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//禁止接收事件时直接退出
if (ReceiveEventFlag) return;
byte[] data = new byte[port.BytesToRead];
this. port.Read(data, 0, data.Length);
if (Received != null) Received(sender, new PortDataReciveEventArgs(data));
}
 
[解决办法]
我这几天也为这个头疼。。晚上回来。。终于发现问题了。。我个人觉得哈。。也许不是很准确。。有待明天去公司连上硬件测试通过。。但先在这说下。。是发送指令的问题。。发送指令那边也就是serialPort1.WriteLine("23 30 31 0d");
有的硬件是需要用16进制的指令来的。。有的硬件是这种的。。COM.Write("AT+CMGD=" + Id + "\r");
所以。。第二种是正确的。。如果是第一种的话。。应该要有个转换。。转换方法如下。。
byte[] bytesSend = System.Text.Encoding.Default.GetBytes("23 30 31 0d");
serialPort1.Write(bytesSend, 0, bytesSend.Length);
然后获取指令就应该是[code=C#][/code]
/// <summary>
/// 开启接收数据线程
/// </summary>
private void ReceiveData(SerialPort serialPort)
{
//同步阻塞接收数据线程
Thread threadReceive = new Thread(new ParameterizedThreadStart(SynReceiveData));
threadReceive.Start(serialPort);

//也可用异步接收数据线程
//Thread threadReceiveSub = new Thread(new ParameterizedThreadStart(AsyReceiveData));
//threadReceiveSub.Start(serialPort);

}
//同步阻塞读取
private void SynReceiveData(object serialPortobj)
{
SerialPort serialPort = (SerialPort)serialPortobj;
System.Threading.Thread.Sleep(0);
serialPort.ReadTimeout = 1000;
try
{
//阻塞到读取数据或超时(这里为2秒)
byte firstByte = Convert.ToByte(serialPort.ReadByte());
int bytesRead = serialPort.BytesToRead;
byte[] bytesData = new byte[bytesRead + 1];
bytesData[0] = firstByte;
for (int i = 1; i <= bytesRead; i++)

bytesData[i] = Convert.ToByte(serialPort.ReadByte()); 
}
this.label1.Text = System.Text.Encoding.Default.GetString(bytesData);


}
catch (Exception e)
{
MessageBox.Show(e.Message);
//处理超时错误
}

serialPort.Close();

}
等待我明天通过测试吧。。哈哈哈。。应该没问题了。。

热点排行