mirror of
https://github.com/eddyem/stm32samples.git
synced 2025-12-06 10:45:11 +03:00
214 lines
6.3 KiB
C
214 lines
6.3 KiB
C
/*
|
|
* This file is part of the windshield project.
|
|
* Copyright 2024 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "adc.h"
|
|
#include "can.h"
|
|
#include "hardware.h"
|
|
#include "proto.h"
|
|
#include "strfunc.h"
|
|
#include "usart.h"
|
|
#include "version.inc"
|
|
|
|
flags_t flags = {
|
|
.can_monitor = 0
|
|
};
|
|
|
|
const char *helpmsg =
|
|
"https://github.com/eddyem/stm32samples/tree/master/F1:F103/CAR_CANbus/WindShield build#" BUILD_NUMBER " @ " BUILD_DATE "\n"
|
|
"'0' - stop PWM\n"
|
|
"'1' - start PWM\n"
|
|
"'a' - RAW ADC values\n"
|
|
"'b' - break motor (extremal stop)\n"
|
|
"'f' - set PWM freq (Hz)\n"
|
|
"'d xx' - set dT to xx ms\n"
|
|
"'m xx' - move motor up (1), down (2), stop (-2) or emerg stop (-1)\n"
|
|
"'p y xx' - set PWM y (l/r) to xx (0..100)\n"
|
|
"'s' - get raw VSEN value\n"
|
|
"'t' - get MCU temperature (*10)\n"
|
|
"'u y xx' - turn on (xx==1) or off (xx==0) y (l/r) MOSFET\n"
|
|
"'v' - get Vdd (*100)\n"
|
|
"'M' - CAN bus monitoring on/off\n"
|
|
"'R' - software reset\n"
|
|
"'T' - get time from start (ms)\n"
|
|
;
|
|
|
|
static void printans(int res){
|
|
if(res) usart_send("OK");
|
|
else usart_send("FAIL");
|
|
}
|
|
|
|
static void usetter(int(*fn)(uint32_t), char* str){
|
|
uint32_t d = 0;
|
|
if(str == getnum(str, &d)) printans(FALSE);
|
|
else printans(fn(d));
|
|
}
|
|
static void isetter(int(*fn)(int32_t), char* str){
|
|
int32_t d = 0;
|
|
if(str == getint(str, &d)) printans(FALSE);
|
|
else printans(fn(d));
|
|
}
|
|
static char pwmch = 0;
|
|
static int setdir(char d){
|
|
pwmch = 0;
|
|
switch(d){
|
|
case 'r':
|
|
case 'l':
|
|
pwmch = d;
|
|
break;
|
|
default:
|
|
usart_send("Direction: l/r\n");
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
static int pwmvalsetter(uint32_t pwm){
|
|
if(pwm > PWMMAX) return FALSE;
|
|
if(pwmch == 'l') set_pwm(PWM_LEFT, pwm);
|
|
else if(pwmch == 'r') set_pwm(PWM_RIGHT, pwm);
|
|
else return FALSE;
|
|
return TRUE;
|
|
}
|
|
static int upsetter(uint32_t set){
|
|
int L = get_pwm(PWM_LEFT), R = get_pwm(PWM_RIGHT);
|
|
switch(pwmch){
|
|
case 'l':
|
|
if(L && set) return FALSE; // shortened
|
|
if(set) set_up(UP_LEFT);
|
|
else up_off();
|
|
break;
|
|
case 'r':
|
|
if(R && set) return FALSE;
|
|
if(set) set_up(UP_RIGHT);
|
|
else up_off();
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
static int startPWM(){
|
|
int l = read_upL(), r = read_upR();
|
|
if(l && r) return FALSE; // both upper active (impossible case, but what if?)
|
|
int L = get_pwm(PWM_LEFT), R = get_pwm(PWM_RIGHT);
|
|
if(L && R) return FALSE; // both PWM active
|
|
if((l && L) || (r && R)) return FALSE; // shortened
|
|
start_pwm();
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* @brief cmd_parser - command parsing
|
|
* @param txt - buffer with commands & data
|
|
*/
|
|
void cmd_parser(char *txt){
|
|
char _1st = txt[0];
|
|
/* usart_send("Got: '");
|
|
usart_send(txt);
|
|
usart_send("'\n");*/
|
|
char *nxtsym = (char*)omit_spaces(txt + 1);
|
|
uint32_t N = 0;
|
|
int proc = 1;
|
|
switch(_1st){ // parse long commands here
|
|
case 'd':
|
|
usetter(set_dT, nxtsym);
|
|
break;
|
|
case 'f':
|
|
if(nxtsym != getnum(nxtsym, &N)){
|
|
if(N < 100 || N > 100000) usart_send("100 <= F <= 100000");
|
|
else TIM3->PSC = (TIM3FREQ/(N*PWMMAX)) - 1;
|
|
}
|
|
usart_send("TIM3->PSC="); usart_send(u2str(TIM3->PSC));
|
|
break;
|
|
case 'm':
|
|
isetter(motor_ctl, nxtsym);
|
|
break;
|
|
case 'p':
|
|
if(setdir(*nxtsym)){
|
|
nxtsym = (char*)omit_spaces(nxtsym + 1);
|
|
usetter(pwmvalsetter, nxtsym); newline();
|
|
}
|
|
usart_send("PWM1="); usart_send(u2str(get_pwm(PWM_RIGHT)));
|
|
usart_send("\nPWM2="); usart_send(u2str(get_pwm(PWM_LEFT)));
|
|
break;
|
|
case 'u':
|
|
if(setdir(*nxtsym)){
|
|
nxtsym = (char*)omit_spaces(nxtsym + 1);
|
|
usetter(upsetter, nxtsym); newline();
|
|
}
|
|
usart_send("UPL="); usart_putchar('0' + read_upL());
|
|
usart_send("\nUPR="); usart_putchar('0' + read_upR());
|
|
break;
|
|
default:
|
|
proc = 0;
|
|
break;
|
|
}
|
|
if(proc) goto eof;
|
|
if(txt[1] != 0) _1st = '?'; // help for wrong message length
|
|
switch(_1st){
|
|
case '0':
|
|
stop_pwm(); printans(TRUE);
|
|
break;
|
|
case '1':
|
|
printans(startPWM());
|
|
break;
|
|
case 'a':
|
|
for(int i = 0; i < NUMBER_OF_ADC_CHANNELS; ++i){
|
|
usart_send("ADC"); usart_putchar('0' + i);
|
|
usart_putchar('='); usart_send(u2str(getADCval(i)));
|
|
newline();
|
|
}
|
|
break;
|
|
case 'b':
|
|
motor_break(); printans(TRUE);
|
|
break;
|
|
case 's':
|
|
usart_send("VSEN="); usart_send(u2str(getADCval(CHVSEN)));
|
|
break;
|
|
case 't':
|
|
usart_send("TMCU="); usart_send(u2str(getMCUtemp()));
|
|
break;
|
|
case 'v':
|
|
usart_send("VDD="); usart_send(u2str(getVdd()));
|
|
break;
|
|
case 'M':
|
|
flags.can_monitor = !flags.can_monitor;
|
|
usart_send("CAN monitoring ");
|
|
if(flags.can_monitor) usart_send("ON");
|
|
else usart_send("OFF");
|
|
break;
|
|
case 'R':
|
|
usart_send("Soft reset\n\n");
|
|
usart_transmit();
|
|
// wait until DMA & USART done
|
|
while(!usart_txrdy);
|
|
while(!(USART1->SR & USART_SR_TC));
|
|
USART1->CR1 = 0; // stop USART
|
|
NVIC_SystemReset();
|
|
break;
|
|
case 'T':
|
|
usart_send("Time=");
|
|
printu(Tms);
|
|
break;
|
|
default: // help
|
|
usart_send(helpmsg);
|
|
break;
|
|
}
|
|
eof:
|
|
newline();
|
|
}
|