最近调试发现一个很无语的现象,我初始化过程中,同时初始化了多个外设
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时钟),串口发送正常。