我选用的GPRS模块是西门子的MC52I,由于降低功耗要用到该模块的休眠模式(AT+CFUN=设置具体的休眠模式)。而休眠模式必须先使能RTS/CTS流控制(AT\Q3设置)。MC52I的RTS和CTS引脚直接连在MSP430F149的I/O口上,具体怎么实现流控制还不太明白,请大家多多指教 经过自己研究终于弄懂是怎么个回事了 现在发出来,有不对的地方望大家指正 MC52I可以通过AT\Q[num] (num=0/1/2/3)选择不使能流控制(num=0),XON/XOFF软件流控制(num=1),仅模块的CTS有效(num=2)和RTS/CTS硬件流控制四种方式。值得注意的是通常情况下MC52I不需要进行这方面的设置,直接默认为不使能流控制方式,但是当你需要使用MC52I的休眠模式时就必须要设置为RTS/CTS硬件流控制即发送AT指令AT\Q3。此时再发送AT指令AT+CFUN=[num] (num=0/5/6/7/8/9 休眠状态, 1表示全功能状态)设置成相关休眠模式即可。如果仅这样做,当你调试时会发现单片机串口收不到MC52I发送过来的数据,也就是说无法进行通信。这跟RTS/CTS没有设置好有关系。 下面介绍下modem下的RTS和CTS定义: RTS有效(低电平)表示DTE(这里就是单片机)可以收,CTS有效表示modem可以收,这两个信号互相独立,分别表示一个方向的流量情况。具体处理如下(借鉴了别人的描述 dengm 发表于 2005-1-14 07:52 侃单片机) 单片机端: 发送数据—— 当发现(不一定及时发现)CTS无效时,停止发送; 当发现(不一定及时发现)CTS有效时,恢复发送; 接收数据—— 0<M<N<LEN_OF_RX_BUFFERS 当接收buffers中的bytes<M 时,给 RTS 有效信号; 当接收buffers中的bytes>N 时,给 RTS 无效信号; modem端: 同上,但RTS与CTS交换 在这里modem端我们无需处理,只需要监测CTS的电平即可,针对上述的单片机串口无法接收到数据的问题,使连接RTS的I/O口输出低电平(如果一直设为低电平表示单片机一直允许接收数据,当传输数据非常大的时候会造成数据丢失,因此需要按照上面给出的bytes>N时,使RTS无效),然后再调试就能够发现单片机接收到modem返回的数据了。 MC52I和单片机串口连接图 图中TXD、RXD直接连到430单片机上的串口即可,这里需要注意的是MC52I的RXD是发送数据的,TXD是接收数据的。所以要按照图中的RXD连接到单片机的RXD,TXD连接到单片机的TXD。我当时就是没注意连错了害的最后跳线,呵呵。RTS、CTS、DTR、DSR、DCD、RING都直接连到单片机的I/O口上即可,RING最好是连到具有中断功能的I/O口上,因为当MC52I接收到来电信号、短信以及上网传过来的数据时都会引起这个引脚产生中断,可以方便处理。RTS/CTS就是上面用的情况,DTR/DSR、DCD没用过,不过最好也连上,防止以后用到。下图为各个管脚的输入输出状态: 复制代码 #include <msp430x14x.h> #include "string.h" //GPRS管脚定义 #define GPRS_IGT_HIGH P1DIR|=BIT6,P1OUT|=BIT6//点火引脚 高电平 #define GPRS_IGT_LOW P1DIR|=BIT6,P1OUT&=~BIT6//点火引脚 低电平 #define GPRS_RTS_H P1DIR|=BIT2,P1OUT|=BIT2 //RTS输出高电平 #define GPRS_RTS_L P1DIR|=BIT2,P1OUT&=~BIT2 //RTS输出低电平 #define GPRS_CTS_FLAG P1DIR&=~BIT4 //设置CTS线为输入线 #define GPRS_CTS (P1IN&BIT4) #define Len 150 typedef unsigned int uint; typedef unsigned char uchar; char recieve_data[150]; uint count = 0; uchar send_error = 0; //****************************************************** //延时函数 void delay(uint time) { uint i,j; for(i=0;i<1000;i++) for(j=0;j<time;j++); } //****************************************************** //初始化时钟 void int_clk() { uchar i = 0; BCSCTL1&=~XT2OFF; //打开XT振荡器 BCSCTL2|=SELM1+SELS;//MCLK 8M and SMCLK 1M do { IFG1 &= ~OFIFG; //清除振荡错误标志 for(i = 0; i < 100; i++) _NOP(); //延时等待 } while ((IFG1 & OFIFG) != 0); //如果标志为1继续循环等待 IFG1&=~OFIFG; } //******************************************************* //串口:初始化函数,接收中断处理函数、发送数据函数 //******************************************************* //初始化串口1 void init_Usart1() { U1CTL |= SWRST; //复位串口 U1CTL |= CHAR; //8位数据 U1TCTL |= SSEL1; //选择SMCLK作为时钟信号 UBR01 = 0x8a; UBR11 = 0x00; //使32KHz晶振时波特率为19200bps UMCTL1 = 0xde; ME2 |= 0x30; //UART接收模块允许 UCTL1 &= ~SWRST; //SWRST复位,USART允许 IE2 |= URXIE1; //接收中断允许 P3SEL = 0xC0; //P3.6 P3.7 P3DIR = 0X40; //P3.6 输出,P3.7 输入 } //****************************************************** //串口1中断服务处理函数 #pragma vector=UART1RX_VECTOR __interrupt void UART1_RX_ISR(void) { char data = 0; data = U1RXBUF; recieve_data[count++] = data; if(count>149) { count=0; } } //发送一个字符 void SendByte(uchar data) { while((IFG2&UTXIFG1)==0);//判断发送缓冲区是否结束 U1TXBUF=data; } //****************************************************** //清楚接收存储区内容 void GPRS_Clearstring() { uchar len=0; count=0; //关闭中断 IE2 &= ~URXIE1;//禁止接收中断 for(;len<Len;len++) recieve_data[len]='\0'; //使能中断 IE2|=URXIE1;//使能接收中断 } //****************************************************** //将命令写入usart数据寄存器 void Send_Data(char * strptr) { uchar i,j; j = strlen(strptr); for(i=0;i<j;i++) { SendByte(strptr[I]); } } //******************************************************** //GPRS模块:启动函数、关闭函数、初始化函数 //******************************************************** //GPRS启动函数 void GPRS_Start(void) { GPRS_IGT_HIGH; delay(1); GPRS_IGT_LOW; delay(100); GPRS_IGT_HIGH; } //****************************************************** //GPRS关闭函数 void GPRS_Close(void) { delay(100); Send_Data("AT^SMSO\r\n"); delay(100); } //****************************************************** //GPRS初始化函数 void GPRS_Init(void) { Send_Data("AT\\Q3\r\n");//设置成RTS/CTS硬件流控制模式 delay(1000); Send_Data("ATE0\r\n"); //关闭回显 delay(100); Send_Data("AT+CMGF=1\r\n");//采用文本方式 delay(100); Send_Data("AT+CFUN=7\r\n");//设置循环功耗节省模式7 delay(100); Send_Data("AT+CFUN\?\r\n");//用于查询设置模式是否成功 delay(100); } //****************************************************** //发送短信函数 //****************************************************** void SendMessage(char *num,char *massge) { char instuct[]="AT+CMGS=\""; char numinstuct[27]; strcpy(numinstuct,instuct); //字符串拷贝函数 strcat(numinstuct,num); //字符串连接函数 strcat(numinstuct,"\"\r\n"); Send_Data(numinstuct); //AT+CMGS=\"13607088025\" 发送接收终端号码 Send_Data(massge); //发送短信内容 SendByte(0x1a); //相当于Ctrl+Z } //*********************************************************** //主函数:启动GPRS模块,设置为循环低功耗 //模式(AT+CFUN=8),发送一条短信,关闭GPRS模块 //*********************************************************** void main() { WDTCTL=WDTPW+WDTHOLD;//关闭看门狗 int_clk(); //系统时钟初始化 init_Usart1(); //初始化串口 GPRS_RTS_L; //设置RTS为低电平,表示单片机一直可以接收数据 //如果发送数据很大,请按照之前描述的对RTS进行适当处理 GPRS_Start(); _EINT();//使能中断 delay(2000); GPRS_Init(); Send_Data("AT\r\n");//发送个AT测试下 SendMessage("13612345678","hello");//发送短信 GPRS_Close();//关闭模块 while(1); } 转自:http://bbs.21ic.com/icview-285499-1-1.html