你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

查看: 3508|回复: 6

【奇怪问题】USART通信第一次正常,第二次死机

[复制链接]

3

主题

13

回帖

0

蝴蝶豆

新手上路

最后登录
1970-1-1
发表于 2011-9-26 14:16:24 | 显示全部楼层 |阅读模式
 大家好,我单片机用的是stm32f103RE,64脚封装的。USART通信遇到了问题,请大家帮忙指教!

不胜感激!

上位机通过USART1向下位机发送一串十六进制数 如 AA 78  01 06 CC 33 C3 3C,
其中0xAA  0x78为一帧数据的开始,0xCC,0x33,0xC3,0x3C为一帧数据的结束,中间两个字节为要发送的数据。

程序实现的功能:下位机收到后通过USART2 向上位机返回收到的数。

遇到的问题:上位机第一次发送数据后,程序中的变量i1=8,下位机返回数据正确,上位机第二次发送数据后,单片机能进中断,但usart1接收缓存中的数据不对,并且此时i1=1,程序死机。复位后,上述问题重复。


主函数
/*******************************************************************************
*  File Name          : main.c
* Author             : Nanjing
* Date First  Issued  : 22/09/2011
* Description        : Main program  body
*  
********************************************************************************
*  History:
* 09/22/2011:  V0.1
********************************************************************************
*  AD采样PC0口分压的值,将采样值每间隔1s向串口发送一次
*******************************************************************************/
/*  Includes  ------------------------------------------------------------------*/
#include  "stm32f10x.h"
#include "stdio.h"
/* Private typedef  -----------------------------------------------------------*/
/* Private  define ------------------------------------------------------------*/
#define  ADC1_DR_Address    ((uint32_t)0x4001244C)     //0x40012400+0x4C,指的是ADC_DR
#define Tim_1ms 0x15a9              // 5545                     
#define Tim_10ms Tim_1ms * 10
#define Tim_1s Tim_1ms *  1000
/* Private macro  -------------------------------------------------------------*/
/* Private  variables  ---------------------------------------------------------*/
ADC_InitTypeDef    ADC_InitStructure;
DMA_InitTypeDef   DMA_InitStructure;
uint32_t  AD_value;
extern volatile uint8_t flag;
__IO uint16_t ADC1ConvertedValue =  0;
  uint8_t j1 = 0 ,j2 = 0;
extern char RX_dat1[100],  RX_dat2[100];
extern volatile uint8_t uart_flag1,uart_flag2;
extern  volatile uint8_t t2;
  uint32_t ADC_filter(void);
ErrorStatus  HSEStartUpStatus;

/* Private function prototypes  -----------------------------------------------*/
void  RCC_Configuration(void) ;
void GPIO_Configuration(void);
void  USART_Configuration(void);
void NVIC_Configuration(void);
    void  Delay(vu32 nCount);


