【江科协-STM32】4. TIM输出比较

1. 输出比较简介

OC(Output Compare)输出比较。

输出比较可以通过CNT(CNT计数器)与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形。

:::tip
CNT计数器是正向计数器。它只能正向累加。

CCR是捕获/比较寄存器,通常是我们给的一个固定值,正如其名,捕获数值后比较数值,这样就可以捕获CNT的数值并进行比较,看是大了、等于还是小了。

TIM输出比较就是这样来决定置1、置0或翻转输出电平。
:::

每个高级定时器和通用定时器都拥有4个输出比较通道。

高级定时器的前三个通道额外拥有死区生成和互补输出的功能。

2. 通用定时器

使用输入捕获时,CCR是作为捕获寄存器;使用输出比较时,CCR是作为比较寄存器。

在这里插入图片描述

3. PWM简介

PWM(Pulse Width Modulation)是脉冲宽度调制。

在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速等领域。

PWM参数:

  • 频率 =1Ts= \frac{1}{T_s}=Ts1
  • 占空比 = TonTs\frac{T_{on}}{T_s}TsTon
  • 分辨率 = 占空比变化步距

当上面电平时间长一点,下面的短一点的时候,上面的模拟量占主导;反之则是下面的模拟量占主导。

请添加图片描述

TonT_{on}Ton是高电平的时间,TST_STS是一个时钟周期的时间。TonTS\frac{T_on}{T_S}TSTon为占空比,指的是高电平时间占整个周期的比例。用百分比表示。

占空比决定了等效的模拟电压的大小。占空比越大,等效的模拟电压就趋近于高电平;越小,等效的模拟电压就趋近于低电平。

请添加图片描述

电机工作也是一个惯性系统。所以直流电机也是可以用PWM调速的。

下图是

请添加图片描述

输入是CNT(CNT计数器)与CCR寄存器值的关系,输出是REF的高低电平。

4. 输出比较模式

模式描述
冻结CNT=CCR时,REF保持为原状态(可用于定速巡航)
匹配时置有效电平CNT=CCR时,REF置有效电平
匹配时置无效电平CNT=CCR时,REF置无效电平
匹配时电平翻转CNT=CCR时,REF电平翻转
强制为无效电平CNT与CCR无效,REF强制为无效电平(可用于暂停波形输出)
强制为有效电平CNT与CCR无效,REF强制为有效电平(可用于暂停波形输出)
PWM模式1向上计数:CNT<CCR时,REF置有效电平, CN>=CCR时,REF置无效电平;向下计数:CNT>CCR时,REF置无效电平, CN<=CCR时,REF置有效电平
PWM模式2向下计数:CNT<CCR时,REF置无效电平, CN>=CCR时,REF置有效电平;向下计数:CNT>CCR时,REF置有效电平, CN<=CCR时,REF置无效电平

改变PWM模式1和2,只是改变了REF电平的极性。使用PWM1的正极性和PWM2的反极性是一样的效果。

5. PWM基本结构

请添加图片描述

蓝色线是CNT的值,黄色线是ARR的值,蓝色线从0开始自增,一直增到ARR,也就是99,之后清零继续自增。

红色线就是CCR,是我们预设的值。绿色线是电平大小。

当CNT<CCR时,置高电平;CNT>=CCR时,置低电平。CNT溢出时,清零,重新置高电平。

进一步分析,我们发现,电平的占空比是受CCR的值影响的。如果我们的CCR设置的低一些,占空比就小一些;如果CCR设置的高一些,占空比就大一些。

REF是一个频率可调,占空比也可调的PWM波形。最终经过极性选择、输出使能,通向GPIO口。

6. 参数计算

我们回到节5的图。

  • PWM频率:Freq=CKPSC/(PSC+1)/(ARR+1)Freq = CK_PSC / (PSC+1) / (ARR+1)Freq=CKPSC/(PSC+1)/(ARR+1)
  • 占空比:Duty=CCR/(ARR+1)Duty = CCR / (ARR+1)Duty=CCR/(ARR+1)
  • 占空比变化步距:DutyStep=1/(ARR+1)DutyStep = 1 / (ARR+1)DutyStep=1/(ARR+1)

我们按高电平第一次回落的点算,此时占空比为 $30 /(99+1) \times 100 % = 30% $

CCR的范围取决于ARR,因为CCR去到和ARR差不多甚至相等的时候,占空比就是百分之百,这样便失去了意义。所以CCR需要始终小于ARR。

变化步距是越小越好的,CCR越大越好。这样代表其变化越细腻。

7. 输出比较通道(高级)

为了更好地切换MOS管开关状态,有了死区生成电路。

请添加图片描述

8. 舵机简介

舵机是一种根据输入PWM信号占空比来控制输出角度的装置。

输入PWM信号要求:周期为20ms,高电平宽度为0.5ms-2.5ms。

请添加图片描述

PWM在此图中是当一个通信协议来用。

9. 舵机硬件电路

请添加图片描述

