Ya que tanto hablamos de evitar el uso de los indeseables delays, aunque particularmente creo que en ciertas ocasiones solucionan el problema fácilmente si el proyecto lo permite, les traigo un problema.
Resumiendo: el amigo locodelafonola me envío un mensaje pidiendo ayuda de como podría evitar el uso de delays en una cierta librería usando un timer para evitar que su proyecto no se vea afectado (en su caso, los delays si importan).
La librería, pensada para manejar un displays 7 segmentos a partir de un I2C usando el integrado TM1637 con un Atmega 328p, es la siguiente:
- tm1637.h:
	
	
	
		
- tm1637.c:
	
	
	
		
Y un ejemplo de su uso sería el siguiente:
	
	
	
		
Se puede ver que la librería está plagada de delays, llegué a contar aproximadamente 90 y pico de delays por cada llamada a la función "TM1637_display_digit".
La solución sencilla sería usar un RTOS, pero no estoy seguro hasta donde le daría al uC agregar uno externo (ej. FreeRTOS) ni tampoco sería conveniente complicar demasiado el proyecto de locodelafonola (que ya es extenso de por si). ¿Cómo lo resolverían uds?
. Lo primero que se destaca es que la librería realiza la comunicación I2C por soft y no aprovecha el I2C por hard que tiene el uC.
				
			Resumiendo: el amigo locodelafonola me envío un mensaje pidiendo ayuda de como podría evitar el uso de delays en una cierta librería usando un timer para evitar que su proyecto no se vea afectado (en su caso, los delays si importan).
