|         我在做一个基于STM32的驱动GPRS模块(TC35)给手机发短信,用AT指令测试连通性,即通过STM32串口发"AT\r“ 给GPRS模块,我用的是原子哥的MINI STM32开发板,由于开发板没有 RS323串口,所以我就用杜邦线连接STM32的串口2,即PA2、PA3,现在遇到的问题是发送完后,接收的并不是OK,可以推断没有连通,之后的信息发送自然做不了。我不知道程序哪里有问题,我已经仔细学习了STM32的串口、数据接收和发送,有没有那位大哥做过,帮我看看程序到底哪里出错了,先谢谢了,急,在线等!下面是主要代码:
 usart.c
 #ifdef EN_USART1_RX   //如果使能了接收
 //串口1中断服务程序
 //注意,读取USARTx->SR能避免莫名其妙的错误
 u8 USART_RX_BUF[64];     //接收缓冲,最大64个字节.
 //接收状态
 //bit7,接收完成标志
 //bit6,接收到0x0d
 //bit5~0,接收到的有效字节数目
 u8 USART_RX_STA=0;       //接收状态标记
 void USART1_IRQHandler(void)
 {
 u8 res;
 if(USART1->SR&(1<<5))//接收到数据
 {
 res=USART1->DR;
 if((USART_RX_STA&0x80)==0)//接收未完成
 {
 if(USART_RX_STA&0x40)//接收到了0x0d
 {
 if(res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
 else USART_RX_STA|=0x80; //接收完成了
 }else //还没收到0X0D
 {
 if(res==0x0d)USART_RX_STA|=0x40;
 else
 {
 USART_RX_BUF[USART_RX_STA&0X3F]=res;
 USART_RX_STA++;
 if(USART_RX_STA>63)USART_RX_STA=0;//接收数据错误,重新开始接收
 }
 }
 }
 }
 }
 #endif
 #ifdef EN_USART2_RX   //如果使能了接收
 u8 USART2_RX_BUF[64];     //接收缓冲,最大64个字节.
 u8 USART2_RX_STA=0;       //接收状态标记
 void USART2_IRQHandler(void)
 { u8 res2;
 if(USART2->SR&(1<<5))//接收到数据
 {
 res2=USART2->DR;
 USART2_RX_BUF[USART2_RX_STA]=res2;
 USART2_RX_STA++;
 if(USART2_RX_STA>63)USART2_RX_STA=0;//接收数据错误,重新开始接收
 }
 
 }
 #endif
 //初始化IO 串口1
 //pclk2
  CLK2时钟频率(Mhz) //bound:波特率
 //CHECK OK
 //091209
 void uart_init(u32 pclk2,u32 bound)
 {
 float temp;
 u16 mantissa;
 u16 fraction;
 temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV
 mantissa=temp;     //得到整数部分
 fraction=(temp-mantissa)*16; //得到小数部分
 mantissa<<=4;
 mantissa+=fraction;
 RCC->APB2ENR|=1<<2;   //使能PORTA口时钟
 RCC->APB2ENR|=1<<14;  //使能串口时钟
 GPIOA->CRH&=0XFFFFF00F;
 GPIOA->CRH|=0X000008B0;//IO状态设置
 
 RCC->APB2RSTR|=1<<14;   //复位串口1
 RCC->APB2RSTR&=~(1<<14);//停止复位
 //波特率设置
 USART1->BRR=mantissa; // 波特率设置
 USART1->CR1|=0X200C;  //1位停止,无校验位.
 #ifdef EN_USART1_RX    //如果使能了接收
 //使能接收中断
 USART1->CR1|=1<<8;    //PE中断使能
 USART1->CR1|=1<<5;    //接收缓冲区非空中断使能
 MY_NVIC_Init(3,3,USART1_IRQChannel,2);//组2,最低优先级
 #endif
 }
 void uart2_init(u32 pclk2,u32 bound)
 {
 float temp;
 u16 mantissa;
 u16 fraction;
 temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV
 mantissa=temp;     //得到整数部分
 fraction=(temp-mantissa)*16; //得到小数部分
 mantissa<<=4;
 mantissa+=fraction;
 RCC->APB2ENR|=1<<2;   //使能PORTA口时钟
 RCC->APB1ENR|=1<<17;  //使能串口时钟
 GPIOA->CRL&=0XFFFF00FF;
 GPIOA->CRL|=0X00008B00;//IO状态设置
 
 RCC->APB1RSTR|=1<<17;   //复位串口1
 RCC->APB1RSTR&=~(1<<17);//停止复位
 //波特率设置
 USART2->BRR=mantissa; // 波特率设置
 USART2->CR1|=0X200C;  //1位停止,无校验位.
 #ifdef EN_USART2_RX    //如果使能了接收
 //使能接收中断
 USART2->CR1|=1<<8;    //PE中断使能
 USART2->CR1|=1<<5;    //接收缓冲区非空中断使能
 MY_NVIC_Init(3,3,USART2_IRQChannel,2);//组2,最低优先级
 #endif
 }
 void SendASC(u8 d)//发送一个字节
 {
 
 USART2->DR=d;
 while((USART2->SR&0X40)==0);//等待发送结束
 }void SendString(u8 *str) //发送字符串
 {
 while(*str)
 {
 SendASC(*str) ;
 str++;
 }
 }
 
 
 gprs.c
 u8 PhoneNum[15]="+8615175655278";  //手机号码
 const u8 *MsContent="Temperature exceeds bid !";  //短信内容
 //查找字符串,在s中查找t
 //返 回 值: 1(t在s中的位置)成功 0失败
 u8 LookFor_Str(u8 *s, u8 *t)
 {
 u8    *s_temp;
 u8    *m_temp;
 u8    *t_temp;
 if (s == 0 ||t == 0)
 return 0;
 for (s_temp = s; *s_temp != '\0'; s_temp++)
 {
 m_temp = s_temp;
 for (t_temp = t; *t_temp == *m_temp; t_temp++, m_temp++);
 if (*t_temp == '\0')
 return 1;
 }
 return 0;
 }
 //发送"AT"联机指令,测试是否连接正确
 void Send_AT(void)
 {
 u8 p;
 u8 i=10;
 while(i--)        //测试10次,在某一次成功就退出
 {
 USART2_RX_STA=0;       //buffer指针清0
 SendString("AT\r");     //发送AT回车
 //delay_ms(100);      //等待接受数据完成
 while(USART2_RX_STA==0);
 //printf("n=%d\n",USART2_RX_STA);
 delay_ms(300);
 printf("b=%s\n",USART2_RX_BUF);
 p=LookFor_Str(USART2_RX_BUF,"OK");     //接收到的数据存在 USART2_RX_BUF
 if(p!=0)        //接收到"OK"
 {
 printf("GSM 模块正常!\n");
 delay_ms(1000);
 break;
 }
 printf("没检测到GSM 模块!\n");
 delay_ms(500);
 }
 }
 //设置短信模式 1:text模式 0 DU模式 //串口发送数组命令到TC35,AT+CMGF=1
 void Set_Mode(u8 mode)
 {
 u8 p,i=10;
 while(i--)        //测试10次,在某一次成功就退出
 {
 USART2_RX_STA=0;       //buffer指针清0
 if(mode) SendString("AT+CMGF=1\r"); //设置短消息模式  1 TEXT
 else    SendString("AT+CMGF=0\r"); //设置短消息模式  PDU模式
 //delay_ms(300);      //等待接受数据完成
 while(flag==0);
 flag=0;
 delay_ms(300);
 p=LookFor_Str(USART2_RX_BUF,"OK");     //接收到的数据存在RsBuf
 if(p!=0)        //接收到"OK"
 {
 printf("短信模式:text");
 delay_ms(1000);
 break;
 }
 printf("短信模式设置失败!");
 delay_ms(500);
 }
 }
 //发送号码void Send_PhoneNum(u8 *str)
 {
 u8 i=0;
 while(*str)
 {
 SendASC(*str) ;
 str++;
 i++;
 if(i==14) break;     //只发送14个
 }
 }
 //发送TEXT短信 AT+CMGS="+8615175655278"//*dialnum 目的号码    *text短信内容
 //返回:1 发送成功  0 发送失败
 u8 TransmitText(u8 *dialnum,u8 *text)
 {
 u8 i=10;
 u8 p;
 while(i--)
 {
 USART2_RX_STA=0;          //buffer指针清0
 SendString("AT+CMGS=");     //信息发送指令 AT+CMGS="+8613760602242"
 SendASC('"');
 Send_PhoneNum(dialnum);     //号码
 SendASC('"');
 SendASC('\r');       //回车
 while(flag==0);
 flag=0;
 delay_ms(300);
 p=LookFor_Str(USART2_RX_BUF,">");    //">"
 if(p!=0)         //如果接受到 >  发送text
 {
 USART2_RX_STA=0;          //清空接收缓冲区
 SendString(text);      //发送短信内容
 SendString("\x1a\r");     //'\x1a'结束符(相当CTRL+Z) '\r'回车符
 while(flag==0);
 flag=0;
 delay_ms(5000);      //这里要延时足够长时间,否则会读取错误
 p=LookFor_Str(USART2_RX_BUF,"OK");   //查找OK
 if(p!=0)       //发送成功
 {
 printf("发送成功 ^_^");
 return 1;
 }
 else
 {
 printf("发送失败");
 delay_ms(1000);
 printf("正在重发");
 }
 }
 }
 printf("多次重发失败");
 return 0;
 }
 //完整的短信发送函数 //dialnum:手机号码 text:短信内容
 void Send_Message(u8 *dialnum,u8 *text)
 {
 Send_AT();       //发送AT
 Set_Mode(1);      //设置短信模式:text
 TransmitText(dialnum,text); //设置
 }
 
 main.c
 #include <stm32f10x_lib.h>
 #include "sys.h"
 #include "usart.h"
 #include "delay.h"
 #include "led.h"
 #include "key.h"
 #include "gprs.h"
 //Mini STM32开发板范例代码3
 //串口实验
 //正点原子@ALIENTEK
 //技术论坛:www.openedv.com
 int main(void)
 {
 Stm32_Clock_Init(9); //系统时钟设置
 delay_init(72);      //延时初始化
 uart_init(72,9600);  //串口初始化为9600
 uart2_init(72,9600);
 LED_Init();      //初始化与LED连接的硬件接口
 while(1)
 {
 Send_AT();
 LED0=!LED0;//闪烁LED,提示系统正在运行.
 }
 
 主函数只是发送"AT"联机指令,测试是否连接正确,老出错,我想只要这个调通了,其他就可以照着写了。程序是学习原子开发板例程写的,都是直接操作寄存器。
 关键函数我已经标红了,希望懂的的大侠帮我看看,串口数据接收和发送那出问题了,谢谢!
 
 |