【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;
}
我要赚赏金
