历史上的今天
返回首页

历史上的今天

今天是:2025年05月27日(星期二)

正在发生

2019年05月27日 | STM32输出可控数量与频率的脉冲

2019-05-27 来源:eefocus

最近在准备电赛做往年的题目,遇到了使用步进电机作为执行器的题目,步进电机有固定的步距角,所以每圈有固定的步数,比如我现在使用的步进电机的步距角为1.8度,所以说转一圈需要走200步,我使用的步进电机驱动器可以进行16细分,这样每转一圈就需要3200步。而这个驱动器使用脉冲来进行控制,每收到一个脉冲就会走一步,所以如果可以每次精确的控制输出的脉冲数,那么在不失步的情况下可以精确控制步进电机转过的角度。


    关于脉冲输出的控制我查阅网上资料后发现有五种方法


    1、单脉冲法,需要一个脉冲中断一次,中断次数多,影响效率


    2、一个定时器输出PWM,另一定时器进行中断计数,与方法1一样,同样需要频繁的中断


    3、用主从定时器门控方式,比较繁琐


    4、用一个定时器(从)作为另一个定时器(主)的外部时钟触发源


    5、高级定时器T1、T8的重复计数方式,RCR计数中断,看手册好像这种方式最简单,能满足一部分人要求,缺点是寄存器只有8位,最多实现255个脉冲计数输出。


    这里我使用了第四个方法。


    pulse.h


#ifndef __PUSEL_H

#define __PUSEL_H

#include "sys.h"

 

void TIM1_config(u32 Cycle);

void TIM2_config(u32 PulseNum);

void Pulse_output(u32 Cycle,u32 PulseNum);

 

 

#endif

 

    pulse.c


#include "pulse.h"

 

 

/***********************TIM1初始化函数*************************/

/****参数:****************************************************/

/******u32 Cycle用于设定计数频率(计算公式:Cycle=1Mhz/目标频率)/

/****返回值:**************************************************/

/******无*****************************************************/

void TIM1_config(u32 Cycle)

{

    GPIO_InitTypeDef GPIO_InitStructure;

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    TIM_OCInitTypeDef  TIM_OCInitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_TIM1 , ENABLE); //时钟使能

 

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;                   //TIM1_CH4 PA11

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

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStructure);

 

    TIM_TimeBaseStructure.TIM_Period = Cycle-1;                 //使用Cycle来控制频率(f=72/(71+1)/Cycle)  当Cycle为100时脉冲频率为10KHZ                           

    TIM_TimeBaseStructure.TIM_Prescaler =71;                    //设置用来作为TIMx时钟频率除数的预分频值                                                     

    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;     //设置时钟分割:TDTS= Tck_tim            

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式

    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;            //重复计数,一定要=0!!!(高级定时器特有)

    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);                                       

 

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;          //选择定时器模式:TIM脉冲宽度调制模式1       

    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能

    TIM_OCInitStructure.TIM_Pulse = Cycle/2-1;                    //设置待装入捕获寄存器的脉冲值(占空比:默认50%,这可也可以调节如果需要的话将它作为一个参数传入即可)                                   

    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;      //输出极性       

 

    TIM_OC4Init(TIM1, &TIM_OCInitStructure);        //使能通道4                                                 

 

    TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable); //设置为主从模式

    TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update); //选择定时器1的触发方式(使用更新事件作为触发输出)

    

 

    TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);               //使能通道4预装载寄存器               

    TIM_ARRPreloadConfig(TIM1, ENABLE);                             //使能TIM1在ARR上的预装载寄存器       

}

/***********************TIM2初始化函数*************************/

/****参数:****************************************************/

/******u32 PulseNum用于设定脉冲数量****************************/

/****返回值:*************************************************/

/******无*****************************************************/

void TIM2_config(u32 PulseNum)

{

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    NVIC_InitTypeDef NVIC_InitStructure; 

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能定时器2的时钟

 

    TIM_TimeBaseStructure.TIM_Period = PulseNum-1;    //脉冲数

    TIM_TimeBaseStructure.TIM_Prescaler =0;    

    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;     

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  

    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);  

 

    TIM_SelectInputTrigger(TIM2, TIM_TS_ITR0); //选择定时器2的输入触发源(内部触发(TIM1))

 

    TIM2->SMCR|=0x07;                                  //设置从模式寄存器(SMS[2:0]:111 外部时钟模式1) 

 

    TIM_ITConfig(TIM2,TIM_IT_Update,DISABLE); //更新中断失能

 

    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;        

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;     

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 

    NVIC_Init(&NVIC_InitStructure); //定时器2中断初始化

}

/************************脉冲输出函数**************************/

/****参数:****************************************************/

