[其他ST产品] STM32F1常用外设介绍

[复制链接]
 楼主| 范德萨发额 发表于 2023-2-28 19:30 | 显示全部楼层
获取指定的标志位函数
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);

 楼主| 范德萨发额 发表于 2023-2-28 19:31 | 显示全部楼层
对置1的标志位进行清除函数
  1. void EXTI_ClearFlag(uint32_t EXTI_Line);
 楼主| 范德萨发额 发表于 2023-2-28 19:31 | 显示全部楼层
在中断函数中获取标志位函数
  1. ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
 楼主| 范德萨发额 发表于 2023-2-28 19:31 | 显示全部楼层
清除中断挂起标志位函数
  1. void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
 楼主| 范德萨发额 发表于 2023-2-28 19:31 | 显示全部楼层
中断分组函数
  1. void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
 楼主| 范德萨发额 发表于 2023-2-28 19:32 | 显示全部楼层
根据结构体里面的参数初始化NVIC函数
  1. void NVIC_Init(NVIC_InitTypedef* NVIC_InitStruct);
 楼主| 范德萨发额 发表于 2023-2-28 19:32 | 显示全部楼层
设置中断向量表函数

NVIC_SetVectorTable函数的功能是设置向量表的位置和偏移。其中输入参数中,对于32位的OFFSET向量表基地址的偏移量对于FLASH,参数值必须高于0x08000100,对于RAM必须高于0X100.
  1. void NVIC_SetVectorTable(uint8_t NVIC_VectTab,uint32_t Offset);
 楼主| 范德萨发额 发表于 2023-2-28 19:44 | 显示全部楼层
系统低功耗配置函数

  1. void NVIC_SystemLPConfig(uint8_t LowPowerMode,FunctionalState NewState)


中断函数要简短快速,不要在中断中执行Delay
 楼主| 范德萨发额 发表于 2023-2-28 19:46 | 显示全部楼层
