打印
[STM32F1]

求助大家了!程序总是死机在串口处

[复制链接]
2364|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hwc5201314|  楼主 | 2016-5-21 20:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 hwc5201314 于 2016-5-21 20:59 编辑

          碰到这个问题已经几天了,还是没解决,我这个程序主要是STM32控制sim900a发送数据到上位机,但是程序每次都是在发送了3次数据后,程序就死机了,          已经确认问题出在串口,但在网上找了很多资料还是没解决。
         下面是源码:
        //main.c


       char tt[] = "27,30,-0.77,-1.38,-11.79,25.190205,110.248857";//测试数据

       int main(void)
    {
          USART1_Config();//信息输出打印在电脑上--用于调试
          USART2_Config();//GSM模块用到的串口
          SysTick_Init();
       while(sim900a_cmd("AT\r","OK",1000) != SIM900A_TRUE)
        {
                        printf("\r\n模块响应测试不正常!!\r\n");
                        printf("\r\n若模块响应测试一直不正常,请检查模块的连接或是否已开启电源开关\r\n");
        }
        printf("\r\n通过了模块响应测试,5秒后开始GPRS测试--TCP/UDP功能\r\n");
        SIM900A_DELAY(5000);

        sim900a_gprs_test();
        Delay_ms(100);
        sim900a_gprs_send(tt);
        Delay_ms(5000);
       while(1)
        {
              sim900a_gprs_send(tt);
              printf("\r\n%d\r\n",++i);
              Delay_ms(10000);               
        }           
       }
      //bsp_usart2.c
      #include "bsp_usart2.h"
#include "bsp_SysTick.h"
#include <stdarg.h>


/// 配置USART2接收中断
static void NVIC_USART2_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    /* Configure the NVIC Preemption Priority Bits */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

    /* Enable the USARTy Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

/*
* 函数名:USART2_Config
* 描述  :USART2 GPIO 配置,工作模式配置
* 输入  :无
* 输出  : 无
* 调用  :外部调用
*/
void USART2_Config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;

        /* config USART2 clock */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

        /* USART2 GPIO config */
   /* Configure USART2 Tx (PA.02) as alternate function push-pull */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
            
  /* Configure USART2 Rx (PA.03) as input floating */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
         
        /* USART2 mode config */
        USART_InitStructure.USART_BaudRate = 38400;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No ;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

        USART_Init(USART2, &USART_InitStructure);
        
        /*        配置中断优先级 */
        NVIC_USART2_Configuration();
        /* 使能串口2接收中断 */
        USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);

        
        USART_Cmd(USART2, ENABLE);
}

/*
* 函数名:fputc
* 描述  :重定向c库函数printf到USART2
* 输入  :无
* 输出  :无
* 调用  :由printf调用
*/
//int fputc(int ch, FILE *f)
//{
///* 将Printf内容发往串口 */
//  USART_SendData(USART2, (unsigned char) ch);
//  while (!(USART2->SR & USART_FLAG_TXE));
//
//  return (ch);
//}

/*
* 函数名:itoa
* 描述  :将整形数据转换成字符串
* 输入  :-radix =10 表示10进制,其他结果为0
*         -value 要转换的整形数
*         -buf 转换后的字符串
*         -radix = 10
* 输出  :无
* 返回  :无
* 调用  :被USART2_printf()调用
*/
static char *itoa(int value, char *string, int radix)
{
    int     i, d;
    int     flag = 0;
    char    *ptr = string;

    /* This implementation only works for decimal numbers. */
    if (radix != 10)
    {
        *ptr = 0;
        return string;
    }

    if (!value)
    {
        *ptr++ = 0x30;
        *ptr = 0;
        return string;
    }

    /* if this is a negative value insert the minus sign. */
    if (value < 0)
    {
        *ptr++ = '-';

        /* Make the value positive. */
        value *= -1;
    }

    for (i = 10000; i > 0; i /= 10)
    {
        d = value / i;

        if (d || flag)
        {
            *ptr++ = (char)(d + 0x30);
            value -= (d * i);
            flag = 1;
        }
    }

    /* Null terminate the string. */
    *ptr = 0;

    return string;

} /* NCL_Itoa */


#if 1
//中断缓存串口数据
#define UART_BUFF_SIZE      255
volatile    uint8_t uart_p = 0;
uint8_t     uart_buff[UART_BUFF_SIZE];

void bsp_USART2_IRQHandler(void)
{
    if(uart_p<UART_BUFF_SIZE)
    {
        if(USART_GetITStatus(USART2, USART_FLAG_ORE) != RESET)
        {
                                                USART_ClearFlag(USART2,USART_FLAG_ORE); //读SR
            uart_buff[uart_p] = USART_ReceiveData(USART2);
            uart_p++;
        }
                                
                                                //溢出-如果发生溢出需要限度SR,再读DR寄存器,则可清楚不断入中断的问题
                                if(USART_GetFlagStatus(USART2,USART_FLAG_ORE)==SET)
                                {
                                                USART_ClearFlag(USART2,USART_FLAG_ORE);        //读SR
                                                uart_buff[uart_p] = USART_ReceiveData(USART2);//读DR
            uart_p++;
                                }
                        }
}



//获取接收到的数据和长度
char *get_rebuff(uint8_t *len)
{
    *len = uart_p;
    return (char *)&uart_buff;
}

