打印
[其他ST产品]

STM32F1常用外设介绍

[复制链接]
楼主: 范德萨发额
手机看帖
扫描二维码
随时随地手机跟帖
121
范德萨发额|  楼主 | 2023-2-28 20:14 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
另一个输入捕获的初始化函数

与上一个函数类似都是用于初始化输入捕获单元的,上一个函数只是单一的配置一个通道,而这个函数可以快速配置两个通道,把外设电路配置成PWMI的电路

void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);

使用特权

评论回复
122
范德萨发额|  楼主 | 2023-2-28 20:15 | 只看该作者
给输入捕获结构体赋一个初始值函数

void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct);

使用特权

评论回复
123
范德萨发额|  楼主 | 2023-2-28 20:15 | 只看该作者
选择输入触发源TRGI函数

调用此函数可以选择从模式的触发源

void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);

使用特权

评论回复
124
范德萨发额|  楼主 | 2023-2-28 20:15 | 只看该作者
选择输出触发源TRGO函数

void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource);

使用特权

评论回复
125
范德萨发额|  楼主 | 2023-2-28 20:15 | 只看该作者
选择从模式函数

void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);

使用特权

评论回复
126
范德萨发额|  楼主 | 2023-2-28 20:16 | 只看该作者
单独配置通道1、2、3、4的分频器函数

在参数结构体里也可以配置

void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);

使用特权

评论回复
127
范德萨发额|  楼主 | 2023-2-28 20:16 | 只看该作者
读取四个通道的CCR函数

输出比较模式下,CCR是只写的,要用SetCompare写入,输入捕获模式下,CCR是只读的,要用GetCapture读出

uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx);

使用特权

评论回复
128
范德萨发额|  楼主 | 2023-2-28 20:17 | 只看该作者
PWMI模式程序示例

void IC_Init(void)
{
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
       
        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
       
        TIM_InternalClockConfig(TIM3);
       
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
        TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
        TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;                //ARR
        TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;                //PSC
        TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
        TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
       
        TIM_ICInitTypeDef TIM_ICInitStructure;
        TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
        TIM_ICInitStructure.TIM_ICFilter = 0xF;
        TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
        TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
        TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//直接模式
        TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);//另一个通道选择相反的配置

        TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);//选择触发源
        TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);//选择从模式
       
        TIM_Cmd(TIM3, ENABLE);
}

uint32_t IC_GetFreq(void)
{
        return 1000000 / (TIM_GetCapture1(TIM3) + 1);
}

uint32_t IC_GetDuty(void)
{
        return (TIM_GetCapture2(TIM3) + 1) * 100 / (TIM_GetCapture1(TIM3) + 1);
}

使用特权

评论回复
129
范德萨发额|  楼主 | 2023-2-28 20:17 | 只看该作者
编码器接口

Encoder Interface编码器接口

编码器接口可接收增量(正交)编码器的信号,根据编码器旋转产生的正交信号脉冲,自动控制CNT自增或自减,从而指示编码器的位置、旋转方向和旋转速度

每个高级定时器和通用定时器都拥有1个编码器接口

两个输入引脚借用了输入捕获的通道1和通道2

对于需要频繁执行,操作简单的任务,一般会设计一个硬件模块来自动完成

使用特权

评论回复
130
范德萨发额|  楼主 | 2023-2-28 20:17 | 只看该作者
把两个编码器的A相和B相,接入STM32,定时器的编码器接口,编码器接口自动控制时基单元中的CNT计数器,进行自增或者自减,例如CNT初始值为0,编码器右转CNT++,右转产生一个脉冲,CNT++,左转CNT–,编码器接口(相当于带有方向控制的外部时钟)同时控制CNT的计数时钟和计数方向,CNT的值就表示了编码器的位置,每隔一段时间取一次CNT的值再把CNT清零,每次取出来的值就带标 了编码器的速度,编码器的测速实际上就是测频法测正交脉冲的频率,CNT计次,每隔一段时间取一次计次,也可以用外部中断来接编码器(用软件资源来弥补硬件资源)

使用特权

评论回复
131
范德萨发额|  楼主 | 2023-2-28 20:18 | 只看该作者

当编码器的旋转轴转起来时,A相和B相就会输出方波信号,转的越快,方波的频率越高,方波的频率就代表了速度,取出任意一相的信号来测量频率,就能知道旋转速度,只有一相的信号无确定旋转方向。

使用特权

评论回复
132
范德萨发额|  楼主 | 2023-2-28 20:18 | 只看该作者
正交信号:当正转时,A相超前B相90度,反转时,A相滞后B相90度。

正转时,第一个时刻,A相上升沿,对应B此时是低电平,第二个时刻,B相上升沿,对应A相高电平,第三个时刻,A相下降沿,对应B相高电平,B相下降沿,对应A相低电平。

反转时,第一个时刻,B相上升沿,对应A相低电平,第二个时刻A相上升沿,对应B相高电平,第三个时刻,B相下降沿,对应A相高电平,第四个时刻,A相下降沿,对应B相低电平。

当A、B相出现这些边沿时,对应另一相的状态,正转和反转正好是相反的

使用特权

