1 votos

ejemplos de gestión de memoria en C

¿Alguien puede recomendar un buen recurso/sitio web para EJEMPLOS de uso de memoria de pic en C? Estoy teniendo dificultades para seguir todo el tema de TBLPTR/TBLRD sin ver que se utiliza en un montón de diferentes, aplicaciones simples. Me sorprende lo difícil que es encontrar ejemplos claros y BÁSICOS de cómo manejar la memoria en los PIC.

Algo así como lo que haría un programa con los resultados del ADC, almacenando en una tabla, eligiendo ubicaciones de memoria, etc.

2voto

Mark Puntos 1998

Estás haciendo una pregunta muy amplia; hay una gran variedad de PICs, y probablemente no usaría la gestión de memoria "formal" para ninguno de ellos. No es necesario.

Los resultados de la conversión A/D, el filtrado, las memorias intermedias UART, etc., normalmente se almacenan en matrices simples en la memoria. Puedes aumentarlas con punteros de cabeza y cola para buffers de anillo o variables de índice u otros medios, pero tus técnicas típicas de manipulación de datos no son diferentes para un PIC de las que tendrías en un PC una vez que tienes la dirección del buffer. Con los pequeños microcontroladores embebidos simplemente declaras el array y lo utilizas.

Alternativamente, puede trabajar con el enlazador para reducir artificialmente la cantidad de memoria disponible que el sistema verá y luego utilizar las instrucciones de lectura/escritura de la tabla y/o los accesos de puntero estándar para llegar a esta memoria "oculta". Se reduce la memoria que el compilador puede utilizar para que la pila (que normalmente crece desde la parte superior de la memoria hacia abajo) no colisione con su área de almacenamiento, o la BSS y el heap (que normalmente se encuentran al principio de la memoria de datos) no interfieran con su área de memoria. El medio exacto para lograr esta magia del enlazador depende del conjunto de compiladores, por supuesto.

Si pudieras dar más detalles, quizás también una aplicación más específica, podría dar respuestas más concretas. Creo que tal vez estés sobreanalizando el tema. C es C; puedes declarar memoria arbitraria y usarla en un PC también, siempre y cuando no te enfrentes a la MMU.

editar para añadir un ejemplo de código de lectura y promediado del ADC:

Suelo escribir mi código de forma sencilla y clara; utilizo pequeñas funciones de propósito único y tiendo a escribir el código como máquinas de estado. También tiendo a dejar la optimización en manos del compilador, a menos que tenga una necesidad específica de optimizar a mano. Esto es el resultado de años (casi dos décadas) de diseño embebido y de aprender las cosas de la manera más difícil.

El código establece una interrupción del temporizador de 1ms, dos canales ADC y luego los muestrea continuamente; las lecturas se filtran utilizando un simple filtro de media deslizante. En este ejemplo, las muestras de datos de cada canal ADC no se almacenan individualmente. Cada canal tiene su propia suma en funcionamiento; los últimos 8 valores (la constante FILTER_POINTS) se promedian y se almacena este valor de conteo filtrado. Hay que tener cuidado de que la variable suma sea lo suficientemente grande como para almacenar el número que se puede crear si 8 muestras del ADC son a escala completa.

Por último, una temperatura en 1/10 de grado F, utilizando una función de conversión. La función de conversión, por supuesto, es específica para los sensores que estoy muestreando. Tu(s) propia(s) función(es) de conversión tendría(n) que ser escrita(s) para adaptarse a tus sensores.

Esto está escrito para ser usado con el compilador CCS; yo hago NO Me gusta este compilador por varias razones, pero es el que usan la mayoría de mis clientes porque su precio es el más bajo entre sus competidores.

#device PIC24F32KA304 ADC=12
#device ANSI
#include <24f32ka304.h>

#fuses OSCIO, NOPROTECT, NOWDT

#use delay(OSC=8MHz, CLOCK=32MHz)
#use standard_io(all)

#include <stdlib.h>
#include <math.h>
#include <stdio.h>

/* I hate mixed case types */
typedef BOOLEAN bool;

/* pin definitions */
#define PIN_FOO     (PIN_C8)
#define PIN_BAR     (PIN_A4)
#define PIN_BAZ     (PIN_A9)

#define VREFP       (0)
#define VREFN       (1)
#define CHAN1       (4)
#define CHAN2       (5)

#define FILTER_POINTS       (8)

/*
 * 10mV per degree F.
 * 2.048V reference, 4096 counts, for 0.5mV per count
 * therefore 10mV/0.5mV or 20 counts per degree F
 */
