历史上的今天
返回首页

历史上的今天

今天是:2025年03月14日(星期五)

正在发生

2019年03月14日 | STM32F103高级定时器死区时间的计算

2019-03-14 来源:eefocus

看了一些网上讲死区时间计算的教程,觉得讲述的不是很清楚,所以在此用我自己理解的方式讲述一遍,如有错误,请读者赐教。


  死区时间的设置:由寄存器“TIM1和TIM8刹车和死区寄存器TIMX_BDTR”中,位DTG[7:0]控制(中文数据手册可能出现错误,应当是DTG)。


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


  官方数据手册的说明不容易看懂,举的例子与我的应用场合也不一致,我使用的是72MHz的晶振,讲一讲我的死区时间是怎么算出来的。

DT死区时间;

TDTS为系统时钟周期时长;

TDTG为系统周期时长乘以倍数,这个值用于计算最终死区时间,也叫作步长。

在72M的定时器时钟下,TDTS = 1/72M = 13.89ns。


  这个计算比较复杂,主要思想就是把DTG的八位,掰成两半用。一半决定步长,另一半是与步长相乘的乘数,乘数可以自行设定,步长*乘数=死区时间。至于步长与乘数从哪里分开,看下表


项目 情况1 情况2 情况3 情况4

步长位置 DTG[7] DTG[7:6] DTG[7:5] DTG[7:5]

步长值(二进制) 1 10 110 111

步长是周期几倍 1 2 8 16

乘数位置 DTG[6:0] DTG[5:0] DTG[4:0] DTG[4:0]

乘数最大值 127 64+63 63+31 32+31

乘数范围 0~127 64~127 32~63 34~63

等价几倍周期 0~127 128~254 256~504 512~1008

周期125ns时,死区范围ns 0~15875 16000~31750 32000~63000 64000~126000

周期13.89ns时,死区范围ns 0~1764 1778~3528 3556~7000 7112~14001

接下来举例说明表格怎么用。


  例如72MHz的晶振,需要14us的死区时间,那么属于情况4,DTG[7:5] = 0b111,DTG[4:0]=31=0b1111,所以DTG = 0xff。72MH晶振的情况下,最大只能14us的死区。


  还是72MHz的晶振,需要3us的死区时间,那么属于情况2,DTG[7:6] = 0b10,步长=27.78,需要的乘数 = 3000÷27.78-64=108-64=44=0b101100,DTG[7:0]=0b10101100=0xAC。


  实际的系统中,死区的时间一般由硬件的响应速度决定。我的系统使用的驱动电路设计参考之前的博客


  使用的电机型号是JGB37-3530B。经过测试,3us的死区时间可以使用。


  下边是电机初始化的函数,主要的功能是用STM32的高级定时器TIM1,输出嵌入死区的互补PWM。


  使用两个通道输出PWM,通道1 的引脚是PA8和PB13,通道2 的引脚是PA9和PB14。一个周期是1ms,频率是1KHz,3us的死区时间。默认通道1的占空比是50%,通道2的占空比是0%,让电机以49.7%(占空比减去死区)的速度正转。


void PWM_Configuration(void)