/* Private functions  ---------------------------------------------------------*/
/*******************************************************************************
*  Function Name  : main
* Description    : Main program.
* Input          :  None
* Output         : None
* Return         :  None
*******************************************************************************/
int  main(void)
{
#ifdef DEBUG
debug() ;
#endif

  /* Configure the  system clocks */
RCC_Configuration();
/* Configure the GPIO ports  */
GPIO_Configuration();
/* Configure the EXTI  */
NVIC_Configuration();
USART_Configuration();
  /* DMA1 channel1  configuration  ----------------------------------------------*/
  DMA_DeInit(DMA1_Channel1);  //开启DMA1的第一通道
  DMA_InitStructure.DMA_PeripheralBaseAddr  = ADC1_DR_Address;     //DMA对应的外设基地址,这个地址从Datasheet查
  DMA_InitStructure.DMA_MemoryBaseAddr =  (uint32_t)&ADC1ConvertedValue;  //该参数用以定义DMA内存基地址
  DMA_InitStructure.DMA_DIR  = DMA_DIR_PeripheralSRC;      //DMA的转换模式是SRC模式,就是从外设向内存中搬运,
  DMA_InitStructure.DMA_BufferSize = 1;      //DMA缓存大小,1个
  DMA_InitStructure.DMA_PeripheralInc =  DMA_PeripheralInc_Disable;  //接收一次数据后,设备地址是否后移
  DMA_InitStructure.DMA_MemoryInc =  DMA_MemoryInc_Disable;     //接收一次数据后,目标内存地址是否后移--重要概念,用来采集多个数据的
  DMA_InitStructure.DMA_PeripheralDataSize  = DMA_PeripheralDataSize_HalfWord;    //转换结果的数据大小
  DMA_InitStructure.DMA_MemoryDataSize =  DMA_MemoryDataSize_HalfWord;  //DMA搬运的数据尺寸,注意ADC是12位的,HalfWord就是16位
  DMA_InitStructure.DMA_Mode  = DMA_Mode_Circular;     //转换模式,循环缓存模式,常用,M2M果果开启了,这个模式失效
  DMA_InitStructure.DMA_Priority =  DMA_Priority_High; //DMA优先级,高
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;      //M2M模式禁止,memory to memory,这里暂时用不上
  DMA_Init(DMA1_Channel1,  &DMA_InitStructure);
  
  /* Enable DMA1 channel1  */
  DMA_Cmd(DMA1_Channel1, ENABLE);
  /* ADC1 configuration  ------------------------------------------------------*/
  ADC_DeInit(ADC1);      //开启ADC1
  ADC_InitStructure.ADC_Mode =  ADC_Mode_Independent;//独立模式
  ADC_InitStructure.ADC_ScanConvMode =  DISABLE;//只是用了一个通道
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;    //连续转换模式开启
  ADC_InitStructure.ADC_ExternalTrigConv =  ADC_ExternalTrigConv_None;   //ADC外部触发开关,关闭
  ADC_InitStructure.ADC_DataAlign  = ADC_DataAlign_Right;  //对齐方式,ADC结果是12位的,显然有个对齐左边还是右边的问题。一般是右对齐
  ADC_InitStructure.ADC_NbrOfChannel  = 1;    //开启通道数,1个
  ADC_Init(ADC1, &ADC_InitStructure);
  /* ADC1  regular channel8 configuration */
  ADC_RegularChannelConfig(ADC1,  ADC_Channel_10, 1, ADC_SampleTime_239Cycles5); //Configures ADC1 Channel10 as:  first converted channel with an 55.5 cycles sample time  
   //规则组通道设置,关键函数  转换器ADC1,选择哪个通道channel,规则采样顺序,1代表规则通道第1个(1到16),最后一个参数是转换时间,越长越准越稳定
  //总转换时间=采样时间+12.5个周期=80个周期=10us
  /*  Enable ADC1 DMA */
  ADC_DMACmd(ADC1, ENABLE);  //ADC命令,和DMA关联。
  
  /*  Enable ADC1 */
  ADC_Cmd(ADC1, ENABLE);    //开启ADC1

  /* Enable ADC1  reset calibaration register */   
  ADC_ResetCalibration(ADC1);   //校准  寄存器复位

  /* Check the end of ADC1 reset calibration register  */
  while(ADC_GetResetCalibrationStatus(ADC1));  //等待校准寄存器复位完成

  /*  Start ADC1 calibaration */
  ADC_StartCalibration(ADC1);  //开始校准
  /*  Check the end of ADC1 calibration  */
  while(ADC_GetCalibrationStatus(ADC1));  //等待校准完成
     
  /* Start  ADC1 Software Conversion */
  ADC_SoftwareStartConvCmd(ADC1, ENABLE);     //连续转换开始,从选择开始,MCU可以不用管了,ADC将通过DMA不断刷新

  while (1)
  {   
      AD_value= ADC_filter();
   Delay(Tim_1s);
  
   if (uart_flag1 ==  1)
           {
               uart_flag1 = 0;
                        for(j1=0;j10;m--)
{
Delay(Tim_1ms);
//n=ADC_GetConversionValue(ADC1);
result  += ADC_GetConversionValue(ADC1);    //返回最近一次ADCx规则组的转换结果Returns the ADC1 Master  data value of the last converted channel

}
return  (uint32_t)(((unsigned long)(result>>4))*3300>>12);  //  result/16  *  3300/12
}

  #ifdef DEBUG
  /*描述:当程序出错时,返回出错的文件名及在源程序中的行号
    输入:—file:指向文件名的指针
   —line:在源程序中的行号
   输出:无
   返回:无
   */
    void assert_failed(u8*file,u32 line)
   {
   while(1) {}
    }
#endif


中断函数

其中0xAA  0x78为一帧数据的开始,0xCC,0x33,0xC3,0x3C为一帧数据的结束,中间还有两个字节。

void USART1_IRQHandler(void)
{  
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //检查相应的中断发生没
{

  
   RX_dat1[i1++] =  USART_ReceiveData(USART1);
      
            if((RX_dat1[0]==0xAA)&&(RX_dat1[1]==0x78)&&(RX_dat1[4]==0xCC)&&(RX_dat1[5]==0x33)&&(RX_dat1[6]==0xC3)&&(RX_dat1[7]==0x3C))
      {
        i1=0;
    uart_flag1 = 1;
     }  
  
   
    USART_ClearITPendingBit(USART1, USART_IT_RXNE);  //清除相应的中断标志位  
}
}



回复

使用道具 举报

3

主题

13

回帖

0

蝴蝶豆

新手上路

最后登录
1970-1-1
 楼主| 发表于 2011-9-26 14:37:01 | 显示全部楼层

RE:【奇怪问题】USART通信第一次正常,第二次死机

希望大家帮忙解决一下,谢谢了
回复 支持 反对

使用道具 举报

134

主题

4489

回帖

239

蝴蝶豆

版主

最后登录
2020-12-9
发表于 2011-9-26 16:28:45 | 显示全部楼层

RE:【奇怪问题】USART通信第一次正常,第二次死机

1、i1没有定义,不知道这个是什么变量
2、接受完以后一定要清除接受缓冲区的数据,不然,下次进来肯定是正确的。我认为这个可能性是最大的。
回复 支持 反对

使用道具 举报

3

主题

13

回帖

0

蝴蝶豆

新手上路

最后登录
1970-1-1
 楼主| 发表于 2011-9-27 12:02:04 | 显示全部楼层

RE:【奇怪问题】USART通信第一次正常,第二次死机

已经验证,此语句逻辑有错
if((RX_dat1[0]==0xAA)&&(RX_dat1[1]==0x78)&&(RX_dat1[4]==0xCC)&&(RX_dat1[5]==0x33)&&(RX_dat1[6]==0xC3)&&(RX_dat1[7]==0x3C))
回复 支持 反对

使用道具 举报

3

主题

13

回帖

0

蝴蝶豆

新手上路

最后登录
1970-1-1
 楼主| 发表于 2011-9-27 12:02:50 | 显示全部楼层

RE:【奇怪问题】USART通信第一次正常,第二次死机

已经验证,此语句逻辑有错
if((RX_dat1[0]==0xAA)&&(RX_dat1[1]==0x78)&&(RX_dat1[4]==0xCC)&&(RX_dat1[5]==0x33)&&(RX_dat1[6]==0xC3)&&(RX_dat1[7]==0x3C))
回复 支持 反对

使用道具 举报

0

主题

6

回帖

0

蝴蝶豆

初级会员

最后登录
2017-12-9
发表于 2011-10-25 10:43:33 | 显示全部楼层

RE:【奇怪问题】USART通信第一次正常,第二次死机

这段程序从理论上讲应该没有什么问题,但楼主没有考虑到如下问题:
1、通讯速率过快会引起误码的增加,如果接收过程中产生了误码则i1变量就不会清零,从而引起接收缓冲区溢出而死机;
2、if((RX_dat1[0]==0xAA)&&(RX_dat1[1]==0x78)&&(RX_dat1[4]==0xCC)&&(RX_dat1[5]==0x33)&&(RX_dat1[6]==0xC3)&&(RX_dat1[7]==0x3C))
     {
        i1=0;
    uart_flag1 = 1;
     }
这段代码貌似很短,但实际占用的时间应该会很大,在中断内部采用此种方式时会导致接收数据的丢失,如果上位机二帧数据发送时间间隔过短,会导致第二帧接收到数据头丢失,从而使i1不能清零,导致死机
回复 支持 反对

使用道具 举报

3

主题

185

回帖

0

蝴蝶豆

新手上路

最后登录
1970-1-1
发表于 2011-10-31 08:58:14 | 显示全部楼层

RE:【奇怪问题】USART通信第一次正常,第二次死机

太长了,程序,不好分析。
不过首先要分析下,流程是否有问题,然后再分析程序。
回复 支持 反对

使用道具 举报

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版