La librería, pensada para manejar un displays 7 segmentos a partir de un I2C usando el integrado TM1637 con un Atmega 328p, es la siguiente:
- tm1637.h:
		Código:
	
	/**
* Copyright (c) 2017, Åukasz Marcin Podkalicki <lpodkalicki@gmail.com>
*
* This is ATtiny13/25/45/85 library for 4-Digit LED Display based on TM1637 chip.
*
* Features:
* - display digits
* - display colon
* - display raw segments
* - display on/off
* - brightness control
*
* References:
* - library: https://github.com/lpodkalicki/attiny-tm1637-library
* - documentation: https://github.com/lpodkalicki/attiny-tm1637-library/README.md
* - TM1637 datasheet: https://github.com/lpodkalicki/attiny-tm1637-library/blob/master/docs/TM1637_V2.4_EN.pdf
*/
#ifndef    _TM1637_H_
#define    _TM1637_H_
#include <avr/pgmspace.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <avr/io.h>
// Main Settings
#define    TM1637_DIO_PIN                PB1
#define    TM1637_CLK_PIN                PB2
#define    TM1637_DELAY_US                (50)
#define    TM1637_DEFAULT_BRIGHTNESS    (7)
// TM1637 commands
#define    TM1637_CMD_SET_DATA            0x40
#define    TM1637_CMD_SET_ADDR            0xC0
#define    TM1637_CMD_SET_DSIPLAY        0x80
// TM1637 data settings (use bitwise OR to contruct complete command)
#define    TM1637_SET_DATA_WRITE        0x00 // write data to the display register
#define    TM1637_SET_DATA_READ        0x02 // read the key scan data
#define    TM1637_SET_DATA_A_ADDR        0x00 // automatic address increment
#define    TM1637_SET_DATA_F_ADDR        0x04 // fixed address
#define    TM1637_SET_DATA_M_NORM        0x00 // normal mode
#define    TM1637_SET_DATA_M_TEST        0x10 // test mode
// TM1637 address settings (use bitwise OR to contruct complete command)
#define    TM1637_SET_ADR_00H            0x00 // address 00
#define    TM1637_SET_ADR_01H            0x01 // address 01
#define    TM1637_SET_ADR_02H            0x02 // address 02
#define    TM1637_SET_ADR_03H            0x03 // address 03
#define    TM1637_SET_ADR_04H            0x04 // address 04
// TM1637 display control command set (use bitwise OR to consruct complete command)
#define    TM1637_SET_DISPLAY_OFF        0x00 // off
#define    TM1637_SET_DISPLAY_ON        0x08 // on
/**
* Initialize TM1637 display driver.
* Clock pin (TM1637_CLK_PIN) and data pin (TM1637_DIO_PIN)
* are defined at the top of this file.
*/
void TM1637_init(void);
/**
* Display digits ('0'..'9') at positions (0x00..0x03)
*/
void TM1637_display_digit(const uint8_t addr, const uint8_t digit);
/**
* Display raw segments at positions (0x00..0x03)
*
*      bits:                 hex:
*        -- 0 --               -- 01 --
*       |       |             |        |
*       5       1            20        02
*       |       |             |        |
*        -- 6 --               -- 40 --
*       |       |             |        |
*       4       2            10        04
*       |       |             |        |
*        -- 3 --               -- 08 --
*
* Example segment configurations:
* - for character 'H', segments=0b01110110
* - for character '-', segments=0b01000000
* - etc.
*/
void TM1637_display_segments(const uint8_t addr, const uint8_t segments);
/**
* Display colon on/off.
*/
void TM1637_display_colon(bool value);
/**
* Clear all display segments (including colon).
*/
void TM1637_clear(void);
/**
* Set display brightness.
* Min brightness: 0
* Max brightness: 7
*/
void TM1637_set_brightness(const uint8_t brightness);
/**
* Turn display on/off.
*/
void TM1637_enable(const bool value);
#endif    /* !_ATTINY_TM1637_H_ */- tm1637.c:
		C:
	
	/**
* Marcin Podkalicki <lpodkalicki@gmail.com>
*
* This is ATtiny13/25/45/85 library for 4-Digit LED Display based on TM1637 chip.
*
* Features:
* - display digits
* - display colon
* - display raw segments
* - display on/off
* - brightness control
*
* References:
* - library: https://github.com/lpodkalicki/attiny-tm1637-library
* - documentation: https://github.com/lpodkalicki/attiny-tm1637-library/README.md
* - TM1637 datasheet: https://github.com/lpodkalicki/attiny-tm1637-library/blob/master/docs/TM1637_V2.4_EN.pdf
*/
#include <stdlib.h>
#include <avr/pgmspace.h>
#include <avr/io.h>
#include <util/delay.h>
#include "tm1637.h"
#define    TM1637_DIO_HIGH()        (PORTB |= _BV(TM1637_DIO_PIN))
#define    TM1637_DIO_LOW()        (PORTB &= ~_BV(TM1637_DIO_PIN))
#define    TM1637_DIO_OUTPUT()        (DDRB |= _BV(TM1637_DIO_PIN))
#define    TM1637_DIO_INPUT()        (DDRB &= ~_BV(TM1637_DIO_PIN))
#define    TM1637_DIO_READ()         (((PINB & _BV(TM1637_DIO_PIN)) > 0) ? 1 : 0)
#define    TM1637_CLK_HIGH()        (PORTB |= _BV(TM1637_CLK_PIN))
#define    TM1637_CLK_LOW()        (PORTB &= ~_BV(TM1637_CLK_PIN))
#define    TM1637_FLAG_ENABLED        (1 << 0)
#define    TM1637_FLAG_SHOWCOLON    (1 << 1)
static void TM1637_configure(void);
static void TM1637_cmd(uint8_t value);
static void TM1637_start(void);
static void TM1637_stop(void);
static uint8_t TM1637_write_byte(uint8_t value);
static const uint8_t _digit2segments[] =
{
//    0x5E, // D
//    0x55, // M
//    0x76, // X
//    0x00, // blank
//    0x77, // a
//    0x5E, // d
//    0x50, // r
//    0x79, // e
//    0x6D, // s
//    0x6D, // s
//    0x00, // blank
    0x3F, // 0
    0x06, // 1
    0x5B, // 2
    0x4F, // 3
    0x66, // 4
    0x6D, // 5
    0x7D, // 6
    0x07, // 7
    0x7F, // 8
    0x6F  // 9
};
static uint8_t _brightness = TM1637_DEFAULT_BRIGHTNESS;
static uint8_t _digit = 0xff;
static uint8_t _flags = 0x00;
void
TM1637_init(void)
{
    DDRB |= (_BV(TM1637_DIO_PIN)|_BV(TM1637_CLK_PIN));
    PORTB &= ~(_BV(TM1637_DIO_PIN)|_BV(TM1637_CLK_PIN));
    _flags |= TM1637_FLAG_ENABLED;
    TM1637_clear();
}
void
TM1637_display_digit(const uint8_t addr, const uint8_t digit)
{
    uint8_t segments = digit < 10 ? _digit2segments[digit] : 0x00;
    if (addr == TM1637_SET_ADR_01H) {
        _digit = digit;
        if (_flags & TM1637_FLAG_SHOWCOLON) {
            segments |= 0x80;
        }
    }
    TM1637_display_segments(addr, segments);
}
void
TM1637_display_segments(const uint8_t addr, const uint8_t segments)
{
    TM1637_cmd(TM1637_CMD_SET_DATA | TM1637_SET_DATA_F_ADDR);
    TM1637_start();
    TM1637_write_byte(TM1637_CMD_SET_ADDR | addr);
    TM1637_write_byte(segments);
    TM1637_stop(); 
    TM1637_configure(); 
}
void
TM1637_display_colon(bool value)
{
    if (value) {
        _flags |= TM1637_FLAG_SHOWCOLON;
    } else {
        _flags &= ~TM1637_FLAG_SHOWCOLON;
    }
    TM1637_display_digit(TM1637_SET_ADR_01H, _digit);
}
void
TM1637_clear(void)
{ 
    TM1637_display_colon(false);
    TM1637_display_segments(TM1637_SET_ADR_00H, 0x00);
    TM1637_display_segments(TM1637_SET_ADR_01H, 0x00);
    TM1637_display_segments(TM1637_SET_ADR_02H, 0x00);
    TM1637_display_segments(TM1637_SET_ADR_03H, 0x00);
    TM1637_display_segments(TM1637_SET_ADR_04H, 0x00);
}
void
TM1637_set_brightness(const uint8_t brightness)
{
    _brightness = brightness & 0x07;
    TM1637_configure();
}
void
TM1637_enable(bool value)
{
    if (value) {
        _flags |= TM1637_FLAG_ENABLED;
    } else {
        _flags &= ~TM1637_FLAG_ENABLED;
    }
    TM1637_configure();
}
void
TM1637_configure(void)
{
    uint8_t cmd;
    cmd = TM1637_CMD_SET_DSIPLAY;
    cmd |= _brightness;
    if (_flags & TM1637_FLAG_ENABLED) {
        cmd |= TM1637_SET_DISPLAY_ON;
    }
    TM1637_cmd(cmd);
}
void
TM1637_cmd(uint8_t value)
{
    TM1637_start();
    TM1637_write_byte(value);
    TM1637_stop();
}
void
TM1637_start(void)
{
    TM1637_DIO_HIGH();
    TM1637_CLK_HIGH();
    _delay_us(TM1637_DELAY_US);
    TM1637_DIO_LOW();
}
void
TM1637_stop(void)
{
    TM1637_CLK_LOW();
    _delay_us(TM1637_DELAY_US);
    TM1637_DIO_LOW();
    _delay_us(TM1637_DELAY_US);
    TM1637_CLK_HIGH();
    _delay_us(TM1637_DELAY_US);
    TM1637_DIO_HIGH();
}
uint8_t
TM1637_write_byte(uint8_t value)
{
    uint8_t i, ack;
    for (i = 0; i < 8; ++i, value >>= 1) {
        TM1637_CLK_LOW();
        _delay_us(TM1637_DELAY_US);
        if (value & 0x01) {
            TM1637_DIO_HIGH();
        } else {
            TM1637_DIO_LOW();
        }
        TM1637_CLK_HIGH();
        _delay_us(TM1637_DELAY_US);
    }
    TM1637_CLK_LOW();
    TM1637_DIO_INPUT();
    TM1637_DIO_HIGH();
    _delay_us(TM1637_DELAY_US);
    ack = TM1637_DIO_READ();
    if (ack) {
        TM1637_DIO_OUTPUT();
        TM1637_DIO_LOW();
    }
    _delay_us(TM1637_DELAY_US);
    TM1637_CLK_HIGH();
    _delay_us(TM1637_DELAY_US);
    TM1637_CLK_LOW();
    _delay_us(TM1637_DELAY_US);
    TM1637_DIO_OUTPUT();
    return ack;
}Y un ejemplo de su uso sería el siguiente:
		C:
	
	/**
* Copyright (c) 2017, Åukasz Marcin Podkalicki <lpodkalicki@gmail.com>
*
* This is ATtiny13 "Running Digits" example using attiny-tm1637-library,
* https://github.com/lpodkalicki/attiny-tm1637-library .
*
*/
#include <stdlib.h>
#include <avr/pgmspace.h>
#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
#include "tm1637.h"
#define F_CPU 16000000UL  // 16 MHz
int main(void)
{
    uint8_t i = 0;
    /* setup */
    TM1637_init();
    /* loop */
    while (1) {
        TM1637_display_digit(TM1637_SET_ADR_00H, i % 0x10);
        TM1637_display_digit(TM1637_SET_ADR_01H, (i + 1) % 0x10);
        TM1637_display_digit(TM1637_SET_ADR_02H, (i + 2) % 0x10);
        TM1637_display_digit(TM1637_SET_ADR_03H, (i + 3) % 0x10);
        TM1637_display_digit(TM1637_SET_ADR_04H, (i + 4) % 0x10);
    //    TM1637_display_digit(TM1637_SET_ADR_05H, (i + 5) % 0x10);
    //    TM1637_display_colon(true);
        _delay_ms(200);
        TM1637_display_colon(false);
        _delay_ms(200);
        i++;
    }
}Se puede ver que la librería está plagada de delays, llegué a contar aproximadamente 90 y pico de delays por cada llamada a la función "TM1637_display_digit".
La solución sencilla sería usar un RTOS, pero no estoy seguro hasta donde le daría al uC agregar uno externo (ej. FreeRTOS) ni tampoco sería conveniente complicar demasiado el proyecto de locodelafonola (que ya es extenso de por si). ¿Cómo lo resolverían uds?
. Lo primero que se destaca es que la librería realiza la comunicación I2C por soft y no aprovecha el I2C por hard que tiene el uC.
 
   
				 
						 
 
		 
 
		 
 
		

 
 
		 
 
		



 
 
		 
 
		 
 
		