Приветствую всех ценителей. Добрый день. Я постараюсь запрограммировать AVR ATMega328. Я использую следующие библиотеки: bme280 avr-st7735
Подпрограмма для таймера от здесь
Я хочу каждые две секунды чтобы получить данные BME280, и я хочу использовать TIMER1 и переполнение, см. код. Я прочитал датчик как обработчик прерываний. Используйте пользовательскую реализацию очереди FIFO. В операции прерывания данные извлекаются в очередь FIFO. Наконец, я попытаюсь прочитать FIFO в основном l oop.
Код:
main. cpp
#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <util/delay.h>
extern "C" {
#include "spi.h"
#include "st7735.h"
#include "st7735_gfx.h"
#include "st7735_font.h"
#include "bme280/bme280.h"
#include <i2c/i2c_master.h>
#include "ftoa/ftoa.h"
}
#include <fifo.hpp>
#include "millis/millis.h"
#include "Utils/avr.hpp"
fifo_struct<float> fifo;
void showVisual()
{
// Just toggle led diode state
}
// global variable to count the number of overflows
volatile uint8_t tot_overflow;
// initialize timer, interrupt and variable
void timer1_init()
{
// set up timer with prescaler = 8
TCCR1B |= (1 << CS11);
// initialize counter
TCNT1 = 0;
// enable overflow interrupt
TIMSK1 |= (1 << TOIE1);
// initialize overflow counter variable
tot_overflow = 0;
}
// TIMER1 overflow interrupt service routine
// called whenever TCNT1 overflows
ISR(TIMER1_OVF_vect)
{
// keep a track of number of overflows
tot_overflow++;
// check for number of overflows here itself
// 61 overflows = 2 seconds delay (approx.)
if (tot_overflow >= 61) // NOTE: '>=' used instead of '=='
{
{
// Get data
float data = 5.5f; //bme280_readTemperature();
// Push to FIFO
fifo_push<float>(&fifo, data); // TODO: Not in the effect! Why?
}
showVisual(); // blink with led
// no timer reset required here as the timer
// is reset every time it overflows
tot_overflow = 0; // reset overflow counter
}
}
extern "C" int main(void)
{
// Init millis
clock_init();
// Init SPI and TFT
spi_init();
st7735_init();
st7735_set_orientation(ST7735_LANDSCAPE_INV);
st7735_fill_rect(0, 0, 128, 128, ST7735_COLOR_BLACK);
// Initialize PWM
// Fast PWM with MAX
TCCR0A |= (1 << WGM01) | (1 << WGM00);
// Mode output
// Noninvert for OC0A
TCCR0A |= (1 << COM0A1);
// Divider to 64
TCCR0B |= (1 << CS01) | (1 << CS00);
// Set pwm to 200/255
OCR0A = 200;
// Initialize I2C and BME280
i2c_init();
fifo = fifo_create<float>(5);
if (!bme_init())
{
// Error!!
}
// initialize timer
timer1_init();
// Enable global interrupts
sei();
wdt_enable(WDTO_2S);
while (1)
{
float val = fifo_pop<float>(&fifo);
uart_puts(val); // Printed 0.0
uart_puts(fifo_count<float>(&fifo)); // Allways print 0!
wdt_reset();
}
}
fifo.h
/**
* This file is a part of FIFO implementation in C/C++
*
* fifo.h
*
* Created on: 14. 1. 2020
* Author: Denis Colesnicov
* Licence: WTFPL
* Version: 4
*/
#ifndef FIFO_HPP_
#define FIFO_HPP_
#include <stdint.h>
/**
* Struktura udrzujici informace pro frontu
*/
template<typename T> struct fifo_struct
{
volatile uint8_t top; /*<! Ukazatel na vrchol zasobniku (na jakou pozici byl vlozen posledni prvek) */
volatile T *data; /*<! Pole s ulozenymi prvkz */
uint8_t size; /*<! Rezervovana velikost fronty */
};
/**
* Vytvori novou frontu
*
* @note Pro fifo_struct::data je pouzita f-ce calloc(...),
* musi se pouZit funkce free(..) pro uvolneni!
* @param _size Kolik ma obsahovat prvku
* @return Vraci frontu
*/
template<typename T> fifo_struct<T> fifo_create(uint8_t _size);
/**
* Kolik prvku je ve fronte
*
* @param _fifo Fronta
* @return Pocet prvku ve fronte
*/
template<typename T> uint8_t fifo_count(fifo_struct<T> *_fifo);
/**
* Pro kolik prvku je rezervovana fronta (maximalni pocet prvku ve fronte)
*
* @param _fifo Fronta
* @return Pocet rezervovanych "mist"
*/
template<typename T> uint8_t fifo_size(fifo_struct<T> *_fifo);
/**
* Odstrani z fronty vsechny ulozene prvky a vynuluje ji.
*
* @note Frontu jiz nadale nebude mozne pouzivat!
* @param _fifo Fronta
*/
template<typename T> void fifo_destroy(fifo_struct<T> *_fifo);
/**
* Vlozi prvek na konec fronty
*
* @param _fifo Fronta
* @param _data Data ke vlozeni
*/
template<typename T> void fifo_push(fifo_struct<T> *_fifo, T _data);
/**
* Vrati data ktera jsou na zacatku fronty.
*
* @note Data zustanou ve fronte (ne odstranuje ziskana data!)
* @param _fifo Fronta
* @return Data
*/
template<typename T> T fifo_first(fifo_struct<T> *_fifo);
/**
* Vrati data ktera jsou na konci fronty.
*
* @note Data zustanou ve fronte (ne odstranuje ziskana data!)
* @param _fifo Fronta
* @return Data
*/
template<typename T> T fifo_last(fifo_struct<T> *_fifo);
/**
* Zredukuje velikost fronty o zadany pocet pozic
* Posune obsah fronty do leva o zadany pocet pozic.
* Data ktera byla na zacatku fronty budou odstranene!
*
* @param _fifo Fronta
* @param _count Pocet pozic k posunu
*/
template<typename T> void fifo_reduce(fifo_struct<T> *_fifo, uint8_t _count);
/**
* Vrati data ze zacatku fronty.
*
* @note Tim dojde k odstraneni techto dat a zredukovani pole.
* @see fifo_reduce(...)
* @param _fifo Fronta
* @return Data
*/
template<typename T> T fifo_pop(fifo_struct<T> *_fifo);
/**
* Trida usnadnujici praci s FIFO frontou
*/
template<typename T>
class Fifo
{
public:
/**
* Vytvori novou frontu
*
* @param _size Kolik ma obsahovat prvku
*/
Fifo(uint8_t _size);
/**
* Odstrani z fronty vsechny ulozene prvky a vynuluje ji.
*
* @note Frontu jiz nadale nebude mozne pouzivat!
* @param _fifo Fronta
*/
~Fifo();
/**
* Vrati data ktera jsou na zacatku fronty.
*
* @note Data zustanou ve fronte (ne odstranuje ziskana data!)
* @param _fifo Fronta
* @return Data
*/
T first();
/**
* Vrati data ktera jsou na konci fronty.
*
* @note Data zustanou ve fronte (ne odstranuje ziskana data!)
* @param _fifo Fronta
* @return Data
*/
T last();
/**
* Kolik prvku je ve fronte
*
* @return Pocet prvku ve fronte
*/
uint8_t count();
/**
* Pro kolik prvku je rezervovana fronta (maximalni pocet prvku ve fronte)
*
* @return Pocet rezervovanych "mist"
*/
uint8_t size();
/**
* Vrati data ze zacatku fronty.
*
* @note Tim dojde k odstraneni techto dat a zredukovani pole.
* @see fifo_reduce(...)
* @return Data
*/
T pop();
/**
* Vlozi prvek na konec fronty
*
* @param _fifo Fronta
* @param _data Data ke vlozeni
*/
void push(T _data);
/**
* Zredukuje velikost fronty o zadany pocet pozic
* Posune obsah fronty do leva o zadany pocet pozic.
* Data ktera byla na zacatku fronty budou odstranene!
*
* @param _count Pocet pozic k posunu
*/
void reduce(uint8_t _count);
private:
fifo_struct<T> m_fifo; /*<! Fronta (FIFO) */
};
#include <stdlib.h>
template<typename T> fifo_struct<T> fifo_create(uint8_t _size)
{
fifo_struct<T> fifo;
fifo.top = 0;
fifo.size = _size;
fifo.data = (T*) calloc(_size, sizeof(T));
return fifo;
}
template<typename T> uint8_t fifo_count(fifo_struct<T> *_fifo)
{
return (uint8_t) _fifo->top;
}
template<typename T> uint8_t fifo_size(fifo_struct<T> *_fifo)
{
return (uint8_t) _fifo->size;
}
template<typename T> void fifo_destroy(fifo_struct<T> *_fifo)
{
_fifo->size = 0;
_fifo->top = 0;
free(_fifo->data);
}
template<typename T> void fifo_push(fifo_struct<T> *_fifo, T _data)
{
if (_fifo->size == _fifo->top)
{
fifo_reduce<T>(_fifo, 1);
}
_fifo->data[_fifo->top] = _data;
_fifo->top++;
}
template<typename T> T fifo_pop(fifo_struct<T> *_fifo)
{
if (_fifo->top == 0)
{
return (T) NULL;
}
T data = _fifo->data[0];
fifo_reduce<T>(_fifo, 1);
return data;
}
template<typename T> T fifo_first(fifo_struct<T> *_fifo)
{
if (_fifo->top == 0)
{
return (T) NULL;
}
return _fifo->data[0];
}
template<typename T> T fifo_last(fifo_struct<T> *_fifo)
{
if (_fifo->top == 0)
{
return (T) NULL;
}
return _fifo->data[_fifo->top - 1];
}
template<typename T> void fifo_reduce(fifo_struct<T> *_fifo, uint8_t _count)
{
for (uint8_t i = 0; i < _fifo->size; i++)
{
_fifo->data[i] = _fifo->data[_count + i];
}
_fifo->top -= _count;
}
template<typename T>
Fifo<T>::Fifo(uint8_t _size)
{
m_fifo = fifo_create<T>(_size);
}
template<typename T>
Fifo<T>::~Fifo()
{
fifo_destroy<T>(&m_fifo);
}
template<typename T>
T Fifo<T>::first()
{
fifo_first<T>(m_fifo);
}
template<typename T>
T Fifo<T>::last()
{
fifo_last<T>(m_fifo);
}
template<typename T>
uint8_t Fifo<T>::count()
{
return fifo_count<T>(m_fifo);
}
template<typename T>
uint8_t Fifo<T>::size()
{
return fifo_size<T>(m_fifo);
}
template<typename T>
T Fifo<T>::pop()
{
return fifo_pop<T>(&m_fifo);
}
template<typename T>
void Fifo<T>::push(T _data)
{
fifo_push<T>(&m_fifo, _data);
}
template<typename T>
void Fifo<T>::reduce(uint8_t _count)
{
fifo_reduce<T>(&m_fifo, _count);
}
#endif /* FIFO_HPP_ */
milli.h
/*
* Project: Lightweight millisecond tracking library
* Author: Zak Kemble, contact@zakkemble.net
* Copyright: (C) 2018 by Zak Kemble
* License: GNU GPL v3 (see License_GPL-3.0.txt) or MIT (see License_MIT.txt)
* Web: http://blog.zakkemble.net/millisecond-tracking-library-for-avr/
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/power.h>
#include <util/atomic.h>
#ifdef __cplusplus
}
#endif
#include "millis.h"
#define CLOCK_SCALE_MICROS 0
#define CLOCK_SCALE_MILLIS 1
#define CLOCK_SCALE CLOCK_SCALE_MICROS
#define MILLIS_TIMER0 0 /**< Use timer0. */
#define MILLIS_TIMER1 1 /**< Use timer1. */
#define MILLIS_TIMER2 2 /**< Use timer2. */
#define MILLIS_TIMER MILLIS_TIMER0 /**< Which timer to use. */
#define MICROSECONDS_PER_TIMER0_OVERFLOW 16384
#define MILLIS_INC 1024
#define FRACT_INC ((1024 % 1000) >> 3)
#define FRACT_MAX (1000 >> 3)
#ifndef F_CPU
#error "F_CPU not defined!"
#endif
#if F_CPU < 256 || F_CPU >= 32640000
#error "Bad F_CPU setting (<256 or >=32640000)"
#endif
#ifndef MILLIS_TIMER
#error "Bad MILLIS_TIMER set"
#endif
// Decide what what prescaler and registers to use
#if MILLIS_TIMER == MILLIS_TIMER0
// Timer0
#if F_CPU > 16320000 // 16.32MHz - 65.28MHz
#define CLOCKSEL (_BV(CS20))
#define PRESCALER 256
#elif F_CPU > 2040000 // 2.04MHz - 16.32MHz
#define CLOCKSEL (_BV(CS01)|_BV(CS00))
#define PRESCALER 64
#elif F_CPU > 255 // 256Hz - 2.04MHz
#define CLOCKSEL (_BV(CS01))
#define PRESCALER 8
#endif
#define REG_TCCRA TCCR0A
#define REG_TCCRB TCCR0B
#define REG_TIMSK TIMSK0
#define REG_OCR OCR0A
#define BIT_WGM WGM01
#define BIT_OCIE OCIE0A
#ifdef TIMER0_COMPA_vect
#define ISR_VECT TIMER0_COMPA_vect
#else
#define ISR_VECT TIM0_COMPA_vect
#endif
#define pwr_enable() power_timer0_enable()
#define pwr_disable() power_timer0_disable()
#define SET_TCCRA() (REG_TCCRA |= _BV(BIT_WGM))
#define SET_TCCRB() (REG_TCCRB |= CLOCKSEL)
#elif MILLIS_TIMER == MILLIS_TIMER1
// Timer1
// 1KHz - 65.28MHz
#define CLOCKSEL (_BV(CS10))
#define PRESCALER 1
#define REG_TCCRA TCCR1A
#define REG_TCCRB TCCR1B
#define REG_TIMSK TIMSK1
#define REG_OCR OCR1A
#define BIT_WGM WGM12
#define BIT_OCIE OCIE1A
#ifdef TIMER1_COMPA_vect
#define ISR_VECT TIMER1_COMPA_vect
#else
#define ISR_VECT TIM1_COMPA_vect
#endif
#define pwr_enable() power_timer1_enable()
#define pwr_disable() power_timer1_disable()
#define SET_TCCRA() (REG_TCCRA |= 0)
#define SET_TCCRB() (REG_TCCRB |= _BV(BIT_WGM)|CLOCKSEL)
#elif MILLIS_TIMER == MILLIS_TIMER2
// Timer2
#if F_CPU > 16320000 // 16.32MHz - 32.64MHz
#define CLOCKSEL (_BV(CS22)|_BV(CS20))
#define PRESCALER 128
#elif F_CPU > 8160000 // 8.16MHz - 16.32MHz
#define CLOCKSEL (_BV(CS22))
#define PRESCALER 64
#elif F_CPU > 2040000 // 2.04MHz - 8.16MHz
#define CLOCKSEL (_BV(CS21)|_BV(CS20))
#define PRESCALER 32
#elif F_CPU > 255 // 256Hz - 2.04MHz
#define CLOCKSEL (_BV(CS21))
#define PRESCALER 8
#endif
#define REG_TCCRA TCCR2A
#define REG_TCCRB TCCR2B
#define REG_TIMSK TIMSK2
#define REG_OCR OCR2A
#define BIT_WGM WGM21
#define BIT_OCIE OCIE2A
#define ISR_VECT TIMER2_COMPA_vect
#define pwr_enable() power_timer2_enable()
#define pwr_disable() power_timer2_disable()
#define SET_TCCRA() (REG_TCCRA |= _BV(BIT_WGM))
#define SET_TCCRB() (REG_TCCRB |= CLOCKSEL)
#else
#error "Bad MILLIS_TIMER set"
#endif
static volatile millis_t timer_value;
// Initialise library
void clock_init()
{
// Timer settings
SET_TCCRA();
SET_TCCRB();
REG_TIMSK |= _BV(BIT_OCIE);
REG_OCR = ((F_CPU / PRESCALER) / 1000);
}
// Get current timer_value
millis_t clock_get()
{
millis_t ms;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
ms = timer_value;
}
return ms;
}
// Turn on timer and resume time keeping
void clock_resume()
{
pwr_enable();
REG_TIMSK |= _BV(BIT_OCIE);
}
// Pause time keeping and turn off timer to save power
void clock_pause()
{
REG_TIMSK &= ~_BV(BIT_OCIE);
pwr_disable();
}
// Reset microseconds count to 0
void clock_reset()
{
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
timer_value = 0;
}
}
// Add time
void clock_add(millis_t ms)
{
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
timer_value += ms;
}
}
// Subtract time
void clock_subtract(millis_t ms)
{
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
timer_value -= ms;
}
}
ISR(ISR_VECT)
{
static unsigned char timer_fract = 0;
#if CLOCK_SCALE == CLOCK_SCALE_MICROS
timer_value += MILLIS_INC;
timer_fract += FRACT_INC;
if (timer_fract >= FRACT_MAX)
{
timer_fract -= FRACT_MAX;
timer_value += 1;
}
#else
timer_value += 1;
timer_fract += 3;
if (timer_fract >= 125)
{
timer_fract -= 125;
timer_value += 1;
}
#endif // CLOCK_SCALE
}
Проблема: данные не сохраняются в FIFO. Вы видите, кто-то решает, пожалуйста ??