PWM信号线直接接到STM32引脚上就可以,比如PA0。舵机内部有驱动电路。

10. 直流电机及驱动简介

直流电机是一种将电能转换为机械能的装置,有两个电极,当电极正接时,电机正转,当电极反接时,电机反转。

直流电机属于大功率器件,GPIO口无法直接驱动,需要配合电机驱动电路来操作。

TB6612是一款双路H桥(一路四个开关管)型的直流电机驱动芯片,可以驱动两个直流电机并且控制其转速及方向。

请添加图片描述

ULN2003则一路只有一个开关管,只能控制电机在一个方向转。

右边的电路即是H桥电路的基本结构,它是由两路推挽电路组成的。上管导通,下管断开,左边输出就是接在VM的电机电源正极。下管导通,上管断开,那就是PGND的电源负极。

如果有两路推挽电路,中间O1和O2接一个电机,左上右下导通,电流就是从左流向右边;右上和左下导通,电流方向就反过来,从右流向左。H桥可以控制电流流过的方向,从而控制电机正反转。

11. 电机硬件电路

左边就是这个电机驱动模块的硬件电路。

右下角的表中,输入是IN1、IN2、PWM和STBY。STBY低电平就待机,高电平就正常工作。右边是输出,O1、O2和模式状态。有电压差电机才会转,否则就是制动状态。此外还有正反转状态之分,取决于O1和O2的高低电平相对状态。

请添加图片描述

要接一个可以输出大电流的电源.

VM是驱动电压输入端,输入电压一般和额定电压保持一致。

VCC不需要大功率,可以和控制器共用一个电源。

GND接系统的负极。随便一个GND就可以。

AO1和AO2是A路的两个输出,其控制端是上面的PWMA、AIN2、AIN1。

PWMA引脚接PWM的信号输出端,其他两个引脚可以任意接两个普通的GPIO口。

三个引脚给一个低功率的控制信号,驱动电路就会从VM汲取电流,输出到电机。从而就能完成低功率控制大功率电路的目的。

BO1和BO2是B路的两个输出,其控制端是上面的PWMB、BIN2、BIN1。

STBY如果不需要待机模式的话,可以直接接VCC(3.3V)。

