前言
这个小车是去年电赛的时候准备的,很遗憾我们赛区因为疫情被取消了比赛,我们也都已经大二大三了,因此我们没有机会再参加两年一次的电赛了。但是这些成果总不能放着吃灰吧,就留给下一届的种子选手做参考吧。实现的功能是最简单的,就还只是个玩具,具体还得根据题目去添加功能和修改代码,至少完成了小车最简单的搭建。
搭建
硬件
硬件上小车为四轮二驱小车,前轮为舵机只控制转向,后两个轮为伺服电机控制速度,都使用pwm分别来控制转动舵机角度和电机转动速度。总体上小车有4个轮子,1个舵机,2个伺服电机,1个电机驱动,1个车底座,1块MSP432P401R单片机,一个12v移动电源,一个HC-05蓝牙模块。
车模底座大概这个样子。
软件
软件上我们在ccs平台使用C进行编写。
原理
实现小车的转向有两种方案,一种是前轮控制左右转向,后轮控制前后移动;另一种是左边两个轮子和右边两个轮子差速(可用pwm调速实现),实现前后左右移动。第二种比较适合四轮四驱的简单要求不高的小车。我们是四轮二驱在这里我们采用第一种(下面代码有个缺点就是我没有给后轮增加调速功能,导致车速完全看电量,有需要的可以自己给后轮增加pwm调速)。
在软件调试中我们会发现供给pwm和串口的时钟频率要用不同的时钟分频,不然会产生冲突导致功能不能正常实现(使用其他外设的时候也要注意时钟频率是否产生冲突)。时钟频率的配置可参阅MSP432的系统时钟和简单系统定时和MSP432的相关定时器。
蓝牙使用HC-05模块连接到单片机串口3(P9.6,P9.7)上,然后在手机上随便用一个蓝牙串口app连接蓝牙发送指定信号就完成实现蓝牙遥控小车了。
源码
/* DriverLib Includes */
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>
/* Standard Includes */
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include"delay.h"
//![Simple UART Config]
/* UART Configuration Parameter. These are the configuration parameters to
* make the eUSCI A UART module to operate with a 9600 baud rate. These
* values were calculated using the online calculator that TI provides
* at:
*http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP430BaudRateConverter/index.html
*/
// Timer_A PWM 配置参数
Timer_A_PWMConfig pwmConfig =
{
TIMER_A_CLOCKSOURCE_SMCLK,
TIMER_A_CLOCKSOURCE_DIVIDER_48,
5000, //12MHz时钟源,5000大约20ms
TIMER_A_CAPTURECOMPARE_REGISTER_1,
TIMER_A_OUTPUTMODE_RESET_SET,
235 //舵机正对正前方
};
const eUSCI_UART_ConfigV1 uartConfig =
{
EUSCI_A_UART_CLOCKSOURCE_SMCLK, // SMCLK Clock Source
78, // BRDIV = 78
2, // UCxBRF = 2
0, // UCxBRS = 0
EUSCI_A_UART_NO_PARITY, // No Parity
EUSCI_A_UART_LSB_FIRST, // LSB First
EUSCI_A_UART_ONE_STOP_BIT, // One stop bit
EUSCI_A_UART_MODE, // UART mode
EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION, // Oversampling
EUSCI_A_UART_8_BIT_LEN // 8 bit data length
};
//![Simple UART Config]
void init0(void)
{
/* 看门狗 WDT */
MAP_WDT_A_holdTimer();
delay_init(3);//延时
/* 设置 P9.6 和 P9.7 为串口引脚 */
MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P9, GPIO_PIN6 | GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);
/* 设置 DCO 为 12MHz */
CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_12);
//MAP_PCM_setPowerState(PCM_AM_LF_VCORE0);
//配置 P2.4 为舵机PWM外围输出
MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN4, GPIO_PRIMARY_MODULE_FUNCTION);
//配置Timer_A
MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);
//![Simple UART Example]
/* 配置 UART 串口模块 */
MAP_UART_initModule(EUSCI_A3_BASE, &uartConfig);
/* 使能串口模块 */
MAP_UART_enableModule(EUSCI_A3_BASE);
/* 使能中断 */
MAP_UART_enableInterrupt(EUSCI_A3_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);
MAP_Interrupt_enableInterrupt(INT_EUSCIA3);
MAP_Interrupt_enableSleepOnIsrExit();
MAP_Interrupt_enableMaster();
/* 配置输出引脚 */
MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);//指示灯,不用也行
MAP_GPIO_setAsOutputPin(GPIO_PORT_P10, GPIO_PIN1);//电机1正
MAP_GPIO_setAsOutputPin(GPIO_PORT_P10, GPIO_PIN2);//电机1负
MAP_GPIO_setAsOutputPin(GPIO_PORT_P10, GPIO_PIN3);//电机2正
MAP_GPIO_setAsOutputPin(GPIO_PORT_P10, GPIO_PIN4);//电机2负
}
int main(void)
{
init0();
uint32_t jj;
MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);
MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P10, GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4);
while(1)
{
}
}
/* EUSCI A3 UART ISR - Echoes data back to PC host */
void EUSCIA3_IRQHandler(void)
{
uint32_t status = MAP_UART_getEnabledInterruptStatus(EUSCI_A3_BASE);
if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG)
{
// MAP_UART_transmitData(EUSCI_A0_BASE, MAP_UART_receiveData(EUSCI_A0_BASE));
uint32_t val;
val = UART_receiveData(EUSCI_A3_BASE);
switch(val)
{
case '1':MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P10, GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4);break;//后轮电机停止
case '2':MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P10, GPIO_PIN1|GPIO_PIN2);break;//后轮电机前进
case '3':MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P10, GPIO_PIN3|GPIO_PIN4);break;//后轮电机后退
case '4':pwmConfig.dutyCycle = 335;MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);break;//前轮舵机左转
case '5':pwmConfig.dutyCycle = 135;MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);break;//前轮舵机正中
case '6':pwmConfig.dutyCycle = 235;MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);break;//前轮舵机右转
}
}
}
int fputc(int ch,FILE *f)
{
UART_transmitData(EUSCI_A3_BASE,ch & 0xFF);
return ch;
}
int fgetc(FILE *f)
{
while(EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG != UART_getInterruptStatus(EUSCI_A3_BASE,EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG));
return UART_receiveData(EUSCI_A3_BASE);
}