void clean_rebuff(void)
{
    uart_p = 0;
}

#endif

/*
* 函数名:USART2_printf
* 描述  :格式化输出,类似于C库中的printf,但这里没有用到C库
* 输入  :-USARTx 串口通道,这里只用到了串口2,即USART2
*                     -Data   要发送到串口的内容的指针
*                           -...    其他参数
* 输出  :无
* 返回  :无
* 调用  :外部调用
*         典型应用USART2_printf( USART2, "\r\n this is a demo \r\n" );
*                             USART2_printf( USART2, "\r\n %d \r\n", i );
*                             USART2_printf( USART2, "\r\n %s \r\n", j );
*/
void USART2_printf(USART_TypeDef* USARTx, char *Data,...)
{
        const char *s;
  int d;   
  char buf[16];

  va_list ap;
  va_start(ap, Data);

        while ( *Data != 0)     // 判断是否到达字符串结束符
        {                                                         
                if ( *Data == 0x5c )  //'\'
                {                                                                          
                        switch ( *++Data )
                        {
                                case 'r':                                                                  //回车符
                                        USART_SendData(USARTx, 0x0d);
                                        Data ++;
                                        break;

                                case 'n':                                                                  //换行符
                                        USART_SendData(USARTx, 0x0a);        
                                        Data ++;
                                        break;
                                
                                default:
                                        Data ++;
                                    break;
                        }                        
                }
                else if ( *Data == '%')
                {                                                                          //
                        switch ( *++Data )
                        {                                
                                case 's':                                                                                  //字符串
                                        s = va_arg(ap, const char *);
          for ( ; *s; s++)
                                        {
                                                USART_SendData(USARTx,*s);
                                                while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );
          }
                                        Data++;
          break;

        case 'd':                                                                                //十进制
          d = va_arg(ap, int);
          itoa(d, buf, 10);
          for (s = buf; *s; s++)
                                        {
                                                USART_SendData(USARTx,*s);
                                                while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );
          }
                                        Data++;
          break;
                                 default:
                                                Data++;
                                    break;
                        }                 
                } /* end of else if */
                else USART_SendData(USARTx, *Data++);
                while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );

        }
}
          //stm32f10x_it.c
        .......
       void SysTick_Handler(void)
{
        
        TimingDelay_Decrement();        
}

void USART1_IRQHandler(void)
{
#if 0
    bsp_USART1_IRQHandler();
#else
    uint8_t ch;

    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        //ch = USART1->DR;
        ch = USART_ReceiveData(USART1);
        printf( "%c", ch );    //将接受到的数据直接返回打印
    }
#endif

}

void USART2_IRQHandler(void)
{

    bsp_USART2_IRQHandler();

}
...........
沙发
天灵灵地灵灵| | 2016-5-22 09:52 | 只看该作者
不要弄个可能出现死循环的程序,在while里加个倒计时,如果定时到了,仍然没有完成,就直接跳过去。

使用特权

评论回复
板凳
天灵灵地灵灵| | 2016-5-22 09:52 | 只看该作者
或者后面判断一下,如果过不去检查初始化。或调用初始化程序。

使用特权

评论回复
地板
hwc5201314|  楼主 | 2016-5-22 10:39 | 只看该作者
天灵灵地灵灵 发表于 2016-5-22 09:52
或者后面判断一下,如果过不去检查初始化。或调用初始化程序。

肯定能过初始化啊,发出3次数据后就死机了

使用特权

评论回复
5
lr_xgm| | 2016-5-22 12:55 | 只看该作者
肯定是代码有问题了,运行情况没有说清楚,死在哪里,不太好定位具体哪儿问题,估计问题1:数组溢出;问题2:串口是否出现挂死,问题3:开启了不该启动的资源。。。。。

使用特权

评论回复
6
xmshao| | 2016-5-22 13:50 | 只看该作者
对你铁板钉钉的 三次 很好奇。或许这是你的突破口。

使用特权

评论回复
7
hwc5201314|  楼主 | 2016-5-22 15:59 | 只看该作者
Debug的时候,定位到接收中断了

使用特权

评论回复
8
Varus| | 2016-5-22 21:09 | 只看该作者
会不会是数组溢出

使用特权

评论回复
9
ywlzh| | 2016-5-22 21:35 | 只看该作者
你都能确定是三次就死机了,为何还悟不出啊,这种知道BUG都不会调试着去解决?硬仿看看,程序跳到哪里你就能判断死机了,而且是在哪一步开始跳的 好好分析

使用特权

评论回复
10
xmshao| | 2016-5-22 21:41 | 只看该作者
死机除了PC指针跑飞外,中断循环进入也是常见的原因之一。
你检查下那些跟UART接收中断有关的标志,RXNE,ORE,尤其ORE.

使用特权

评论回复
11
wahahaheihei| | 2016-5-23 11:07 | 只看该作者
Debug一下,按步进行,看看卡在哪儿,然后那个判断的变量。

使用特权

评论回复
12
天灵灵地灵灵| | 2016-5-23 15:18 | 只看该作者
对了的按步调试,看看出在什么地方,然后看看那个变量是怎么配置。

使用特权

评论回复
13
子翁| | 2016-5-23 16:10 | 只看该作者
现象描述的不详细,串口发送、接收用查询方式试试,排除中断嵌套问题。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

30

帖子

1

粉丝