ATTiny1614 Timer B issue

I have a DrAzzy ATTiny1614 dev board running at 5V.

I'm attempting to setup TCB to have a approx 240Hz rate (~4.xx ms). I'm in the "Periodic Interrupt Mode" and expect the counter to reach a number initiate an interrupt and restart at 0. In my testing I changed to a CCMP of 16384 hoping to make the results easier for me to trouble shoot.

My issue is I can't calculate the actual results measured with a logic analyzer. I tested the analyzer with another instrument and it believe it to be accurate.

My results are way off the expected times.
I'm testing with 10Mhz and 8Mhz. The measured times change at a proportion that verifies a change of 10:8 in clock.

I think there is a prescaler that defaults to 8. Even if this is the case I can't reconcile this with my calculation.

Can anyone see my error?
Thanks
John

image

My code, be gentle I'm still learning the registers.

/*
 * ATTiny1614 Timer B test
 */

#include <avr/io.h>
#include <avr/interrupt.h>

#define PIN_LED_bp 7                  // PA7
#define PIN_LED_bm (1 << PIN_LED_bp)  // = 0b010000000
#define COMPARE 0x4000

int main(void) {
  // LED
  PORTA.DIRSET = PIN_LED_bm;  // _bm  is bit mask ??
  // or  PORTA.DIR |=0x80;

  // TCB0    By default, the TCB is in Periodic Interrupt mode.
  TCB0.CCMP = COMPARE;
  TCB0.INTCTRL = TCB_CAPT_bm;
  TCB0.CTRLA = 0x01;  //TCB_ENABLE_bm;  0x03 = 251 HZ 0x01 = 502.4 Hz

  sei();

  while (1) {
  }
}

volatile uint16_t count = 0;
ISR(TCB0_INT_vect) {
  TCB0.INTFLAGS |= TCB_CAPT_bm;  //clear the interrupt flag(to reset TCB0.CNT)

  if (PORTA.OUT & PIN_LED_bm) {
    PORTA.OUTCLR = PIN_LED_bm;
  } else {
    PORTA.OUTSET = PIN_LED_bm;
  }
}

Are you seeing different frequencies when compiling for different processor clock speeds?

O, now I see you don't set the CPU prescaler. Can you try include this function in your sketch?

Put this at the top of your 'main' function

  F_CPU_init ();   // reconfigure CPU clock prescaler

and put this somewhere at the bottom

void F_CPU_init () {
  // reconfigure CPU clock prescaler
#if (F_CPU == 20000000)
  /* No division on clock */
  _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0x00);
#elif (F_CPU == 16000000)
  /* No division on clock */
  _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0x00);
#elif (F_CPU == 10000000) // 20MHz prescaled by 2
  /* Clock DIV2 */
  _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_2X_gc));
#elif (F_CPU == 8000000) // 16MHz prescaled by 2
  /* Clock DIV2 */
  _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_2X_gc));
#elif (F_CPU == 5000000) // 20MHz prescaled by 4
  /* Clock DIV4 */
  _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_4X_gc));
#elif (F_CPU == 4000000) // 16MHz prescaled by 4
  /* Clock DIV4 */
  _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_4X_gc));
#elif (F_CPU == 1000000) // 16MHz prescaled by 16
  /* Clock DIV16 */
  _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_16X_gc));
#else
#ifndef F_CPU
#error "F_CPU not defined"
#else
#error "F_CPU defined as an unsupported value for untuned internal oscillator"
#endif
#endif
}

Thank you, I will try your suggestion.

I have been using the 10Mhz clock and the 8Mhz clock (set as you show in Post #2)
When testing with these two clock settings, the measured values change in a 10:8 proportion, as one would expect.

I was under the impression the MCLKCTRLB defaulted to the "reset" settings shown below.

That's also my impression. When not using Setup and Loop, you skip the Arduino core initialization and you have the MCU in reset condition as per the datasheet.

BTW, if you want a 250Hz interrupt, you can also do that with the RTC. Frees up TCB0 again and the RTC is running at it's own speed independent of any CPU clock speed.
It has a selectable 32KHz or 1KHz oscillator.
In below example sketch I set the PIT at 258Hz and the RTC at 250Hz.
for the PIT you can choose from 14 values (see comment) and for the RTC you let it count to a 16bit number, so that's way more flexible. Because of the 32KHz oscillator the RTC uses you cannot get high frequencies.

int main(void) {
  VPORTA_DIR |= PIN7_bm;   // set pin PA7 as output
  VPORTB_DIR |= PIN0_bm;   // set pin PB0 as output
  F_CPU_init ();   // reconfigure CPU clock prescaler

  //Configure clock source used by both PIT and RTC
  RTC_CLKSEL = RTC_CLKSEL_INT32K_gc; /* Internal 32kHz OSC */
  //RTC_CLKSEL = RTC_CLKSEL_INT1K_gc; /* Internal 1kHz OSC */

  //Configure RTC
  while (RTC_STATUS & RTC_PERBUSY_bm) {} // wait until RTC_PER is available for writing
  RTC_PER = 65; // write period (16bit) to period
  //  RTC_PER = 50000; // write period (16bit) to period
  RTC_INTCTRL |= RTC_OVF_bm; // activate overflow interrupts
  RTC_CTRLA |= RTC_RTCEN_bm; // turn on RTC

  //Configure PIT
  RTC_PITINTCTRL |= RTC_PI_bm;    // activate PIT Interrupt enable
  RTC_PITCTRLA   |= RTC_PERIOD_CYC64_gc | RTC_PITEN_bm;// set PIT period and enable
  //The Realtimer-Counter (RTC) have a own 32,768KHz Cristal.
  // 32.768KHz / CYCprescale = periodtime in mS
  //
  //  BIN         NAME        TIME
  // 0b00001001  CYC4        0,122 mS
  // 0b00011001  CYC8        0,244 mS
  // 0b00011001  CYC16       0,488 mS
  // 0b00100001  CYC32       0,977 mS
  // 0b00101001  CYC64       1,953 mS
  // 0b00110001  CYC128      3,906 mS
  // 0b00111001  CYC256      7,813 mS
  // 0b01000001  CYC512      15,63 mS
  // 0b01001001  CYC1024     31,25 mS
  // 0b01010001  CYC2048     62,50 mS
  // 0b01011001  CYC4096    125,00 mS
  // 0b01100001  CYC8192    250,00 mS
  // 0b01101001  CYC16384   500,00 mS
  // 0b01110001  CYC32768  1000,00 mS
  sei(); // turn on global interrupts

  while (1); // nothing to do here

}
ISR(RTC_PIT_vect) {             // RTC Interrupt
  RTC_PITINTFLAGS = RTC_PI_bm;  // clear  Interrupt Flag
  PORTA_OUTTGL = PIN7_bm;       // toggle Pin/A6
}

ISR(RTC_CNT_vect) {             // RTC Interrupt
  RTC_INTFLAGS = RTC_OVF_bm;    // clear  Interrupt Flag
  PORTB_OUTTGL = PIN0_bm;       // toggle Pin/B5
}

void F_CPU_init () {
  // reconfigure CPU clock prescaler
#if (F_CPU == 20000000)
  /* No division on clock */
  _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0x00);
#elif (F_CPU == 16000000)
  /* No division on clock */
  _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0x00);
#elif (F_CPU == 10000000) // 20MHz prescaled by 2
  /* Clock DIV2 */
  _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_2X_gc));
#elif (F_CPU == 8000000) // 16MHz prescaled by 2
  /* Clock DIV2 */
  _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_2X_gc));
#elif (F_CPU == 5000000) // 20MHz prescaled by 4
  /* Clock DIV4 */
  _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_4X_gc));
#elif (F_CPU == 4000000) // 16MHz prescaled by 4
  /* Clock DIV4 */
  _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_4X_gc));
#elif (F_CPU == 1000000) // 16MHz prescaled by 16
  /* Clock DIV16 */
  _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_16X_gc));
#else
#ifndef F_CPU
#error "F_CPU not defined"
#else
#error "F_CPU defined as an unsupported value for untuned internal oscillator"
#endif
#endif
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.