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

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

[复制链接]
老来多遗忘 提问时间:2011-9-26 14:16 /
 大家好,我单片机用的是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);  //清除相应的中断标志位  
}
}



收藏 评论6 发布时间:2011-9-26 14:16

举报

6个回答
老来多遗忘 回答时间:2011-9-26 14:37:01

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

希望大家帮忙解决一下,谢谢了
废鱼 回答时间:2011-9-26 16:28:45

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

1、i1没有定义,不知道这个是什么变量
2、接受完以后一定要清除接受缓冲区的数据,不然,下次进来肯定是正确的。我认为这个可能性是最大的。
老来多遗忘 回答时间: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))
老来多遗忘 回答时间: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))
newya 回答时间: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不能清零,导致死机
火雷达 回答时间:2011-10-31 08:58:14

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

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

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版