完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
一、简介
本文介绍如何在SimpleBLEPeripheral工程中,使用PWM控制直流电机。 二、实验平台 协议栈版本:BLE-CC254x-1.4.0 编译软件:IAR 8.20.2 硬件平台:Smart RF(主芯片CC2541) 三、版权声明 博主:甜甜的大香瓜 声明:喝水不忘挖井人,转载请注明出处。 原文地址:http://blog.csdn.NET/feilusia 联系方式:897503845@qq.com 香瓜BLE之CC2541群:127442605 香瓜BLE之CC2640群:557278427 香瓜BLE之Android群:541462902 香瓜单片机之STM8/STM32群:164311667 甜甜的大香瓜的小店(淘宝店):https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i 四、 实验前提 1、在进行本文步骤前,请先 阅读 以下博文: 1)《CC2541之PWM》:http://blog.csdn.net/feilusia/article/details/50459970 2、在进行本文步骤前,请先 实现以下博文: 1)《CC2541之按键》: http://blog.csdn.net/feilusia/article/details/47336473 五、基础知识 1、直流电机是什么? 答:电机也就是马达,小时候玩的四驱车里的马达就是电机,能控制正反转、速度。 常用的电机有两类,直流电机与步进电机。 1)直流电机:便宜、只有2根控制线因此操作较易、转动误差大。无转动精度要求时可使用。 2)步进电机:较贵、有4根控制线因此操作较难、可根据脉冲计算步数进行精确定位。有转动精度要求可使用。 2、单片机中如何使用直流电机? 答:单片机是不能直接驱动电机的,需要有驱动电路。可以上淘宝买一个5V的直流电机+两路的H桥模块。 连接如下: H桥模块一共6个输入口,如上图最下面的6个引脚,从左到右依次为:B-1A、B-1B、GND、VCC、A-1A、A-1B。 H桥模块一共4个输出口,如上图最上面的4个引脚,左边两个引脚可以为一个电机使用,右边两个引脚可以为另一个电机使用。 注:本文的实验中使用如上图,也就是使用右边的通道,A-1A接P10、A-1B接P11。 六、实验步骤 1、编写并添加自定义的电机驱动 1)写一个电机驱动PWM.c(存放在“……BLE-CC254x-1.4.0ProjectsbleSimpleBLEPeripheralSourceGUA”路径下) //****************************************************************************** //name: PWM.c //introduce: 香瓜自定义的PWM驱动 //author: 甜甜的大香瓜 //changetime: 2016.04.14 //email: 897503845@qq.com //****************************************************************************** #include 《ioCC2540.h》 #include “PWM.h”/*********************宏定义************************/#ifndef BV#define BV(n) (1 《《 (n))#endif/*********************内部变量************************/static U8 sPWM_P10 = 0; //P10static U8 sPWM_P11 = 0; //P11//****************************************************************************** //name: PWM_Init //introduce: PWM的初始化 //parameter: none //return: none //author: 甜甜的大香瓜 //email: 897503845@qq.com //changetime: 2016.04.14 //****************************************************************************** void PWM_Init(void){ P1DIR |= BV(0)|BV(1); //P11和P10定义为输出 P1SEL |= BV(0)|BV(1); //将P11和P10设置为外设功能; T4CTL = 0x80; //16分频(8K)、关timer、自由运行模式 T4CC0 = 255 - sPWM_P10; //P10的初始化值,warm T4CC1 = 255 - sPWM_P11; //P11的初始化值,cold T4CCTL0 = 0x2C; //00 101 100无中断、Clear output on compare, set on 0x00、比较模式、No Capture T4CCTL1 = 0x2C; //00 101 100无中断、Clear output on compare, set on 0x00、比较模式、No Capture T4CTL |= BV(4); //开始定时器 }//****************************************************************************** //name: PWM_SetLed //introduce: PWM的两通道值设置 //parameter: nPWM_P10:p10的pwm值 // nPWM_P11:p11的pwm值 //return: none //author: 甜甜的大香瓜 //email: 897503845@qq.com //changetime: 2016.04.14 //******************************************************************************void PWM_SetLed(U8 nPWM_P10, U8 nPWM_P11){ sPWM_P10 = nPWM_P10; sPWM_P11 = nPWM_P11;}//****************************************************************************** //name: PWM_GetLed //introduce: PWM的两通道值读取 //parameter: nPWM_P10:p10的pwm值 // nPWM_P11:p11的pwm值 //return: none //author: 甜甜的大香瓜 //email: 897503845@qq.com //changetime: 2016.04.14 //******************************************************************************void PWM_GetLed(U8 *nPWM_P10, U8 *nPWM_P11){ *nPWM_P10 = sPWM_P10; *nPWM_P11 = sPWM_P11;}//****************************************************************************** //name: PWM_ControlData_Deal //introduce: 将占空比的数据与电机控制情况,转换成p10、p11的pwm数 //parameter: nPWM_P10:p10的pwm值 // nPWM_P11:p11的pwm值 // nDuty_Cycle:占空比// nMotor_Status:停止、正转、反转//return: none //author: 甜甜的大香瓜 //email: 897503845@qq.com //changetime: 2016.04.14 //******************************************************************************void PWM_ControlData_Deal(U8 *nPWM_P10, U8 *nPWM_P11, U8 nMotor_Duty_Cycle, U8 nMotor_Status){ switch(nMotor_Status) { case sMotor_Status_OFF: *nPWM_P10 = 0; *nPWM_P11 = 0; break; case sMotor_Status_POSITIVE: *nPWM_P10 = 0; *nPWM_P11 = (U8)(0xFF*nMotor_Duty_Cycle*0.01); break; case sMotor_Status_negative: *nPWM_P10 = (U8)(0xFF*nMotor_Duty_Cycle*0.01); *nPWM_P11 = 0; break; default: *nPWM_P10 = 0; *nPWM_P11 = 0; break; }}//****************************************************************************** //name: PWM_Pulse //introduce: PWM的值更新 //parameter: none //return: none //author: 甜甜的大香瓜 //email: 897503845@qq.com //changetime: 2016.04.14 //****************************************************************************** void PWM_Pulse(void){ // Set up the timer registers T4CC0 = 255 - sPWM_P10; //P10的初始化值,warm T4CC1 = 255 - sPWM_P11; //P11的初始化值,cold // Reset timer T4CTL &= ~BV(2); // start timer T4CTL |= BV(4); } 2)写一个电机驱动头文件PWM.h(存放在“……BLE-CC254x-1.4.0ProjectsbleSimpleBLEPeripheralSourceGUA”路径下) //****************************************************************************** //name: PWM.h //introduce: 香瓜自定义的PWM驱动头文件 //author: 甜甜的大香瓜 //changetime: 2016.04.14 //email: 897503845@qq.com //****************************************************************************** #ifndef PWM_H#define PWM_H/*********************宏定义************************/ #ifndef U8typedef unsigned char U8;#endif#ifndef U16typedef unsigned short U16;#endif#define sMotor_Status_OFF 0x00 //停止(P11低、P10低)#define sMotor_Status_POSITIVE 0x01 //正转(P11高、P10低) #define sMotor_Status_negative 0x02 //反转(P11低、P10高)/*********************函数声明************************/ extern void PWM_Init(void);extern void PWM_SetLed(U8 nPWM_P10, U8 nPWM_P11);extern void PWM_GetLed(U8 *nPWM_P10, U8 *nPWM_P11);extern void PWM_ControlData_Deal(U8 *nPWM_P10, U8 *nPWM_P11, U8 nMotor_Duty_Cycle, U8 nMotor_Status);extern void PWM_Pulse(void);#endif 3)工程中添加PWM.c和PWM.h 4)在IAR设置中添加按键驱动源文件路径 $PROJ_DIR$。。。。SimpleBLEPeripheralSourceGUA 2、定义PWM相关事件 1)定义PWM相关事件(SimpleBLEPeripheral.c的SimpleBLEPeripheral_ProcessEvent中) //香瓜 //PWM处理事件 if ( events & SBP_PWM_DEAL_EVT ) { //更新PWM PWM_ControlData_Deal(&sPWM_P10, &sPWM_P11, motor_config.Duty_Cycle, sMotor_Status);//根据占空比和电机转动情况,计算pwm值 PWM_SetLed(sPWM_P10, sPWM_P11); //先更新pwm值 PWM_Pulse(); //执行到计数器上 //如果有定时,则会定时一段时间后停止 if((sMotor_Status != sMotor_Status_OFF) && (motor_config.Time!= 0))//开启定时器 { osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_PWM_STOP_EVT, motor_config.Time ); } return (events ^ SBP_PWM_DEAL_EVT); } //PWM停止事件 if ( events & SBP_PWM_STOP_EVT ) { sMotor_Status = sMotor_Status_OFF; //0(停止)、1(正转)、2(反转) PWM_ControlData_Deal(&sPWM_P10, &sPWM_P11, motor_config.Duty_Cycle, sMotor_Status);//根据占空比和电机转动情况,计算pwm值 PWM_SetLed(sPWM_P10, sPWM_P11); //先更新pwm值 PWM_Pulse(); //执行到计数器上 return (events ^ SBP_PWM_STOP_EVT); } //香瓜 2)定义PWM相关事件的宏(SimpleBLEPeripheral.h中) //香瓜 #define SBP_PWM_DEAL_EVT 0x0004 //PWM的处理事件#define SBP_PWM_STOP_EVT 0x0008 //PWM停止事件 //香瓜 3)定义PWM事件的定时执行时间(SimpleBLEPeripheral.c中) //香瓜#define SBP_PWM_DEAL_EVT_PERIOD 1 //香瓜 上面的SBP_PWM_STOP_EVT事件,只有在有定时控制电机时才使用到。 下文中会将定时部分代码注释,有需要时再添加使用。 3、初始化PWM相关 1)添加PWM的头文件(SimpleBLEPeripheral.c中) //香瓜#include “PWM.h” //香瓜 2)定义PWM使用到的变量(SimpleBLEPeripheral.c中) //香瓜typedef struct { uint8 Duty_Cycle; //电机转速(0~64) uint32 Time; //转动时间 }MOTOR_CONFIG; MOTOR_CONFIG motor_config; static uint8 sPWM_P10 = 0; //p10static uint8 sPWM_P11 = 0; //p11static uint8 sMotor_Status = sMotor_Status_OFF; //0(停止)、1(正转)、2(反转)//香瓜 3)初始化变量、PWM驱动等(SimpleBLEPeripheral.c的SimpleBLEPeripheral_Init中) //香瓜 //给结构体数据赋初值 motor_config.Duty_Cycle = 0x00; //根据占空比和电机转动情况,计算pwm值 PWM_ControlData_Deal(&sPWM_P10, &sPWM_P11, motor_config.Duty_Cycle, sMotor_Status); //PWM初始化 PWM_SetLed(sPWM_P10, sPWM_P11); PWM_Init(); //默认是ENABLE的,会让RF期间停止MCU HCI_EXT_HaltDuringRfCmd(HCI_EXT_HALT_DURING_RF_DISABLE); //香瓜 4、修改按键处理函数(SimpleBLEPeripheral.c中) //香瓜static void simpleBLEPeripheral_HandleKeys( uint8 shift, uint8 keys ){ VOID shift; // Intentionally unreferenced parameter //切换电机开关机情况 if ( keys & HAL_KEY_UP ) { switch(sMotor_Status) { //停止电机状态,切换到正转状态 case sMotor_Status_OFF: { sMotor_Status = sMotor_Status_POSITIVE; break; } //正转状态,切换到反转状态 case sMotor_Status_POSITIVE: { sMotor_Status = sMotor_Status_negative; break; } //反转状态,切换到停止状态 case sMotor_Status_negative: { sMotor_Status = sMotor_Status_OFF; break; } //其他情况,切换到停止状态 default: { sMotor_Status = sMotor_Status_OFF; break; } } }/* if ( keys & HAL_KEY_DOWN ) { switch(motor_config.Time) { //无定时状态,切换到2S停止状态 case 0: { motor_config.Time = 2000; break; } //2S停止状态,切换到10S停止状态 case 2000: { motor_config.Time = 10000; break; } //10S停止状态,切换到无停止状态 case 10000: { motor_config.Time = 0; break; } //其他情况,切换到无停止状态 default: { motor_config.Time = 0; break; } } }*/ //切换占空比 if ( keys & HAL_KEY_SW_6 ) { switch(motor_config.Duty_Cycle) { //占空比为0的状态,切换到占空比为50的状态 case 0x00: { motor_config.Duty_Cycle = 0x32; break; } //占空比为50的状态,切换到占空比为100的状态 case 0x32: { motor_config.Duty_Cycle = 0x64; break; } //占空比为100的状态,切换到占空比为0的状态 case 0x64: { motor_config.Duty_Cycle = 0x00; break; } //其他情况,切换到占空比为0的状态 default: { motor_config.Duty_Cycle = 0x00; break; } } } //执行pwm处理事件变化电机 osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_PWM_DEAL_EVT, SBP_PWM_DEAL_EVT_PERIOD ); }//香瓜为了不使例子过于复杂,代码中将电机转动定时部分的代码注释。 需要定时控制电机时可参考上面的注释代码进行添加。 5、将IAR设置中的LCD宏关闭 如果不关闭,在上电时会造成P10、P11的电平不稳,这个电平不稳就是LCD驱动造成的。 因此,需要在此禁止LCD的驱动初始化。 七、注意事项 暂无 八、实验结果 1、通过按Smart RF板上的UP键,可以不停地切换“停止、正转、反转”的停转状态。 2、通过按Smart RF板上的S1键,可以不停地切换“0%、50%、100%”的占空比。 |
|
|
|
只有小组成员才能发言,加入小组>>
659浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-26 16:12 , Processed in 0.668818 second(s), Total 78, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号