Author Topic: 32F417 - a cunning way to reset two DMA pointers from an edge on a pin, etc?  (Read 5318 times)

0 Members and 1 Guest are viewing this topic.

Online peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 4121
  • Country: gb
  • Doing electronics since the 1960s...
I have the two DACs outputting waveforms. This is done by loading values from two RAM tables, using DMA. The DACs are both to be triggered from the same timer so they run in sync but they get their data from different tables, via DMA. The DMAs are configured to read from circular buffers, as is normal for repetitive waveform generation.

I don't yet know if one can use a single timer to trigger both DACs but it's not a huge deal if one can't because two identically configured timers should be for ever in sync.

The next job is to sync these two waveform generators to a reference input, so that a +ve edge arriving on an input pin resets both DMA source pointers to their starting addresses. Is this possible? It is obviously possible if using interrupts but I would prefer to avoid that, due to latency issues.

The reference input waveform's +ve edges will go (via a comparator, to detect zero crossings accurately) to a timer (TIM1) for the purpose of measuring its period. I have PE7-PE10 available as inputs. There will be a separate RTOS thread which will use this period count to calculate the appropriate values for the two tables feeding the DACs. Is it possible, on a +ve edge, to transfer the contents of TIM1 into a RAM location, using DMA, (and zero TIM1) from where this RTOS thread could pick it up? Again, all obviously possible if interrupting from the input pin.

I have been going through the RM but there are so many options and while some of it is obviously possible, I don't think other parts are.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15340
  • Country: fr
So first question - yes absolutely: each DAC has a separate selectable trigger source (from 8 sources, 6 of them being timers). You can use the same trigger source for both, absolutely.

As to the DMA thing. First note is that I would personally use the double buffer mode rather than the circular buffer mode for streaming samples to DACs. Now it probably all depends on your exact use case - maybe you're storing a single period of signal in the buffers and just want to generate it continuously, in which case the circular mode would be appropriate.

Regarding automatically resetting DMA pointers upon a certain trigger (here an external input) without using interrupts, I honestly don't know. I have read the DMA section in the RM and I'm frankly not sure this is possible, but I may have missed it.

What would be your requirement in terms of latency? What's the sample rate?
 

Offline bson

  • Supporter
  • ****
  • Posts: 2448
  • Country: us
You can even run them in dual DAC mode - one trigger, one DMA channel stream feeding one of the DAC_DHR*D registers, for example DAC_DHR12RD.  This is a 32-bit register with two 16-bit halves, one for each channel; they're right-aligned, so the DAC will only use the low 12 bits.  If instead you use DAC_DHR12LD it will use the top 12 bits (useful if you have 16-bit samples).  This of course only makes sense if you have a dual waveform.  If you need to mix and match waveforms between the two channels it's probably preferable to use a separate DMA channel stream for each waveform.
 

Offline bson

  • Supporter
  • ****
  • Posts: 2448
  • Country: us
Instead of resetting the DMA source address, have pin edge stop the timer and generate an interrupt.   In the interrupt handler, update the DMA addresses, number of words to transfer (if you change waveforms), and release the timer.
 

Offline Cerebus

  • Super Contributor
  • ***
  • Posts: 10576
  • Country: gb
If you read the timer documentation very carefully (Is there any other way to read ST documentation?) you will find that you can set a timer up 'all ready to go' and then start it running for the first time from an external trigger so that it is synchronised to the external signal. Then you can either leave it free running, or use it a a sort of 'stretched one shot' to come around and wait for the start signal again.

I use it (in an STM32F411) in the first mode to synchronise a timer to a PPS input on a GPSDO to get initial fast synchronisation to GPS.

I know this is only part of the puzzle, but at least it's something. Doesn't help you with resetting the DMA, but perhaps helps with the start synchronisation to an external source.

Here's the relevant bit of the timer initialisation code.

