|
从网上找来的一个串口发送AT指令给短信收发设备没有返回值的问题:
请教一个关于串口连接短信收发设备发短信的问题,我看这里也有很多贴子时关于这个问题的,可是我没有我的答案,我用C#写的,打开串口后,发送“AT\r”,返回“OK”正常,但是再发送其他AT指令的话就都没有返回值了。但奇怪的是,我用超级终端打开过串口后,再在程序里打开串口,发送其他AT指令就会有正常的返回值了(例如:“AT+CGMI\r”)。请问有人知道是怎么回事吗?
回答:
我也碰到过这种 问题 研究了很长时间才解决,发送完 号码时候 要发送个 特殊的内容,在超级终端里面是不用输入那个特殊的标志的
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));
}
/// <summary>
/// 判读 com口是不是打开的
/// </summary>
/// <returns>打开 true ,否则 false</returns>
public bool IsOpen()
{
return port.IsOpen;
}
/// <summary>
/// 初始化 Modem
/// </summary>
public void Initial()
{
if (!this.IsOpen())
{
this.Open();
}
string result = "";
string all = "";
string newLine = Environment.NewLine;
if (this.Check("AT" + Environment.NewLine, 100).ToLower() != "true")
{
this.port.Write("32"); //如果处于发送状态则强制结束
this.port.Write("AT"+Environment.NewLine);
}
this.SendCommand("AT+CMEE=1" + newLine, ref result, 1000); //设置报错方式
all += result;
this.SendCommand("AT+CMGF=0"+newLine,ref result,500);//设置为PDU方式
all+=result ;
this.SendCommand("AT+CNMI=2,2" + newLine, ref result, 500); //不接收短信,不接收小区广播方式 AT+CSMS=1,0,1,0 // AT+CNMI=2,2 设置为
all+=result ;
this.SendCommand("AT+CSMP=17,167,0,8" + newLine, ref result, 500); //短信在短信中心保存24小时
all += result;
this.SendCommand("AT&w"+newLine ,ref result ,500 ); //保存以上设置
all += result;
if (all.Length - all.ToLower().Replace("ok", "").Length !=10) //结果中 不够 5个 ok
{
Exception e = new Exception("设置 ModeM出错");
throw e;
}
}
/// <summary>
/// 获得配置文件
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
///
public static string GetConfig(string key)
{
return ConfigurationSettings.AppSettings[key];
}
/// <summary>
/// 检测 短信收发设备 是否有信号 无信号可能说明没钱了
/// </summary>
/// <param name="cmd"></param>
/// <param name="time"></param>
/// <returns></returns>
public string Check(string cmd, int time)
{
string rst = "";
this.SendCommand(cmd, ref rst, 1000);
if (rst.ToLower().Contains("ok"))
return "true";
return rst;
}
/// <summary>
/// 发送短息 包括超长短信
/// </summary>
/// <param name="phone">接收方号码</param>
/// <param name="msg">要发送的信息</param>
/// <returns></returns>
public int SendMessage(string phone, string msg)
{
int star = 0; //用于分割长短信
int last = msg.Length; //短信内容长度
string buffer = "more"; //用来标识长短信 参考参数
const int longmsg = 67; // 超长短信每条个容纳67个unicode字符
int i = 1; //用于计数发送的第几条短信
int result = 0;
if (msg.Length == 0||phone .Length<11) // 如果短信长度为0 或者手机号码长度小于11返回
return 0;
if (msg.Length > 70) //需要短信分页的 如果发送信息长度小于等于70则用 单条发送的方法
{
string[] txt = new string[(msg.Length /67)+1]; //超长短信是67个汉字分割的,分割长几条发送
for (star = 0; star < txt.Length; star++)
{
txt[star] = msg.Substring(star *67, (last /67 - star) > 0 ? 67 : (last - star * 67)); //短信分页
}
//以下是发送功能入口
foreach (string t in txt)
{
result=this.BaseSendMessage(phone, t, buffer,txt.Length,i);
if (result>0)
{
i++;
continue;
}
else //有一条发送失败则 返回
{
//break;
return result;
}
}
return 1; //全部发送成功
}
else
{
//单条短信发送方法入口
if (this.BaseSendMessage(phone, msg,"",0,0) > 0) //发送成功
return 1;
else
return 0;
}
}
/// <summary>
/// 发送短信的函数
/// </summary>
/// <param name="phone">接收的号码</param>
/// <param name="msg">单条发送内容</param>
/// <param name="buffer">参考标识</param>
/// <param name="count">长短信中共几条</param>
/// <param name="index">长短信中当前是第几条</param>
/// <returns>状态标志 1:发送成功 0:发送失败 2:AT+CMGS 失败 </returns>
public int BaseSendMessage(string phone, string msg,string buffer,int count,int index)
{
string result = ""; //用于保存端口返回结果
string smg ; //用于保存编码后的发送信息
if (buffer.Length > 1) //长短信 编码后正文
smg = this.PDU.smsDecodedsms( phone, msg, count.ToString() , index.ToString() ) + "32";
else
smg = this.PDU.smsDecodedsms(phone, msg) + "32"; //单条短信编码后的正文
//发送前的准备工作
if (this.Check("AT" + Environment.NewLine, 100).ToLower() != "true")
{
this.port.Write("32"); //如果处于发送状态则强制结束
this.port.Write("AT" + Environment.NewLine);
}
//发送 AT+CMGS 命令
this.SendCommand("AT+CMGS=" + this.PDU.nLength+ "\n", ref result, 1000); //+buffer.Length).ToString()+
if (result.ToLower().Contains(">"))
{
//短信正文发送
this.SendCommand(smg, ref result, 6000); //6秒钟的发送 时间足够 机器反应了
if (result.ToLower().Contains("ok"))
{
return 1;
}
else //正文发送失败再发送一次
{
//发送 AT+CMGS 命令
this.SendCommand("AT+CMGS=" + this.PDU.nLength + "\n", ref result, 10000); //+buffer.Length).ToString()+
this.SendCommand(smg, ref result, 10000); //10秒钟的发送 时间足够 机器反应了
if (result.ToLower().Contains("ok"))
{
return 1;
}
else
return 0;
}
}// AT+CMGS 命令失败
else
{
return 2;
}
}
/// <summary>
/// 检查信号 目前无效
/// </summary>
/// <returns></returns>
public bool CheckSingal()
{
string s = ""; //保存结果
if (this.Check("AT" + Environment.NewLine, 100).ToLower() != "true")
{
this.port.Write("32"); //如果处于发送状态则强制结束
this.port.Write("AT" + Environment.NewLine);
}
this.SendCommand("AT+CREG? " + Environment.NewLine, ref s, 5000);
if (!s.Contains("CREG: 0,1")) // sim 没信号了
{
MessageBox.Show("天线未接好,或者手机欠费了!");
return false ;
}
return true;
}
}
/// <summary>
/// 接收短信事件代理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public delegate void PortDataReceivedEventHandle(object sender, PortDataReciveEventArgs e);
/// <summary>
///
/// </summary>
public class PortDataReciveEventArgs : EventArgs
{
/// <summary>
///
/// </summary>
public PortDataReciveEventArgs()
{
this.data = null;
}
/// <summary>
///
/// </summary>
/// <param name="data"></param>
public PortDataReciveEventArgs(byte[] data)
{
this.data = data;
}
/// <summary>
///
/// </summary>
private byte[] data;
/// <summary>
///
/// </summary>
public byte[] Data
{
get { return data; }
set { data = value; }
}
}
|
|