I have a problem as in the subject. I have this function on one maple mini:
void callDomofon(int nrLok, int ileDzwonkow){
digitalWrite(domofonPin, HIGH);
delay(257);
digitalWrite(domofonPin, LOW);
delay(200);
for(int i = 1; i <= nrLok; i++){
digitalWrite(domofonPin, HIGH);
delayMicroseconds(12);
digitalWrite(domofonPin, LOW);
delayMicroseconds(170);
}
for(int i = 1; i <= ileDzwonkow; i++){
digitalWrite(domofonPin, LOW);
delay(96);
for(int x = 1; x <= 14; x++){
for(int y = 1; y <= 185; y++){
digitalWrite(domofonPin, HIGH);
delayMicroseconds(172);
digitalWrite(domofonPin, LOW);
delayMicroseconds(146);
}
for(int z = 1; z <= 78; z++){
digitalWrite(domofonPin, HIGH);
delayMicroseconds(370);
digitalWrite(domofonPin, LOW);
delayMicroseconds(396);
}
digitalWrite(domofonPin, HIGH);
delayMicroseconds(370);
digitalWrite(domofonPin, LOW);
delayMicroseconds(172);
}
digitalWrite(domofonPin, LOW);
delay(1780);
}
}
Some hints:
– make the ISR as short as possible – the ISR runtime should be less than 10microseconds, as your shortest pulse is 12 microseconds long
– disable the systick interrupt, otherwise it will block some IRQs of your pulses.
On the other hand if you disable the systick IRQ you will not be able to call delay-related functions…
Hmmm
const int domofonPin = 3;
int state = 0;
void setup() {
Serial.begin(250000);
pinMode(domofonPin, OUTPUT);
analogWrite(domofonPin, LOW);
}
void loop() {
String strser = "";
if (Serial.available () > 0) {
strser = Serial.readStringUntil('\n');
}
if (strser != ""){
if (strser.startsWith("start")){
Serial.println("Starting");
callDomofon(61, 0);
} else if (strser.startsWith("stop")){
Serial.println("Stopping");
endDomofon();
} else {
Serial.println("ERR");
}
}
}
void callDomofon(int nrLok, int ileDzwonkow){
digitalWrite(domofonPin, HIGH);
delay(257);
digitalWrite(domofonPin, LOW);
delay(200);
for(int i = 1; i <= nrLok; i++){
digitalWrite(domofonPin, HIGH);
delayMicroseconds(12);
digitalWrite(domofonPin, LOW);
delayMicroseconds(170);
}
for(int i = 1; i <= ileDzwonkow; i++){
digitalWrite(domofonPin, LOW);
delay(96);
for(int x = 1; x <= 14; x++){
for(int y = 1; y <= 185; y++){
digitalWrite(domofonPin, HIGH);
delayMicroseconds(172);
digitalWrite(domofonPin, LOW);
delayMicroseconds(146);
}
for(int z = 1; z <= 78; z++){
digitalWrite(domofonPin, HIGH);
delayMicroseconds(370);
digitalWrite(domofonPin, LOW);
delayMicroseconds(396);
}
digitalWrite(domofonPin, HIGH);
delayMicroseconds(370);
digitalWrite(domofonPin, LOW);
delayMicroseconds(172);
}
digitalWrite(domofonPin, LOW);
delay(1780);
}
}
void endDomofon(){
digitalWrite(domofonPin, HIGH);
delay(268);
digitalWrite(domofonPin, LOW);
}
257005
13
13
12
12
13
13
13
13
1013
13
10
12
13
13
13
12
13
13
13
13
12
13
13
12
13
13
13
11
12
13
12
16
13
13
13
12
12
13
13
13
13
13
13
12
12
13
13
13
12
12
13
13
13
13
13
13
12
13
13
13
13
257005
12
13
12
13
13
13
13
12
13
13
13
13
13
13
13
12
13
13
13
12
12
13
13
11
13
12
13
12
12
13
13
13
12
12
13
12
12
13
13
13
13
13
13
12
12
13
13
13
12
12
13
12
14
13
13
13
12
13
13
13
13
Also mind there are other process running in the background.
If I were you, I would set the interrupt on RISING edge – I will get 1 interrupt per pulse then..
initialising it to zero will occur only once.
stephen
Measuring periods only could be easier..
stephen
#include <SPI.h>
void setup() {
// Setup SPI 1
SPI.begin(); //Initialize the SPI_1 port.
SPI.setBitOrder(MSBFIRST); // Set the SPI_1 bit order
SPI.setDataMode(SPI_MODE0); //Set the SPI_2 data mode 0
SPI.setClockDivider(SPI_CLOCK_DIV128); // 72/128 = 562.5khz
Serial.begin(115200);
}
uint8_t last_data = 0;
uint32_t repeat = 0;
void loop() {
uint8_t data;
data = SPI.transfer(0);
if(data != last_data) {
Serial.print(repeat);
Serial.print(" ");
Serial.println(last_data);
last_data = data;
repeat = 1;
} else {
repeat++;
}
}
1466029 0
1 1
49035 255
1 254
37128 0
1 7
18894 0
34 255
29 0
34 255
1 0
1 255
1 0
1 255
1 0
5 255
1 0
1 255
19 0
1 255
64 0
27 255
1 192
58 0
1 3
24 255
19 0
1 63
1 255
1 0
12 255
1 240
1 0
1 255
1 0
1 255
38 0
1 63
1 0
1 255
57 0
1 31
57 255
1 0
1 255
4 0
17 255
1 224
1 0
1 255
1 0
7 255
7 0
17 255
23 0
1 255
65 0
1 31
70 255
1 248
12 255
1 224
53 0
1 15
1 255
1 0
1 255
1 0
5 255
1 240
1 0
1 255
1 0
1 255
70 0
1 31
74 255
1 224
22 255
1 254
60 0
15 255
1 248
1 255
1 0
10 255
1 192
1 0
1 255
1 0
1 255
10 0
1 3
1 0
1 255
71 0
33 255
1 252
57 0
24 255
63 0
1 31
1 0
1 255
2 0
16 255
1 252
1 0
1 255
1 0
6 255
1 254
33 0
1 63
1 0
1 255
50 0
1 7
1 255
24 0
1 63
3 255
1 0
15 255
1 128
1 0
1 255
1 0
1 255
1 0
57 255
1 0
1 255
20 0
1 1
1 0
1 255
81 0
1 3
1 255
1 0
15 255
1 248
1 0
1 255
1 0
5 255
1 0
24 255
1 240
63 0
1 63
69 255
1 240
15 255
1 252
51 0
15 255
1 224
1 255
1 0
1 255
1 0
10 255
1 128
1 0
1 255
1 0
1 255
73 0
1 1
1 255
63 0
25 255
1 224
57 0
1 15
1 255
1 0
1 255
1 0
1 255
1 254
1 0
1 255
1 0
1 255
59 0
16 255
1 192
69 0
1 127
29 255
1 224
62 0
1 63
1 255
1 0
11 255
1 240
1 0
1 255
1 0
1 255
1 0
1 255
18 0
1 15
1 0
1 255
39 0
1 63
50 255
1 0
1 255
15 0
1 63
1 255
1 0
1 255
1 0
2 255
4 0
1 63
1 255
1 0
1 255
66 0
1 63
70 255
1 252
23 255
56 0
1 31
62 255
1 240
1 255
1 0
1 255
1 0
11 255
3 0
1 127
1 255
46 0
10 255
46 0
5 255
1 128
1 0
1 255
15 0
1 31
28 0
1 3
1 15
1 255
1 0
2 255
1 240
1 0
1 255
1 0
51 255
1 252
6 255
81 0
1 1
1 255
58 0
20 255
53 0
1 1
1 255
Here is what I did:
Under -> STM32F1\cores\maple\libmaple -> in timer.c
after function -> static void output_compare_mode(timer_dev *dev, uint8 channel);
I’ve added :
static void input_capture_mode(timer_dev *dev, uint8 channel);
Under -> STM32F1\cores\maple\libmaple -> in timer.c
after function -> static void output_compare_mode(timer_dev *dev, uint8 channel);
I’ve added :
static void input_capture_mode(timer_dev *dev, uint8 channel);
Several timers can be cascaded for time periods longer than ~65.5ms.
Here is my code for getting the measurements with explanation how I’m trying to set the needed registers (at the end of the code).
#define RX1 PA0 //timer 2, channel 1
uint16_t ccr1, ccr2, measure;
void setup() {
Serial.begin(115200);
pinMode(RX1, INPUT);
TIMER2->regs.gen->CCMR1 = 0b100000001;
TIMER2->regs.gen->CCMR2 = 0b0;
TIMER2->regs.gen->CCER = 0b00110001;
TIMER2->regs.gen->SMCR = 0b1010100;
Timer2.attachInterrupt(TIMER_CH1, ppm_pwm_input);
}
void loop() {
/********************************************************************
*SystemFrequency/1000 1ms = 7200 cykliCPU / 1ms *
*SystemFrequency/100000 10us = 720 cykliCPU / 10us *
*SystemFrequency/1000000 1us = 72 cykliCPU / 1us *
********************************************************************/
if(measure != 0){
Serial.print(ccr1/7200);
Serial.print("\t");
Serial.println(ccr2/7200);
measure = 0;
}
}
void ppm_pwm_input(void) {
measure = 1;
ccr1 = TIMER2->regs.gen->CCR1;
ccr2 = TIMER2->regs.gen->CCR2;
}
/*
PWM input mode example:
CC1S bits in CCMR1 set to 01 - CC1 channel is configured as input, IC1 is mapped on TI1 - CCR1
IC1PSC bits in CCMR1 set to 00 - no prescaler, capture is done each time an edge is detected on the capture input
IC1F bits in CCMR1 set to 0000 - No filter, sampling is done at fDTS
CC2S bits in CCMR1 set to 10 - CC2 channel is configured as input, IC2 is mapped on TI1 - CCR2
IC2PSC bits in CCMR1 set to 00 - no prescaler, capture is done each time an edge is detected on the capture input
IC2F bits in CCMR1 set to 0000 - No filter, sampling is done at fDTS
CCMR1: 0b100000001
| IC2F | IC2PSC | CC2S | IC1F | IC1PSC | CC1S |
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
PWM: | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
----------------
CC1E bits in CCER set to 1 - enable capture
CC1P bits in CCER set to 0 - rising edge
CC2E bits in CCER set to 1 - enable capture
CC2P bits in CCER set to 1 - falling edge
CCER: 0b00110001
| Reserv. | CC4P | CC4E | Reserv. | CC3P | CC3E | Reserv. | CC2P | CC2E | Reserv. | CC1P | CC1E |
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
PWM: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 1 |
----------------
ETP bits in SMCR set to 0 - ETR is non-inverted, active at high level or rising edge
ECE bits in SMCR set to 0 - External clock mode 2 disabled
ETPS bits in SMCR set to 00 - Prescaler OFF
ETF bits in SMCR set to 0000 - No filter, sampling is done at fDTS
MSM bits in SMCR set to 0 - No action
TS bits in SMCR set to 101 - Filtered Timer Input 1 (TI1FP1)
SMS bits in SMCR set to 100 - Reset Mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter and generates an update of the registers
SMCR: 0b1010100
| ETP | ECE | ETPS | ETF | MSM | TS | Reserv. | SMS |
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | Reserv. | 2 | 1 | 0 |
PWM: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | Reserv. | 1 | 0 | 0 |
*/
A first result: https://github.com/bjornfor/stm32-test/ … /PWM_Input
It is a HAL-based (not a libmaple-core) example, but it contains the needed register settings and the flow.
[konczakp – Tue Jun 20, 2017 5:35 pm] –
If You can help me to understand this HAL thing then maybe I could make it in arduino environment.
Sorry, I cannot, that is why I still stick to libmaple code ![]()
But direct register setting is not bad, at all, just that you should know what you do ![]()
I have found something like this but I don’t know if this is correct for Arduino IDE
volatile uint32_t *DWT_CONTROL = (uint32_t *) 0xE0001000;
volatile uint32_t *DWT_CYCCNT = (uint32_t *) 0xE0001004;
volatile uint32_t *DEMCR = (uint32_t *) 0xE000EDFC;
volatile uint32_t *LAR = (uint32_t *) 0xE0001FB0; // <-- added lock access register
*DEMCR = *DEMCR | 0x01000000; // enable trace
*LAR = 0xC5ACCE55; // <-- added unlock access to DWT (ITM, etc.)registers
*DWT_CYCCNT = 0; // clear DWT cycle counter
*DWT_CONTROL = *DWT_CONTROL | 1; // enable DWT cycle counter
// some code here
// .....
count = *DWT_CYCCNT;
http://docs.leaflabs.com/static.leaflab … dwaretimer
EDIT: My example of debug counter is working somehow (it measures something) so now I will try to get it working with input capture
/*
CC1S bits in CCMR1 set to 01 - CC1 channel is configured as input, IC1 is mapped on TI1 - CCR1
CCMR1:
| IC2F | IC2PSC | CC2S | IC1F | IC1PSC | CC1S |
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
----------------
CC1E bits in CCER set to 1 - enable capture
CC1P bits in CCER set to 1 - falling edge
CCER:
| Reserv. | CC4P | CC4E | Reserv. | CC3P | CC3E | Reserv. | CC2P | CC2E | Reserv. | CC1P | CC1E |
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
*/
#define RX1 PA0 //timer 2, channel 1
int c = 0, data_ready = 0;
String out1, out2;
volatile uint32_t *DWT_CONTROL = (uint32_t *) 0xE0001000;
volatile uint32_t *DWT_CYCCNT = (uint32_t *) 0xE0001004;
volatile uint32_t *DEMCR = (uint32_t *) 0xE000EDFC;
volatile uint32_t *LAR = (uint32_t *) 0xE0001FB0; // <-- added lock access register
void setup() {
Serial.begin(115200);
pinMode(RX1, INPUT);
*DEMCR = *DEMCR | 0x01000000; // enable trace
*LAR = 0xC5ACCE55; // <-- added unlock access to DWT (ITM, etc.)registers
Timer2.setPrescaleFactor(72); // set prescaler to get us (micro sec) counting, It can be changed on the fly as this control register is buffered
TIMER2->regs.gen->CCMR1 = 0b1;
TIMER2->regs.gen->CCMR2 = 0b0;
TIMER2->regs.gen->CCER = 0b11;
Timer2.attachInterrupt(TIMER_CH1, ppm_input);
}
void loop() {
/********************************************************************
*SystemFrequency/1000 1ms = 7200 cykliCPU / 1ms *
*SystemFrequency/100000 10us = 720 cykliCPU / 10us *
*SystemFrequency/1000000 1us = 72 cykliCPU / 1us *
********************************************************************/
if(data_ready != 0){
if(out1.length() > 4){
Serial.print("String1 : ");
Serial.println(countImpuls(out1));
out1 = "";
}
if(out2.length() > 4){
Serial.print("String2 : ");
Serial.println(countImpuls(out2));
out2 = "";
}
data_ready = 0;
}
}
void ppm_input(void) {
if(c == 0){ // falling edge
TIMER2->regs.gen->CCER = 0b1; // edge detection change
c = 1; // go to second entrance
*DWT_CYCCNT = 0; // clear DWT cycle counter
*DWT_CONTROL = *DWT_CONTROL | 1; // enable DWT cycle counter
} else { // rising edge
if(((*DWT_CYCCNT)/72) < 50){
out1 += ((*DWT_CYCCNT)/72);
out1 += " ";
} else if(((*DWT_CYCCNT)/72) >= 50 &&((*DWT_CYCCNT)/72) < 200){
out2 += ((*DWT_CYCCNT)/72);
out2 += " ";
} else {
data_ready = 1; // data ready
}
TIMER2->regs.gen->CCER = 0b11; // edge detection change
c = 0; // go to first entrance
}
TIMER2->regs.gen->SR = 0; // delete capture input flag notification
}
int countImpuls(String message){
int x = 0, commaPosition = 0;
do
{
commaPosition = message.indexOf(' ');
if(commaPosition != -1)
{
x++;
message = message.substring(commaPosition+1, message.length());
}
else
{
}
}
while(commaPosition >=0);
return x;
}