/******u32 Cycle用于设定计数频率(计算公式:Cycle=1Mhz/目标频率)/

/******u32 PulseNum用于设定输出脉冲的数量(单位:个)************/

/****返回值:**************************************************/

/******无*****************************************************/

void Pulse_output(u32 Cycle,u32 PulseNum)

{

    TIM2_config(PulseNum); //设置脉冲数量

    TIM_Cmd(TIM2, ENABLE); //使能TIM2(从定时器)

    TIM_ClearITPendingBit(TIM2,TIM_IT_Update); //清除中断标志位

    TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); //使能更新中断

    TIM1_config(Cycle); //使能定时器1(主定时器)

    

    TIM_Cmd(TIM1, ENABLE); //使能定时器1

    TIM_CtrlPWMOutputs(TIM1, ENABLE);    //高级定时器一定要加上,主输出使能

}

 

 

 

/********************定时器2的中断服务函数**********************/

/****参数:****************************************************/

/******u32 PulseNum用于设定脉冲数量****************************/

/****返回值:*************************************************/

/******无*****************************************************/

/****函数说明:************************************************/

/*当TIM的CNT寄存器的值到达设定的Update值会触发更新中断,此时设定的脉冲数已输出完毕,关闭TIM1和TIM2*/

void TIM2_IRQHandler(void) 

    if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) //TIM_IT_Update

    { 

        TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // 清除中断标志位 

        TIM_CtrlPWMOutputs(TIM1, DISABLE);  //主输出使能

        TIM_Cmd(TIM1, DISABLE); //关闭定时器 

        TIM_Cmd(TIM2, DISABLE); //关闭定时器 

        TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE); //关闭TIM2更新中断

        

    } 

 

    main.c


#include "sys.h"

#include "delay.h"

#include "led.h"

#include "usart.h"

#include "pulse.h"

 

 

int main()

{

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2

delay_init();     //延时函数初始化

uart_init(9600); //9600  

led_init();

while(1)

{

LED=1;

delay_ms(500);

LED=0;

delay_ms(500);

Pulse_output(100,3200);

}

}

 

    脉冲频率10KHz,每经过1s会输出3200个脉冲,步进电机会转1周。


    经过测试,可以快速输出可控频率和数量的脉冲,控制效果也良好,具体实用效果还需要在项目中运用后再更新。


推荐阅读

史海拾趣

Asia Electronics Ind Co Ltd公司的发展小趣事

随着公司产品的不断成熟和市场的不断扩大,Asia Electronics Ind Co Ltd积极寻求市场拓展的机会。公司加强与国际知名企业的合作,通过参加国际电子展、建立海外销售渠道等方式,不断提升品牌知名度和影响力。同时,公司还注重品牌形象的塑造,通过统一的品牌标识、宣传资料等,增强消费者对品牌的认知度和信任度。

Astro Industries Inc公司的发展小趣事

面对日益激烈的市场竞争,Astro Industries Inc意识到成本控制的重要性。于是,公司开始着手进行供应链的整合与优化。通过与优质供应商建立长期合作关系,公司确保了原材料的稳定供应和质量可控。同时,公司还引入了先进的生产管理系统,提高了生产效率,降低了生产成本。这些措施使得Astro Industries Inc在保持产品质量的同时,也具备了更强的市场竞争力。

台湾三礼(3L)公司的发展小趣事

近年来,随着环保意识的提升和绿色能源的普及,三礼公司也积极投身于绿色生产领域。2019年,公司在广西南宁开始建设新厂,预定投资3亿元人民币用于厂房及自动化设备的建设。新厂总建筑面积达70,000平方米,将成为公司目前所有生产基地中规模最大的一个。同时,公司还计划全面架设太阳能发电系统,目标是在未来三年内承担公司总需求电量的30%。这一举措不仅有助于降低公司的生产成本,还体现了公司对环保事业的积极贡献。

这五个故事只是三礼公司发展历程中的一部分缩影,但它们却生动地展现了公司在电子行业中的成长轨迹和不懈努力。从北美市场的拓展到中国内地生产能力的扩大,再到技术突破和新产品开发,三礼公司始终保持着敏锐的市场洞察力和强大的创新能力。同时,公司还积极投身于绿色生产领域,为推动电子行业的可持续发展做出了积极贡献。

芯佰微(Corebai)公司的发展小趣事

芯佰微(Corebai)公司自创立之初,就致力于成为电子行业中微电子领域的领军企业。创始人团队凭借对半导体技术的深厚理解和对市场需求的敏锐洞察,确立了公司的核心技术路线——专注于高性能模拟和数字集成电路的研发。在创业初期,芯佰微就投入大量资源用于技术研发,成功研发出多款具有自主知识产权的集成电路产品,奠定了公司在行业中的技术基础。

