【LAUNCHXL-F280049C】②初试driverlib驱动串口-电子产品世界论坛
https://forum.eepw.com.cn/thread/393642/1
【LAUNCHXL-F280049C】③eCAP、PWM模块测试及电机测速小试牛刀-电子产品世界论坛
https://forum.eepw.com.cn/thread/393681/1
综合测评的第2、第3贴,本篇完成作品提交:电机控制交互系统
核心交互系统采用的是迪文串口480X272电容触摸屏:
串口屏的电路部分很简单
VCC
TXD--------->开发板RXD/ GPIO28
RXD--------->开发板TXD/ GPIO29
GND
如下图,需拔掉短接帽(TXD,RXD),将串口屏端子接到J101下部分(而非去XDS110虚拟串口)。
串口屏软件设计部分在此篇不过多赘述:
如下图:最下方文本框,对应变量地址0x1020,变量类型:2Byte无符号整数
第3篇帖子中,已测得编码电机的单个脉冲时间t,就可以通过60/t计算得到电机转速rpm
然后持续将电机转速指令输出给串口屏文本框即可
//RPM,初始值为0 uint16_t msg1[8] = {0x5A, 0xA5, 0x05, 0x82, 0x10, 0x20, 0x00, 0x00}; //0~1 0x5A 0xA5 串口屏指令识别符 //2 0x05 数据长度=5 //3 0x82 写指令 0x83读指令 //4~5 0x1020 串口屏对象地址 //6~7 0x00 0x00 2Byte数据 SCI_writeCharArray(SCIA_BASE, msg1, 8);
需要注意的是,计算出来的电机转速rpm是整数,而发给串口屏的数据需要是16进制,因此需要进行转换。
另外,本程序预留了左上角、右上角两个按钮,按下分别可加减可变文本框(图中71),
开发板定时抓取其中数字,作为PWM占空比,可进行100挡位电机调速接口。
项目实物图如下:
运行视频如下:
程序源码见以下:
// // Included Files // #include "driverlib.h" #include "device.h" #include "board.h" #include <stdlib.h> // // Defines // #define PWM3_TIMER_MIN 500U #define PWM3_TIMER_MAX 8000U #define EPWM_TIMER_UP 1U #define EPWM_TIMER_DOWN 0U // // Globals // uint32_t ecap1IntCount; uint32_t motor_cycle,motor_cycle1,motor_cycle2,motor_cycle3; uint16_t rpm; uint32_t ecap1PassCount; uint32_t epwm3TimerDirection; volatile uint32_t cap2Count; volatile uint32_t cap3Count; volatile uint32_t cap4Count; volatile uint16_t epwm3PeriodCount; // // Function Prototypes // void error(void); void initECAP(void); void initEPWM(void); uint16_t loopCounter = 0; char hexNum; void decToHex(int decNum) { char rem1=0,rem2=0,i = 0; hexNum=0; rem1 = decNum / 16 +'0'; rem2 = decNum % 16; if (rem2 < 10) { rem2 = rem2 + '0'; // 将数字转换为字符 } else if (rem2==10) {rem2=0x0A;} else if (rem2==11) {rem2=0x0B;} else if (rem2==12) {rem2=0x0C;} else if (rem2==13) {rem2=0x0D;} else if (rem2==14) {rem2=0x0E;} else if (rem2==15) {rem2=0x0F;} hexNum = rem1<<1; hexNum= hexNum + rem2; } // // Main // void main(void) { // // Initialize device clock and peripherals // Device_init(); // // Disable pin locks and enable internal pullups. // Device_initGPIO(); // // GPIO28 is the SCI Rx pin. // GPIO_setControllerCore(DEVICE_GPIO_PIN_SCIRXDA, GPIO_CORE_CPU1); GPIO_setPinConfig(DEVICE_GPIO_CFG_SCIRXDA); GPIO_setDirectionMode(DEVICE_GPIO_PIN_SCIRXDA, GPIO_DIR_MODE_IN); GPIO_setPadConfig(DEVICE_GPIO_PIN_SCIRXDA, GPIO_PIN_TYPE_STD); GPIO_setQualificationMode(DEVICE_GPIO_PIN_SCIRXDA, GPIO_QUAL_ASYNC); // // GPIO29 is the SCI Tx pin. // GPIO_setControllerCore(DEVICE_GPIO_PIN_SCITXDA, GPIO_CORE_CPU1); GPIO_setPinConfig(DEVICE_GPIO_CFG_SCITXDA); GPIO_setDirectionMode(DEVICE_GPIO_PIN_SCITXDA, GPIO_DIR_MODE_OUT); GPIO_setPadConfig(DEVICE_GPIO_PIN_SCITXDA, GPIO_PIN_TYPE_STD); GPIO_setQualificationMode(DEVICE_GPIO_PIN_SCITXDA, GPIO_QUAL_ASYNC); // // Initialize PIE and clear PIE registers. Disables CPU interrupts. // Interrupt_initModule(); // // Initialize the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR). // Interrupt_initVectorTable(); // // Initialize SCIA and its FIFO. // SCI_performSoftwareReset(SCIA_BASE); // // Configure SCIA for echoback. // SCI_setConfig(SCIA_BASE, DEVICE_LSPCLK_FREQ, 115200, (SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE | SCI_CONFIG_PAR_NONE)); SCI_resetChannels(SCIA_BASE); SCI_resetRxFIFO(SCIA_BASE); SCI_resetTxFIFO(SCIA_BASE); SCI_clearInterruptStatus(SCIA_BASE, SCI_INT_TXFF | SCI_INT_RXFF); SCI_enableFIFO(SCIA_BASE); SCI_enableModule(SCIA_BASE); SCI_performSoftwareReset(SCIA_BASE); #ifdef AUTOBAUD // // Perform an autobaud lock. // SCI expects an 'a' or 'A' to lock the baud rate. // SCI_lockAutobaud(SCIA_BASE); #endif // // Configure GPIO4/5 as ePWM3A/3B // GPIO_setPadConfig(4,GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_4_EPWM3_A); GPIO_setPadConfig(5,GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_5_EPWM3_B); // // Board initialization // Configure GPIO 16 as eCAP input // Enable interrupts required for this example // Board_init(); // // Configure ePWM // initEPWM(); // // Initialize counters: // cap2Count = 0U; cap3Count = 0U; cap4Count = 0U; ecap1IntCount = 0U; ecap1PassCount = 0U; epwm3PeriodCount = 0U; // // Enable Global Interrupt (INTM) and Real time interrupt (DBGM) // EINT; ERTM; //RPM,初始值为0 uint16_t msg1[8] = {0x5A, 0xA5, 0x05, 0x82, 0x10, 0x20, 0x00, 0x00}; //0~1 0x5A 0xA5 串口屏指令识别符 //2 0x05 数据长度=5 //3 0x82 写指令 0x83读指令 //4~5 0x1020 串口屏对象地址 //6~7 0x00 0x00 2Byte数据 SCI_writeCharArray(SCIA_BASE, msg1, 8); // // Loop forever. Suspend or place breakpoints to observe the buffers. // for(;;) { DEVICE_DELAY_US(500); decToHex(rpm); msg1[7] = hexNum; //itoa(rpm, msg1[7], 16); //msg1[7] = (rpm / 16 < 10) ? (rpm / 16 + '0') : (rpm / 16 - 10 + 'A'); //msg1[7] = (rpm % 16 < 10) ? (rpm % 16 + '0') : (rpm % 16 - 10 + 'A'); //decimalToHex(rpm, msg1[7]) ; SCI_writeCharArray(SCIA_BASE, msg1, 8); } } // // initEPWM - Configure ePWM // void initEPWM() { // // Disable sync(Freeze clock to PWM as well) // SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC); // // Configure ePWM // Counter runs in up-count mode. // Action qualifier will toggle output on period match // EPWM_setTimeBaseCounterMode(EPWM3_BASE, EPWM_COUNTER_MODE_UP); EPWM_setTimeBasePeriod(EPWM3_BASE, PWM3_TIMER_MIN); EPWM_setPhaseShift(EPWM3_BASE, 0U); EPWM_setActionQualifierAction(EPWM3_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_TOGGLE, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD); EPWM_setClockPrescaler(EPWM3_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_2); epwm3TimerDirection = EPWM_TIMER_UP; // // Enable sync and clock to PWM // SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC); } // // myECAP0 ISR // __interrupt void INT_myECAP0_ISR(void) { // // Get the capture counts. Each capture should be 2x the ePWM count // because of the ePWM clock divider. // cap2Count = ECAP_getEventTimeStamp(myECAP0_BASE, ECAP_EVENT_2); cap3Count = ECAP_getEventTimeStamp(myECAP0_BASE, ECAP_EVENT_3); cap4Count = ECAP_getEventTimeStamp(myECAP0_BASE, ECAP_EVENT_4); motor_cycle1=cap2Count/100; //单个编码脉冲时间 单位us motor_cycle2=cap3Count/100; motor_cycle3=cap4Count/100; motor_cycle = motor_cycle1*2*1152/1000; //电机转一圈时间 单位ms (电机输出轴转一圈输出1152个脉冲) rpm=60000/motor_cycle; //6000ms epwm3PeriodCount = EPWM_getTimeBasePeriod(EPWM3_BASE); ecap1IntCount++; // // Keep track of the ePWM direction and adjust period accordingly to // generate a variable frequency PWM. // // // Count correct captures // ecap1PassCount++; // // Clear interrupt flags for more interrupts. // ECAP_clearInterrupt(myECAP0_BASE,ECAP_ISR_SOURCE_CAPTURE_EVENT_4); ECAP_clearGlobalInterrupt(myECAP0_BASE); // // Start eCAP // ECAP_reArm(myECAP0_BASE); // // Acknowledge the group interrupt for more interrupts. // Interrupt_clearACKGroup(INT_myECAP0_INTERRUPT_ACK_GROUP); } // // error - Error function // void error() { ESTOP0; }