Code: [Select]
    rccEnableTIM5(FALSE);
    rccResetTIM5();
    nvicEnableVector(STM32_TIM5_NUMBER, STM32_TIMCAP_TIM5_IRQ_PRIORITY);
   
                                                            // ======================= Configure timer 5 ==========================
    TIM5->CR1   = TIM_CR1_URS ;                              // Only overflow and underflow events generate an event interrupt.

    TIM5->CR2   = 0;
    TIM5->SMCR  = TIM_SMCR_SMS_2 | TIM_SMCR_SMS_1           // SMS(110) - trigger mode, start on TRGI
                | TIM_SMCR_TS_2 | TIM_SMCR_TS_0 ;           // TS(101) - TRGI is TI1FP1
                                                           
    [Irrelevant settings snipped.]

    // NOTE WELL
    // We do NOT enable the timer, that is done automatically by the first PPS pulse received.
Anybody got a syringe I can use to squeeze the magic smoke back into this?
 

Offline bson

  • Supporter
  • ****
  • Posts: 2448
  • Country: us
You might able to set up one DMA to trigger on an external pin, to do a transfer from memory to memory, without increment, with its destination memory being the address register of another DMA stream?  Not sure if that works, or if memory to memory truly has to be exactly that or if it can be something like a DMA register, given you will only do exactly aligned 32-bit to 32-bit.
 

Online peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 4121
  • Country: gb
  • Doing electronics since the 1960s...
" I would personally use the double buffer mode rather than the circular buffer mode for streaming samples to DACs. Now it probably all depends on your exact use case - maybe you're storing a single period of signal in the buffers and just want to generate it continuously, in which case the circular mode would be appropriate."

I looked this up and it seems to be for usage where one wants to be dynamically changing the DMA addresses. I may well want that. The source buffer for DMA -> DAC will always be a fixed size e.g. 500 values, but it will be recomputed frequently - probably around every 100ms. I want to vary the frequency and amplitude of the waveform. The frequency can be done in two ways: change the timer driving the DAC, or change the DMA source table length. Both give similarly fine control; I will be generating around 400Hz and with say a 250 sample table that is 100kHz i.e. 10us between samples, and the timer (which will be driven from APB1 or APB2; both 42MHz in my case) which with a x1 prescaler gives a frequency control resolution of 1/420 of 10us, while varying the table length will give a resolution of 1/250. The timer value can be changed without messing up its current cycle AFAIK, and the DMA double buffer mode gives you the same thing for the source address (but seems a lot more complicated to configure).

It would be handy to be generating one table while the DMA is reading from another, and then switch the tables, preferably at the next zero crossing so there are no glitches. Again, this would be trivial with an interrupt from the DMA, with the ISR checking if the other table is ready for use.

Normally the output will be a sinewave, but the amplitude will vary, from +1 through zero to -1. For those who know, this is to emulate an LVDT. Of course the obvious way to do this is to have a four quadrant multiplying DAC, with the above mentioned reference waveform being its input, and with the digital input coming from software, but I want to do it all in the CPU.

For measurement of the input waveform period, I recall reading somewhere that one can config a DMA to be triggered from a pin and do a transfer from a timer to memory, but we also want to reset the timer, and if the timer is configured to reset from the pin also, does the timer get reset before or after the DMA transfer? :) Again, an ISR would make this more obviously controlled.
« Last Edit: November 11, 2021, 07:16:10 am by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline wek

  • Frequent Contributor
  • **
  • Posts: 536
  • Country: sk
For measurement of the input waveform period, I recall reading somewhere that one can config a DMA to be triggered from a pin and do a transfer from a timer to memory, but we also want to reset the timer, and if the timer is configured to reset from the pin also, does the timer get reset before or after the DMA transfer? :)
You do input capture together with the reset. This in itself is described in the PWM input mode subchapter of the TIM chapter of RM (you want to read out the period only but the principle is the same).  Reset is delayed by the slave-mode controller by a couple of cycles (this is not specified by ST, putting it into the realm of "what's a clock or two amongst friends" type of handwaves) later so the counter's value is captured before the reset happens.