#define COUNTS_PER_DEGREE       (20)
#define COUNTS_PER_DEG_TENTHS       (COUNTS_PER_DEGREE / 10)

/* globals */
volatile bool one_ms_flag;
volatile bool onehundred_ms_flag;
volatile bool one_second_flag;

unsigned int32 chan1_sum, chan2_sum;        /* summing values for the averaging filter */
unsigned int16 chan1_counts, chan2_counts;  /* raw ADC values for temp sensors */
unsigned int16 chan1_temp, chan2_temp;      /* temperatures, in 0.1 degrees F steps */

/*
 * Timer ISR
 */
#INT_TIMER1 level=7
void system_isr(void)
{
    static int ticks = 0;

    one_ms_flag = TRUE;

    if ((ticks % 100) == 0) {
        onehundred_ms_flag = TRUE;
    }

    if (++ticks > 999) {

        one_second_flag = TRUE;
        ticks = 0;
    }
}

/*
 * stupid simple sliding average (FILTER_POINTS data points)
 * runsum is the running average (which is basically the sum of the last FILTER_POINTS values)
 * function returns the new average
 */
static unsigned int16 filter_analog(unsigned int32 *runsum, unsigned int16 new)
{
    *runsum -= *runsum / FILTER_POINTS;
    *runsum += new;

    return *runsum / FILTER_POINTS;
}

/*
 * counts are 0.5mV/count, and sensor is 10mV/oF
 * returns in 1/10 degrees (60F = 600)
 * rounds to half a degree
 */
int to_degrees_f(int counts)
{
    int deg_f;
    int tenths;

    deg_f = counts / COUNTS_PER_DEG_TENTHS;
    tenths = deg_f % 10;
    deg_f /= 10;
    deg_f *= 10;

    if (tenths >= 5) {
        deg_f += 5;
    }

    return deg_f;
}

/*
 * ADC loop
 * meant to be called every 100ms or so.
 * if reset is true, will reset the ADC state machine and reconfigure the ADC.
 */
void adc_loop(bool reset)
{
    static enum { ADC_INIT=0, SMPL_CHAN1, SMPL_CHAN2 } adc_state = ADC_INIT;
    unsigned int16 adc_value;

    if (reset) {
        adc_state = ADC_INIT;
    }

    switch(adc_state) {
    case ADC_INIT:
        setup_adc(ADC_CLOCK_DIV_128);
        setup_adc_ports(sAN0|sAN1, VREF_VREF);
        set_adc_channel(CHAN1);
        read_adc(ADC_START_ONLY);
        chan1_sum = chan2_sum = FILTER_SEED;
        chan1_counts = chan2_counts = 0;
        chan1_temp = chan2_temp = 0;
        adc_state = SMPL_CHAN1;
        break;

    case SMPL_CHAN1:
        adc_value = read_adc(ADC_READ_ONLY);
        chan1_counts = filter_analog(&chan1_sum, adc_value);
        chan1_temp = to_degrees_f(chan1_counts);
        set_adc_channel(CHAN2);
        read_adc(ADC_START_ONLY);
        adc_state = SMPL_CHAN2;
        break;

    case SMPL_CHAN2:
        adc_value = read_adc(ADC_READ_ONLY);
        chan2_counts = filter_analog(&chan2_sum, adc_value);
        chan2_temp = to_degrees_f(chan2_counts);
        set_adc_channel(CHAN1);
        read_adc(ADC_START_ONLY);
        adc_state = SMPL_CHAN1;
        break;

    default:
        adc_state = ADC_INIT;
    };
}

void main(void)
{

/* Set up timer1 for 1ms interrupts. Tcy = Fosc/2 = 16MHz, /64 is 4us. 250 4us ticks is 1ms. */
    setup_timer1(TMR_INTERNAL | TMR_DIV_BY_64, 250);

/* set up I/O */
    output_low(PIN_FOO);
    output_low(PIN_BAR);
    output_float(PIN_BAZ);

/* reset the ADC subsystem */
    adc_loop(TRUE);

/* variable setup */
    one_second_flag = onehundred_ms_flag = one_ms_flag = FALSE;

    enable_interrupts(INT_TIMER1);

/* main loop */
    while (1) {
        if (one_ms_flag) {
            /* do stuff every 1ms */

            one_ms_flag = FALSE;
        }

        if (onehundred_ms_flag) {
            adc_loop(FALSE);

            onehundred_ms_flag = FALSE;
        }

        if (one_second_flag) {
            /* do stuff every 1s */

            one_second_flag = FALSE;
        }
    }
}

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X