mirror of
https://github.com/eddyem/stm32samples.git
synced 2026-02-01 04:45:09 +03:00
add flowsensor & something more
This commit is contained in:
parent
7a470da982
commit
6409272876
@ -9,13 +9,24 @@ Protocol: [ command line ]
|
||||
All messages are asynchroneous!
|
||||
|
||||
Commands:
|
||||
d - (only when EBUG defined) go into debug commands
|
||||
R - reset MCU
|
||||
|
||||
Ax - turn on(x=1)/off(x=0) external alarm or check its value
|
||||
Cx - set cooler PWM to x
|
||||
d - (only when EBUG defined) go into debug commands
|
||||
F - get flow sensor rate for 5s period
|
||||
Hx - set heater PWM to x
|
||||
L - check water level sensor value
|
||||
Px - set pump PWM to x
|
||||
R - reset MCU
|
||||
Tx - get NTC temperature for channel x
|
||||
t - get MCU temperature
|
||||
V - get Vdd value *100V
|
||||
|
||||
Debugging commands:
|
||||
w - test watchdog
|
||||
A - show raw ADC value (next letter is index, 0..5)
|
||||
F - get flow_cntr value & PB state
|
||||
T - show raw T values
|
||||
w - test watchdog
|
||||
|
||||
|
||||
Messages:
|
||||
MCUTEMP10=x - mcu temperature * 10 (degrC)
|
||||
|
||||
@ -40,7 +40,6 @@ static inline void iwdg_setup(){
|
||||
IWDG->KR = IWDG_REFRESH; /* (6) */
|
||||
}
|
||||
|
||||
|
||||
static inline void adc_setup(){
|
||||
uint16_t ctr = 0; // 0xfff0 - more than 1.3ms
|
||||
// Enable clocking
|
||||
@ -106,6 +105,7 @@ static inline void adc_setup(){
|
||||
* PF0 - floating input - water level alert
|
||||
* PF1 - push-pull - external alarm
|
||||
* PA0..PA3 - ADC_IN0..3
|
||||
* PA4, PA6, PA7 - PWM outputs
|
||||
* Registers
|
||||
* MODER - input/output/alternate/analog (2 bit)
|
||||
* OTYPER - 0 pushpull, 1 opendrain
|
||||
@ -119,20 +119,70 @@ static inline void adc_setup(){
|
||||
*/
|
||||
static inline void gpio_setup(){
|
||||
// Enable clocks to the GPIO subsystems
|
||||
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOFEN;
|
||||
GPIOA->MODER = GPIO_MODER_MODER13_O | GPIO_MODER_MODER14_O |
|
||||
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOFEN;
|
||||
GPIOA->MODER =
|
||||
GPIO_MODER_MODER13_O | GPIO_MODER_MODER14_O |
|
||||
GPIO_MODER_MODER4_AF | GPIO_MODER_MODER6_AF |
|
||||
GPIO_MODER_MODER7_AF |
|
||||
GPIO_MODER_MODER0_AI | GPIO_MODER_MODER1_AI |
|
||||
GPIO_MODER_MODER2_AI | GPIO_MODER_MODER3_AI;
|
||||
GPIOA->OTYPER = 3 << 13; // both opendrain
|
||||
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; // enable syscfg clock for EXTI
|
||||
GPIOA->OTYPER = 3 << 13; // 13/14 opendrain
|
||||
GPIOF->MODER = GPIO_MODER_MODER1_O;
|
||||
// PB1 - interrupt input
|
||||
/* (2) Select Port B for pin 1 external interrupt by writing 0001 in EXTI1*/
|
||||
/* (3) Configure the corresponding mask bit in the EXTI_IMR register */
|
||||
/* (4) Configure the Trigger Selection bits of the Interrupt line on rising edge*/
|
||||
/* (5) Configure the Trigger Selection bits of the Interrupt line on falling edge*/
|
||||
SYSCFG->EXTICR[0] = SYSCFG_EXTICR1_EXTI1_PB; /* (2) */
|
||||
EXTI->IMR = EXTI_IMR_MR1; /* (3) */
|
||||
//EXTI->RTSR = 0x0000; /* (4) */
|
||||
EXTI->FTSR = EXTI_FTSR_TR1; /* (5) */
|
||||
/* (6) Enable Interrupt on EXTI0_1 */
|
||||
/* (7) Set priority for EXTI0_1 */
|
||||
NVIC_EnableIRQ(EXTI0_1_IRQn); /* (6) */
|
||||
NVIC_SetPriority(EXTI0_1_IRQn, 3); /* (7) */
|
||||
// alternate functions:
|
||||
// PA4 - TIM14_CH1 (AF4)
|
||||
// PA6 - TIM16_CH1 (AF5), PA7 - TIM17_CH1 (AF5)
|
||||
GPIOA->AFR[0] = (GPIOA->AFR[0] &~ (GPIO_AFRL_AFRL4 | GPIO_AFRL_AFRL6 | GPIO_AFRL_AFRL7)) \
|
||||
| (4 << (4 * 4)) | (5 << (6 * 4)) | (5 << (7 * 4));
|
||||
}
|
||||
|
||||
static inline void timers_setup(){
|
||||
;
|
||||
// timer 14 ch1 - cooler PWM
|
||||
// timer 16 ch1 - heater PWM
|
||||
// timer 17 ch1 - pump PWM
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN | RCC_APB1ENR_TIM14EN; // enable clocking for timers 3 and 14
|
||||
RCC->APB2ENR |= RCC_APB2ENR_TIM16EN | RCC_APB2ENR_TIM17EN; // & timers 16/17
|
||||
// PWM mode 1 (active -> inactive)
|
||||
TIM14->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1;
|
||||
TIM16->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1;
|
||||
TIM17->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1;
|
||||
// frequency
|
||||
TIM14->PSC = 59; // 0.8MHz for 3kHz PWM
|
||||
TIM16->PSC = 18749; // 2.56kHz for 10Hz PWM
|
||||
TIM17->PSC = 5; // 8MHz for 31kHz PWM
|
||||
// ARR for 8-bit PWM
|
||||
TIM14->ARR = 254;
|
||||
TIM16->ARR = 254;
|
||||
TIM17->ARR = 254;
|
||||
// start in OFF state
|
||||
// TIM14->CCR1 = 0; and so on
|
||||
// enable main output
|
||||
TIM14->BDTR |= TIM_BDTR_MOE;
|
||||
TIM16->BDTR |= TIM_BDTR_MOE;
|
||||
TIM17->BDTR |= TIM_BDTR_MOE;
|
||||
// enable PWM output
|
||||
TIM14->CCER = TIM_CCER_CC1E;
|
||||
TIM16->CCER = TIM_CCER_CC1E;
|
||||
TIM17->CCER = TIM_CCER_CC1E;
|
||||
// enable timers
|
||||
TIM14->CR1 |= TIM_CR1_CEN;
|
||||
TIM16->CR1 |= TIM_CR1_CEN;
|
||||
TIM17->CR1 |= TIM_CR1_CEN;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void hw_setup(){
|
||||
sysreset();
|
||||
gpio_setup();
|
||||
@ -141,3 +191,13 @@ void hw_setup(){
|
||||
USART1_config();
|
||||
iwdg_setup();
|
||||
}
|
||||
|
||||
/*
|
||||
* Flow sensor counter
|
||||
*/
|
||||
void exti0_1_isr(){
|
||||
if (EXTI->PR & EXTI_PR_PR1){
|
||||
EXTI->PR |= EXTI_PR_PR1; /* Clear the pending bit */
|
||||
++flow_cntr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,6 +20,12 @@
|
||||
#define HARDWARE_H
|
||||
#include "stm32f0.h"
|
||||
|
||||
// measure flow sensor data each 5 seconds
|
||||
#define FLOW_RATE_MS 4999
|
||||
extern uint16_t flow_rate, flow_cntr;
|
||||
|
||||
extern volatile uint32_t Tms;
|
||||
|
||||
void hw_setup(void);
|
||||
|
||||
#endif // HARDWARE_H
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
update=Сб 17 ноя 2018 18:50:24
|
||||
update=Чт 20 дек 2018 22:32:48
|
||||
version=1
|
||||
last_client=kicad
|
||||
[pcbnew]
|
||||
@ -25,43 +25,6 @@ version=1
|
||||
NetIExt=net
|
||||
[general]
|
||||
version=1
|
||||
[eeschema]
|
||||
version=1
|
||||
LibDir=
|
||||
[eeschema/libraries]
|
||||
LibName1=power
|
||||
LibName2=device
|
||||
LibName3=switches
|
||||
LibName4=relays
|
||||
LibName5=motors
|
||||
LibName6=transistors
|
||||
LibName7=conn
|
||||
LibName8=linear
|
||||
LibName9=regul
|
||||
LibName10=74xx
|
||||
LibName11=cmos4000
|
||||
LibName12=adc-dac
|
||||
LibName13=memory
|
||||
LibName14=xilinx
|
||||
LibName15=microcontrollers
|
||||
LibName16=dsp
|
||||
LibName17=microchip
|
||||
LibName18=analog_switches
|
||||
LibName19=motorola
|
||||
LibName20=texas
|
||||
LibName21=intel
|
||||
LibName22=audio
|
||||
LibName23=interface
|
||||
LibName24=digital-audio
|
||||
LibName25=philips
|
||||
LibName26=display
|
||||
LibName27=cypress
|
||||
LibName28=siliconi
|
||||
LibName29=opto
|
||||
LibName30=atmel
|
||||
LibName31=contrib
|
||||
LibName32=valves
|
||||
LibName33=stm32
|
||||
[schematic_editor]
|
||||
version=1
|
||||
PageLayoutDescrFile=
|
||||
@ -72,3 +35,6 @@ NetFmtName=Pcbnew
|
||||
SpiceForceRefPrefix=0
|
||||
SpiceUseNetNumbers=0
|
||||
LabSize=60
|
||||
[eeschema]
|
||||
version=1
|
||||
LibDir=
|
||||
|
||||
@ -26,6 +26,8 @@
|
||||
#include "protocol.h"
|
||||
|
||||
volatile uint32_t Tms = 0;
|
||||
uint16_t flow_rate = 0; // flow sensor rate
|
||||
uint16_t flow_cntr = 0; // flow sensor trigger counter
|
||||
|
||||
// Called when systick fires
|
||||
void sys_tick_handler(void){
|
||||
@ -33,7 +35,7 @@ void sys_tick_handler(void){
|
||||
}
|
||||
|
||||
int main(void){
|
||||
// uint32_t lastT = 0;
|
||||
uint32_t lastTflow = 0;
|
||||
char *txt;
|
||||
hw_setup();
|
||||
SysTick_Config(6000, 1);
|
||||
@ -47,9 +49,11 @@ int main(void){
|
||||
RCC->CSR |= RCC_CSR_RMVF; // remove reset flags
|
||||
while (1){
|
||||
IWDG->KR = IWDG_REFRESH;
|
||||
/*if(lastT > Tms || Tms - lastT > 499){
|
||||
lastT = Tms;
|
||||
}*/
|
||||
if(Tms - lastTflow > FLOW_RATE_MS){ // onse per one second check flow sensor counter
|
||||
lastTflow = Tms;
|
||||
flow_rate = flow_cntr;
|
||||
flow_cntr = 0;
|
||||
}
|
||||
if(usart1_getline(&txt)){ // usart1 received command, process it
|
||||
txt = process_command(txt);
|
||||
}else txt = NULL;
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
* 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 "hardware.h"
|
||||
#include "protocol.h"
|
||||
#include "usart.h"
|
||||
#include "adc.h"
|
||||
@ -40,6 +41,14 @@ static void debugging_proc(const char *command){
|
||||
}
|
||||
put_string("ADC value: ");
|
||||
put_uint(getADCval(i));
|
||||
put_string(", ");
|
||||
usart1_sendbuf();
|
||||
break;
|
||||
case 'F':
|
||||
put_string("PB_IDR, flow_cntr: ");
|
||||
put_uint(GPIOB->IDR);
|
||||
put_string(", ");
|
||||
put_uint(flow_cntr);
|
||||
usart1_sendbuf();
|
||||
break;
|
||||
case 'T': // all raw T values
|
||||
@ -70,7 +79,8 @@ static void get_ntc(const char *str){
|
||||
}
|
||||
|
||||
#define SEND(x) usart1_send_blocking(x, 0)
|
||||
|
||||
#define STR(a) XSTR(a)
|
||||
#define XSTR(a) #a
|
||||
/**
|
||||
* @brief process_command - command parser
|
||||
* @param command - command text (all inside [] without spaces)
|
||||
@ -79,16 +89,66 @@ static void get_ntc(const char *str){
|
||||
char *process_command(const char *command){
|
||||
const char *ptr = command;
|
||||
char *ret = NULL;
|
||||
int32_t N;
|
||||
usart1_sendbuf(); // send buffer (if it is already filled)
|
||||
switch(*ptr++){
|
||||
case '?': // help
|
||||
SEND("R - reset\nTx - get NTC temp\nt - get MCU temp\nV - get Vdd");
|
||||
SEND(
|
||||
"Ax - alarm on(1)/off(0)\n"
|
||||
"Cx - cooler PWM\n"
|
||||
"F - get flow sensor rate for " STR(FLOW_RATE_MS) "ms\n"
|
||||
"Hx - heater PWM\n"
|
||||
"L - check water level\n"
|
||||
"Px - pump PWM\n"
|
||||
"R - reset\n"
|
||||
"Tx - get NTC temp\n"
|
||||
"t - get MCU temp\n"
|
||||
"V - get Vdd"
|
||||
);
|
||||
#ifdef EBUG
|
||||
SEND("d -> goto debug:");
|
||||
SEND("\tw - test watchdog\n\tAx - get raw ADCx value");
|
||||
SEND("\tT - show raw T values");
|
||||
SEND("d -> goto debug:\n"
|
||||
"\tAx - get raw ADCx value\n"
|
||||
"\tF - get flow_cntr\n"
|
||||
"\tT - show raw T values\n"
|
||||
"\tw - test watchdog"
|
||||
);
|
||||
#endif
|
||||
break;
|
||||
case 'A': // turn alarm on/off
|
||||
if(*ptr == '1') pin_set(GPIOF, 2);
|
||||
else if(*ptr == '0')pin_clear(GPIOF, 2);
|
||||
put_string("ALRM=");
|
||||
put_char(pin_read(GPIOF, 2) + '0');
|
||||
break;
|
||||
case 'C': // cooler PWM - TIM14CH1
|
||||
if(getnum(ptr, &N) && N > -1 && N < 256){
|
||||
TIM14->CCR1 = N;
|
||||
}
|
||||
put_string("COOLERPWM=");
|
||||
put_int(TIM14->CCR1);
|
||||
break;
|
||||
case 'F':
|
||||
put_string("FLOWRATE=");
|
||||
put_uint(flow_rate);
|
||||
break;
|
||||
case 'H': // heater PWM - TIM16CH1
|
||||
if(getnum(ptr, &N) && N > -1 && N < 256){
|
||||
TIM16->CCR1 = N;
|
||||
}
|
||||
put_string("HEATERPWM=");
|
||||
put_int(TIM16->CCR1);
|
||||
break;
|
||||
case 'L': // water level
|
||||
put_string("WATERLEVEL=");
|
||||
put_char('0' + pin_read(GPIOF, 1));
|
||||
break;
|
||||
case 'P': // pump PWM - TIM17CH1
|
||||
if(getnum(ptr, &N) && N > -1 && N < 256){
|
||||
TIM17->CCR1 = N;
|
||||
}
|
||||
put_string("PUMPPWM=");
|
||||
put_int(TIM17->CCR1);
|
||||
break;
|
||||
case 'R': // reset MCU
|
||||
NVIC_SystemReset();
|
||||
break;
|
||||
|
||||
@ -34,10 +34,10 @@ static uint8_t linerdy = 0 // received data ready
|
||||
;
|
||||
|
||||
static int rbufno = 0; // current rbuf number
|
||||
static char rbuf[2][UARTBUFSZ], tbuf[UARTBUFSZ]; // receive & transmit buffers
|
||||
static char rbuf[2][UARTBUFSZ+1], tbuf[UARTBUFSZ]; // receive & transmit buffers
|
||||
static char *recvdata = NULL;
|
||||
|
||||
static char trbuf[UARTBUFSZ]; // auxiliary buffer for data transmission
|
||||
static char trbuf[UARTBUFSZ+1]; // auxiliary buffer for data transmission
|
||||
static int trbufidx = 0;
|
||||
|
||||
int put_char(char c){
|
||||
@ -161,18 +161,19 @@ void usart1_isr(){
|
||||
}
|
||||
}
|
||||
switch(rb){
|
||||
case '[':
|
||||
datalen[rbufno] = 0;
|
||||
tmout = 0;
|
||||
break;
|
||||
case '[':
|
||||
datalen[rbufno] = 0;
|
||||
tmout = 0;
|
||||
break;
|
||||
case ']': // close command - line ready!
|
||||
dlen = datalen[rbufno];
|
||||
if(dlen){
|
||||
linerdy = 1;
|
||||
incmd = 0;
|
||||
recvdata = rbuf[rbufno];
|
||||
rbufno = !rbufno;
|
||||
datalen[rbufno] = 0;
|
||||
linerdy = 1;
|
||||
incmd = 0;
|
||||
recvdata = rbuf[rbufno];
|
||||
rbuf[rbufno][dlen] = 0;
|
||||
rbufno = !rbufno;
|
||||
datalen[rbufno] = 0;
|
||||
}
|
||||
tmout = 0;
|
||||
break;
|
||||
@ -257,3 +258,38 @@ TXstatus usart1_send_blocking(const char *str, int len){
|
||||
txrdy = 1;
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
// read `buf` and get first integer `N` in it
|
||||
// @return pointer to first non-number if all OK or NULL if first symbol isn't a space or number
|
||||
char *getnum(const char *buf, int32_t *N){
|
||||
char c;
|
||||
int positive = -1;
|
||||
int32_t val = 0;
|
||||
//usart1_send_blocking(buf, 0);
|
||||
while((c = *buf++)){
|
||||
if(c == '\t' || c == ' '){
|
||||
if(positive < 0) continue; // beginning spaces
|
||||
else break; // spaces after number
|
||||
}
|
||||
if(c == '-'){
|
||||
if(positive < 0){
|
||||
positive = 0;
|
||||
continue;
|
||||
}else break; // there already was `-` or number
|
||||
}
|
||||
if(c < '0' || c > '9') break;
|
||||
if(positive < 0) positive = 1;
|
||||
val = val * 10 + (int32_t)(c - '0');
|
||||
}
|
||||
if(positive != -1){
|
||||
if(positive == 0){
|
||||
if(val == 0) return NULL; // single '-'
|
||||
val = -val;
|
||||
}
|
||||
*N = val;
|
||||
}else return NULL;
|
||||
/* usart1_sendbuf();
|
||||
put_uint(val);
|
||||
put_char('\n');*/
|
||||
return (char*)buf-1;
|
||||
}
|
||||
|
||||
@ -50,5 +50,6 @@ int put_string(const char *str);
|
||||
int put_int(int32_t N);
|
||||
int put_uint(uint32_t N);
|
||||
|
||||
char *getnum(const char *buf, int32_t *N);
|
||||
|
||||
#endif // __USART_H__
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user