shijugushanzh73543 2022-01-19 16:31 采纳率: 0%
浏览 153

stm32 多个外设初始化,串口1发送失效的问题

最近调试发现一个很无语的现象,我初始化过程中,同时初始化了多个外设

    Device_Init();            //外设初始化
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);      //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    RS232_init(115200);         //串口初始化为115200
    RS485_Init(115200);  
    DMA1_UARTConfig();        //串口DMA配置
    UpDataInit();            //程序更新初始化
    Adc3_Init();              //温度传感器
    TIM1_PWM_Init(99,35);      //
    TIM3_PWM_Init(99,35);       //
    TIM4_Cap_Init(0XFFFF,72-1);    //以1Mhz的频率计数,捕获电机转速
    TIM2_Int_Init(9,7199);//10Khz的计数频率,计数到9就是1ms

发现串口1收数正常,发数为空,但是能够正常进发数完成中断。我尝试把任意两个定时器初始化注释掉,发现串口1发数正常了。

    Device_Init();            //外设初始化
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);      //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    RS232_init(115200);         //串口初始化为115200
    RS485_Init(115200);  
    DMA1_UARTConfig();        //串口DMA配置
    UpDataInit();            //程序更新初始化
    Adc3_Init();              //温度传感器
    //TIM1_PWM_Init(99,35);      //
    //TIM3_PWM_Init(99,35);       //
    TIM4_Cap_Init(0XFFFF,72-1);    //1Mhz的频率计数,捕获电机转速
    TIM2_Int_Init(9,7199);//10Khz的计数频率,计数到9就是1ms

然后我又尝试把两个初始化函数注释掉,4个定时器函数保留,发现串口1发数也正常;

    Device_Init();            //外设初始化
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);      //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    RS232_init(115200);         //串口初始化为115200
    RS485_Init(115200);  
    DMA1_UARTConfig();        //串口DMA配置
    //UpDataInit();            //程序更新初始化
    //Adc3_Init();              //温度传感器
    TIM1_PWM_Init(99,35);      //
    TIM3_PWM_Init(99,35);       //
    TIM4_Cap_Init(0XFFFF,72-1);    //1Mhz的频率计数,捕获电机转速
    TIM2_Int_Init(9,7199);//10Khz的计数频率,计数到9就是1ms

难道说stm32的外设使用有限制么,不过每次异常的都只有串口1的发送。串口的配置我检查了好几遍应该没问题,和其他外设端口也没有冲突,真是奇了怪了。
补充一下信息 ADC初始化

void  Adc3_Init(void)
{     
    GPIO_InitTypeDef GPIO_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF,ENABLE);//使能PORTF时钟    
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8;//PF8 anolog输入
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;        //模拟输入引脚
    GPIO_Init(GPIOF, &GPIO_InitStructure);    
    ADC_InitTypeDef ADC_InitStructure; 

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3    , ENABLE );      //使能ADC3通道时钟
    
  RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,ENABLE);//ADC复位
    
  RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,DISABLE);//复位结束        
    
    ADC_DeInit(ADC3);  //复位ADC3,将外设 ADC3的全部寄存器重设为缺省值
    
    
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;    //ADC工作模式: 独立模式
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;    //模数转换工作在单通道模式
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;    //模数转换工作在单次转换模式
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;    //转换由软件而不是外部触发启动
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;    //ADC数据右对齐
    ADC_InitStructure.ADC_NbrOfChannel = 1;    //顺序进行规则转换的ADC通道的数目
    ADC_Init(ADC3, &ADC_InitStructure);    //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器  
    
    
    ADC_Cmd(ADC3, ENABLE);    //使能指定的ADC3
    
    ADC_ResetCalibration(ADC3);    //使能复位校准  
     
    while(ADC_GetResetCalibrationStatus(ADC3));    //等待复位校准结束
    
    ADC_StartCalibration(ADC3);     //开启AD校准
 
    while(ADC_GetCalibrationStatus(ADC3));     //等待校准

}                  


void RS232_init(u32 bound){
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
     
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);    //使能USART1,GPIOA时钟
    
    USART_DeInit(USART1);  //复位串口1
  
       //USART1_TX   GPIOA.9
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
   
  //USART1_RX      GPIOA.10初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10 


  //Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        //子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器
  
   //USART 初始化设置

    USART_InitStructure.USART_BaudRate = bound;//串口波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
    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(USART1, &USART_InitStructure); //初始化串口1
  
  USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口空闲中断
  USART_ITConfig(USART1, USART_IT_TC,   ENABLE);  // 使能串口发送中断
  USART_Cmd(USART1, ENABLE);                    //使能串口1 


}

void TIM1_PWM_Init(u16 arr,u16 psc)
{  
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;
    

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);    //使能定时器1时钟
    //RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
    
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM1_CH1
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO

   //初始化TIM1
    TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
    TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 
    TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
    
    //初始化TIM3 Channel1 PWM模式     
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
     TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性高
    TIM_OCInitStructure.TIM_Pulse=0;
    TIM_OCInitStructure.TIM_OCIdleState=TIM_OCIdleState_Set;
    TIM_OC1Init(TIM1, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2
    TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);  //使能TIM1在CCR2上的预装载寄存器
    

 
    TIM_Cmd(TIM1, ENABLE);  //使能TIM1
    TIM_CtrlPWMOutputs(TIM1,ENABLE);        //MOE 主输出使能,高级定时器必须开启这个

}
 void UpDataInit()
 {
      u8   ucflashdata[16]={0};
        
        ucflashdata[0] = 0x55;
        ucflashdata[1] = 0x55;
        ucflashdata[2] = 0x55;
        ucflashdata[3] = 0x55;
        ucflashdata[4] = 0x0;
        ucflashdata[5] = 0x0;
        ucflashdata[6] = 0x0;
        ucflashdata[7] = 0x0;    
        ucflashdata[8] = 0x0;
        ucflashdata[9] = 0x0;
        ucflashdata[10] =0x0;
        ucflashdata[11] = 0x0;    
        ucflashdata[12] = 0xaa;
        ucflashdata[13] = 0xaa;
        ucflashdata[14] = 0xaa;
        ucflashdata[15] = 0xaa;    
    iap_write_appbin(FLASH_DATA_ADDR,ucflashdata,16);//将更新标志和帧数写入到flash中        
     
 }

测试了多种情况,发现将定时器1时钟关闭后,串口发送正常,将ADC初始化、和程序更新初始化挪到串口初始化之前(此时不需要关闭定时器1时钟),串口发送正常。

  • 写回答

2条回答 默认 最新

  • 高贵的狗子 2022-01-20 09:09
    关注

    先把优化关了吧,其他的从这上面也看不出来

    评论

报告相同问题?

问题事件

  • 修改了问题 1月21日
  • 创建了问题 1月19日

悬赏问题

  • ¥15 高通uboot 打印ubi init err 22
  • ¥20 PDF元数据中的XMP媒体管理属性
  • ¥15 R语言中lasso回归报错
  • ¥15 网站突然不能访问了,上午还好好的
  • ¥15 有没有dl可以帮弄”我去图书馆”秒选道具和积分
  • ¥15 semrush,SEO,内嵌网站,api
  • ¥15 Stata:为什么reghdfe后的因变量没有被发现识别啊
  • ¥15 振荡电路,ADS仿真
  • ¥15 关于#c语言#的问题,请各位专家解答!
  • ¥15 这个如何解决详细步骤