[STM32F1] stm32(F103c8t6)自学笔记

[复制链接]
5098|177
 楼主| t60yz 发表于 2023-11-22 11:39 | 显示全部楼层
1.5 高级定时器框图

92687655d77e9802c4.png
 楼主| t60yz 发表于 2023-11-22 11:39 | 显示全部楼层
1.6 定时中断基本结构
7832655d77f6e0235.png
 楼主| t60yz 发表于 2023-11-22 11:39 | 显示全部楼层
1.7 时序图(详细解释)
计数流程:选择时钟源-->确定滤波的几分频-->确定预分频PSC-->确定重装载值ARR-->溢出触发中断

分频过程:外部输入规律的高低电平脉冲信号,经过选择分频模式后,信号转化输入预分频器开始计数,每到达预分频器设置的阈值溢出时就产生一个脉冲给计数器,计数器+1,最后当计数器计数值等于自动装载器设置的阈值时产生溢出,触发中断,因此在一分频模式下:

定时频率(时间)=(预分频值/初始时钟频率)*预装载值

如定时1s,则1 s=(7200)/72Mhz * 10000                     (取值范围 0~65535)

这就像是两个定时器级联一样,增大了计数范围

最新理解:

已知公式 t=1/f

那么内部时钟经过预分频后每记一次的时间就为:t1=1/(72Mhz/PSC+1)

那么分频器每隔t1时间就产生信号给计数器,直到计数器经过t2=t1*(ARR+1)的时间或者说累加到等于ARR时,产生中断同时计数器清零。

所以整个过程花费时间(每次中断的间隔时间)为:t2=1/(72Mhz/PSC+1)*(ARR+1)

比如要计时 1s :1 s = 1 / ( 72Mhz / 7200)* 10000
 楼主| t60yz 发表于 2023-11-22 11:39 | 显示全部楼层
 楼主| t60yz 发表于 2023-11-22 11:40 | 显示全部楼层
 楼主| t60yz 发表于 2023-11-22 11:40 | 显示全部楼层
 楼主| t60yz 发表于 2023-11-22 11:40 | 显示全部楼层
 楼主| t60yz 发表于 2023-11-22 11:40 | 显示全部楼层
 楼主| t60yz 发表于 2023-11-22 11:40 | 显示全部楼层
2.定时器中断计数(代码)
[code]#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "timer2.h"

/***************************************************/定时器2
#include "stm32f10x.h"
#include "timer2.h"

extern int num;
void timer2_init(void)
{
        //**1.打开总的RCC
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//因为定时器2是通用定时器,在APB1总线上
        //**2.选定定时器接入的时钟
        TIM_InternalClockConfig(TIM2);//设置定时器2使用内部时钟,可不写,上电默认
        //**3.配置时基单元
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
       
        TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;//设置分频
        TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;//设置向上计数
        TIM_TimeBaseInitStruct.TIM_Period=10000-1;//设置预装载值
        TIM_TimeBaseInitStruct.TIM_Prescaler=7200-1;//设置预分频值
        TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;//高级计数器功能,重复计数器
        TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);//初始化时基单元
        TIM_ClearFlag(TIM2,TIM_FLAG_Update);//初始化时会产生标志位,需要清除
        //**4.使能时基单元的中断
        TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
        //**5.配置NVIC
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//分组
       
        NVIC_InitTypeDef NVIC_InitStruct;
        NVIC_InitStruct.NVIC_IRQChannel=TIM2_IRQn;
        NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
        NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
        NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
        NVIC_Init(&NVIC_InitStruct);
        //**6.开始计数
        TIM_Cmd(TIM2,ENABLE);

}

//**配置中断函数
void TIM2_IRQHandler(void)
{
        if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
        {
                num++;
        }
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//一定要清除标志位
}

/***************************************************/主函数

int num;
int main(void)
{
        OLED_Init();
        timer2_init();
        OLED_ShowString(1,1,"Hello,my honey");
//        OLED_ShowString(2,1,"Hello WangFang");
//        OLED_ShowString(3,1,"Hello Tomorrow");
//        OLED_ShowString(4,1,"I miss you");
        while(1)
        {
                OLED_ShowString(2,1,"NUM:");
                OLED_ShowNum(2,5,num,5);
               
                OLED_ShowString(3,1,"Prescaler:");
                OLED_ShowNum(3,11,TIM_GetPrescaler(TIM2),5);
               
                OLED_ShowString(4,1,"Counter:");
                OLED_ShowNum(4,9,TIM_GetCounter(TIM2),5);
        }
}
 楼主| t60yz 发表于 2023-11-22 11:40 | 显示全部楼层
3.外部时钟的定时器中断(代码)
相对于2的使用内部时钟,此方法不同之处仅在于使用函数:

TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00);//第二个设置分频,第三个设置触发方式,第四个设置采样频率(滤波器)
 楼主| t60yz 发表于 2023-11-22 11:41 | 显示全部楼层
  1. #include "stm32f10x.h"                  // Device header
  2. #include "OLED.h"
  3. #include "timer2.h"

  4. /***************************************************/定时器2
  5. #include "stm32f10x.h"
  6. #include "timer2.h"

  7. extern int num;
  8. void timer2_init(void)
  9. {
  10.         //**1.打开总的RCC,要配置GPIO从而传入外部时钟
  11.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//因为定时器2是通用定时器,在APB1总线上
  12.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
  13.         //**2.配置定时器接入外部时钟 同时配置外部时钟输入的引脚
  14.         //TIM_InternalClockConfig(TIM2);//设置定时器2使用内部时钟,可不写,上电默认
  15.        
  16.         GPIO_InitTypeDef GPIO_InitStruct;
  17.        
  18.         GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
  19.         GPIO_InitStruct.GPIO_Pin=GPIO_Pin_12;
  20.         GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
  21.         GPIO_Init(GPIOB,&GPIO_InitStruct);
  22.        
  23.         TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00);//第二个设置分频,第三个设置触发方式,第四个设置采样频率(滤波器)
  24.         //**3.配置时基单元
  25.         TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
  26.        
  27.         TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;//设置分频
  28.         TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;//设置向上计数
  29. //        TIM_TimeBaseInitStruct.TIM_Period=10000-1;//设置预装载值       //外部时钟的话用不了这么高的频率
  30. //        TIM_TimeBaseInitStruct.TIM_Prescaler=7200-1;//设置预分频值
  31.         TIM_TimeBaseInitStruct.TIM_Period=10-1;//设置预装载值
  32.         TIM_TimeBaseInitStruct.TIM_Prescaler=2-1;//设置预分频值
  33.         TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;//高级计数器功能,重复计数器
  34.         TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);//初始化时基单元
  35.         TIM_ClearFlag(TIM2,TIM_FLAG_Update);//初始化时会产生标志位,需要清除
  36.         //**4.使能时基单元的中断
  37.         TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
  38.         //**5.配置NVIC
  39.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//分组
  40.        
  41.         NVIC_InitTypeDef NVIC_InitStruct;
  42.         NVIC_InitStruct.NVIC_IRQChannel=TIM2_IRQn;
  43.         NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  44.         NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
  45.         NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
  46.         NVIC_Init(&NVIC_InitStruct);
  47.         //**6.开始计数
  48.         TIM_Cmd(TIM2,ENABLE);

  49. }

  50. //**配置中断函数
  51. void TIM2_IRQHandler(void)
  52. {
  53.         if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
  54.         {
  55.                 num++;
  56.         }
  57.         TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

  58. }


  59. /***************************************************/主函数

  60. int num;
  61. int main(void)
  62. {
  63.         OLED_Init();
  64.         timer2_init();
  65.         OLED_ShowString(1,1,"Hello,my honey");
  66. //        OLED_ShowString(2,1,"Hello WangFang");
  67. //        OLED_ShowString(3,1,"Hello Tomorrow");
  68. //        OLED_ShowString(4,1,"I miss you");
  69.         while(1)
  70.         {
  71.                 OLED_ShowString(2,1,"NUM:");
  72.                 OLED_ShowNum(2,5,num,5);
  73.                
  74.                 OLED_ShowString(3,1,"Prescaler:");
  75.                 OLED_ShowNum(3,11,TIM_GetPrescaler(TIM2),5);
  76.                
  77.                 OLED_ShowString(4,1,"Counter:");
  78.                 OLED_ShowNum(4,9,TIM_GetCounter(TIM2),5);
  79.         }
  80. }
 楼主| t60yz 发表于 2023-11-22 11:41 | 显示全部楼层
4.TIM(OC)比较输出(PWM)!!!
4.1 结构原理介绍(模式)
69754655d786c27a16.png
 楼主| t60yz 发表于 2023-11-22 11:41 | 显示全部楼层
 楼主| t60yz 发表于 2023-11-22 11:41 | 显示全部楼层
 楼主| t60yz 发表于 2023-11-22 11:41 | 显示全部楼层
 楼主| t60yz 发表于 2023-11-22 11:42 | 显示全部楼层
8种模式

TIM_OCMode                        函数库描述                             解释


TIM_OCMode_Timing       TIM输出比较                      冻结,输出比较不起作用
TIM_OOCMode_Active     TIM输出比较主动模式        当比较发生时,强制输出高电平
TIM_OCMode_Inactiive    TIM输出比较非主动模式     当比较发生时,强制输出低电平
TIM_OCMode_Toggle       TIM输出比较触发模式        当比较发生时,输出翻转
TIM_OCMode_PWM1        TIM脉冲宽度调制模式1      PWM1
TIM_OCMode_PWM2        TIM脉冲宽度调制模式2      PWM2
 楼主| t60yz 发表于 2023-11-22 11:42 | 显示全部楼层
 楼主| t60yz 发表于 2023-11-22 11:42 | 显示全部楼层
 楼主| t60yz 发表于 2023-11-22 11:42 | 显示全部楼层
 楼主| t60yz 发表于 2023-11-22 11:42 | 显示全部楼层
4.2 输出设备(舵机,直流电机)

68901655d78ab12306.png
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部