atmega328 ctc mode timer - c++

So i wanted to make a timer on the atmega328p µC using the CTC Modus. The idea was, that every 10milliseconds when the interrupt function is called , in that function i schould increase a variable millisekunden by 10. and once it reaches 1000 it schould be printed out .
The datasheet can be found here: https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf With registers i can change the Mode to the CTC Mode and set up the right Prescaler on the timer.
It is a 16Mhz CPU. So the formula is : T_clock * Prescaler * OCR0A = time( unit is seconds)
So i calculated: (1/ 1610^6) * 1024 * x = 1010^-3(i wanted 10 milli seconds).
and x is then 155.
With the bits CS00 and CS02 i set up the prescaler to 1024. OCR0A was then set to 155 as the formula says. CTC mode was enabled by setting the BIT WGM01. And the last thing was that i increase the variable millisekunden in the interrupt function. For some reason it doesnt want to work. Can anyone pease help me?
#include "Arduino.h"
volatile unsigned long int millisekunden;
unsigned long int last_msg;
char buffer[128];
void setup() {
TCCR0A |= (1 << WGM01); // CTC Modus
TCCR0B |= (1 << CS02) | (1 << CS00); // Prescaler 1024
OCR0A = 155;
// Compare Interrupt
TIMSK0 |= (1 << OCIE0A);
Serial.begin(9600);
}
void loop() {
if (millisekunden - last_msg >= 1000) {
sprintf(buffer, "t=[%lu]", millisekunden);
Serial.println(buffer);
last_msg = millisekunden;
}
}
// Timer-Interrupt-Routine
ISR(TIMER0_COMPA_vect) {
millisekunden = millisekunden + 10;
}

You forgot to globally enable interrupts. Add sei() at the end of setup()

Related

How do I port C++ code to Esp8266 and Esp32 using interrupts from code written for older boards