<think>好的,我现在需要帮助用户实现使用STM32科协的资源来输出正弦波,特别是关于DAC的配置和示例代码。首先,我需要回顾一下用户的问题,确保我理解所有的关键点。用户提到了STM32科协、正弦波输出、DAC配置,所以核心是如何通过STM32的DAC生成正弦波,并且参考科协的示例代码。 首先,我应该考虑STM32的DAC模块的基本工作原理。DAC(数字模拟转换器)可以将数字值转换为模拟电压输出。生成正弦波通常需要预先计算一个正弦表(数组),然后通过定时器触发DAC转换,逐个输出这些值,从而形成连续的波形。 接下来,用户提到了科协的示例代码,可能是指科大自动化协会(可能是一个教育机构或资源提供者)的相关资料。我需要假设用户可能参考了他们的教程或代码库,因此需要给出符合他们示例代码风格的配置步骤。 首先,配置DAC的步骤可能包括: 1. 启用DAC时钟:在STM32中,外设通常需要先启用对应的时钟。DAC通常挂在APB1总线上,但具体型号可能不同,需要查阅参考手册。 2. 配置GPIO:将对应的DAC输出引脚设置为模拟模式,例如PA4或PA5,这取决于使用的DAC通道。 3. 配置DAC:设置DAC的工作模式,是否使用触发,是否启用缓冲等。例如,使用定时器触发DAC转换,以实现精确的采样率。 4. 配置定时器:生成定时中断或触发事件,以更新DAC的输出值。定时器的频率决定了正弦波的频率。 5. 生成正弦波数据表:计算一个周期内的正弦波样本,存储为数组,供DAC转换使用。 6. 在中断服务程序中更新DAC的值:每次定时器触发时,从数组中取出下一个值写入DAC的数据寄存器。 接下来,我需要考虑可能的示例代码结构。例如,使用HAL库的话,配置DAC和定时器的代码可能涉及HAL_DAC_Start_DMA,或者使用定时器触发来启动转换。此外,生成正弦波数组时,需要计算正确的点数,使得输出频率正确。例如,如果定时器触发频率为Fs,那么正弦波的频率f = Fs / N,其中N是一个周期内的点数。 另外,用户可能需要关于如何计算正弦表的指导。例如,使用C语言中的sin函数生成一个数组,量化为12位DAC的值(0到4095)。例如,对于N点,每个点的值为2048 + 2047*sin(2π*i/N),然后转换为整数。 现在需要考虑可能的错误点。比如,DAC的输出范围是否正确(是否使用缓冲,输出电压范围),定时器的配置是否正确,是否启用了DMA传输以减少CPU负载,或者是否在中断中逐个发送数据。此外,如果DAC的触发源设置不正确,可能导致输出不更新。 科协的示例代码可能使用标准外设库或HAL库,所以需要确定用户使用的库类型。但用户可能没有明确说明,所以可能需要提供通用的HAL库代码示例,或者提示用户根据具体库调整。 另外,用户的问题中还提到了引用站内的两个引用,但引用内容似乎与舵机引脚和VoIP协议有关,可能与当前问题无关,可能是用户误贴或者系统错误。因此,可能忽略这些引用,专注于DAC配置。 总结步骤: 1. 配置DAC的GPIO为模拟输入(虽然作为输出,但STM32的DAC引脚需要配置为模拟模式)。 2. 初始化DAC,设置触发源为定时器(例如TIM6)。 3. 配置定时器以产生所需的触发频率。 4. 生成正弦波数据表。 5. 使用DMA或中断来传输数据到DAC。 可能的代码示例: 初始化部分: 启用时钟: __HAL_RCC_DAC1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); 配置GPIO: GPIO_InitStruct.Pin = GPIO_PIN_4; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 配置DAC: DAC_ChannelConfTypeDef sConfig = {0}; sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO; // 假设使用TIM6作为触发源 sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1); 配置定时器: htim6.Instance = TIM6; htim6.Init.Prescaler = 预分频值; htim6.Init.CounterMode = TIM_COUNTERMODE_UP; htim6.Init.Period = 自动重载值; HAL_TIM_Base_Init(&htim6); HAL_TIM_Base_Start(&htim6); 生成正弦表: #define SAMPLES 256 uint32_t sineWave[SAMPLES]; for(int i=0; i<SAMPLES; i++){ sineWave[i] = (uint32_t)(2048 + 2047 * sin(2 * M_PI * i / SAMPLES)); } 启动DAC: HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)sineWave, SAMPLES, DAC_ALIGN_12B_R); 这样,DAC会在每次定时器触发时自动从DMA获取下一个样本,循环播放,生成连续的正弦波。 用户可能需要调整定时器的频率和样本数来控制输出波形的频率。例如,定时器触发频率Fs = TIM6_CLK / (Prescaler +1) / (Period +1)。输出频率为Fs / SAMPLES。 此外,需要注意DAC的输出缓冲是否开启,这可能会影响驱动能力。如果负载较大,可能需要外接运算放大器。 最后,用户可能需要参考科协的具体示例代码,可能存在特定的配置细节,比如使用不同的定时器或DAC通道,或者不同的库函数。因此,建议用户查阅其提供的资料,同时根据上述步骤进行调整。</think>[用户可见层] ### STM32正弦波输出实现步骤(基于DAC) #### 1. DAC基础配置 1. **启用时钟**: ```c __HAL_RCC_DAC1_CLK_ENABLE(); // 使能DAC1时钟 __HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟(假设使用PA4/DAC1) ``` 2. **配置GPIO为模拟模式**: ```c GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_4; // DAC1通道对应PA4 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; // 必须设为模拟模式 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); ``` 3. **初始化DAC**: ```c DAC_ChannelConfTypeDef dac_config; dac_config.DAC_Trigger = DAC_TRIGGER_T6_TRGO; // 使用TIM6触发 dac_config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; HAL_DAC_ConfigChannel(&hdac1, &dac_config, DAC_CHANNEL_1); ``` #### 2. 定时器配置(触发DAC更新) ```c // 配置TIM6(基本定时器) TIM_HandleTypeDef htim6; htim6.Instance = TIM6; htim6.Init.Prescaler = 90 - 1; // 假设系统时钟90MHz,分频后1MHz htim6.Init.Period = 100 - 1; // 周期100,触发频率=1MHz/100=10kHz HAL_TIM_Base_Init(&htim6); HAL_TIM_Base_Start(&htim6); // 启动定时器 ``` #### 3. 生成正弦波数据表 ```c #define SAMPLE_POINTS 256 // 一个周期采样点数 uint32_t sine_table[SAMPLE_POINTS]; for (int i = 0; i < SAMPLE_POINTS; i++) { float angle = 2 * M_PI * i / SAMPLE_POINTS; sine_table[i] = (uint32_t)(2048 * (1 + sin(angle))); // 12位DAC范围:0-4095 } ``` #### 4. 启动DAC输出(DMA模式) ```c // 启动DAC DMA传输(自动循环) HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1, sine_table, SAMPLE_POINTS, DAC_ALIGN_12B_R); ``` #### 关键公式 输出正弦波频率计算公式: $$f_{out} = \frac{f_{trigger}}{N}$$ 其中: - $f_{trigger}$:定时器触发频率(示例中为10kHz) - $N$:正弦表长度(示例中256) - 示例输出频率:$10kHz / 256 \approx 39.06Hz$ --- ### 科协示例代码适配建议 1. **DAC触发模式**:科协代码可能使用`TIM4`或`TIM7`,需根据实际代码修改触发源[^2]。 2. **引脚兼容性**:若开发板DAC通道连接PA5,需修改GPIO配置为`GPIO_PIN_5`。 3. **DMA优化**:建议启用DMA以减少CPU占用(如示例代码所示)。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

城主_全栈开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值