评论回复
133
范德萨发额|  楼主 | 2023-2-28 20:20 | 只看该作者
编码器接口的设计逻辑是:首先把A相和B相的所有边沿作为计数器的计数时钟,出现边沿信号时,就计数自增或者自减,

使用特权

评论回复
134
范德萨发额|  楼主 | 2023-2-28 20:21 | 只看该作者
编码器接口的两个引脚,借用了输入捕获单元的前两个通道,编码器的输入引脚就是定时器的CH1和CH2两个引脚,信号的通路就是,CH1通过这里,通向编码器接口,CH3和CH4和编码器接口无关,其中CH1和CH2的输入捕获滤波器和边沿检测,编码器接口也有使用,但是后面的是否交叉,预分频器和CCR寄存器,与编码器接口无关,这就是编码器接口的输入部分,编码器接口的输出部分,相当于从模式控制器,控制CNT的计数时钟和计数方向,输出过程就是如果产生边沿信号,并且对应另一相的状态为正转,则控制CNT自增否则控制CNT自减,此时计数时钟和计数方向都处于编码器接口托管的状态,计数器的自增和自减,受编码器的控制。

使用特权

评论回复
135
范德萨发额|  楼主 | 2023-2-28 20:22 | 只看该作者
编码器接口的基本结构:


输入捕获的前两个通道,通过GPIO口接入编码器的A、B相然后通过滤波器和边沿检测极性选择,产生TI1TP1和TI2FP2,通向编码器接口,编码器接口通过控制预分频器控制CNT计数器的时钟,同时,编码器接口还根据编码器的旋转方向,控制CNT的计数方向,编码器正转时,CNT自增,编码器反转时,CNT自减,一般设置ARR为65535,最大量程

使用特权

评论回复
136
范德萨发额|  楼主 | 2023-2-28 20:22 | 只看该作者
工作模式:

编码器接口的工作逻辑:TI1FP1和TI2FP2接的就是编码器的A、B相,在A相和B相的上升沿或者下降沿触发计数,向上计数还是向下计数取决于边沿信号发生时,另一相的电平状态(相对信号的电平)

使用特权

评论回复
137
范德萨发额|  楼主 | 2023-2-28 20:22 | 只看该作者
配置流程:

第一步,RCC开启时钟,开启GPIO和定时器的时钟

第二步,配置GPIO,配置为输入模式

第三步,配置时基单元,预分频器选择不分频,自动重装,一般给最大65535

第四步,配置输入捕获单元,只需要配置滤波器和极性两个参数

第五步,配置编码器接口模式,调用一个库函数即可

第六步,调用TIM_cmd启动定时器

如果需要测量编码器的速度:每隔一段固定的闸门时间,取出一次CNT,然后把CNT清零

使用特权

评论回复
138
范德萨发额|  楼主 | 2023-2-28 20:23 | 只看该作者
定时器编码器接口配置函数

void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,
                                uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity);

    1
    2

配置上拉输入还是下拉输入:看外部模块输出的默认电平,与外部模块输出的默认电平相同,防止默认电平打架,如果不确定外部模块输出的默认状态,或者外部信号输出功率非常小,尽量选择浮空输入

使用特权

评论回复
139
范德萨发额|  楼主 | 2023-2-28 20:23 | 只看该作者
编码器接口程序示例
void Encoder_Init(void)
{
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
       
        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
               
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
        TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
        TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;                //ARR
        TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;                //PSC
        TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
        TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
       
        TIM_ICInitTypeDef TIM_ICInitStructure;
        TIM_ICStructInit(&TIM_ICInitStructure);
        TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
        TIM_ICInitStructure.TIM_ICFilter = 0xF;
        TIM_ICInit(TIM3, &TIM_ICInitStructure);
        TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
        TIM_ICInitStructure.TIM_ICFilter = 0xF;
        TIM_ICInit(TIM3, &TIM_ICInitStructure);
       
        TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//编码器电机模式
       
        TIM_Cmd(TIM3, ENABLE);//开启定时器
}

int16_t Encoder_Get(void)
{
        int16_t Temp;
        Temp = TIM_GetCounter(TIM3);//获取CNT的值
        TIM_SetCounter(TIM3, 0);//设置CNT的值
        return Temp;
}

使用特权

评论回复
140
范德萨发额|  楼主 | 2023-2-28 20:23 | 只看该作者
ADC模拟数字转换器

ADC(Analog-Digital Converter)模拟-数字转换器

ADC可以将引脚上连续变换的模拟量转换成内存中储存的数字变量,建立模拟电路到数字电路的桥梁,ADC读取引脚上的模拟电压,转换为一个数据,存在寄存器里,再把这个数据读取到变量里来,就可以进行显示、判断、记录等操作

12位(分辨率,位数越高,量化结果就越精细,对应分辨率就越高)逐次逼近型ADC,1us转换时间(转换频率),

输入电压范围:0-3.3V,转换结果范围:0~4095,ADC的输入电压要求在芯片的负极和正极之间变化,最低电压是负极0V,最高电压是正极3.3V,经过ADC转换之后最小值是0,最大值是4095,0V对应0,3.3V对应4095,中间都是一一对应的线性关系。

使用特权

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

本版积分规则