OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7899|回复: 3

SIM900A 与单片机通信

[复制链接]

23

主题

292

帖子

0

精华

高级会员

Rank: 4

积分
501
金钱
501
注册时间
2013-9-17
在线时间
17 小时
发表于 2013-12-6 22:11:53 | 显示全部楼层 |阅读模式

void USART2Write(u8* data,u16 len)
{
u16 i;
    
    USART_ClearFlag(USART2, USART_FLAG_TC);//清除数据发送完成标志位 开始本次发送
for (i=0; i<len; i++)
{
USART_SendData(USART2, data);
        while(USART_GetFlagStatus(USART2,USART_FLAG_TC) == RESET);//等待发送结束
}
}

//检测sim900a是否返回正确的操作响应 必须检测到此次发送OK了 才发送下一个命令
u8* Sim900a_Check_Cmd(u8* str)
    char *strx=0;
if(USART_RX_STA & 0X8000) //接收到一次数据了
USART_RX_BUF[USART_RX_STA & 0X7FFF]=0;        //添加结束符
strx=strstr((const char*)USART_RX_BUF,(const char*)str);
return (u8*)strx;
}

//单片机发送指令给SIM900A模块
u8 Sim900a_Send_Cmd(u8* SeCmd, u16 SeLen, u8* reCmd, u16 waitTime)   //SEND and ACK Handle
{
u8 flag = 0;
    USART_RX_STA = 0;
    USART2Write((u8*)SeCmd, SeLen); 
    USART2Write("\r\n", 2);     ///------------------------------------------------------------ 原子哥说这个地方不太合理 但是我也不知道怎么去修改  
    if(reCmd && waitTime)
    {
        while(--waitTime)
        {
            delay_ms(10);
            if(USART_RX_STA & 0x8000)   //如果接收到数据成功
            { 
                if(Sim900a_Check_Cmd(reCmd)) //检测模块返回的状态
                {
//                    LCD_ShowString(30,140,240,320,16, Sim900a_Check_Cmd(reCmd));
                    break;
                }
                 USART_RX_STA = 0;
            }
            if(waitTime == 0)flag = 1;
        }
}
    return flag;
}
//模块上电之后就发送 AT ATE0 测试下 关回显  -------  经测试 是没有问题的
u8 Open_Sim900a(void)
{
    POINT_COLOR = RED;
    
    if(STATUS) //一直为高 说明GSM模块供电正常了
    {
        while(Sim900a_Send_Cmd((u8*)"AT",5, (u8*)"OK",200)) //return fail cmd
        {
            LCD_ShowString(10, 90, 240, 320, 16,"Failed to connect GSM ");
            delay_ms(800);
            LCD_ShowString(10, 90, 240, 320, 16,"connected GSM again   ");
            delay_ms(800);  
        }
        Boot_State = 0;  //链接GSM模块成功
        while(Sim900a_Send_Cmd((u8*)"ATE0",4, (u8*)"OK", 200))  //关闭回显
        {
            LCD_ShowString(10, 90, 240, 320, 16,"failed to close auto return ");
            delay_ms(800);
            LCD_ShowString(10, 90, 240, 320, 16,"                            ");
            delay_ms(800);
        }    
    }
        return Boot_State;
}

//Sim900a 接听电话  ------- 可以正常打电话
u8 Sim900a_ATD_PHONE(void)
{
    u8 flag;
    if(Sim900a_Send_Cmd((u8*)"ATD18502553670;",15, (u8*)"\r\nOK\r\n", 200)) //return fail cmd
    {
        flag = 1;
    }
    else flag =0;
    //省略。。
return flag;
}

以上代码 打电话没问题 、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、 

以下则是问题所在
我想获取一下信号值 -- AT+CSQ   ....  “+CSQ:21,0”    想得到21这个信号值  之后还会有很多类似的问题需要处理   大家看看我这个单片机发送和SIM900A接收没问题了吧 反过来我就发现有问题 但是无处着手
所以斗胆问问 
用的是原子哥的与战舰调试的代码 改了一点点  程序就死在这里了 ……
        u8 p[20], *p1,*p2;
        if(sim900a_send_cmd("AT+CSQ","+CSQ:",200)==0) //查询信号质量
{
p1=(u8*)strstr((const char*)(USART2_RX_BUF),":");
p2=(u8*)strstr((const char*)(p1),",");
p2[0]=0;//加入结束符
sprintf((char*)p,"信号质量:%s",p1+2);
// Show_Str(x,y+20,200,16,p,16,0);
     
                LCD_ShowString(10,120,240,320,16,(u8*)p);
                USART2_RX_STA=0;
}

我的问题是 我该如何获取模块返回给我的有效的数据  串口中断收 是 原子哥的没有改动 。。。 