程序示例

  1. int16_t Encoder_Count;

  2. void Encoder_Init(void)
  3. {
  4.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启GPIO时钟
  5.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//开启AFIO时钟
  6.        
  7.         GPIO_InitTypeDef GPIO_InitStructure;//定义初始化结构体
  8.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
  9.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;//开启引脚
  10.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//设置响应速度
  11.         GPIO_Init(GPIOB, &GPIO_InitStructure);//配置参数
  12.        
  13.         GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);//选择中断线路
  14.         GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);
  15.        
  16.         EXTI_InitTypeDef EXTI_InitStructure;//定义外部中断结构体
  17.         EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1;//设置中断线
  18.         EXTI_InitStructure.EXTI_LineCmd = ENABLE;//开启中断线路
  19.         EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断模式
  20.         EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
  21.         EXTI_Init(&EXTI_InitStructure);//写入参数
  22.        
  23.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组
  24.        
  25.         NVIC_InitTypeDef NVIC_InitStructure;//定义NVIC结构体
  26.         NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//设置中断通道
  27.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//通道使能
  28.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
  29.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//响应优先级
  30.         NVIC_Init(&NVIC_InitStructure);//写入参数

  31.         NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;//设置中断通道
  32.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//通道使能
  33.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
  34.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;//响应优先级
  35.         NVIC_Init(&NVIC_InitStructure);//写入参数
  36. }

  37. int16_t Encoder_Get(void)
  38. {
  39.         int16_t Temp;
  40.         Temp = Encoder_Count;
  41.         Encoder_Count = 0;
  42.         return Temp;
  43. }

  44. void EXTI0_IRQHandler(void)//线路0中断函数
  45. {
  46.         if (EXTI_GetITStatus(EXTI_Line0) == SET)//判断中断挂起位
  47.         {
  48.                 /*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
  49.                 if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)//读取输入高低电平
  50.                 {
  51.                         if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
  52.                         {
  53.                                 Encoder_Count --;
  54.                         }
  55.                 }
  56.                 EXTI_ClearITPendingBit(EXTI_Line0);//清除中断挂起标志位
  57.         }
  58. }

  59. void EXTI1_IRQHandler(void)//线路1中断函数
  60. {
  61.         if (EXTI_GetITStatus(EXTI_Line1) == SET)//判断标志位
  62.         {
  63.                 /*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
  64.                 if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)//读取输入高低电平
  65.                 {
  66.                         if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
  67.                         {
  68.                                 Encoder_Count ++;
  69.                         }
  70.                 }
  71.                 EXTI_ClearITPendingBit(EXTI_Line1);//清除中断挂起标志位
  72.         }
  73. }

 楼主| 范德萨发额 发表于 2023-2-28 19:46 | 显示全部楼层
定时器

    TIM(Timer)定时器

    定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断

    16位计数器、预分频、自动重装寄存器的时基单元,在72M计数时钟下可以实现最大59.65s的定时

    不仅具备基本的定时器中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能

    根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型

    对72MHz计72个数就是1MHz,也就是1us的时间,计72000个数,那就是1KHz也就是1ms的时间

    59.65s =65536 X 65536X 1/72M/(中断频率倒数),

    STM32的定时器支持级联的模式:一个定时器的输出当做另一个定时器的输入最大定时时间就是59.65s X 65536 X 65536
 楼主| 范德萨发额 发表于 2023-2-28 19:46 | 显示全部楼层
 楼主| 范德萨发额 发表于 2023-2-28 19:46 | 显示全部楼层
预分频器(PSC):对输入的基准频率提前进行一个分频的操作
实际分频系数 = 预分频器的值 + 1,最大可以写65535即65536分频
计数器(CNT):也是16位,值可以从0~65535,当计数器的值自增(自减)到目标值时,产生中断,完成定时
 楼主| 范德萨发额 发表于 2023-2-28 19:48 | 显示全部楼层
自动重装寄存器():也是16位当计数值等于自动重装值时,就是计时的时间到了,就会产生一个中断信号,并且清零计数器,计数器自动开始下一次的计数计时,计数值等于自动重装值的中断一般叫做“更新中断”,此更新中断就会通往NVIC,再配置好NVIC的定时器通道,定时器上的更新中断就会得到CPU的响应了,对应的事件叫做“更新事件”,更新事件不会触发中断,但可以触发内部其他电路的工作
 楼主| 范德萨发额 发表于 2023-2-28 19:48 | 显示全部楼层
5823463fdea080b691.png

从基准时钟,到预分频器,再到计数器,计数器自增,同时不断地与自动重装寄存器进行比较,计数器和自动重装寄存器的值相等时,即计时时间到,这时会产生一个更新中断和更新事件,CPU响应更新中断,就完成了定时中断的任务了。
 楼主| 范德萨发额 发表于 2023-2-28 19:48 | 显示全部楼层
主从触发模式

使用定时器的主模式,可以把定时器的更新事件映射到触发输出TRGO(Trigger Out)的位置,TRGO直接接到DAC的触发转换引脚上,这样定时器的更新就不需要再通过中断来触发DAC转换了

3572563fdea1ed9cf0.png
 楼主| 范德萨发额 发表于 2023-2-28 19:49 | 显示全部楼层
缓冲寄存器:某个时刻把预分频器由0改成了1,当计数计到一半的时候改变了分频值,这个变化不会立即生效,而是会等到本次计数周期结束时,产生了了更新事件,预分频器的值才会被传递到缓冲寄存器里面去,才会生效。
 楼主| 范德萨发额 发表于 2023-2-28 19:49 | 显示全部楼层
举个例子来说,如果我们想改变ARR寄存器中的值,但是当前的定时还没有结束,在这时如果未设置影子寄存器,那么设定的值会立即生效。而如果设置了影子寄存器,那么新的值会在当前计数周期结束之后生效。
 楼主| 范德萨发额 发表于 2023-2-28 19:49 | 显示全部楼层
计数器计数频率:CK_CNT = CK_PSC / (PSC + 1)

计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1) = CK_PSC / (PSC + 1) / (ARR + 1)
 楼主| 范德萨发额 发表于 2023-2-28 19:50 | 显示全部楼层
开启定时器步骤

    第一步,RCC开启时钟
    第二步,选择时基单元的时钟源
    第三步,配置时基单元
    第四步,配置输出中断控制,允许更新中断输出到NVIC
    第五步,配置NVIC,在NVIC中打开定时器中断的通道,并分配一个优先级
    第六步,运行控制
    第七步,使能计数器
 楼主| 范德萨发额 发表于 2023-2-28 19:50 | 显示全部楼层
定时器常用的库函数
恢复缺省配置函数
  1. void TIM_DeInit(TIM_TypeDef* TIMx);
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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