当前位置: 首页 > wzjs >正文

影业的网站怎么做网站建设与管理就业前景

影业的网站怎么做,网站建设与管理就业前景,鲜花网站建设源代码,广州化妆品网站建设公司排名简介 (2025/4/21) 本库对目前仅针对TB6600驱动下的42步进电机的基础功能进行了一定的封装, 也是我初次尝试以面向对象的思想去编写嵌入式代码, 和直流电机的驱动步骤相似在调用stepmotor_attach()函数和stepmotor_init()函数之后仅通过结构体数组stepm然后指定枚举变量中的id即…

简介

(2025/4/21)

        

        本库对目前仅针对TB6600驱动下的42步进电机的基础功能进行了一定的封装, 也是我初次尝试以面向对象的思想去编写嵌入式代码, 和直流电机的驱动步骤相似在调用stepmotor_attach()函数和stepmotor_init()函数之后仅通过结构体数组stepm然后指定枚举变量中的id即可完成对步进电机的基础操作, 其中最核心的是控制函数step_move的实现, 该函数可以在开环状态下指定步进电机的步数频率(速度)进行控制, 后续可能会更新一些经典的控制模型如梯形加减速.
先贴一下项目代码
项目源码

cubemx 配置

如果要使用此库, 你只需要在cubemx中完成以下配置:

  1. 打开定时器的PWM通道并将 Prescaler设置为83(我的时钟主频为84分频后为1MHz, 这个并不是一定得是1MHz, 后面会说)

  2. 打开NVIC

  3. 配置相关的GPIO, 如方向引脚, 这个很简单我就不贴图了

移植

如果你的硬件平台和我一样, 无脑粘贴就行, 如果不一样, 则需要修改相关代码

  1. 修改类型(如果不是stm32HAL库)
    主要是硬件层结构体的类型声明, 和stepmotor_attach函数, 需要修改类型