EA Elektro-Automatik公司的发展小趣事

EA Elektro-Automatik深知持续创新是企业发展的重要动力。因此,公司始终将创新作为企业文化的核心价值观之一。公司鼓励员工积极提出创新想法和解决方案,并为他们提供充分的支持和资源。此外,EA Elektro-Automatik还积极参与各类科研项目和行业标准的制定工作,推动整个行业的创新和发展。这种企业文化不仅为公司带来了更多的机会和挑战,也为企业的长期发展奠定了坚实的基础。

以上是关于EA Elektro-Automatik公司在电子行业发展的5个相关故事。这些故事展示了公司从创立到成为全球知名电子测量品牌的发展历程和取得的成就。

Blaze Display Technology Co Ltd公司的发展小趣事

在国内市场取得一定成绩后,Blaze公司开始积极拓展国际市场。通过与全球知名企业的合作,公司成功将产品打入国际市场,并赢得了良好的口碑。此外,公司还积极参加国际电子展会和交流活动,与全球同行建立了广泛的合作关系,为公司的进一步发展奠定了坚实的基础。

问答坊 | AI 解惑

JPEG2000中嵌入式块编码的FPGA设计

摘要: 为了使JPEG2000能应用到便携产品中,采用了高效存储结构的硬件实现方案,并设计了相应的寄存器组和控制逻辑。仿真结果表明所设计所设计的编码器能够在0.256s内完成对一帧512×512的灰度图像的编码。 关键词: 基于最优截断的嵌入式编码 JP ...…

查看全部问答>

电源赛预测题

本帖最后由 paulhyde 于 2014-9-15 09:25 编辑 大家看看  …

查看全部问答>

卖一块二手gec 2440开发板,价钱800,可砍价.带触摸屏.仅限苏州地区当面交易,可以先试用.资料齐全.联系请加msn:guyuguang8628391@h

GEC2440开发板硬件构成 硬件功能介绍: ◆ 采用三星公司的 S3C2440,系统稳定运行在405MHz,最高可达530MHz; ◆ 64M 字节的 SDRAM,由两片 K4S561632 组成,工作在 32 位模式下; ◆ 64M 字节 NAND Flash,采用的是 K9F1208,可以兼容 16M ...…

查看全部问答>

IDE编译出错

\"data\"   segment   too   large    尝试过的解决办法 1、设置 DATA格式为 XDATA: 但是程序不能在单片机上正常运行 2、改变数组存储方式uchar key0[16][40],key1[16][40] TO uchar code key0[16][40 ...…

查看全部问答>

如何调用PDA外界设备

比如说 设置一个按钮,点击可以打开PDA上的 照相机或者浏览器或者图片查看器等, 象这样的功能怎么实现?…

查看全部问答>

evc读写u盘

请教各位大虾,MARY1021897@SOHU.COM 我在PC104上插了U盘,需要在evc的应用程序里把TXT文本存储在U盘里。 将文件转移到u盘操作很慢,用了MoveFile,从本地剪切到u盘,一分钟都不能转移完成。到底怎么回事?求救了…

查看全部问答>

请问中断嵌套为什么cpu在中断级别低时,高的中断级别进不

看过浪淘沙曾经的留言:硬件的中断嵌套功能是指,当CPU响应某个中断请求时,处理该中断的过程,可以被软件中断级别比它高的中断所打断;在这里硬件的支持中断嵌套引入了一个软件中断级别的概念,通常我们说的中断级别称为硬件中断级别。我在程 ...…

查看全部问答>

关于IAR的最高级别优化

    用的IAR 4.42A 开发STM32F103 开始是调试模式没有优化,代码长度104k 开了最高级别代码大小优化后,一下子变成了84k,开机运行挺正常,但是运行一会TFT就花屏。。死机。。。   &n ...…

查看全部问答>

stm32初始化位置的尝试

MCU开发时肯定会涉及到外设初始化这个问题,对于初始化外设通常来说有两种做法: 1、在程序初始化时集中把所有程序中要用的外设依次全部初始化,这样,在写各个模块功能时就不再管初始化问题了, 2、在每个功能模块中单独写一个本功能模块 ...…

查看全部问答>

关于硬件IIC通信的问题请教!

利用1611上的硬件IIC通信,同一430打算利用主发送方式、从接收方式2种方式来进行数据通信。 在调试中发现:发送数据后对方能接收到,但对方回发数据却接收不到或乱码(2机对联,通信方式一样,即发送时都为主,接收时都为从),这是为什么?接收和 ...…

查看全部问答>