打印
[STM32F1]

定时器中断

[复制链接]
920|26
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
//  定时器3初始化
void TIM3_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        NVIC_InitTypeDef NVIC_InitStructure;

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

        TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值         计数到5000为500ms
        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
        TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

        TIM_ITConfig(  //使能或者失能指定的TIM中断
                TIM3, //TIM2
                TIM_IT_Update ,
                ENABLE  //使能
                );
        NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
        NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

        TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设
                                                         
}

沙发
junpeng324|  楼主 | 2018-11-27 21:26 | 只看该作者
关于定时器的定时时间计算公式大家懂吗

使用特权

评论回复
板凳
junpeng324|  楼主 | 2018-11-27 21:27 | 只看该作者
这里使用了arr 与psc

使用特权

评论回复
地板
junpeng324|  楼主 | 2018-11-27 21:29 | 只看该作者
arr:设置在下一个更新事件装入活动的自动重装载寄存器周期的值

使用特权

评论回复
5
junpeng324|  楼主 | 2018-11-27 21:30 | 只看该作者
psc;  设置用来作为TIMx时钟频率除数的预分频值

使用特权

评论回复
6
junpeng324|  楼主 | 2018-11-27 21:38 | 只看该作者

使用特权

评论回复
7
junpeng324|  楼主 | 2018-11-27 21:39 | 只看该作者
这里设置了500ms中断一次

使用特权

评论回复
8
junpeng324|  楼主 | 2018-11-27 21:39 | 只看该作者
TIM3_Int_Init(4999,7199);//10Khz的计数频率,计数到5000为500ms  

使用特权

评论回复
9
junpeng324|  楼主 | 2018-11-27 21:40 | 只看该作者
下面是串口的初始化

使用特权

评论回复
10
junpeng324|  楼主 | 2018-11-27 21:40 | 只看该作者
void uart_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时钟
  
        //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=3 ;//抢占优先级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_RXNE, ENABLE);//开启串口接受中断
  USART_Cmd(USART1, ENABLE);                    //使能串口1

}

使用特权

评论回复
11
junpeng324|  楼主 | 2018-11-27 21:41 | 只看该作者
可以调用usart_init(9600) 来初始化串口,波特率为9600

使用特权

评论回复
12
junpeng324|  楼主 | 2018-11-27 21:42 | 只看该作者
下面是定时器中断函数 没进入中断将在里面执行程序

使用特权

评论回复
13
junpeng324|  楼主 | 2018-11-27 21:43 | 只看该作者

// 定时器中断函数
void TIM3_IRQHandler(void)   //TIM3中断
{
        if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
                {
                 TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源
                 LED1=!LED1;
                 printf("定时器中断500ms 到了\r\n");
                }
}

使用特权

评论回复
14
junpeng324|  楼主 | 2018-11-27 21:44 | 只看该作者
每500ms 翻转一次led 的电平,串口打印一次数据

使用特权

评论回复
15
junpeng324|  楼主 | 2018-11-27 21:49 | 只看该作者
下面需要初始化ADC

使用特权

评论回复
16
junpeng324|  楼主 | 2018-11-27 21:50 | 只看该作者
//初始化ADC
//这里我们仅以规则通道为例
//我们默认将开启通道0~3                                                                                                                                          
void  Adc_Init(void)
{        
        ADC_InitTypeDef ADC_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1        , ENABLE );          //使能ADC1通道时钟


        RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

        //PA1 作为模拟通道输入引脚                        
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                //模拟输入引脚
        GPIO_Init(GPIOA, &GPIO_InitStructure);       

        ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值

        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //ADC工作模式:ADC1和ADC2工作在独立模式
        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(ADC1, &ADC_InitStructure);        //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   

  
        ADC_Cmd(ADC1, ENABLE);        //使能指定的ADC1
       
        ADC_ResetCalibration(ADC1);        //使能复位校准  
         
        while(ADC_GetResetCalibrationStatus(ADC1));        //等待复位校准结束
       
        ADC_StartCalibration(ADC1);         //开启AD校准

        while(ADC_GetCalibrationStatus(ADC1));         //等待校准结束

//        ADC_SoftwareStartConvCmd(ADC1, ENABLE);                //使能指定的ADC1的软件转换启动功能

}                                  

使用特权

评论回复
17
junpeng324|  楼主 | 2018-11-27 22:21 | 只看该作者
//获得ADC值
//ch:通道值 0~3
u16 Get_Adc(u8 ch)   
{
          //设置指定ADC的规则组通道,一个序列,采样时间
        ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );        //ADC1,ADC通道,采样时间为239.5周期                                      
  
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);                //使能指定的ADC1的软件转换启动功能       
         
        while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束

        return ADC_GetConversionValue(ADC1);        //返回最近一次ADC1规则组的转换结果
}

使用特权

评论回复
18
junpeng324|  楼主 | 2018-11-27 22:23 | 只看该作者
求多次采集的平均值
u16 Get_Adc_Average(u8 ch,u8 times)
{
        u32 temp_val=0;
        u8 t;
        for(t=0;t<times;t++)
        {
                temp_val+=Get_Adc(ch);
                delay_ms(5);
        }
        return temp_val/times;
}          

使用特权

评论回复
19
junpeng324|  楼主 | 2018-11-27 22:25 | 只看该作者
if(time_flag==1)
                {
                   time_flag=0;
                         adcx=Get_Adc_Average(ADC_Channel_2,10);
                         temp= (float) adcx*(3.3/4096);   //电压值
                    printf("%f \r\n",temp);   
                }

使用特权

评论回复
20
junpeng324|  楼主 | 2018-11-27 22:27 | 只看该作者
每500ms读取一次电压值
  

使用特权

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

本版积分规则

37

主题

1130

帖子

8

粉丝