I am trying to port some C++ Arduino code to more recent ESP8266 and ESP32 boards.
I have checked already the Arduino Stack Exchange forum unfortunately without results
Porting this C++ code from older Arduino to Esp8266/Esp32 does not work, I have added also the compiling errors at the bottom of this question:
/* rcTiming.ino -- JW, 30 November 2015 --
* Uses pin-change interrupts on A0-A4 to time RC pulses
*
* Ref: https://arduino.stackexchange.com/questions/18183/read-rc-receiver-channels-using-interrupt-instead-of-pulsein
*
*/
#include <Streaming.h>
static byte rcOld; // Prev. states of inputs
volatile unsigned long rcRises[4]; // times of prev. rising edges
volatile unsigned long rcTimes[4]; // recent pulse lengths
volatile unsigned int rcChange=0; // Change-counter
// Be sure to call setup_rcTiming() from setup()
void setup_rcTiming() {
rcOld = 0;
pinMode(A0, INPUT); // pin 14, A0, PC0, for pin-change interrupt
pinMode(A1, INPUT); // pin 15, A1, PC1, for pin-change interrupt
pinMode(A2, INPUT);
pinMode(A3, INPUT);
PCMSK1 |= 0x0F; // Four-bit mask for four channels
PCIFR |= 0x02; // clear pin-change interrupts if any
PCICR |= 0x02; // enable pin-change interrupts
}
// Define the service routine for PCI vector 1
ISR(PCINT1_vect) {
byte rcNew = PINC & 15; // Get low 4 bits, A0-A3
byte changes = rcNew^rcOld; // Notice changed bits
byte channel = 0;
unsigned long now = micros(); // micros() is ok in int routine
while (changes) {
if ((changes & 1)) { // Did current channel change?
if ((rcNew & (1<<channel))) { // Check rising edge
rcRises[channel] = now; // Is rising edge
} else { // Is falling edge
rcTimes[channel] = now-rcRises[channel];
}
}
changes >>= 1; // shift out the done bit
++channel;
++rcChange;
}
rcOld = rcNew; // Save new state
}
void setup() {
Serial.begin(115200);
Serial.println("Starting RC Timing Test");
setup_rcTiming();
}
void loop() {
unsigned long rcT[4]; // copy of recent pulse lengths
unsigned int rcN;
if (rcChange) {
// Data is subject to races if interrupted, so off interrupts
cli(); // Disable interrupts
rcN = rcChange;
rcChange = 0; // Zero the change counter
rcT[0] = rcTimes[0];
rcT[1] = rcTimes[1];
rcT[2] = rcTimes[2];
rcT[3] = rcTimes[3];
sei(); // reenable interrupts
Serial << "t=" << millis() << " " << rcT[0] << " " << rcT[1]
<< " " << rcT[2] << " " << rcT[3] << " " << rcN << endl;
}
sei(); // reenable interrupts
}
The compiling error is:
expected constructor, destructor, or type conversion before '(' token
at line:
ISR(PCINT1_vect) {
I am seeking suggestions to get it working thank you.
All ESP32 GPIO pins are interrupt-capable pins.
You can use interrupts, but in a different way.
attachInterrupt(GPIOPin, ISR, Mode);
Mode – Defines when the interrupt should be triggered. Five constants are predefined as valid values:HIGH, LOW, CHANGE, RISING, FALLING
void IRAM_ATTR ISR() {
Statements;
}
Interrupt service routines should have the IRAM_ATTR attribute, according to the ESP32 documentation

TIM6 , basic time generation function not working

I am trying to use TIM6 on STM32F103C8T6 to generate time and blink an led but the timer doesnt see to be working, what other parameters do i need to initialize in order to be able to use the timer ? code below ?
#include "stm32f10x.h"
int main(void)
{
RCC->APB1ENR |= 0x00000010 ; // CLOCK SIGNAL TO BASIC TIMER 6 IS INITIALIZED
RCC->APB2ENR |= 0x00000004 ; //CLOCK SIGNAL TO GPIO PORT A IS INITIALIZED
GPIOA->CRL |= 0x33333333 ; // LOWER PINS OF GPIO PORT A ARE DEFINED AS PUSH AND PULL OUTPUT
TIM6->CR1 |= 0x0081 ; // COUNTER AND AUTO RELOAD BUFFER ENABLED
TIM6->PSC |= 0x1F40 ; // PRESCALER SET AS 8000
TIM6->ARR |= 0x05DC ; // AUTO RELOAD REGISTER SET AT 1000
while(1)
{
if ( TIM6->CNT == 1000 )
{
GPIOA->BSRR |= 0X0044 ; //SET PINS 2 AND 6 OF GPIOA TO HIGH
}
if ( TIM6->CNT == 0x05DC )
{
GPIOA->BRR |= 0X0044 ; //SET PINS 2 AND 6 OF GPIOA TO HIGH
}
}
}
STM32F103C8T6 has only TIM1 - TIM4, so trying to use TIM6 is doomed to fail. See "Table 4. Timer feature comparison" in the datasheet (page 17).

How to delay a output about 15 minutes after pressing a button?

I am learning micro controller programming. I need help to complete my program at WinAVR with Atmega8L-8PU.
i have added 3 buttons, when the buttons pressed: first button will supply output for 15 minutes, 2nd one will 30 minutes and the last 3rd one will 45 minutes. after elapsing each time that should auto reset for the next press.
Here is my codes i have wrote but i cant added time duration. if anybody can make it it will be very helpful for me. Advance Thanks :).
#define numberofButtons 3
#include <avr/io.h>
#include"buttonpress.h"
int main(void)
{
DDRB = 0b00000000;
DDRD = 0b00000111;
PORTB = (1<<PINB0)|(1<<PINB1)|(1<<PINB2);
while(1)
{
if (buttonpressed(0, PINB, 0, 100))
{
PORTD ^= (1<<PIND0);
}
if (buttonpressed(1, PINB, 1, 100))
{
PORTD ^= (1<<PIND1);
}
if (buttonpressed(2, PINB, 2, 100))
{
PORTD ^= (1<<PIND2);
}
}
}
i have tried this way but it also not working........ :(
#define numberofButtons 3
#include"buttonpress.h"
#include <avr/io.h>
#include <avr/interrupt.h>
unsigned char seconds =0;
int minutes;
int main ()
{
DDRB = 0b00000000;
DDRD = 0b00000111;
PORTB = (1<<PINB0)|(1<<PINB1)|(1<<PINB2);
volatile int seconds;
DDRD |= (1<<PIND0)|(1<<PIND1)|(1<<PIND2);
TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode
TIMSK |= (1 << OCIE1A); // Enable CTC interrupt
sei(); // Enable global interrupts
OCR1A = 15624; // Set CTC compare value to 1Hz at 8MHz AVR clock, with a prescaler of 64
TCCR1B |= ((1 << CS10) | (1 << CS11)); // Start timer at Fcpu/64
while (1)
{
if(seconds==60)
{
minutes++;
seconds=0;
}
{
if (buttonpressed(0, PINB, 0, 100))
{
PORTD ^= (1<<PIND0);
int total_seconds=900;
while(total_seconds-seconds!=0)
{
//Delay of 15 min
}
}
} return 0;
}
}
ISR (TIMER1_COMPA_vect)
{
seconds++;
}
You can setup Timer0 to call interrupt each second for example. During each interrupt you have to increment internal counter. After elapsing required time (15, 30, 45 min) implement your own logic (Like shutdown desired port).
It very simple if you have functions to get a counter from the CPU, a counter that increases with a specific interval that can be calculated.
Then when the button is pressed, you set a variable to the current value of the counter plus the amount that corresponds to 15 minutes. And in the loop, you check the current value of the counter to the variable you set on key-press. When the current counter is equal or larger than the variable, then 15 minutes have passed.
Some pseudo-code
int main(void)
{
int eventHapening = 0;
while (1)
{
if (keypress)
{
eventHappening = currentCounter + 15 minutes;
}
// Check that eventHappening is non-zero to prevent false positives
if (eventHappening != 0 && currentCounter >= eventHappening)
{
// Do something
eventHappening = 0; // Reset, and disable event
}
}
}
If you have access to the header file time.h, then the following could be a solution:
#define numberofButtons 3
#include <avr/io.h>
#include<time.h>
#include"buttonpress.h"
void wait(double x)
{
clock_t begin, end;
double time_spent, limit=1000*60*x;
begin = clock();
while(time_spent<= limit)
{
end = clock();
time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
}
}
int main(void)
{
DDRB = 0b00000000;
DDRD = 0b00000111;
PORTB = (1<<PINB0)|(1<<PINB1)|(1<<PINB2);
while(1)
{
if (buttonpressed(0, PINB, 0, 100))
{
PORTD ^= (1<<PIND0);
wait(15);
}
if (buttonpressed(1, PINB, 1, 100))
{
PORTD ^= (1<<PIND1);
wait(15);
}
if (buttonpressed(2, PINB, 2, 100))
{
PORTD ^= (1<<PIND2);
wait(15);
}
}
}
Most probably the above code would not get any error. As the code have some dependencies I could successfully compile a similar program which is given below.
#define numberofButtons 3
#include <stdio.h>
#include<time.h>
void wait(double x)
{
clock_t begin, end;
double time_spent, limit=1000*60*x;
begin = clock();
while(time_spent<= limit)
{
end = clock();
time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
}
}
int main(void)
{
char c;
while((c = getchar())!='e')
{
if (c == 'a')
{
printf("I am in a! Come after 15 min!\n");
wait(15);
printf("WOW! How could you pass 15 min!!\n");
}
if (c == 'b')
{
printf("I am in b! Come after 15 min!\n");
wait(15);
printf("WOW! How could you pass 15 min!!\n");
}
if (c == 'c')
{
printf("I am in c! Come after 15 min!\n");
wait(15);
printf("WOW! How could you pass 15 min!!\n");
}
}
}
You can see here that it has no compilation error while compiling with c.
You didn't tag your question as AVR, which is why the existing answers are ignoring the fact that you have actual AVR timers.
More accurately, those timers are CPU cycle counters. TIMER1 in particular is a 16 bit counter. If you set the TCCR1 clock select bits to 101, this will count one tick every 1024 CPU cycles. Let's assume a 16 Mhz clock, that means 16000000 CPU cycles per second = 15625 ticks per second.
As TIMER1 is a 16 bit value, it overflows every 4.2 seconds. You can use this overflow to generate an interrupt. 900 seconds is just 214.6 interrupts - can you get away with 898 seconds? Of course, you could also count overflows of TIMER0. Since that's only 8 bits, you have 256 times as many overflows: 54931 in 900 seconds.

GPIO mode register

I've adjusted the example from here for the STM3240G-EVAL board in order to blink LEDs 3 and 4. I have it working, but am confused by the Mode register setting:
GPIOG->MODER |= (GPIO_MODER_MODER6_0 | GPIO_MODER_MODER8_0) ;
When I read the reference manual (p186), it claims that the mode must be set to 01 for output, yet setting it to 0 in this way works just fine. Ideally I'd like to be able to change to the other modes, but I would have assumed that the above code would have changed pins 6 and 8 of port G to input pins. I must be missing something.
Here's my complete main document in case it's relevant:
#include "stm32f4xx.h"
/* We will use PG6 and PG8 connected to LEDs 1 and 2 because they're the same port. */
/* Find base register value for Port G */
void delay (int a);
int main(void)
{
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f0xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f0xx.c file
*/
/* GPIOG Periph clock enable */
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOGEN;
GPIOG->MODER |= (GPIO_MODER_MODER6_0 | GPIO_MODER_MODER8_0) ;
/* Configure PG6 and PG8 in output mode */
GPIOG->OTYPER &= ~(GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_8) ;
// Ensure push pull mode selected--default
GPIOG->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR6|GPIO_OSPEEDER_OSPEEDR8);
//Ensure maximum speed setting (even though it is unnecessary)
GPIOG->PUPDR &= ~(GPIO_PUPDR_PUPDR6|GPIO_PUPDR_PUPDR8);
//Ensure all pull up pull down resistors are disabled
while (1)
{
/* Set PG6 and PG8 */
/* the bit set/reset low register SETS the output data register */
/* the bit set/reset high register RESETS the output data register */
GPIOG -> BSRRL = (1 << 6);
GPIOG -> BSRRL = (1 << 8);
delay(500000);
/* Reset PC8 and PC9 */
GPIOG -> BSRRH = (1 << 6);
GPIOG -> BSRRH = (1 << 8);
delay(500000);
}
return 0;
}
void delay (int a)
{
volatile int i,j;
for (i=0 ; i < a ; i++)
{
j++;
}
return;
}
You aren't setting it to zero, you're setting it to one.
The definition of the GPIO_MODER_MODER6_0 constant is 0x00001000. The mask for the GPIO_MODER_MODER6 bits is 0x00003000, so you're putting bits 01 into the right place.
If the constant GPIO_MODER_MODER6_0 were defined as zero, then or'ing it into the configuration register would have no effect in any case. To set both bits to zero you'd need to do something like:
GPIOG->MODER &= ~(GPIO_MODER_MODER6_0 | GPIO_MODER_MODER6_1);
The _0 and _1 suffixes refer to the bit numbers for masking, not the values being written.