DMA part is, that you trigger the DMA from the given channel itself. The captured value stays there the whole period until the next edge causing capture. Btw., TIM1 has a priviledge to have individual DMA triggers from individual channels, see DMA2 request mapping table in DMA chapter in RM.

I personally don't t do the reset part; I simply capture, DMA to RAM buffer, and calculate period from difference.

Now for the "resetting DMA" part - doable, by triggering a timer (maybe through the internal master-slave link) which in turn would trigger two successive writes into the Control register of DMA stream which  feeds the DAC, which would toggle its enable bit. However, I personally wouldn't do this, it's too risky, as DMA disable needs a wait for the given channel to finish its job, and this is a nearly unspecifiable time, as it depends on bus conflicts etc. Read: it's potentially risky. [EDIT] I've realized that you'd need another DMA to clear the DMA status flags in between the two writes to control register; that'd mean another timer and another DMA, moving it firmer into the impractical corner. [/EDIT]With 168MHz system clock you have 1680 cycles between DAC sampled at 100kHz, with carefully crafted interrupt it's enough to reset the DMA between two consecutive DAC samples, and I don't see why would you need better latency for this. With 500Hz of input signal this would not present any significant processing load either.

Btw. I don't understand why would you want to ever reset the DMA, as that would create a discontinuity in your output signal; I've just commented on your original request.

JW
« Last Edit: November 11, 2021, 09:18:19 am by wek »
 

Online peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 4121
  • Country: gb
  • Doing electronics since the 1960s...
Great points - many thanks.

Yes - no need to reset the counter used to measure the input waveform period. It would be TIM1, which I have kept reserved for this job because it has the most features. The 32 bit count will take ages to overflow and one could either handle the overflow correctly (like the other thread we had here, for the CYCCNT) or disregard the value if it has overflowed and go for the next one. I would still like to set up DMA to copy the counter value to RAM, on a zero crossing, because that will give me a "totally zero" latency.

Also no need to reset the two DMA source pointers on the zero crossing, because I can control the phase of the generated waveform (relative to the zero crossings of the input one) by generating the wave tables with an appropriate shift. So the two DMAs, stuffing the two DACs, can free-run across a constant RAM source area. The double buffer option will still be very useful.

I need to check that PE7-PE10 can trigger the DMA transfer from the TIM1 32 bit counter to a RAM address, on a +ve edge. It is probably limited to some DMA channels only. Currently I have all DMAs spare, though two channels will be used for the DACs. I find it very confusing to work out what can work with what.

If we aren't resetting the DMA source pointers, the actual phase locking needs to be done somehow, and one way is to feed the output waveform into a comparator and use a timer to measure the delay between that and the input waveform, and then have a feedback loop to zero that.
« Last Edit: November 11, 2021, 09:45:15 am by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline Psi

  • Super Contributor
  • ***
  • Posts: 10228
  • Country: nz
You might able to set up one DMA to trigger on an external pin, to do a transfer from memory to memory, without increment, with its destination memory being the address register of another DMA stream?  Not sure if that works, or if memory to memory truly has to be exactly that or if it can be something like a DMA register, given you will only do exactly aligned 32-bit to 32-bit.

This. 

I've had to do that before, it seems a bit hacky to use DMA to set a hardware config register, but works and it sometimes the only way to do some things.
Greek letter 'Psi' (not Pounds per Square Inch)
 

Offline ozcar

  • Frequent Contributor
  • **
  • Posts: 342
  • Country: au
You might able to set up one DMA to trigger on an external pin, to do a transfer from memory to memory, without increment, with its destination memory being the address register of another DMA stream?  Not sure if that works, or if memory to memory truly has to be exactly that or if it can be something like a DMA register, given you will only do exactly aligned 32-bit to 32-bit.

I can't see that working. The Fine Manual says that the DMA stream memory address register can only be written when the stream is disabled, or for double buffer mode, if the other buffer is in use at the time.
 

Offline Psi

  • Super Contributor
  • ***
  • Posts: 10228
  • Country: nz