void USART2_IRQHandler(void)                 //串口2中断服务程序
{
u8 Res;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
        Res =USART_ReceiveData(USART2) & 0x7f;             //(USART1->DR); 读取接收到的数据
USART_ClearITPendingBit(USART2, USART_IT_RXNE);   //清除接收完成标志位
        
        if((USART_RX_STA & 0x8000) == 0)    //接收未完成
{
if(USART_RX_STA & 0x4000)       //接收到了0x0d 
{
if(Res != 0x0a)   
                    USART_RX_STA = 0;        //接收错误,重新开始
else 
                    USART_RX_STA |= 0x8000; //接收完成了 
//                    LCD_ShowString(10, 150, 240, 320, 16, USART_RX_BUF);
}
else //还没收到0X0D  结束位
{
if(Res == 0x0d)
                    USART_RX_STA |= 0x4000;
else
{
USART_RX_BUF[USART_RX_STA & 0X3FFF] = Res;  //计算长度
USART_RX_STA++;
//                    LCD_ShowString(10, 170, 240, 320, 16, USART_RX_BUF);
if(USART_RX_STA > (USART_REC_LEN-1))
                     USART_RX_STA=0;     //接收数据错误,重新开始接收  
}  
}
}    
     } 
}












闷鱼闷闷不乐吃焖鱼
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165538
金钱
165538
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-12-6 23:05:04 | 显示全部楼层
回复【楼主位】闷鱼:
---------------------------------
你的指针没分配内存呢?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

23

主题

292

帖子

0

精华

高级会员

Rank: 4

积分
501
金钱
501
注册时间
2013-9-17
在线时间
17 小时
 楼主| 发表于 2013-12-7 02:11:48 | 显示全部楼层
这就造成了 野指针 么  之后 我改了 p = malloc(50); ----- free(p);

情况依旧  。。
现在罗列如下  希望原子哥分析下 谢谢 


1. 我没有使用 DMA 只是用串口普通的发送  中断收 中断函数用的原子哥的源码

2. 然后
         // 用串口看 GSM返回的值是 0D 0A 2B(+) 43(C) 53(S) 51(Q) 3A( 20(SPACE) 32(2) 31(1) 2C(,) 30(0) 0D 0A 4F(O) 4B(K) 0D 0A
         // 也就是                                                         \r\n+CSQ: 21,0\r\nOK\r\n

        if(Sim900a_Send_Cmd((u8*)"AT+CSQ", 6, (u8*)"+CSQ:",200) == 0) 
        {
            p1=(u8*)strstr((const char*)(USART_RX_BUF)," ");    //这句话的目的是 把指针指向 空格 的地方 也就是起始地址
/*
     这里的BUF 每次只能接收到 “OK” 我注意到模块返回的字符串 里面包含了 三个 [0XOD  0XOA]
     相当于三条以
 [0XOD  0XOA] 结尾的语句  串口会当作收了三次数据 所以 TC位会被置高三次
     第一次 是 收到 0x0d 0x0a  BUF是空的 没有有效数据
     第二次 是 收到 +CSQ: 21,0
     第三次 是 收到  OK 
     虽然前面 我需要的 那个 信号值 被清掉了
      但是我觉得 在第二条语句的时候 捕捉不到 21 信号值 我觉得很奇怪  。。。。。。。。。。。。。。。。。  

*/
            p2=(u8*)strstr((const char*)(p1),",");   //指定结束符的位置
            p2[0]=0;                                           //在这个地方加入结束符 就确定那个
            sprintf((char*)p,"NET:%s",p1+2); //格式化输出   ------就在执行完这句话之后  程序直接跳转到 蓝色字体部分  就死在那个while 里面了
            LCD_ShowString(10, 140, 240, 320, 16, (u8*)p);
            USART_RX_STA=0;
        }
程序就跑到stm32f10x_it.c中的 这个函数所以程序就死了  这是怎么回事 ?
   void HardFault_Handler(void)
   {
     /* Go to infinite loop when Hard Fault exception occurs */
     while (1){ }     // i was dead here.................
   }
3. 问题很多 一个一个来了  只能 。。  原子哥不要抛弃我啊
闷鱼闷闷不乐吃焖鱼
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165538
金钱
165538
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-12-7 11:03:10 | 显示全部楼层
第一个问题,你用的我们的判断0X0D,0X0A的方式来接收数据?这明显不行,你看我例程,用的是超时法,而不是回车判断,你用回车判断,你就得有极快的速度去响应,否则就必定有数据丢失。你第一个问题应该就是数据丢失,这种情况,你自己仿真应该很好查出来,既然收不到21,那你能看下收到的是什么吧?看下收到的是什么,然后结合我前面说的,自己想一下。
第二个问题,p1,你收到的到底是什么?是否真有数据,如果没数据,你就去sprintf到p里面,可能会导致死机。这里你做两件事:1,你的p是否真的分配内存成功了?仿真看看p的值,是不是等于0??2,你的p1,到底是什么东西?p1+2,又是指向哪里,这个你都可以仿真查看。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-15 16:08

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表