打印
[其他ST产品]

STM32F1常用外设介绍

[复制链接]
楼主: 范德萨发额
手机看帖
扫描二维码
随时随地手机跟帖
41
范德萨发额|  楼主 | 2023-2-28 19:30 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
获取指定的标志位函数
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);

使用特权

评论回复
42
范德萨发额|  楼主 | 2023-2-28 19:31 | 只看该作者
对置1的标志位进行清除函数
void EXTI_ClearFlag(uint32_t EXTI_Line);

使用特权

评论回复
43
范德萨发额|  楼主 | 2023-2-28 19:31 | 只看该作者
在中断函数中获取标志位函数
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);

使用特权

评论回复
44
范德萨发额|  楼主 | 2023-2-28 19:31 | 只看该作者
清除中断挂起标志位函数
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);

使用特权

评论回复
45
范德萨发额|  楼主 | 2023-2-28 19:31 | 只看该作者
中断分组函数
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);

使用特权

评论回复
46
范德萨发额|  楼主 | 2023-2-28 19:32 | 只看该作者
根据结构体里面的参数初始化NVIC函数
void NVIC_Init(NVIC_InitTypedef* NVIC_InitStruct);

使用特权

评论回复
47
范德萨发额|  楼主 | 2023-2-28 19:32 | 只看该作者
设置中断向量表函数

NVIC_SetVectorTable函数的功能是设置向量表的位置和偏移。其中输入参数中,对于32位的OFFSET向量表基地址的偏移量对于FLASH,参数值必须高于0x08000100,对于RAM必须高于0X100.
void NVIC_SetVectorTable(uint8_t NVIC_VectTab,uint32_t Offset);

使用特权

评论回复
48
范德萨发额|  楼主 | 2023-2-28 19:44 | 只看该作者
系统低功耗配置函数

void NVIC_SystemLPConfig(uint8_t LowPowerMode,FunctionalState NewState)


中断函数要简短快速,不要在中断中执行Delay

使用特权

评论回复
49
范德萨发额|  楼主 | 2023-2-28 19:46 | 只看该作者
程序示例

int16_t Encoder_Count;

void Encoder_Init(void)
{
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启GPIO时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//开启AFIO时钟
       
        GPIO_InitTypeDef GPIO_InitStructure;//定义初始化结构体
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;//开启引脚
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//设置响应速度
        GPIO_Init(GPIOB, &GPIO_InitStructure);//配置参数
       
        GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);//选择中断线路
        GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);
       
        EXTI_InitTypeDef EXTI_InitStructure;//定义外部中断结构体
        EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1;//设置中断线
        EXTI_InitStructure.EXTI_LineCmd = ENABLE;//开启中断线路
        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断模式
        EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
        EXTI_Init(&EXTI_InitStructure);//写入参数
       
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组
       
        NVIC_InitTypeDef NVIC_InitStructure;//定义NVIC结构体
        NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//设置中断通道
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//通道使能
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//响应优先级
        NVIC_Init(&NVIC_InitStructure);//写入参数

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

int16_t Encoder_Get(void)
{
        int16_t Temp;
        Temp = Encoder_Count;
        Encoder_Count = 0;
        return Temp;
}

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

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

使用特权

评论回复
50
范德萨发额|  楼主 | 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

使用特权

评论回复
51
范德萨发额|  楼主 | 2023-2-28 19:46 | 只看该作者

使用特权

评论回复
52
范德萨发额|  楼主 | 2023-2-28 19:46 | 只看该作者
预分频器(PSC):对输入的基准频率提前进行一个分频的操作
实际分频系数 = 预分频器的值 + 1,最大可以写65535即65536分频
计数器(CNT):也是16位,值可以从0~65535,当计数器的值自增(自减)到目标值时,产生中断,完成定时

使用特权

评论回复
53
范德萨发额|  楼主 | 2023-2-28 19:48 | 只看该作者
自动重装寄存器():也是16位当计数值等于自动重装值时,就是计时的时间到了,就会产生一个中断信号,并且清零计数器,计数器自动开始下一次的计数计时,计数值等于自动重装值的中断一般叫做“更新中断”,此更新中断就会通往NVIC,再配置好NVIC的定时器通道,定时器上的更新中断就会得到CPU的响应了,对应的事件叫做“更新事件”,更新事件不会触发中断,但可以触发内部其他电路的工作

使用特权

评论回复
54
范德萨发额|  楼主 | 2023-2-28 19:48 | 只看该作者


从基准时钟,到预分频器,再到计数器,计数器自增,同时不断地与自动重装寄存器进行比较,计数器和自动重装寄存器的值相等时,即计时时间到,这时会产生一个更新中断和更新事件,CPU响应更新中断,就完成了定时中断的任务了。

使用特权

评论回复
55
范德萨发额|  楼主 | 2023-2-28 19:48 | 只看该作者
主从触发模式

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

使用特权

评论回复
56
范德萨发额|  楼主 | 2023-2-28 19:49 | 只看该作者
缓冲寄存器:某个时刻把预分频器由0改成了1,当计数计到一半的时候改变了分频值,这个变化不会立即生效,而是会等到本次计数周期结束时,产生了了更新事件,预分频器的值才会被传递到缓冲寄存器里面去,才会生效。

使用特权

评论回复
57
范德萨发额|  楼主 | 2023-2-28 19:49 | 只看该作者
举个例子来说,如果我们想改变ARR寄存器中的值,但是当前的定时还没有结束,在这时如果未设置影子寄存器,那么设定的值会立即生效。而如果设置了影子寄存器,那么新的值会在当前计数周期结束之后生效。

使用特权

评论回复
58
范德萨发额|  楼主 | 2023-2-28 19:49 | 只看该作者
计数器计数频率:CK_CNT = CK_PSC / (PSC + 1)

计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1) = CK_PSC / (PSC + 1) / (ARR + 1)

使用特权

评论回复
59
范德萨发额|  楼主 | 2023-2-28 19:50 | 只看该作者
开启定时器步骤

    第一步,RCC开启时钟
    第二步,选择时基单元的时钟源
    第三步,配置时基单元
    第四步,配置输出中断控制,允许更新中断输出到NVIC
    第五步,配置NVIC,在NVIC中打开定时器中断的通道,并分配一个优先级
    第六步,运行控制
    第七步,使能计数器

使用特权

评论回复
60
范德萨发额|  楼主 | 2023-2-28 19:50 | 只看该作者
定时器常用的库函数
恢复缺省配置函数
void TIM_DeInit(TIM_TypeDef* TIMx);

使用特权

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

本版积分规则