You might able to set up one DMA to trigger on an external pin, to do a transfer from memory to memory, without increment, with its destination memory being the address register of another DMA stream?  Not sure if that works, or if memory to memory truly has to be exactly that or if it can be something like a DMA register, given you will only do exactly aligned 32-bit to 32-bit.

I can't see that working. The Fine Manual says that the DMA stream memory address register can only be written when the stream is disabled, or for double buffer mode, if the other buffer is in use at the time.

So there's no single bit you can flip on the DMA control registers to cause it to restart and start again from zero?
(or timer register if you are using a timer output to set the DMA read address.)

In fact that is probably the way to do it, setup timer to control both DMA read address's then you can use another DMA to copy a 0 into the timer count register on GPIO trigger
« Last Edit: November 11, 2021, 10:21:13 am by Psi »
Greek letter 'Psi' (not Pounds per Square Inch)
 

Offline wek

  • Frequent Contributor
  • **
  • Posts: 536
  • Country: sk
It would be TIM1, which I have kept reserved for this job because it has the most features. The 32 bit count will take ages to overflow
TIM1 is a 16-bit counter.

TIM2 and TIM5 are 32-bit.

I need to check that PE7-PE10 can trigger the DMA transfer from the TIM1 32 bit counter to a RAM address, on a +ve edge.
As I've said, you want to capture *and* transfer the captured value.

It is probably limited to some DMA channels only.
The elements in DMA in 'F4 are called Streams. The individual input signals to one stream, selected as the particular trigger, are called channels. Read the DMA chapter in RM.

As I've said, TIM1 has individual triggers to different DMA streams, so you can individually capture and then trigger DMA transfer on any of the four TIM1 channels.


I find it very confusing to work out what can work with what.
The usual learning process, i.e. thoroughly reading the relevant chapters in RM, and performing small experiments to check the understanding, should help with this.

JW
 

Online peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 4121
  • Country: gb
  • Doing electronics since the 1960s...
Googling around, everyone seems to be doing period measurement using CH1 of "some" timer, and this is TIM1 to whose pins I have access on my board:



and TIM1_CH1 is accessible on PE9, so feeding that with a comparator should work.

The Q is whether TIM1 can trigger DMA to store the value reached.

I think most people use the Cube IDE "graphical pin configurator / code generator" to find out what can go to where :) Does the RM spell that out anywhere?
« Last Edit: November 11, 2021, 04:20:25 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline bson

  • Supporter
  • ****
  • Posts: 2448
  • Country: us
the timer (which will be driven from APB1 or APB2; both 42MHz in my case) which with a x1 prescaler gives a frequency control resolution of 1/420 of 10us,
Note that if the APB bus clocks are divided down from HCLK (and not equal to HCLK) the APB timer clocks are twice the bus clocks.  So you get 1/840 of 10μs.  If HCLK is used straight up as an APB clock (/1), then that APB bus' timer clock will be HCLK as well.
« Last Edit: November 11, 2021, 04:37:17 pm by bson »
 

Offline bson

  • Supporter
  • ****
  • Posts: 2448
  • Country: us
I think most people use the Cube IDE "graphical pin configurator / code generator" to find out what can go to where :) Does the RM spell that out anywhere?
Section 10.3.3, "Channel Selection".

 

Online peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 4121
  • Country: gb
  • Doing electronics since the 1960s...
Thank you :)

I wonder if DMA is needed to retrieve the counter value at all. From the RM, page 538:

Input capture mode
In Input capture mode, the Capture/Compare registers (TIMx_CCRx) are used to latch the
value of the counter after a transition detected by the corresponding ICx signal.


So the value reached is latched in CCR anyway, from which it can be read out "at leisure".

And CH1 feeds through to IC1.

What am I missing?
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline bson

  • Supporter
  • ****
  • Posts: 2448
  • Country: us
