前言
这个小车是去年电赛的时候准备的,很遗憾我们赛区因为疫情被取消了比赛,我们也都已经大二大三了,因此我们没有机会再参加两年一次的电赛了。但是这些成果总不能放着吃灰吧,就留给下一届的种子选手做参考吧。实现的功能是最简单的,就还只是个玩具,具体还得根据题目去添加功能和修改代码,至少完成了小车最简单的搭建。
搭建
硬件
硬件上小车为三轮二驱小车,前轮为舵机只控制转向,后两个轮为伺服电机控制速度,都使用pwm分别来控制转动舵机角度和电机转动速度。总体上小车有3个轮子,1个舵机,2个伺服电机,1个电机驱动,1个车底座,1块MSP432单片机,一个12v移动电源,一个HC-05蓝牙模块。
软件
软件上我们在ccs平台使用C进行编写。
原理
实现小车的转向有两种方案,一种是前轮控制左右转向,后轮控制前后移动;另一种是前轮不动,后轮两个轮子差速(可用pwm调速实现),实现前后左右移动。这里我们采用第一种,第二种比较适合四轮四驱的简单要求不高的小车。 在软件调试中我们会发现供给pwm和串口的时钟频率要用不同的时钟分频,不然会产生冲突导致功能不能正常实现(使用其他外设的时候也要注意时钟频率是否产生冲突)。时钟频率的配置可参阅MSP432的系统时钟和简单系统定时和MSP432的相关定时器。 蓝牙使用HC-05模块连接到单片机串口3上,再随便用一个手机app连接蓝牙发送指定信号就完成实现蓝牙遥控小车了。
源码
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include"oled.h"
#include"bmp.h"
#include"delay.h"
Timer_A_PWMConfig pwmConfig =
{
TIMER_A_CLOCKSOURCE_SMCLK,
TIMER_A_CLOCKSOURCE_DIVIDER_48,
5000,
TIMER_A_CAPTURECOMPARE_REGISTER_1,
TIMER_A_OUTPUTMODE_RESET_SET,
235
};
const eUSCI_UART_ConfigV1 uartConfig =
{
EUSCI_A_UART_CLOCKSOURCE_SMCLK,
78,
2,
0,
EUSCI_A_UART_NO_PARITY,
EUSCI_A_UART_LSB_FIRST,
EUSCI_A_UART_ONE_STOP_BIT,
EUSCI_A_UART_MODE,
EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION,
EUSCI_A_UART_8_BIT_LEN
};
void init0(void)
{
MAP_WDT_A_holdTimer();
delay_init(3);
MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P9, GPIO_PIN6 | GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);
CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_12);
MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN4, GPIO_PRIMARY_MODULE_FUNCTION);
MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);
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);
MAP_GPIO_setAsOutputPin(GPIO_PORT_P10, GPIO_PIN2);
MAP_GPIO_setAsOutputPin(GPIO_PORT_P10, GPIO_PIN3);
MAP_GPIO_setAsOutputPin(GPIO_PORT_P10, GPIO_PIN4);
}
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)
{
}
}
void EUSCIA3_IRQHandler(void)
{
uint32_t status = MAP_UART_getEnabledInterruptStatus(EUSCI_A3_BASE);
if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG)
{
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);
}
|