typedef struct {// todo 硬件参数层TIM_HandleTypeDef* htim;    //定时器句柄uint32_t Channel;           // 输出通道GPIO_TypeDef* enType;       //使能引脚类别uint16_t  enPin;            //使能引脚pinGPIO_TypeDef* dirType;      //方向引脚类别uint16_t  dirPin;           //方向引脚pin
}STEPMOTOR_HARDWARE;
void stepmotor_attach(STEPID id,TIM_HandleTypeDef* htim,uint32_t Channel,           // 输出通道GPIO_TypeDef* enType,        //使能引脚类别uint16_t  enPin,             //使能引脚pinGPIO_TypeDef* dirType,      //方向引脚类别uint16_t  dirPin           //方向引脚pin);

    2. 底层接口函数封装
这里都添加在了step_motor.c中的部分以static声明的函数当中, 根据注释功能修改函数的实现:

static void en_set(STEPID id){// todo 使能置高STEPMOTOR_HARDWARE* hw = &stepmotorhws[id];hw->enType->BSRR = hw->enPin;
}
static void en_reset(STEPID id){// todo 使能置低STEPMOTOR_HARDWARE* hw = &stepmotorhws[id];hw->enType->BSRR = (uint32_t)hw->enPin << 16U;                 // 置位
}static void dir_set(STEPID id){// todo 方向置高STEPMOTOR_HARDWARE* hw = &stepmotorhws[id];hw->dirType->BSRR = hw->dirPin;
}
static void dir_reset(STEPID id){// todo 方向置低STEPMOTOR_HARDWARE* hw = &stepmotorhws[id];hw->dirType->BSRR = (uint32_t)hw->dirPin << 16U;                 // 置位
}static void tim_start(STEPID id){// todo 定时器启动STEPMOTOR_HARDWARE* hw = &stepmotorhws[id];hw->htim->Instance->CR1 |= TIM_CR1_CEN;
}
static void tim_stop(STEPID id){// todo 定时器停止并清0STEPMOTOR_HARDWARE* hw = &stepmotorhws[id];__HAL_TIM_SET_COUNTER(hw->htim, 0);__HAL_TIM_CLEAR_FLAG(hw->htim, TIM_FLAG_UPDATE);
}static void pwm_start(STEPID id){// todo pwm启动STEPMOTOR_HARDWARE* hw = &stepmotorhws[id];HAL_TIM_PWM_Start(hw->htim, hw->Channel);
}
static void pwm_stop(STEPID id){// todo pwm停止 其实将比较值赋为0就行STEPMOTOR_HARDWARE* hw = &stepmotorhws[id];HAL_TIM_PWM_Stop(hw->htim, hw->Channel);
}static void pwm_startIT(STEPID id){// todo pwm中断开启STEPMOTOR_HARDWARE* hw = &stepmotorhws[id];HAL_TIM_PWM_Start_IT(hw->htim, hw->Channel);
}
static void pwm_stopIT(STEPID id){// todo pwm中断停止STEPMOTOR_HARDWARE* hw = &stepmotorhws[id];HAL_TIM_PWM_Stop_IT(hw->htim, hw->Channel);
}
static void pwm_setcompare(STEPID id, int32_t freq){// todo 设置50%的占空比// todo 重新设置占空比(占空比永远为比较值的一半, 即50%占空比)STEPMOTOR_HARDWARE* hw = &stepmotorhws[id];if(freq > 0){hw->htim->Instance->ARR = Hclk/freq - 1;__HAL_TIM_SET_COMPARE(hw->htim, hw->Channel, hw->htim->Instance->ARR/2); // 占空比无所谓 一半即可}
}

    3. 频率宏定义
step_motor.h中的:

#define   Hclk       1000000  //时间总频

这个是预分频后的频率
根据实际情况来, 如果你是72MHz主频, 定时器的Prescaler设置为71, 则不用改, 因为分频后依然为1MHz
如果你的定时器的Prescaler值设置为0, 那么这个就是你的时钟主频了
这个值参与ARR的赋值计算(在**static void pwm_setcompare(STEPID id, int32_t freq);**中), 所以你得好好根据自己ARR的量程来, 像c8t6是65535最大, 那么你最好将Prescaler值给大一些              

    4. 中断修改(如果不是stm32HAL库)
具体的修改逻辑看看下面的步数&速度控制这个标题下的内容, 根据你的平台中断逻辑进行修改.

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{if(htim == stepm[SM1].hw->htim)    // 回调函数检测为某个步进电机对应的定时器{Stepper_UpdateHandler(SM1);}
}

初始化

成员变量概览

先看看一个对象所包含的属性, 这里我都敲了注释, 主要是使用STEPMOTOR作为对象的类型.

typedef struct {// todo 硬件参数层TIM_HandleTypeDef* htim;    //定时器句柄uint32_t Channel;           // 输出通道GPIO_TypeDef* enType;       //使能引脚类别uint16_t  enPin;            //使能引脚pinGPIO_TypeDef* dirType;      //方向引脚类别uint16_t  dirPin;           //方向引脚pin// todo 硬件API重写层STEPMOTOR_INTERFACE enSet;                // 方向引脚置位STEPMOTOR_INTERFACE enReset;                // 方向引脚置位STEPMOTOR_INTERFACE dirSet;                // 方向引脚置位STEPMOTOR_INTERFACE dirReset;                // 方向引脚置位STEPMOTOR_INTERFACE htimStop;              // 停止并复位定时器STEPMOTOR_INTERFACE htimStart;              // 重新启动定时器STEPMOTOR_INTERFACE pwmStop;                // pwm停止STEPMOTOR_INTERFACE pwmStart;               // pwm启动STEPMOTOR_INTERFACE pwmStopIT;             // pwm中断计数停止STEPMOTOR_INTERFACE pwmStartIT;            // pwm中断计数启动STEPMOTOR_SPEED_INTERFACE pwmSetCompare;          // pwm设置为50%的占空比}STEPMOTOR_HARDWARE;typedef struct{STEPMOTOR_HARDWARE* hw;  // 硬件接口封装层// todo 参数层uint32_t cur_freq;  // 当前频率Hzuint16_t cur_step;  // 当前步数uint8_t dir;        // 当前方向// todo 目标值uint16_t tar_step;  // 目标步数// todo 限制层uint8_t is_limit_step;          // 你是否要限制步数uint8_t is_finish;              // 是否完成路程int16_t accumulate_step;       // 累计步数int32_t max_step;              // 最大步数  - 配合累计步数以限幅int32_t min_step;              // 最小步数  - 配合累计步数以限幅uint32_t min_freq;             // 最小运行频率uint32_t max_freq;             // 最大运行频率// todo 函数接口层STEPMOTOR_INTERFACE limitStep;STEPMOTOR_INTERFACE noLimitStep;STEPMOTOR_STEP_INTERFACE stepMove;      // 指定步数和速度进行移动STEPMOTOR_INTERFACE stop;               // 立即停止STEPMOTOR_RANGE_INTERFACE setRange;     // 设置相关范围的接口}STEPMOTOR;

我们需要将step_motor.cstep_motor.h添加到你的工程目录下面, 然后调用初始化函数

void stepmotor_attach(STEPID id,                  // 电机idTIM_HandleTypeDef* htim,    // 电机对应定时器uint32_t Channel,           // 输出通道GPIO_TypeDef* enType,        //使能引脚类别uint16_t  enPin,             //使能引脚pinGPIO_TypeDef* dirType,      //方向引脚类别uint16_t  dirPin           //方向引脚pin);
stepmotor_init();

前者stepmotor_attach是引脚定向, 为了后面我们可以用结构体数组引出各种属性和函数进行调用, 以下是函数的实现流程

void stepmotor_attach(STEPID id,TIM_HandleTypeDef* htim,uint32_t Channel,           // 输出通道GPIO_TypeDef* enType,        //使能引脚类别uint16_t  enPin,             //使能引脚pinGPIO_TypeDef* dirType,      //方向引脚类别uint16_t  dirPin           //方向引脚pin){STEPMOTOR_HARDWARE* hw = &stepmotorhws[id];// todo 硬件引脚重指定hw->htim = htim;            // 硬件接口初始化hw->Channel = Channel;hw->enType = enType;hw->enPin = enPin;hw->dirType = dirType;hw->dirPin = dirPin;// todo 硬件函数接口hw->enSet = en_set;hw->enReset = en_reset;hw->dirSet = dir_set;hw->dirReset = dir_reset;hw->htimStart = tim_start;hw->htimStop = tim_stop;hw->pwmStop = pwm_stop;hw->pwmStart = pwm_start;hw->pwmStartIT = pwm_startIT;hw->pwmStopIT = pwm_stopIT;hw->pwmSetCompare = pwm_setcompare;// todo 控制接口函数stepm[id].hw = hw;stepm[id].limitStep = limit_step;stepm[id].noLimitStep = no_limit_step;stepm[id].stepMove = step_move;    // 移动函数接口赋值stepm[id].stop = step_stop;        // 立即停止接口指定stepm[id].setRange = set_range;    // 范围设置指向
}

stepmotor_init() 是初始化函数, 在这里cubemx已经初始化完成, 我只添加了相关外设如定时器中断等启动函数也可以添加自己的初始化代码.

void stepmotor_init(void){for(uint8_t i = 0; i < STEP_SUM; i++){STEPMOTOR* m = &stepm[i];                      // 获取对象指针// todo 其他初始化// todo 启动m->hw->pwmStartIT(i);   // PWM中断m->hw->enSet(i);        // 使能引脚使能}
}

使用库进行控制

步数&速度控制

目前没有添加太多的算法, 仅仅是开环的指定速度位移移动的函数, 不过这应该也是后续底层最为核心的函数:

    // 指定id             id      指定走多少步  指定速度/频率
stepm[STEPID].stepMove(STEPID, int32_t,     uint32_t);

仅仅是使用的话, 只需要传入对应电机对象id和相关参数即可, 其中第二个参数是用于指定目标是多少步, 支持正负号, 可以输入负值, 它意味着电机朝反方向转.
同时, 因为我们在初始化配置的时候开启了PWM中断所以在这里我们也需要在中断中添加部分代码:

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{if(htim == stepm[SM1].hw->htim)    // 回调函数检测为某个步进电机对应的定时器{Stepper_UpdateHandler(SM1);}
}

在中断回调函数HAL_TIM_PWM_PulseFinishedCallback中, 我们只需要重复执行Stepper_UpdateHandler函数就行, 关于这个函数的实现其实很简单, 下面我会说明.

stepMove函数的具体实现如下:

// todo 以指定速度(频率), 移动指定步数
static void step_move(STEPID id, int32_t tar_steps, uint32_t freq){STEPMOTOR* m = &stepm[id];if(tar_steps == 0 || freq <=0){m->is_finish = 1;return;}m->is_finish = 0;   // 刷新完成标志位// todo 停止并复位定时器m->hw->pwmStopIT(id);m->hw->htimStop(id);//todo 方向引脚置位m->dir = (tar_steps >= 0) ? 1 : 0;if(m->dir) m->hw->dirSet(id);else m->hw->dirReset(id);// todo 设置目标步数 并对其进行步数限幅if(m->is_limit_step){int32_t pre_accumulate_step = m->accumulate_step;  // 存储上一次的步数m->accumulate_step = (int16_t) LIMIT(m->accumulate_step + tar_steps, m->max_step, m->min_step);m->tar_step = abs( m->accumulate_step - pre_accumulate_step);}else{m->tar_step = tar_steps;}m->cur_step = 0;    // 每刷新一次当前步数置为0// todo 限制频率范围  注意符号和取值范围freq = LIMIT((int32_t)freq, (int32_t)m->max_freq, (int32_t)m->min_freq);m->cur_freq = freq; // 获取当前频率// todo 重新设置占空比(占空比永远为比较值的一半, 即50%占空比)m->hw->pwmSetCompare(id, freq);// todo 重新启动定时器m->hw->htimStart(id);// todo 启用更新中断m->hw->pwmStartIT(id);
}

以及中断函数

// todo (重要)定时器更新中断处理(需在stm32f4xx_it.c(或者中断回调函数)中调用)
void Stepper_UpdateHandler(STEPID id) {STEPMOTOR* m = &stepm[id];if(m->cur_step < m->tar_step) {m->cur_step++;} else {                            // todo 如果检测到当前步数到了目标值就直接PWM_Stop不发波了m->is_finish = 1;m->hw->pwmStopIT(id);}
}

每一步的操作我都敲了注释, 总体上的控制思路如下(这也是比较常用的控制思路):
通过PWM中断去对每一步进行计数存入成员变量cur_step中, 方波每个周期进一次中断, 同时步进电机收到一个脉冲, 电机走一步. 当电机的当前步数大于等于目标步数pwm停止.

电机停止

stepm[STEPID].stop(STEPID);

调用即可, 函数实现仅仅是让目标步数等于当前步数

// todo 立即停止电机
static void step_stop(STEPID id) {STEPMOTOR * m = &stepm[id];//__HAL_TIM_DISABLE_IT(m->hw->htim, TIM_IT_UPDATE);m->tar_step = m->cur_step;
}

设置范围

//                      id     模式    最大值      最小值
stepm[STEPID].setRange(STEPID, char , int32_t , int32_t );

这里提供了两种模式:

  • 'f': 设置速度/频率范围 -- 较为常见
  • 's': 设置最大累计步数范围 -- 我控制二维步进云台时用的, 防止云台跑到范围外, 对累计的步数进行限幅
// todo 立即停止电机
static void set_range(STEPID id, char mode, int32_t ma, int32_t mi){STEPMOTOR* m = &stepm[id];switch (mode) {case 'f':   // todo 设置频率范围m->max_freq = ma;m->min_freq = mi;break;case 's':m->max_step = ma;m->min_step = mi;break;}
}

是否启用位移限幅

主要是对标志位is_limit_step进行操作, 如果你不需要累计位移控制, 比如说小车的应用场景, 可以置位不再限幅

//todo 调用示例
stepm[STEPID].limitStep(STEPID);
stepm[STEPID].noLimitStep(STEPID);//todo 实现
static void limit_step(STEPID id){stepm[id].is_limit_step = 1;}
static void no_limit_step(STEPID id){stepm[id].is_finish = 0;}
http://www.dtcms.com/wzjs/157228.html

相关文章:

  • 只做网站的人员工资免费seo在线工具
  • wp_query wordpress湖南seo优化公司
  • 怎样建个自己的网站seo第三方点击软件
  • 羽毛球赛事2022赛程宝鸡seo
  • 伍佰亿网站怎么样关键词查询神器
  • 用dw制作购物网站首页河北搜索引擎优化
  • 做珠宝首饰网站百度app官网下载
  • 中国建设教育协会bim考点网站广告公司注册
  • 门户网站建设预算表站长工具友链检测
  • 南京做网站yuanmus软文范例100字以内
  • 做调查问卷赚钱网站有哪些google站长工具
  • 哪家网站做的好淘宝客推广一天80单
  • 二级域名网站可以做360推广东莞网站推广企业
  • 做游戏交易网站有哪些内容企业网站大全
  • 微信手机客户端网站建设百度快速收录权限
  • 书城网站建设项目定义网络营销软件排行
  • 网站建设为了什么seo整站优化解决方案
  • 六安网站优化seo管理是什么
  • 上海企业专属网站建设平台信息流广告哪个平台好
  • 多个域名绑定同一个网站2023网站分享
  • 广州仿网站营销网站建设免费
  • 公司网站建设的好处太原seo全网营销
  • 基于开源框架的网站开发关键词挖掘站网
  • 怎么做动态网站视频怎么自己做网站推广
  • 专业做app下载网站哪里有网络推广
  • 常州做网站价格360搜索关键词优化软件
  • 建设现金分期网站怎样制作属于自己的网站
  • 网站建设域名跳转博客宁波网络推广联系方式
  • 外国炫酷网站设计刚开的店铺怎么做推广
  • 搬家公司网站模板网站优化的方式有哪些