It's like anything else - you don't want to run interrupts at very high rates.  DMA is a lot cheaper for higher rate transfers, and even more so if your interrupt handler also has to manage buffer pointers and counters in memory somewhere.  The drawback of course is it's a planning puzzle to allocate DMA streams, or do it dynamically and accept there's DMA contention (can't say read an SPI device while a USART is transmitting).  Of course if there's contention you have to implement a dynamic assignment or queueing system.
 

Online peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 4121
  • Country: gb
  • Doing electronics since the 1960s...
Another reason for not interrupting from the zero crossings is that noise on that pin will likely hang up the whole system - unless the ISR is written to disable further interrupts until some timer has expired, etc.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Online peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 4121
  • Country: gb
  • Doing electronics since the 1960s...
Would anyone agree that feeding zero crossings into PE9 and using TIM1 should maintain a continuously latched value (of the waveform period) in CCR, as posted above
https://www.eevblog.com/forum/microcontrollers/32f417-a-cunning-way-to-reset-two-dma-pointers-from-an-edge-on-a-pin-etc/msg3806189/#msg3806189

I will prototype it when I get a chance but wonder if anyone can see a problem.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline wek

  • Frequent Contributor
  • **
  • Posts: 536
  • Country: sk
If given pin is set to AF in GPIO_MODER and the so is appropriate value for TIM1_CH1 in GPIO_AFR, and TIM1 clock is enabled in RCC and its CH1 is set to Input Capture from "it's own" pin in TIM1_CCMR1, then upon arrival of an edge (with polarity and "stability" given by respective fields in TIM1_CCER and TIM1_CCMR1), current value of TIM1_CNT is copied into TIM1_CCR1 and TIM1_SR.CC1IF is set (which in turn can trigger interrupt or DMA if respective CC1IE/CC1DE in TIM1_DIER is set).

The value in TIM1_CCR1 remains "continuously latched", until next such edge arrives.

JW
 

Online peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 4121
  • Country: gb
  • Doing electronics since the 1960s...
Thank you.

I have no idea how I got the idea that something (an ISR, or a DMA writing to a fixed RAM address) needs to capture the timer value. It is completely unnecessary - so long as the RTOS gets around to it before the next cycle, and even then it doesn't matter if a few values are lost, in the context of frequency/period measurement of a slowly changing input waveform.

Basically, you set up the timer and you have a dead simple frequency meter :)

Syncing the two outputs to the input is a separate thing. I was thinking of a simple way of feeding one of them (they will always be in sync, by writing both DACs with a 32 bit value), and the input waveform (squared-up) to a XOR gate, lowpass filter that, feed to an ADC, and when the measured DC is at minimum, you are in sync. A slick way is to use another timer to measure the time delay.
« Last Edit: November 19, 2021, 10:44:44 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Online peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 4121
  • Country: gb
  • Doing electronics since the 1960s...
I am having a bit of trouble with setting up TIM1 and wonder if anyone can spot anything obvious. This is the code

Code: [Select]
// Set up TIM1 for ~400Hz waveform period measurement, via PE9
static void KDE_config_TIM1_period_measure(void)
{
GPIO_InitTypeDef  GPIO_InitStruct;

__GPIOE_CLK_ENABLE(); // already enabled in switch init but never mind
GPIO_InitStruct.Pin  = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP; // PE9 = pullup because comparator driving it is open drain o/p
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

// Set up TIM1 to count up and on PE9 +ve edge transfer the count to CCR and reload with 0
__HAL_RCC_TIM1_CLK_ENABLE(); // TIM1EN=1 in RCC2ENR and does a short delay

TIM1->CR1 = 0; // TIM1 upcounter, counter disabled for now

TIM1->ARR = 0xffff; // auto reload (0 does not work, even if up-counting)

TIM1->PSC = 3; // prescaler=4, for 10.5MHz counter speed

TIM1->CCMR1 = (1 << 4) // IC1F: input filter = 2
|(0 << 2) // IC1PSC: input prescaler off
|(1 << 0); // CC1S: channel is input

TIM1->CCER = (0 << 3) // CC1NP: CC1 rising edge capture
    |(0 << 2) // CC1NE: oc1n not active
|(0 << 1) // CC1P: rising edge capture
|(1 << 0); // CC1E: enable CC1 capture

TIM1->CNT = 0;
TIM1->CR2 = 0; // TI1S=0 - TIM1_CH1 pin is connected to TI1 input
TIM1->RCR = 0;
TIM1->SMCR = 0; // slave mode disabled
TIM1->DIER = 0; // interrupts disabled

TIM1->CR1 = (1 << 0); // CEN=1 - enable TIM1

}

