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.