Arduino Class Redefinition Error

In my Arduino IDE I have set up a program that runs eight LEDs through a shift register and now am trying to make a class to control the shift register. So far I have created the file and created a constructor with a few functions for the class, but when I try to verify the code the IDE says that I am redefining the class shiftreg here is the error message:
In file included from Lab9_step3.cpp:97:
shiftreg.h:2: error: redefinition of 'class shiftreg'
shiftreg.h:3: error: previous definition of 'class shiftreg'
and my code for lab_9 is:
/* ---------------------------------------------------------
* | Arduino Experimentation Kit Example Code |
* | CIRC-05 .: 8 More LEDs :. (74HC595 Shift Register) |
* ---------------------------------------------------------
*
* We have already controlled 8 LEDs however this does it in a slightly
* different manner. Rather than using 8 pins we will use just three
* and an additional chip.
*
*
*/
#include "shiftreg.h"
//Pin Definitions
//Pin Definitions
//The 74HC595 uses a serial communication
//link which has three pins
shiftreg a(2, 3, 4);
int sensorPin = 0; // select the input pin for the potentiometer
int sensorValue = 0; // variable to store the value coming from the sensor
/*
* setup() - this function runs once when you turn your Arduino on
* We set the three control pins to outputs
*/
void setup()
{
a.pinmode();
}
/*
* loop() - this function will start after setup finishes and then repeat
* we set which LEDs we want on then call a routine which sends the states to the 74HC595
*/
void loop() // run over and over again
{
for(int i = 0; i < 256; i++){
a.update(i);
// read the value from the sensor:
sensorValue = analogRead(sensorPin);
delay(sensorValue);
}
}
/******************************
/*
* updateLEDsLong() - sends the LED states set in ledStates to the 74HC595
* sequence. Same as updateLEDs except the shifting out is done in software
* so you can see what is happening.
*/
// void updateLEDsLong(int value){
// digitalWrite(latch, LOW); //Pulls the chips latch low
// for(int i = 0; i < 8; i++){ //Will repeat 8 times (once for each bit)
// int bit = value & B10000000; //We use a "bitmask" to select only the eighth
// //bit in our number (the one we are addressing this time thro
// //ugh
// value = value << 1; //we move our number up one bit value so next time bit 7 will
// // be
// //bit 8 and we will do our math on it
// if(bit == 128){digitalWrite(data, HIGH);} //if bit 8 is set then set our data pin high
// else{digitalWrite(data, LOW);} //if bit 8 is unset then set the data pin low
// digitalWrite(clock, HIGH); //the next three lines pulse the clock pin
// delay(1);
// digitalWrite(clock, LOW);
// }
// digitalWrite(latch, HIGH); //pulls the latch high shifting our data into being displayed
// }
//
//
// //These are used in the bitwise math that we use to change individual LEDs
// //For more details http://en.wikipedia.org/wiki/Bitwise_operation
// int bits[] = {B00000001, B00000010, B00000100, B00001000, B00010000, B00100000, B01000000, B10000000};
// int masks[] = {B11111110, B11111101, B11111011, B11110111, B11101111, B11011111, B10111111, B01111111};
// /*
// * changeLED(int led, int state) - changes an individual LED
// * LEDs are 0 to 7 and state is either 0 - OFF or 1 - ON
// */
// void changeLED(int led, int state){
// ledState = ledState & masks[led]; //clears ledState of the bit we are addressing
// if(state == ON){ledState = ledState | bits[led];} //if the bit is on we will add it to le
// //dState
// updateLEDs(ledState); //send the new LED state to the shift register
// }
// **********************************/
and my code for shiftreg.h is:
/*Shift Register
*/ (Error occurs here)
class shiftreg (and here)
{
private:
//Pin Definitions
//Pin Definitions
//The 74HC595 uses a serial communication
//link which has three pins
int data;
int clock;
int latch;
public:
shiftreg (int _data, int _clock, int _latch);
void update(int value);
void pinmode();
};
and my code for shiftreg.cpp is:
#include "shiftreg.h"
/*shiftreg constructor:
*/
shiftreg::shiftreg (int _data, int _clock, int _latch)
{
data = _data;
clock = _clock;
latch = _latch;
//Used for single LED manipulation
int ledState = 0;
const int ON = HIGH;
const int OFF = LOW;
}
/*
* updateLEDs() - sends the LED states set in ledStates to the 74HC595
* sequence
*/
void shiftreg::update(int value)
{
digitalWrite(latch, LOW); //Pulls the chips latch low
shiftOut(data, clock, MSBFIRST, value); //Shifts out the 8 bits to the shift register
digitalWrite(latch, HIGH); //Pulls the latch high displaying the data
}
/*
*/
void shiftreg::pinmode()
{
pinMode(data, OUTPUT);
pinMode(clock, OUTPUT);
pinMode(latch, OUTPUT);
}
Thanks for the help!
According to the error message you're including shiftreg.h on line 97 of Lab9_step3.cpp. What's on the 96 lines above that? The error probably lies somewhere in there.
If I had to guess, I'd say you're, either directly, or indirectly, including shiftreg.h twice (or more) in Lab9_step3.cpp, and the error's occurring because you don't have include guards in your header file.
Try adding the following to shiftreg.h
#ifndef SHIFTREG_H
#define SHIFTREG_H
class shiftreg
{
// ...
};
#endif