This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
大家好、
要求:用 DRV8836DSSR 芯片来驱动空心杯电机、但现在有一些问题、如下所示:
所用的主控制芯片是 TMS320F28035 (56引脚)芯片、主控制芯片和 DRV8836芯片的硬件原理图如下:
从原理图可以清楚地看到主控制芯片和 DRV8836的连接关系。
CCS 使用 EPWM1和 EPWM2调节 DRV8836的完整代码如下:
第一个是 main.c 文件:
#include "Config.h" extern Uint16 RamfuncsLoadSize; void main(void) { InitSysCtrl(); DINT; InitPieCtrl(); IER = 0x0000; IFR = 0x0000; InitPieVectTable(); memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (Uint32)&RamfuncsLoadSize); LED_Init(); // 初始化LED- InitMotor(); // 初始化电机- Timer0_init(); // 定时器0初始化,1ms周期中断- PieCtrlRegs.PIECTRL.bit.ENPIE = 1; EINT; ERTM; while(1) { int f=900; /* 实现的任务1(10ms为一个周期): * 调控电机油门或转向*/ if(timer0Base.loop100HzCnt >= 10) { timer0Base.loop100HzCnt = 0; LED2_TOGGLE; DELAY_US(200*1000); MotorPwmFlash(f,2); LED3_TOGGLE; } } }
MOTO.c 文件:
#include "stdio.h" #include "Moto.h" uint8_t Turningmodeselection=Noturn; uint16_t MOTO1_PWM=0; /******************************************************************************* * 函 数 名: void InitMotor(void) * 函数功能: DRV8836双通道驱动电路初始化 *******************************************************************************/ void InitMotor(void) { EALLOW; nSLEEPMUX = 0; nSLEEPDIR = 1; //GPIO模式;输出模式 MODEMUX = 0; MODEDIR = 1; AIN1MUX = 0; AIN1DIR = 1; AIN2MUX = 0; AIN2DIR = 1; BIN1MUX = 0; BIN1DIR = 1; BIN2MUX = 0; BIN2DIR = 1; EDIS; nSLEEPLOW(); // DRV8836关闭模式 MODELOW(); // DRV8836为IN/IN模式 AIN1LOW(); AIN2LOW(); // BSDC1关闭 BIN1LOW(); BIN2LOW(); // BSDC2关闭 InitEPWM_AQ_DB(); // PWM 初始化函数 nSLEEPON(); // 唤醒Drv8836 printf("\r\nPWM(DRV8836) init...OK"); } /******************************************************************************* * 函 数 名: void InitEPWM_AQ_DB(void) * 函数功能: PWM1/2初始化 *******************************************************************************/ void InitEPWM_AQ_DB(void) { char i; volatile struct EPWM_REGS *PWMDef[] = {&EPwm1Regs,&EPwm1Regs,&EPwm2Regs,&EPwm3Regs,&EPwm4Regs,&EPwm5Regs,&EPwm6Regs}; EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC =0; //失能时基模块时钟 SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK =1; //时钟启用 SysCtrlRegs.PCLKCR1.bit.EPWM2ENCLK =1; //时钟启用 EDIS; InitEPwmGpio(); //开启时钟及初始化配置 EALLOW; PieVectTable.EPWM1_INT = &epwm1_isr; PieVectTable.EPWM2_INT = &epwm2_isr; EDIS; for(i=1;i<4;i++) { EALLOW; PWMDef[i]->TBCTL.bit.CTRMODE = TB_COUNT_UP; // 递增计数模式 PWMDef[i]->TBPRD = EPWM_TIMER_TBPRD; // 设置定时器周期 PWMDef[i]->TBCTL.bit.PHSEN = TB_DISABLE; // 禁止相位加载 PWMDef[i]->TBPHS.half.TBPHS = 0x0000; // 时基相位寄存器的值赋值0 PWMDef[i]->TBCTR = 0x0000; // 时基计数器清零,时基计数器为16 位, 读该寄存器的值可以得到时基计数器 (TBCTR) 的值。 写该寄存器可以设置时基计数器的值。 PWMDef[i]->TBCTL.bit.HSPCLKDIV = HTB_DIV1; // SYSCLKOUT=60M HZ PWMDef[i]->TBCTL.bit.CLKDIV = TB_DIV64; // 设置时基时钟速率 PWMDef[i]->CMPCTL.bit.SHDWAMODE = CC_SHADOW; //设置影子 PWMDef[i]->CMPCTL.bit.SHDWBMODE = CC_SHADOW; PWMDef[i]->CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; //设置加载模式,0加载 PWMDef[i]->CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // 设置比较寄存器的值 PWMDef[i]->CMPA.half.CMPA = 0; // 清零 PWMDef[i]->CMPB = 0; // 清零 // 设置动作限定;首先默认为转动方向为正转,这时只有PWMiA输出占空比; PWMDef[i]->AQCTLA.bit.ZRO = AQ_SET; // 计数到0时PWMxA输出高电平 PWMDef[i]->AQCTLA.bit.CAU = AQ_CLEAR; // 递增计数时,发生比较寄存器A匹配时清除PWMxA输出 PWMDef[i]->AQCTLB.bit.ZRO = AQ_CLEAR; // 计数到0时PWMxB输出低电平 PWMDef[i]->AQCTLB.bit.CBU = AQ_CLEAR; // 递增计数时,发生比较寄存器A匹配时清除PWMxB输出 // 1次0匹配事件发生时产生一个中断请求; PWMDef[i]->ETSEL.bit.INTSEL = ET_CTR_ZERO; // 选择0匹配事件中断 PWMDef[i]->ETSEL.bit.INTEN = 1; // 使能事件触发中断 PWMDef[i]->ETPS.bit.INTPRD = ET_1ST; // 1次事件产生中断请求 EDIS; } EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC =1; EDIS; IER |= M_INT3; //中断初始化 PieCtrlRegs.PIEIER3.bit.INTx1 = 1; PieCtrlRegs.PIEIER3.bit.INTx2 = 1; } /******************************************************************************* * 函 数 名: interrupt void epwm1_isr(void) * 函数功能: 控制尾翼电机的转速 *******************************************************************************/ interrupt void epwm1_isr(void) { switch (Turningmodeselection){ case Noturn: //保证下面EPWMA和EPWMB相互切换同时输出0电平; EPwm1Regs.CMPA.half.CMPA = 0;//改变脉宽 EPwm1Regs.CMPB = 0; //改变脉宽 break; case Turnleft: //保证下面EPWMA和EPWMB相互切换同时输出0电平; EPwm1Regs.CMPA.half.CMPA = 0;//改变脉宽 EPwm1Regs.CMPB = 0; //改变脉宽 EPwm1Regs.AQCTLA.bit.ZRO = AQ_CLEAR; // 计数到0时PWM1A输出低电平 EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // 递增计数时,发生比较寄存器A匹配时清除PWM1A输出 EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET; // 计数到0时PWM1B输出高电平 EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR; // 递增计数时,发生比较寄存器A匹配时清除PWM1B输出 EPwm1Regs.CMPA.half.CMPA = Vertailmotor_PWM; EPwm1Regs.CMPB = Vertailmotor_PWM; break; case Turnright: //保证下面EPWMA和EPWMB相互切换同时输出0电平; EPwm1Regs.CMPA.half.CMPA = 0;//改变脉宽 EPwm1Regs.CMPB = 0; //改变脉宽 EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; // 计数到0时PWM1A输出高电平 EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // 递增计数时,发生比较寄存器A匹配时清除PWM1A输出 EPwm1Regs.AQCTLB.bit.ZRO = AQ_CLEAR; // 计数到0时PWM1B输出低电平 EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR; // 递增计数时,发生比较寄存器A匹配时清除PWM1B输出 EPwm1Regs.CMPA.half.CMPA = Vertailmotor_PWM; EPwm1Regs.CMPB = Vertailmotor_PWM; break; default: break;} // end switch EPwm1Regs.ETCLR.bit.INT = 1; // 清除中断标志位 PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; // 清除PIE应答寄存器 } /******************************************************************************* * 函 数 名: interrupt void epwm2_isr(void) * 函数功能: 控制机翼电机的转速 *******************************************************************************/ interrupt void epwm2_isr(void) { if(MOTO1_PWM>=CMPX_MAX) MOTO1_PWM = CMPX_MAX; if(MOTO1_PWM<=CMPX_MIN) MOTO1_PWM = CMPX_MIN; EPwm2Regs.CMPA.half.CMPA = MOTO1_PWM; EPwm2Regs.ETCLR.bit.INT = 1; // 清除中断标志位 PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; // 清除PIE应答寄存器 } /******************************************************************************* * 函 数 名: void MotorPwmFlash(int16_t MOTO1_PWM,int16_t MOTO2_DELAY,uint8_t Turningmodeselection) * 函数功能: 更新主翼电机占空比和尾翼转向 *******************************************************************************/ void MotorPwmFlash(int16_t MOTO1_PWM2,uint8_t Turningmodeselecting) { MOTO1_PWM=MOTO1_PWM2; Turningmodeselection=Turningmodeselecting; }
Moto.h:
#ifndef INC_MOTO_H_ #define INC_MOTO_H_ #include "extern_variable.h" #define PWM_FRE 600000 #define EPWM_TIMER_TBPRD 999 /* 电机档位定义*/ #define CMPX_MIN 0 #define CMPX_HALF 500 #define CMPX_MAX 999 #define Vertailmotor_PWM 300 extern uint8_t Turningmodeselection; extern uint16_t MOTO1_PWM; enum {Noturn = 0,Turnleft,Turnright}; #define nSLEEP GPIO5 #define nSLEEPMUX GpioCtrlRegs.GPAMUX1.bit.nSLEEP #define nSLEEPDIR GpioCtrlRegs.GPADIR.bit.nSLEEP #define nSLEEPTOGGLE() GpioDataRegs.GPATOGGLE.bit.nSLEEP = 1 #define nSLEEPON() GpioDataRegs.GPASET.bit.nSLEEP =1 #define nSLEEPLOW() GpioDataRegs.GPACLEAR.bit.nSLEEP =1 #define MODE GPIO4 #define MODEMUX GpioCtrlRegs.GPAMUX1.bit.MODE #define MODEDIR GpioCtrlRegs.GPADIR.bit.MODE #define MODETOGGLE() GpioDataRegs.GPATOGGLE.bit.MODE = 1 #define MODEON() GpioDataRegs.GPASET.bit.MODE =1 #define MODELOW() GpioDataRegs.GPACLEAR.bit.MODE =1 #define BIN2 GPIO0 #define BIN2MUX GpioCtrlRegs.GPAMUX1.bit.BIN2 #define BIN2DIR GpioCtrlRegs.GPADIR.bit.BIN2 #define BIN2TOGGLE() GpioDataRegs.GPATOGGLE.bit.BIN2 = 1 #define BIN2ON() GpioDataRegs.GPASET.bit.BIN2 =1 #define BIN2LOW() GpioDataRegs.GPACLEAR.bit.BIN2 =1 #define BIN1 GPIO1 #define BIN1MUX GpioCtrlRegs.GPAMUX1.bit.BIN1 #define BIN1DIR GpioCtrlRegs.GPADIR.bit.BIN1 #define BIN1TOGGLE() GpioDataRegs.GPATOGGLE.bit.BIN1 = 1 #define BIN1ON() GpioDataRegs.GPASET.bit.BIN1 =1 #define BIN1LOW() GpioDataRegs.GPACLEAR.bit.BIN1 =1 #define AIN2 GPIO2 #define AIN2MUX GpioCtrlRegs.GPAMUX1.bit.AIN2 #define AIN2DIR GpioCtrlRegs.GPADIR.bit.AIN2 #define AIN2TOGGLE() GpioDataRegs.GPATOGGLE.bit.AIN2 = 1 #define AIN2ON() GpioDataRegs.GPASET.bit.AIN2 =1 #define AIN2LOW() GpioDataRegs.GPACLEAR.bit.AIN2 =1 #define AIN1 GPIO3 #define AIN1MUX GpioCtrlRegs.GPAMUX1.bit.AIN1 #define AIN1DIR GpioCtrlRegs.GPADIR.bit.AIN1 #define AIN1TOGGLE() GpioDataRegs.GPATOGGLE.bit.AIN1 = 1 #define AIN1ON() GpioDataRegs.GPASET.bit.AIN1 =1 #define AIN1LOW() GpioDataRegs.GPACLEAR.bit.AIN1 =1 /* 包含头文件*/ void InitMotor(void); void InitEPWM_AQ_DB(void); void MotorPwm1Flash(int16_t MOTO1_PWM); interrupt void epwm1_isr(void); void MotorPwm2Flash(uint8_t Turningmodeselection); interrupt void epwm2_isr(void); void MotorPwmFlash(int16_t MOTO1_PWM,uint8_t Turningmodeselection); #endif /* INC_MOTO_H_ */
这段代码可以正常运行、我个人认为这段代码没有问题、但电机无法正常旋转、所以我不知道问题出在哪里。
当代码正常运行时,我希望图片显示出额定电压为3.7V 的空心杯马达可以正常旋转。
但实际情况是电机根本不旋转、CCS 软件接口跳转到一个奇怪的接口、如下图所示。
空心杯电机的两根电线正确连接到(AOUT1、AOUT2)或(BOUT1、BOUT2)接口、电机不仅无反应、而且软件将进入上面的接口。
尽管空心杯马达的额定电压为3.7V,但它可以通过连接到马达的1.5V 电压进行旋转。
我给 DRV8836的电源电压在1S 锂电池分压后对于整个电路是3.3V、我没有直接将1S 锂电池接至 DRV8836 (VCC 和 GND)。
在我的测试中、我发现在正常运行情况下、当我连接(AOUT1直接连接到 AOUT2)或(BOUT1直接连接到 BOUT2)时、也会出现上图中的 CCS 接口。
我使用 EPWM2A 连接 AIN2和 EPWM2B 来连接 AIN1、给定的占空比为80%。 我通过示波器正确观察到了波形。 根据预期计算,AOUT1和 AOUT2引脚的电压输出为3.3V*0.8=2.64V,足以驱动空心杯电机,但电机在插入后不移动,且软件停止调试。
1.代码有问题吗?
2.硬件电路有问题(1S 锂电池应该直接连接到8836的 VCC 和 GND 吗?)
3、CCS 为什么有一个不熟悉的接口? (我正在使用 XDS100V1仿真器)
4.如何配置中空杯马达以使其正常运行?
您能帮助检查这个问题吗? 谢谢。
此致、
切里
您好 Cherry:
我会仔细研究您的问题、并尽快与您联系。
此致、
巴勃罗·阿梅特
您好 Cherry:
相关的教程。 请向 CCS 团队咨询、因为我不是这方面的专家。 但是、我可以帮助解决电机和 DRV 相关问题。
2. 硬件电路有问题(1S 锂电池是否应直接连接到8836的 VCC 和 GND?)
这应该不是问题。 我的确注意到、VCC 线路上没有大容量电容器。 它在原理图中的其他某个位置吗? 我们建议最小10uF 的大容量电容和0.1uF 的去耦电容。
根据预期的计算,AOUT1和 AOUT2引脚的电压输出为3.3V*0.8=2.64V,足以驱动空心杯电机,但电机在插入后不会移动且软件停止调试。[/引述]当软件停止 Debug 时。 输入信号是否会变为低电平?
此致、
巴勃罗·阿梅特
尊敬的 Pablo Armet:
感谢您的支持。
我的 CCS 代码应该没有问题、因为我使用了示波器来观察符合预取指令的 ePWM 波形。
在我的测试后中空杯马达没有问题。
1. DRV8836芯片的使用应该存在问题。 DRV8836的数据手册未详述。 例如、未详细指定应输入哪些信号 AIN1和 AIN2。
您能向我提供 DRV8836用例吗? 包含所用的 C 语言代码和硬件原理图
请参考数据手册、在 DRV8836的 VCC 处连接一个10uF 电容器。 请参阅下面的硬件原理图。
3.当软件停止调试时,以下情况将首先出现在 CCS 界面上,然后没有信号输入到 DRV8836的 AIN1\AIN2和 BIN1\BIN2。 如果将直流有刷空心杯电机插入 DRV8836的 XOUT1和 XOUT 端口(X=A 或 B)、则会触发故障。
4.猜猜可能出现的问题:由于 DRV8836封装很小,它是否与我的焊接有关?
5.猜测可能的问题:我在软件类型中配置了 DRV8836,但只进行了简单的配置,我不知道是否正确。
谢谢。此致、
切里
您好 Cherry:
1. DRV8836芯片的使用应该存在问题。 DRV8836的数据手册未详述。 例如,没有详细指定应输入的信号 AIN1和 AIN2。
对于满量程步进、输入应该如下面所示(当处于 PWM 模式时)
2.i 请参考数据手册、并在 DRV8836的 VCC 处连接一个10uF 电容器。 请查看下面的硬件原理图。
建议添加一个与10uF 并联的0.1uF 电容器。
当软件停止调试时、以下情况将首先出现在 CCS 接口上、然后没有信号输入到 DRV8836的 AIN1\AIN2和 BIN1\BIN2。 如果将直流有刷空心杯电机插入 DRV8836的 XOUT1和 XOUT 端口(X=A 或 B)、则将触发故障。[/报价]这是 CCS 问题还是电机驱动器问题? 看起来有些东西会导致 CCS 程序停止、输入没有信号导致电机停止。 您能否提供输入信号的波形?
4. 猜猜可能出现的问题:由于 DRV8836封装很小,它是否与我的焊接有关?让我们首先尝试了解 DRV8836是否触发了故障。
问题1:此问题是否始终发生、或者电机是否成功旋转了一段时间、然后停止?
Q2:在不将电机连接到输出的情况下、OUTx 信号是否遵循数据表中的控制逻辑表? 本质上、OUTx 电压是否基于提供的 INx 信号而符合预期?
Q3:连接电机并尝试驱动电机后、可以使用电流探头检查电机电流吗? 它是否超出 OCP 限制?
Q4:您能否提供一个波形来显示驱动时和电机停止时的 OUTx 电压?
5. 猜测可能的问题:我在软件类型中配置了 DRV8836,但仅进行了简单的配置,我不知道它是否正确。您能否提供从 uC 到 DRV8836的输入信号? 我可以确认。
此致、
巴勃罗·阿梅特
[/quote]