mirror of
https://github.com/eddyem/stm32samples.git
synced 2025-12-06 10:45:11 +03:00
start
This commit is contained in:
parent
7d8cbd55cf
commit
9ecce531cb
Binary file not shown.
@ -7,7 +7,7 @@ PP - push-pull, OD - open drain, I - floating input, A - analog input, AFn - alt
|
||||
1 - active high, 0 - active low.
|
||||
### Sorted by pin number
|
||||
|
||||
|**Pin #**|**Pin name **| **function**| **settings**|**comment ** |
|
||||
|**Pin #**|**Pin name** | **function**| **settings**| **comment** |
|
||||
|---------|-------------|-------------|-------------|------------------|
|
||||
| 1 | VBAT | 3v3 | | |
|
||||
| 2 | PC13 | buzzer | PP1 | |
|
||||
@ -63,7 +63,7 @@ PP - push-pull, OD - open drain, I - floating input, A - analog input, AFn - alt
|
||||
### Sorted by port
|
||||
// sort -Vk4 Readme.md
|
||||
|
||||
|**Pin #**|**Pin name **| **function**| **settings**|**comment ** |
|
||||
|**Pin #**|**Pin name** | **function**| **settings**| **comment** |
|
||||
|---------|-------------|-------------|-------------|------------------|
|
||||
| 44 | BOOT0 | boot | | |
|
||||
| 7 | NRST | reset | | |
|
||||
@ -118,6 +118,7 @@ PP - push-pull, OD - open drain, I - floating input, A - analog input, AFn - alt
|
||||
## DMA usage
|
||||
### DMA1
|
||||
|
||||
Channel1 - ADC1.
|
||||
|
||||
### DMA2
|
||||
|
||||
|
||||
@ -68,16 +68,15 @@ void adc_setup(){
|
||||
// ADC1: channels 1-4,10,16; ADC2: channel 1
|
||||
ADC1->SMPR1 = ADC_SMPR1_SMP1 | ADC_SMPR1_SMP2 | ADC_SMPR1_SMP3 | ADC_SMPR1_SMP4;
|
||||
ADC1->SMPR2 = ADC_SMPR2_SMP16;
|
||||
// 11 conversions in group: 1...10->16
|
||||
// 5 conversions in group: 1..4,16
|
||||
ADC1->SQR1 = (1<<6) | (2<<12) | (3<<18) | (4<<24) | (NUMBER_OF_ADC_CHANNELS-1);
|
||||
ADC1->SQR2 = (16<<0);
|
||||
ADC2->SMPR1 = ADC_SMPR1_SMP1;
|
||||
ADC2->SQR1 = (1<<6) | (NUMBER_OF_ADC2_CHANNELS-1);
|
||||
// configure DMA for ADC
|
||||
ADC1->CFGR = ADC_CFGR_CONT | ADC_CFGR_DMAEN | ADC_CFGR_DMACFG;
|
||||
DMA1_Channel1->CPAR = (uint32_t) (&(ADC1->DR));
|
||||
DMA1_Channel1->CMAR = (uint32_t)(ADC_array);
|
||||
DMA1_Channel1->CNDTR = NUMBER_OF_ADC1_CHANNELS * 9;
|
||||
DMA1_Channel1->CNDTR = NUMBER_OF_ADC_CHANNELS * 9;
|
||||
DMA1_Channel1->CCR |= DMA_CCR_MINC | DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0 | DMA_CCR_CIRC;
|
||||
DMA1_Channel1->CCR |= DMA_CCR_EN;
|
||||
enADC(ADC1);
|
||||
@ -93,12 +92,8 @@ uint16_t getADCval(int nch){
|
||||
#define PIX_SORT(a,b) { if ((a)>(b)) PIX_SWAP((a),(b)); }
|
||||
#define PIX_SWAP(a,b) { temp=(a);(a)=(b);(b)=temp; }
|
||||
uint16_t p[9];
|
||||
int addr = nch, adval = NUMBER_OF_ADC1_CHANNELS;
|
||||
if(nch >= NUMBER_OF_ADC1_CHANNELS){
|
||||
adval = NUMBER_OF_ADC2_CHANNELS;
|
||||
addr += ADC2START - NUMBER_OF_ADC1_CHANNELS;
|
||||
}
|
||||
for(int i = 0; i < 9; ++i, addr += adval) // first we should prepare array for optmed
|
||||
int addr = nch;
|
||||
for(int i = 0; i < 9; ++i, addr += NUMBER_OF_ADC_CHANNELS) // first we should prepare array for optmed
|
||||
p[i] = ADC_array[addr];
|
||||
PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ;
|
||||
PIX_SORT(p[0], p[1]) ; PIX_SORT(p[3], p[4]) ; PIX_SORT(p[6], p[7]) ;
|
||||
@ -120,61 +115,10 @@ float getADCvoltage(uint16_t ADCval){
|
||||
|
||||
// return MCU temperature (degrees of celsius)
|
||||
float getMCUtemp(){
|
||||
float temperature = ADCvals[ADC_TSENS] - (float) *TEMP30_CAL_ADDR;
|
||||
float temperature = ADC_array[ADC_TSENS] - (float) *TEMP30_CAL_ADDR;
|
||||
temperature *= (110.f - 30.f);
|
||||
temperature /= (float)(*TEMP110_CAL_ADDR - *TEMP30_CAL_ADDR);
|
||||
temperature += 30.f;
|
||||
return(temperature);
|
||||
}
|
||||
|
||||
// calculate R (Ohms) by given `ADCval` for main 10 ADC channels with 1k in upper arm of divider
|
||||
float calcR(uint16_t ADCval){
|
||||
return 1000.f/(4096.f/((float)ADCval) - 1.f);
|
||||
}
|
||||
|
||||
/****** R(T, K):
|
||||
T -= 273.15; % convert to K
|
||||
_A = 3.9083e-03;
|
||||
_B = -5.7750e-07;
|
||||
_C = 0.;
|
||||
if(T < 0.); _C = -4.1830e-12; endif
|
||||
R = 1000.*(1 + _A*T + _B*T.^2 - _C.*T.^3*100. + _C.*T.^4);
|
||||
|
||||
=====> for T=[70:400] Kelvins
|
||||
|
||||
function T = pt1000Tapp(R)
|
||||
k1 = 27.645;
|
||||
k2 = 0.235268;
|
||||
k3 = 1.0242e-05;
|
||||
k4 = 0.;
|
||||
if(R < 1000)
|
||||
k1 = 31.067;
|
||||
k2 = 2.2272e-01;
|
||||
k3 = 2.5251e-05;
|
||||
k4 = -5.9001e-09;
|
||||
endif
|
||||
T = k1 + k2*R + k3*R.^2 + k4*R.^3;
|
||||
endfunction
|
||||
|
||||
mean(T-Tapp)= -3.3824e-04
|
||||
std(T-Tapp')= 3.2089e-03
|
||||
max(abs(T-Tapp'))= 0.011899
|
||||
|
||||
********/
|
||||
|
||||
// approximate calculation of T (K) for platinum 1k PTC
|
||||
float calcT(uint16_t ADCval){
|
||||
float R = calcR(ADCval);
|
||||
if(R < 1000.){
|
||||
return (31.067 + R * (2.2272e-01 + R * (2.5251e-05 - R * 5.9001e-09)));
|
||||
}
|
||||
return (27.645 + R * (0.235268 + R * 1.0242e-05));
|
||||
}
|
||||
|
||||
// MPX5050: V=VS(P x 0.018 + 0.04); for 3v3 ADU=4096(P*0.018+0.04) ====>
|
||||
// 0.018P=ADU/4096-0.04,
|
||||
// P(kPa) = 55.556*(ADU/4096-0.04)
|
||||
float calcPres5050(){
|
||||
float adu = (float)ADCvals[ADC_EXT]/4096. - 0.04;
|
||||
return 55.556*adu;
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 12.0.0, 2023-12-03T20:20:42. -->
|
||||
<!-- Written by QtCreator 12.0.1, 2024-01-05T23:37:25. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
|
||||
@ -7,6 +7,8 @@ proto.c
|
||||
proto.h
|
||||
ringbuffer.c
|
||||
ringbuffer.h
|
||||
strfunc.c
|
||||
strfunc.h
|
||||
usart.c
|
||||
usart.h
|
||||
usb.c
|
||||
|
||||
@ -18,149 +18,19 @@
|
||||
|
||||
#include "adc.h"
|
||||
#include "proto.h"
|
||||
#include "strfunc.h"
|
||||
#include "usart.h"
|
||||
#include "usb.h"
|
||||
#include "version.inc"
|
||||
|
||||
uint8_t starttest = 0;
|
||||
|
||||
char *omit_spaces(const char *buf){
|
||||
while(*buf){
|
||||
if(*buf > ' ') break;
|
||||
++buf;
|
||||
}
|
||||
return (char*)buf;
|
||||
}
|
||||
|
||||
// In case of overflow return `buf` and N==0xffffffff
|
||||
// read decimal number & return pointer to next non-number symbol
|
||||
static char *getdec(const char *buf, uint32_t *N){
|
||||
char *start = (char*)buf;
|
||||
uint32_t num = 0;
|
||||
while(*buf){
|
||||
char c = *buf;
|
||||
if(c < '0' || c > '9'){
|
||||
break;
|
||||
}
|
||||
if(num > 429496729 || (num == 429496729 && c > '5')){ // overflow
|
||||
*N = 0xffffff;
|
||||
return start;
|
||||
}
|
||||
num *= 10;
|
||||
num += c - '0';
|
||||
++buf;
|
||||
}
|
||||
*N = num;
|
||||
return (char*)buf;
|
||||
}
|
||||
// read hexadecimal number (without 0x prefix!)
|
||||
static char *gethex(const char *buf, uint32_t *N){
|
||||
char *start = (char*)buf;
|
||||
uint32_t num = 0;
|
||||
while(*buf){
|
||||
char c = *buf;
|
||||
uint8_t M = 0;
|
||||
if(c >= '0' && c <= '9'){
|
||||
M = '0';
|
||||
}else if(c >= 'A' && c <= 'F'){
|
||||
M = 'A' - 10;
|
||||
}else if(c >= 'a' && c <= 'f'){
|
||||
M = 'a' - 10;
|
||||
}
|
||||
if(M){
|
||||
if(num & 0xf0000000){ // overflow
|
||||
*N = 0xffffff;
|
||||
return start;
|
||||
}
|
||||
num <<= 4;
|
||||
num += c - M;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
++buf;
|
||||
}
|
||||
*N = num;
|
||||
return (char*)buf;
|
||||
}
|
||||
// read octal number (without 0 prefix!)
|
||||
static char *getoct(const char *buf, uint32_t *N){
|
||||
char *start = (char*)buf;
|
||||
uint32_t num = 0;
|
||||
while(*buf){
|
||||
char c = *buf;
|
||||
if(c < '0' || c > '7'){
|
||||
break;
|
||||
}
|
||||
if(num & 0xe0000000){ // overflow
|
||||
*N = 0xffffff;
|
||||
return start;
|
||||
}
|
||||
num <<= 3;
|
||||
num += c - '0';
|
||||
++buf;
|
||||
}
|
||||
*N = num;
|
||||
return (char*)buf;
|
||||
}
|
||||
// read binary number (without b prefix!)
|
||||
static char *getbin(const char *buf, uint32_t *N){
|
||||
char *start = (char*)buf;
|
||||
uint32_t num = 0;
|
||||
while(*buf){
|
||||
char c = *buf;
|
||||
if(c < '0' || c > '1'){
|
||||
break;
|
||||
}
|
||||
if(num & 0x80000000){ // overflow
|
||||
*N = 0xffffff;
|
||||
return start;
|
||||
}
|
||||
num <<= 1;
|
||||
if(c == '1') num |= 1;
|
||||
++buf;
|
||||
}
|
||||
*N = num;
|
||||
return (char*)buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief getnum - read uint32_t from string (dec, hex or bin: 127, 0x7f, 0b1111111)
|
||||
* @param buf - buffer with number and so on
|
||||
* @param N - the number read
|
||||
* @return pointer to first non-number symbol in buf
|
||||
* (if it is == buf, there's no number or if *N==0xffffffff there was overflow)
|
||||
*/
|
||||
char *getnum(const char *txt, uint32_t *N){
|
||||
char *nxt = NULL;
|
||||
char *s = omit_spaces(txt);
|
||||
if(*s == '0'){ // hex, oct or 0
|
||||
if(s[1] == 'x' || s[1] == 'X'){ // hex
|
||||
nxt = gethex(s+2, N);
|
||||
if(nxt == s+2) nxt = (char*)txt;
|
||||
}else if(s[1] > '0'-1 && s[1] < '8'){ // oct
|
||||
nxt = getoct(s+1, N);
|
||||
if(nxt == s+1) nxt = (char*)txt;
|
||||
}else{ // 0
|
||||
nxt = s+1;
|
||||
*N = 0;
|
||||
}
|
||||
}else if(*s == 'b' || *s == 'B'){
|
||||
nxt = getbin(s+1, N);
|
||||
if(nxt == s+1) nxt = (char*)txt;
|
||||
}else{
|
||||
nxt = getdec(s, N);
|
||||
if(nxt == s) nxt = (char*)txt;
|
||||
}
|
||||
return nxt;
|
||||
}
|
||||
|
||||
const char* helpmsg =
|
||||
"https://github.com/eddyem/stm32samples/tree/master/F3:F303/CANbus4BTA build#" BUILD_NUMBER " @ " BUILD_DATE "\n"
|
||||
"'a' - print ADC values\n"
|
||||
"'i' - print USB->ISTR state\n"
|
||||
"'p' - toggle USB pullup\n"
|
||||
"'N' - read number (dec, 0xhex, 0oct, bbin) and show it in decimal\n"
|
||||
"'R' - software reset\n"
|
||||
"'T' - test usb sending a very large message\n"
|
||||
"'T' - get MCU T\n"
|
||||
"'U' - get USB status\n"
|
||||
"'W' - test watchdog\n"
|
||||
;
|
||||
@ -168,6 +38,11 @@ const char* helpmsg =
|
||||
static char stbuf[256], *bptr = NULL;
|
||||
static int blen = 0;
|
||||
static void initbuf(){bptr = stbuf; blen = 255; *bptr = 0;}
|
||||
static void bufputchar(char c){
|
||||
if(blen == 0) return;
|
||||
*bptr++ = c; --blen;
|
||||
*bptr = 0;
|
||||
}
|
||||
static void add2buf(const char *s){
|
||||
while(blen && *s){
|
||||
*bptr++ = *s++;
|
||||
@ -181,34 +56,37 @@ const char *parse_cmd(const char *buf){
|
||||
initbuf();
|
||||
if(buf[1] == '\n' || !buf[1]){ // one symbol commands
|
||||
switch(*buf){
|
||||
case 'a':
|
||||
for(int i = 0; i < ADC_TSENS; ++i){
|
||||
bufputchar('A'); bufputchar(i+'0'); bufputchar('=');
|
||||
add2buf(u2str(getADCval(i))); bufputchar('\n');
|
||||
}
|
||||
return stbuf;
|
||||
break;
|
||||
case 'i':
|
||||
add2buf("USB->ISTR=");
|
||||
add2buf(u2hexstr(USB->ISTR));
|
||||
add2buf(uhex2str(USB->ISTR));
|
||||
add2buf(", USB->CNTR=");
|
||||
add2buf(u2hexstr(USB->CNTR));
|
||||
add2buf("\n");
|
||||
add2buf(uhex2str(USB->CNTR));
|
||||
break;
|
||||
case 'p':
|
||||
pin_toggle(USBPU_port, USBPU_pin);
|
||||
add2buf("USB pullup is ");
|
||||
if(pin_read(USBPU_port, USBPU_pin)) add2buf("off\n");
|
||||
else add2buf("on\n");
|
||||
if(pin_read(USBPU_port, USBPU_pin)) add2buf("off");
|
||||
else add2buf("on");
|
||||
break;
|
||||
case 'R':
|
||||
USB_sendstr("Soft reset\n");
|
||||
usart_send("Soft reset\n");
|
||||
NVIC_SystemReset();
|
||||
break;
|
||||
case 'T':
|
||||
add2buf("STARTT=");
|
||||
add2buf(u2str(Tms)); add2buf("\n");
|
||||
starttest = 10;
|
||||
add2buf("T=");
|
||||
add2buf(float2str(getMCUtemp(), 1));
|
||||
break;
|
||||
case 'U':
|
||||
add2buf("USB status: ");
|
||||
if(usbON) add2buf("ON");
|
||||
else add2buf("OFF");
|
||||
add2buf("\n");
|
||||
break;
|
||||
case 'W':
|
||||
USB_sendstr("Wait for reboot\n");
|
||||
@ -218,10 +96,11 @@ const char *parse_cmd(const char *buf){
|
||||
default:
|
||||
return helpmsg;
|
||||
}
|
||||
bufputchar('\n');
|
||||
return stbuf;
|
||||
}
|
||||
uint32_t Num = 0;
|
||||
char *nxt;
|
||||
const char *nxt;
|
||||
switch(*buf){ // long messages
|
||||
case 'N':
|
||||
++buf;
|
||||
@ -242,41 +121,3 @@ const char *parse_cmd(const char *buf){
|
||||
}
|
||||
return stbuf;
|
||||
}
|
||||
|
||||
|
||||
// return string with number `val`
|
||||
char *u2str(uint32_t val){
|
||||
static char strbuf[11];
|
||||
char *bufptr = &strbuf[10];
|
||||
*bufptr = 0;
|
||||
if(!val){
|
||||
*(--bufptr) = '0';
|
||||
}else{
|
||||
while(val){
|
||||
*(--bufptr) = val % 10 + '0';
|
||||
val /= 10;
|
||||
}
|
||||
}
|
||||
return bufptr;
|
||||
}
|
||||
|
||||
char *u2hexstr(uint32_t val){
|
||||
static char strbuf[11] = "0x";
|
||||
char *sptr = strbuf + 2;
|
||||
uint8_t *ptr = (uint8_t*)&val + 3;
|
||||
int8_t i, j, z=1;
|
||||
for(i = 0; i < 4; ++i, --ptr){
|
||||
if(*ptr == 0){ // omit leading zeros
|
||||
if(i == 3) z = 0;
|
||||
if(z) continue;
|
||||
}
|
||||
else z = 0;
|
||||
for(j = 1; j > -1; --j){
|
||||
uint8_t half = (*ptr >> (4*j)) & 0x0f;
|
||||
if(half < 10) *sptr++ = half + '0';
|
||||
else *sptr++ = half - 10 + 'a';
|
||||
}
|
||||
}
|
||||
*sptr = 0;
|
||||
return strbuf;
|
||||
}
|
||||
|
||||
@ -20,11 +20,5 @@
|
||||
|
||||
#include <stm32f3.h>
|
||||
|
||||
extern uint8_t starttest;
|
||||
|
||||
const char *parse_cmd(const char *buf);
|
||||
char *omit_spaces(const char *buf);
|
||||
char *getnum(const char *buf, uint32_t *N);
|
||||
char *u2str(uint32_t val);
|
||||
char *u2hexstr(uint32_t val);
|
||||
|
||||
|
||||
337
F3:F303/CANbus4BTA/strfunc.c
Normal file
337
F3:F303/CANbus4BTA/strfunc.c
Normal file
@ -0,0 +1,337 @@
|
||||
/*
|
||||
* This file is part of the canbus4bta 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 <stm32f3.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* @brief hexdump - dump hex array by 16 bytes in string
|
||||
* @param sendfun - function to send data
|
||||
* @param arr - array to dump
|
||||
* @param len - length of `arr`
|
||||
*/
|
||||
void hexdump(int (*sendfun)(const char *s), uint8_t *arr, uint16_t len){
|
||||
char buf[52], *bptr = buf;
|
||||
for(uint16_t l = 0; l < len; ++l, ++arr){
|
||||
for(int16_t j = 1; j > -1; --j){
|
||||
register uint8_t half = (*arr >> (4*j)) & 0x0f;
|
||||
if(half < 10) *bptr++ = half + '0';
|
||||
else *bptr++ = half - 10 + 'a';
|
||||
}
|
||||
if(l % 16 == 15){
|
||||
*bptr++ = '\n';
|
||||
*bptr = 0;
|
||||
sendfun(buf);
|
||||
bptr = buf;
|
||||
}else *bptr++ = ' ';
|
||||
}
|
||||
if(bptr != buf){
|
||||
*bptr++ = '\n';
|
||||
*bptr = 0;
|
||||
sendfun(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief _2str - convert value into string buffer
|
||||
* @param val - |value|
|
||||
* @param minus - ==0 if value > 0
|
||||
* @return buffer with number
|
||||
*/
|
||||
static char *_2str(uint32_t val, uint8_t minus){
|
||||
static char strbuf[12];
|
||||
char *bufptr = &strbuf[11];
|
||||
*bufptr = 0;
|
||||
if(!val){
|
||||
*(--bufptr) = '0';
|
||||
}else{
|
||||
while(val){
|
||||
uint32_t x = val / 10;
|
||||
*(--bufptr) = (val - 10*x) + '0';
|
||||
val = x;
|
||||
//*(--bufptr) = val % 10 + '0';
|
||||
//val /= 10;
|
||||
}
|
||||
}
|
||||
if(minus) *(--bufptr) = '-';
|
||||
return bufptr;
|
||||
}
|
||||
|
||||
// return string with number `val`
|
||||
char *u2str(uint32_t val){
|
||||
return _2str(val, 0);
|
||||
}
|
||||
char *i2str(int32_t i){
|
||||
uint8_t minus = 0;
|
||||
uint32_t val;
|
||||
if(i < 0){
|
||||
minus = 1;
|
||||
val = -i;
|
||||
}else val = i;
|
||||
return _2str(val, minus);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief uhex2str - print 32bit unsigned int as hex
|
||||
* @param val - value
|
||||
* @return string with number
|
||||
*/
|
||||
char *uhex2str(uint32_t val){
|
||||
static char buf[12] = "0x";
|
||||
int npos = 2;
|
||||
uint8_t *ptr = (uint8_t*)&val + 3;
|
||||
int8_t i, j, z=1;
|
||||
for(i = 0; i < 4; ++i, --ptr){
|
||||
if(*ptr == 0){ // omit leading zeros
|
||||
if(i == 3) z = 0;
|
||||
if(z) continue;
|
||||
}
|
||||
else z = 0;
|
||||
for(j = 1; j > -1; --j){
|
||||
uint8_t half = (*ptr >> (4*j)) & 0x0f;
|
||||
if(half < 10) buf[npos++] = half + '0';
|
||||
else buf[npos++] = half - 10 + 'a';
|
||||
}
|
||||
}
|
||||
buf[npos] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief omit_spaces - eliminate leading spaces and other trash in string
|
||||
* @param buf - string
|
||||
* @return - pointer to first character in `buf` > ' '
|
||||
*/
|
||||
const char *omit_spaces(const char *buf){
|
||||
while(*buf){
|
||||
if(*buf > ' ') break;
|
||||
++buf;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief getdec - read decimal number & return pointer to next non-number symbol
|
||||
* @param buf - string
|
||||
* @param N - number read
|
||||
* @return Next non-number symbol. In case of overflow return `buf` and N==0xffffffff
|
||||
*/
|
||||
static const char *getdec(const char *buf, uint32_t *N){
|
||||
char *start = (char*)buf;
|
||||
uint32_t num = 0;
|
||||
while(*buf){
|
||||
char c = *buf;
|
||||
if(c < '0' || c > '9'){
|
||||
break;
|
||||
}
|
||||
if(num > 429496729 || (num == 429496729 && c > '5')){ // overflow
|
||||
*N = 0xffffff;
|
||||
return start;
|
||||
}
|
||||
num *= 10;
|
||||
num += c - '0';
|
||||
++buf;
|
||||
}
|
||||
*N = num;
|
||||
return buf;
|
||||
}
|
||||
// read hexadecimal number (without 0x prefix!)
|
||||
static const char *gethex(const char *buf, uint32_t *N){
|
||||
const char *start = buf;
|
||||
uint32_t num = 0;
|
||||
while(*buf){
|
||||
char c = *buf;
|
||||
uint8_t M = 0;
|
||||
if(c >= '0' && c <= '9'){
|
||||
M = '0';
|
||||
}else if(c >= 'A' && c <= 'F'){
|
||||
M = 'A' - 10;
|
||||
}else if(c >= 'a' && c <= 'f'){
|
||||
M = 'a' - 10;
|
||||
}
|
||||
if(M){
|
||||
if(num & 0xf0000000){ // overflow
|
||||
*N = 0xffffff;
|
||||
return start;
|
||||
}
|
||||
num <<= 4;
|
||||
num += c - M;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
++buf;
|
||||
}
|
||||
*N = num;
|
||||
return buf;
|
||||
}
|
||||
// read octal number (without 0 prefix!)
|
||||
static const char *getoct(const char *buf, uint32_t *N){
|
||||
const char *start = (char*)buf;
|
||||
uint32_t num = 0;
|
||||
while(*buf){
|
||||
char c = *buf;
|
||||
if(c < '0' || c > '7'){
|
||||
break;
|
||||
}
|
||||
if(num & 0xe0000000){ // overflow
|
||||
*N = 0xffffff;
|
||||
return start;
|
||||
}
|
||||
num <<= 3;
|
||||
num += c - '0';
|
||||
++buf;
|
||||
}
|
||||
*N = num;
|
||||
return buf;
|
||||
}
|
||||
// read binary number (without b prefix!)
|
||||
static const char *getbin(const char *buf, uint32_t *N){
|
||||
const char *start = (char*)buf;
|
||||
uint32_t num = 0;
|
||||
while(*buf){
|
||||
char c = *buf;
|
||||
if(c < '0' || c > '1'){
|
||||
break;
|
||||
}
|
||||
if(num & 0x80000000){ // overflow
|
||||
*N = 0xffffff;
|
||||
return start;
|
||||
}
|
||||
num <<= 1;
|
||||
if(c == '1') num |= 1;
|
||||
++buf;
|
||||
}
|
||||
*N = num;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief getnum - read uint32_t from string (dec, hex or bin: 127, 0x7f, 0b1111111)
|
||||
* @param buf - buffer with number and so on
|
||||
* @param N - the number read
|
||||
* @return pointer to first non-number symbol in buf
|
||||
* (if it is == buf, there's no number or if *N==0xffffffff there was overflow)
|
||||
*/
|
||||
const char *getnum(const char *txt, uint32_t *N){
|
||||
const char *nxt = NULL;
|
||||
const char *s = omit_spaces(txt);
|
||||
if(*s == '0'){ // hex, oct or 0
|
||||
if(s[1] == 'x' || s[1] == 'X'){ // hex
|
||||
nxt = gethex(s+2, N);
|
||||
if(nxt == s+2) nxt = (char*)txt;
|
||||
}else if(s[1] > '0'-1 && s[1] < '8'){ // oct
|
||||
nxt = getoct(s+1, N);
|
||||
if(nxt == s+1) nxt = (char*)txt;
|
||||
}else{ // 0
|
||||
nxt = s+1;
|
||||
*N = 0;
|
||||
}
|
||||
}else if(*s == 'b' || *s == 'B'){
|
||||
nxt = getbin(s+1, N);
|
||||
if(nxt == s+1) nxt = (char*)txt;
|
||||
}else{
|
||||
nxt = getdec(s, N);
|
||||
if(nxt == s) nxt = (char*)txt;
|
||||
}
|
||||
return nxt;
|
||||
}
|
||||
|
||||
// get signed integer
|
||||
const char *getint(const char *txt, int32_t *I){
|
||||
const char *s = omit_spaces(txt);
|
||||
int32_t sign = 1;
|
||||
uint32_t U;
|
||||
if(*s == '-'){
|
||||
sign = -1;
|
||||
++s;
|
||||
}
|
||||
const char *nxt = getnum(s, &U);
|
||||
if(nxt == s) return txt;
|
||||
if(U & 0x80000000) return txt; // overfull
|
||||
*I = sign * (int32_t)U;
|
||||
return nxt;
|
||||
}
|
||||
|
||||
// be careful: if pow10 would be bigger you should change str[] size!
|
||||
static const float pwr10[] = {1.f, 10.f, 100.f, 1000.f, 10000.f};
|
||||
static const float rounds[] = {0.5f, 0.05f, 0.005f, 0.0005f, 0.00005f};
|
||||
#define P10L (sizeof(pwr10)/sizeof(uint32_t) - 1)
|
||||
char *float2str(float x, uint8_t prec){
|
||||
static char str[16] = {0}; // -117.5494E-36\0 - 14 symbols max!
|
||||
if(prec > P10L) prec = P10L;
|
||||
if(isnan(x)){ memcpy(str, "NAN", 4); return str;}
|
||||
else{
|
||||
int i = isinf(x);
|
||||
if(i){memcpy(str, "-INF", 5); if(i == 1) return str+1; else return str;}
|
||||
}
|
||||
char *s = str + 14; // go to end of buffer
|
||||
uint8_t minus = 0;
|
||||
if(x < 0){
|
||||
x = -x;
|
||||
minus = 1;
|
||||
}
|
||||
int pow = 0; // xxxEpow
|
||||
// now convert float to 1.xxxE3y
|
||||
while(x > 1000.f){
|
||||
x /= 1000.f;
|
||||
pow += 3;
|
||||
}
|
||||
if(x > 0.) while(x < 1.){
|
||||
x *= 1000.f;
|
||||
pow -= 3;
|
||||
}
|
||||
// print Eyy
|
||||
if(pow){
|
||||
uint8_t m = 0;
|
||||
if(pow < 0){pow = -pow; m = 1;}
|
||||
while(pow){
|
||||
register int p10 = pow/10;
|
||||
*s-- = '0' + (pow - 10*p10);
|
||||
pow = p10;
|
||||
}
|
||||
if(m) *s-- = '-';
|
||||
*s-- = 'E';
|
||||
}
|
||||
// now our number is in [1, 1000]
|
||||
uint32_t units;
|
||||
if(prec){
|
||||
units = (uint32_t) x;
|
||||
uint32_t decimals = (uint32_t)((x-units+rounds[prec])*pwr10[prec]);
|
||||
// print decimals
|
||||
while(prec){
|
||||
register int d10 = decimals / 10;
|
||||
*s-- = '0' + (decimals - 10*d10);
|
||||
decimals = d10;
|
||||
--prec;
|
||||
}
|
||||
// decimal point
|
||||
*s-- = '.';
|
||||
}else{ // without decimal part
|
||||
units = (uint32_t) (x + 0.5);
|
||||
}
|
||||
// print main units
|
||||
if(units == 0) *s-- = '0';
|
||||
else while(units){
|
||||
register uint32_t u10 = units / 10;
|
||||
*s-- = '0' + (units - 10*u10);
|
||||
units = u10;
|
||||
}
|
||||
if(minus) *s-- = '-';
|
||||
return s+1;
|
||||
}
|
||||
31
F3:F303/CANbus4BTA/strfunc.h
Normal file
31
F3:F303/CANbus4BTA/strfunc.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the canbus4bta 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
void hexdump(int (*sendfun)(const char *s), uint8_t *arr, uint16_t len);
|
||||
char *u2str(uint32_t val);
|
||||
char *i2str(int32_t i);
|
||||
char *uhex2str(uint32_t val);
|
||||
char *float2str(float x, uint8_t prec);
|
||||
const char *getnum(const char *txt, uint32_t *N);
|
||||
const char *omit_spaces(const char *buf);
|
||||
const char *getint(const char *txt, int32_t *I);
|
||||
@ -1,2 +1,2 @@
|
||||
#define BUILD_NUMBER "2"
|
||||
#define BUILD_DATE "2023-12-03"
|
||||
#define BUILD_NUMBER "9"
|
||||
#define BUILD_DATE "2024-01-05"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user