and this outputs varying CNT but 0 all the time for CCR1 (with a 400Hz 0 to +3.3V input on PE9)

Code: [Select]
// Loop for ever, yielding to RTOS when nothing to do
while (1)
{
uint16_t cnt = TIM1->CNT;
uint16_t ccr1 = TIM1->CCR1;
debug_thread_printf("===== TIM1 = %5u %5u", cnt, ccr1);

osDelay(1000);
}

TIM1 values, after stepping through above code, are



(except ARR=0xffff now)

Funnily enough, in my efforts to split up this project to get it done faster, I paid someone freelance to write this code, and I believe he had it all working, but he did it on some development board, so the code is of no use to me except for reference. He used TIM5 for this (which I can't access because of no available pins) and this was his code

Code: [Select]
void timer5_init(void)
{
RCC->APB1ENR |= (1u << 3); // TIM 5 clock enable
TIM5->CR1 &= 0xfffe; // disable TIM4
TIM5->CCMR1 = (3u << 12) // filter = 8
|(0u << 10) // prescale off
|(1u << 8); // CC2 channel is input mapped to T12
TIM5->CCMR2 = (3u << 4) // filter = 8
|(0u << 2) // prescale off
|1u; // CC3 channel is input mapped to T13
TIM5->CCER = (0u << 7) // CC2 rising edge capture
    |(0u << 6) // reserved keep at 0
|(0u << 5) // CC2 rising edge capture 2nd bit
|(1u << 4) // enable CC2 capture
|(0u << 11) // CC2 rising edge capture
|(0u << 10) // reserved keep at 0
|(0u << 9) // CC2 rising edge capture 2nd bit
|(1u << 8); // enable CC3 capture
TIM5->DIER = (1u << 10) // DMA enabled onCC2
|(1u << 11); // DMA enabled on CC3
TIM5->CNT = 0u;
TIM5->CR2 = 0u; // be sure CCDS = 0 so DMA requests on CC event

// set up GPIO so PA1 is TIM5 CH2 and PA2 is TIM5 CH3

GPIOA->MODER &= 0xffffffc3;
GPIOA->MODER |= 0x000a0028; // pins A1 and A2 to AF mode

GPIOA->AFR[0] &= 0xfffff00f; // set AF for TIM5 on both
GPIOA->AFR[0] |= 0x00000220;


tim5_dma_init();
}

Any tips much appreciated. I can confirm PE9 has a pullup now (earlier code sets it to a pulldown) so the pin config has clearly worked. There is also a HAL function for setting up the timer but it is quite complicated. It seems to be HAL_TIM_OC_Init and HAL_TIM_OC_ConfigChannel: to use the Timer to generate an  Output Compare signal. Of course I have googled for solutions; all online seem to use the HAL functions but as usual nobody posts how (or if) they solved it - typical online issue. I have worked through the timer section in the RM and through this: https://www.st.com/resource/en/application_note/dm00236305-generalpurpose-timer-cookbook-for-stm32-microcontrollers-stmicroelectronics.pdf

Post edited because I got the counter running, but not the compare feature.
« Last Edit: November 21, 2021, 10:06:43 am by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline wek

  • Frequent Contributor
  • **
  • Posts: 536
  • Country: sk
TIMx_ARR must not be 0.

JW
 

Online peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 4121
  • Country: gb
  • Doing electronics since the 1960s...
Yes - posts crossed - found that just this second :)

BTW PCLK1 & 2 are 42MHz, so a precaler of 3 (actually =4) should give a reasonable count with a 400Hz input.
« Last Edit: November 21, 2021, 10:19:23 am by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf