Timer/Counter2 on Nano - Don't understand scope significance in setting OCR2A

Using an Arduino Nano but wanting to develop in Studio 7.
I want to output a square wave on D11 which is OC2A. I am using CTC (mode 2) and just for this test example have selected a prescaler of /32.
I want to use Studio 7 to do the bulk of the development as I prefer the interface.
I include a sample of code that started as Arduino sketch but was imported into Studio 7 and also a piece of code written directly into Studio 7.
The raw Studio 7 code works as expected but I would love to use some of the Arduino libraries to aid debug such as SendOnlySoftwareSerial.
I have tried, without success, to manually import Arduino libraries into Studio 7 and keep coming back to the concept of importing an Arduino sketch with pre loaded libraries, into Studio 7.
The query code below was the result of such a sketch import.

I don't understand why setting OC2A in setup() has no affect on frequency. I need to set the value of OC2A in loop().
Something must be messing with TCCR2A and TCCR2B before I get to setup() as I also need to mask out the bits of interest. Something must also be changing OC2A after I set it in setup().
I thought the send serial or delay functions might be using Timer2 and changing it so I made sure to test these in code and commented out. That made no difference.
Could you explain what is happening behind the scenes.

Here is my sketch and query

// Description
/*
This code started as an Arduino sketch with the SendOnlySoftwareSerial library added.
It was then imported into Studio 7 as I like this environment.
I want to generate a waveform at D11 which is OC2A which means I need to use Timer/Counter2
I am using a Pololu ISP to load this via the ISP pins to my Arduino Nano

When I do this, the setting of OCR2A in setuo() has no affect on output frequency.
I had to mask out the bits in TCCR2A TCCR2B before setting them as desired.
I also made the code block atomic but I don't think that is relevant here.
I had to set the value of OCR2A in loop()

Compare this to other code snippet written directly in Studio 7 - 
What is affecting the timer (I also tried Timer/Counter0 with similar results)?

*/

#include <Arduino.h>
#include <SendOnlySoftwareSerial.h>

#define F_CPU 8000000		// External clock of 8MHz 
#include <avr/io.h>			// pulls in (most of) the register and register bit names

#include <util/delay.h>		// needed for the delay functions

// pin definition
#define TX PB3			// PB3 output (D11) (MOSI)	(OC2A) - rf
#define SER PD6			// PD6 output (D6)			(OCC0A) - debug

SendOnlySoftwareSerial mySerial(SER);								// Tx pin for serial debug output

void setup() {
	DDRB |= (1<<TX);												// defined as output pins
	DDRD |= (1<<SER);												// defined as output pins

	mySerial.begin(9600);
	mySerial.println(F("Starting"));
	
	uint8_t oldSREG = SREG;										// grab a copy of the current value of the system register
	cli();														// turn off interrupts	
	OCR2A = 0xDF; // if I try just to set OCR2A here  - whatever the value, I only ever get a 250kHz square wave on PB3 (D11)
	TCCR2A &= ~((1<<COM2A1)|(1<<COM2A0)|(1<<WGM21)|(1<<WGM20)); // I need to mask out the bits I want to clear or I get no output at all on PB3 - why is that?
	TCCR2A |=(0<<COM2A1)|(1<<COM2A0)|(1<<WGM21)|(0<<WGM20);		// toggle on compare match, CTC mode2
	TCCR2B &= ~((1<<WGM22)|(1<<CS22)|(1<<CS21)|(1<<CS20));		// I need to mask out the bits I want to clear - why is that?
	TCCR2B |= (0<<WGM22)|(0<<CS22)|(1<<CS21)|(1<<CS20);			//  prescaler /32
	SREG = oldSREG;												// enable interrupts if they were enabled before 
}

void loop() {
	OCR2A = 0xDF;			// with CS2[2:0] as 0x011, 0xDF generates 1.115kHz on PB3 (D11) - but why do I have to do this each loop?
	mySerial.print(F(".")); // commenting this out and all references to SendOnlySoftwareSerial has no effect on above frequency
	_delay_ms(100);			// commenting this out has no effect on above frequency
}

The next code sample is the raw Studio 7 code that works as expected

/*
 * GarageTXSkeleton.cpp
 *
 * Created: 16/02/2022 15:17:50
 * Author : Peter
 
 This code was written directly into Studio 7 but has no Arduino libraries
 */ 

#define F_CPU 8000000		// 
#include <avr/io.h>			// pulls in (most of) the register and register bit names
#include <util/delay.h>		// needed for the delay functions


// pin definition
#define TX PB3		// PB3 (D11) (MOSI)			(OC2A) rf

int main(void){
	DDRB |= (1<<TX); 
	OCR2A = 0xDF;	// with CS2[2:0] as 0x011, 0xDF generates 1.115kHz on PB3 (D11)
	// no need to mask out any bits before I set only the ones I want
	TCCR2A |= (0<<COM2A1)|(1<<COM2A0)|(1<<WGM21)|(0<<WGM20); // toggle on compare match, CTC mode2
	TCCR2B |= (0<<WGM22)|(0<<CS22)|(1<<CS21)|(1<<CS20);		//  prescaler /32

    while (1) 
    {
		_delay_ms(100);
    }
}

Just for reference, I wrote the same code into a brand new Arduino sketch and loaded this via Arduino as ISP. The result was the same in that I needed to set OCRA2 in loop() for its value to have any affect. Here is that sketch...

#include <SendOnlySoftwareSerial.h>

#define F_CPU 8000000    // External clock of 8MHz 
#include <avr/io.h>     // pulls in (most of) the register and register bit names
#include <util/delay.h>   // needed for the delay functions

// pin definition
#define TX PB3      // PB3 output (D11) (MOSI)  (OC2A) - rf
#define SER PD6     // PD6 output (D6)      (OCC0A) - debug

SendOnlySoftwareSerial mySerial(SER);                // Tx pin for serial debug output

void setup() {
  // put your setup code here, to run once:
  DDRB |= (1<<TX);                        // defined as output pins
  DDRD |= (1<<SER);                       // defined as output pins

  mySerial.begin(9600);
  mySerial.println(F("Starting"));
  
  uint8_t oldSREG = SREG;                   // grab a copy of the current value of the system register
  cli();                            // turn off interrupts  
  OCR2A = 0xDF; // if I try just to set OCR2A here  - whatever the value, I only ever get a 250kHz square wave on PB3 (D11)
  TCCR2A &= ~((1<<COM2A1)|(1<<COM2A0)|(1<<WGM21)|(1<<WGM20)); // I need to mask out the bits I want to clear or I get no output at all on PB3 - why is that?
  TCCR2A |=(0<<COM2A1)|(1<<COM2A0)|(1<<WGM21)|(0<<WGM20);   // toggle on compare match, CTC mode2
  TCCR2B &= ~((1<<WGM22)|(1<<CS22)|(1<<CS21)|(1<<CS20));    // I need to mask out the bits I want to clear - why is that?
  TCCR2B |= (0<<WGM22)|(0<<CS22)|(1<<CS21)|(1<<CS20);     //  prescaler /32
  SREG = oldSREG;         
}

void loop() {
  // put your main code here, to run repeatedly:
  OCR2A = 0xDF;     // with CS2[2:0] as 0x011, 0xDF generates 1.115kHz on PB3 (D11) - but why do I have to do this each loop?
  mySerial.print(F(".")); // commenting this out and all references to SendOnlySoftwareSerial has no effect on above frequency
  _delay_ms(100);     // commenting this out has no effect on above frequency
}

And then to bring me right back into Arduino land, I did a Burn Bootloader onto my Uno and used the on board USB port to Upload the same sketch. Sadly the same result.

To use Arduino libraries without using the Arduino 'main()' you need to do the initialization that is in the Arduino 'main()':

#include <Arduino.h>

// Declared weak in Arduino.h to allow user redefinitions.
int atexit(void (* /*func*/ )()) { return 0; }

// Weak empty variant initialization function.
// May be redefined by variant files.
void initVariant() __attribute__((weak));
void initVariant() { }

void setupUSB() __attribute__((weak));
void setupUSB() { }

int main(void)
{
	init();

	initVariant();

#if defined(USBCON)
	USBDevice.attach();
#endif
	
	setup();
    
	for (;;) {
		loop();
		if (serialEventRun) serialEventRun();
	}
        
	return 0;
}

Hi John
Many thanks, I'll certainly give this a go.

Hi John
I appreciate that this has probably been covered elsewhere but I am a 'nearly newbie'.
I looked at your suggestion to use Arduino libraries without the Arduino 'main()' but I was probably starting at the wrong place.
Are you able to aim me at a 'step by step' - starting with a 'Blinky' programme written in Studio 7 (example would be my GarageTXSkeleton.cpp above)?
What Arduino files do I need to copy where into Studio 7?
What steps do I need to do to - for example - to import the SendOnlySoftwareSerial library so that I can compile it successfully in Studio 7?
I have tried adding directories into the Project | Properties | Toolchain | AVR/GNU C++ Compiler section.
I have tried Add Library from the Solution Explorer but I seem to just go round in circles.

My most successful result was importing Arduino sketches with basic libraries into Studio 7 with ATtiny13a as the target processor but there are no 'supported' combinations that feature the ATting85 and I need this as I ran out of space on the ATiny13A.

I really would like to bypass the sketch import wizard so I can add just the Arduino libraries I want using the target MCU I want. I would be grateful for any help. Thanks.

Sorry. I don't use Studio 7. I just know that the Arduino runtime won't work if you don't initialize it and your Studio 7 program won't work after you initialize the Arduino runtime because it assumes the timer has not been initialized.

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