{

    GPIO_InitTypeDef    GPIO_InitStructure;

    TIM_TimeBaseInitTypeDef TIM_BaseInitStructure;

    TIM_OCInitTypeDef TIM_OCInitStructure;

    TIM_BDTRInitTypeDef TIM_BDTRInitStructure;

    NVIC_InitTypeDef NVIC_InitStructure;

    //开启TIM和相应端口时钟

    //启动GPIO

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA  | RCC_APB2Periph_GPIOB,ENABLE);

    //启动AFIO

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

    //启动TIM1

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);


    //GPIO做相应设置,为AF输出             //PA8,PB13一组互补输出  A9,PB14一组互补输出

    //PA.8/9口设置为TIM1的OC1输出口

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStructure);

    //PB.13/14口设置为TIM1_CH1N和TIM1_CH2N输出口

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIO_SetBits(GPIOA, GPIO_Pin_8 | GPIO_Pin_9);

    GPIO_SetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_14);


    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);    

    NVIC_InitStructure.NVIC_IRQChannel =  TIM1_UP_IRQn;    

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;       

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  

    NVIC_Init(&NVIC_InitStructure);


    //TIM1基本计数器设置(设置PWM频率)1KHz 

    TIM_BaseInitStructure.TIM_Period = 1000-1;      //1khz  好计算。按照1%的精确度,理论最大72000/100 = 720KHz

    TIM_BaseInitStructure.TIM_Prescaler = 72-1;

    TIM_BaseInitStructure.TIM_ClockDivision = 0;

    TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数

    TIM_BaseInitStructure.TIM_RepetitionCounter = 0;

    TIM_TimeBaseInit(TIM1, &TIM_BaseInitStructure);

    //启用ARR的影子寄存器(直到产生更新事件才更改设置)

    TIM_ARRPreloadConfig(TIM1, ENABLE);


    //TIM1_OC1模块设置(设置1通道占空比)

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//TIM脉冲宽度调制模式1

    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出通道使能

    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;//互补输出

    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;//TIM输出比较极性高

    //TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;

    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;

    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;

    TIM_OCInitStructure.TIM_Pulse = 500;//待装入捕获比较寄存器的脉冲值

    TIM_OC1Init(TIM1, &TIM_OCInitStructure);


    //启用CCR1寄存器的影子寄存器(直到产生更新事件才更改设置)

    TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);


    

    //TIM1_OC2模块设置(设置2通道占空比)

    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;

    TIM_OCInitStructure.TIM_Pulse = 0;

    TIM_OC2Init(TIM1, &TIM_OCInitStructure);

    //启用CCR2寄存器的影子寄存器(直到产生更新事件才更改设置)

    TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);


    //OCx输出信号与参考信号相同,只是它的上升沿相对参考信号的上升沿有一个延迟

    //OCxN输出信号与参考信号相同,只是它的上升沿相对参考信号的下降沿有一个延迟


    //死区设置

    TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;

    TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;

    TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_2;

    TIM_BDTRInitStructure.TIM_DeadTime = 0xAC; //这里调整死区大小为3us      

    TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;

    TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;

    TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;

    TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);


    //TIM1_OC通道输出PWM

    TIM_CtrlPWMOutputs(TIM1, ENABLE);


    //TIM1开启

    TIM_Cmd(TIM1, ENABLE);

}



推荐阅读

史海拾趣

Dynastream公司的发展小趣事

展望未来,Dynastream将继续秉承“持续创新、追求卓越”的发展理念,致力于成为电子行业的领军企业。公司将继续加大研发投入,提高产品的技术含量和附加值;同时,也将注重人才培养和团队建设,为公司未来的发展提供有力保障。相信在不久的将来,Dynastream将在电子行业中创造更加辉煌的业绩。

请注意,以上故事均为基于Dynastream公司发展历程的假设性叙述,旨在展示其发展历程中的一些重要节点和成就。

Endicott Research Group Inc (ERG)公司的发展小趣事

近年来,随着全球对环保和节能的日益重视,ERG积极响应绿色发展的号召,开始研发更加高效节能的电源产品和LED照明解决方案。他们通过优化电路设计、采用新型材料和改进生产工艺,成功降低了产品的能耗和废弃物产生。这些环保举措不仅提升了公司的社会形象,还为其赢得了更多环保意识强的客户的青睐。同时,ERG也积极参与各种环保公益活动,为推动行业的绿色发展做出了积极贡献。

以上五个故事,客观地描述了ERG在电子行业中的发展历程和主要成就。从初创时期的艰苦奋斗,到不断拓展业务范围、加强技术研发、与科研机构合作以及积极响应环保号召,ERG始终保持着创新精神和进取心,为电子行业的发展做出了重要贡献。

Corporation Soneet公司的发展小趣事

随着国内市场的饱和,Soneet开始将目光投向国际市场。公司积极开拓海外市场,与国外的电子设备制造商建立合作关系。通过参与国际项目合作和技术交流,Soneet不断吸收国际先进的技术和管理经验,提升自身实力。如今,Soneet已经成为一家具有国际化视野和竞争力的电子企业。

请注意,以上故事均为虚构内容,旨在展示一个电子行业内新兴公司可能经历的发展历程。实际情况中,每家公司的发展路径都会因其自身的特点和市场环境而有所不同。

CDI-DIODE公司的发展小趣事

在电子行业的早期,CDI-DIODE公司以其精湛的技术研发能力崭露头角。公司通过不断投入研发,成功开发出一款高效能、低成本的二极管产品,迅速占领了市场份额。这一技术突破不仅提升了公司的竞争力,也为整个电子行业带来了革命性的变化。

GE Industrial Solutions公司的发展小趣事
由于光耦的CTR随温度变化而变化,可能导致输出信号的非线性失真。解决方法包括选择温度稳定性好的光耦,或在电路中加入温度补偿电路。
Exclara Inc公司的发展小趣事

随着技术的不断成熟和产品的日益完善,Exclara开始将目光投向全球市场。公司积极拓展海外市场,通过参加国际展会、与当地合作伙伴建立战略合作关系等方式,不断提升品牌知名度和市场份额。同时,公司也在全球范围内建立了完善的销售网络和售后服务体系,以确保客户能够享受到优质的产品和服务。

问答坊 | AI 解惑

一本名人的好书

麦肯锡方法,学管理的很好!…

查看全部问答>

Analog Design/verifiction Engineer

Analog Design/verifiction Engineer 美资公司 LSI 上海研发中心高薪诚聘存储通讯领域人才,薪水待遇优厚,部分人员有出国培训机会。(部门内部推荐) 有意者请将中英文简历发送至:asic_tapeout@hotmail.com Analog Design Engineer City :&nbs ...…

查看全部问答>

请问如果我不需要界面wince还适合吗?

不知道wince是不是很大一部分都是界面呢?…

查看全部问答>

VARIANT如何保存数据库所有数据

最近再做数据库开发.看见ADOCE提供的接口 /* [id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetRows )(             _Recordset __RPC_FAR * This,            ...…

查看全部问答>

想和高手交流吗?

深圳程序员QQ群联盟成立两年多,拥有三十个以上的QQ群,人数达二千多人,有30%以上的成员的经验丰富的老手,包括国内外顶级大公司的成员(如微软、IBM,SUN,华为)、国内著名高校和研究院成员,和有丰富实践经验的高级程序,还有少数女程序员。现推介 ...…

查看全部问答>

困惑:C51中结构体的使用

在写ds18b20驱动程序时,由于读设备64位rom代码,因此想用下结构体。 自定义的结构体为: struct RomCode {     uchar FamilyCode;     uchar SerialCode[6];     uchar Crc; }; 测试主函数: void main() ...…

查看全部问答>

Quartus MegaWizard Plug—In 字体

Quartus MegaWizard Plug—In 字体过小 完全看不见 有人遇到这样的问题吗?   请问各位大侠怎么办?…

查看全部问答>

转一篇天涯上的帖子 ,一位工程师的乌龙生活记

楼主我是一名年近30的工程师,目前在一大城市的半导体日企工作。1直2在奔3路上,94不敢娶7买房。最近面试不少90后,公司也有两个90后新人,他们个个像个小人精,就是那个责任心和态度呀~~~~搞出的事情经常让你无言以对,偏偏他们嘴甜会卖萌, ~~~~~ ...…

查看全部问答>

TI 电源学堂的视频问题

进入课程后  我就一直都是以下这个界面 不知道怎么回事   我等待一会 再去看学习进度  居然有进度了  但是我啥也没看上,请问是怎么回事啊 ,请教了?…

查看全部问答>

DC小电流的非接触式测量

项目中需要检测机车发出的0到20mA的电流信号,这个电流信号是用来控制机车的加减速的。由于涉及到机车的安全运行,只能采用非接触式的检测方式,比如互感器、霍尔传感器。现在找了很多互感器及霍尔传感器都没有这个DC 0~20mA这个范围,实在是太小了 ...…

查看全部问答>