могу объяснить более подробно для ПИК16. Правда вспоминаю эти ПИКи, как черную полосу своей жизни. Использовался компилятор "HI-TECH C Microchip PIC V8.02" и PIC16F877.
Мне надо было разместить массивы констант в программной памяти, еепромка была вся занята. Должна быть предусмотрена возможность перезаписи этих констант самим прибором при калибровке. Для этого протект этой области памяти программ должен быть отключен.
Исходя из всего этого массив констант расположил с адреса 0x0800.
Программный код, работающий с этим массивом а адреса 0x1000
МПЛАБ и подобную хрень не использовал. Создавал проект в самом HI-TECH и компиляцию запускал из его ИДЕ.
-------------------------------------
В проекте *.prj в секции линкера
List: Linker options Abs Auto
добавил строки
Entry: -pspline=0800h
Entry: -pspl=1000h
В файле "spline.h" описание данных
<c>
#ifndef _MY_spline_H
#define _MY_spline_H
typedef struct
{ double x;
double y;
double m;
} data_vector;
#define MAX_POINT 8
extern const data_vector arr_spl1[];
extern const data_vector arr_spl2[];
extern const data_vector arr_spl3[];
extern const data_vector arr_spl4[];
extern const data_vector arr_spl5[];
extern data_vector const *const arr_adr[];
double spline( char index, double point_x );
#endif //_MY_spline_H
</c>
В файле "spline.с" инициализация данных и работа с ними в штатном режиме (только чтение)
<c>
// и в опциях линкера эту секцию поместим с адреса 0x0800 (-pspline=0800h) и эту область протект не будем!
#pragma psect const%%u=spline
// Код поместим в секцию spl - во второй половине программной памяти, закрытой от чтения
#pragma psect text%%u=spl
// При 24-х битной double размер массива векторов для 1-го газа = 72 байта
// Не забыть при чтении-записи флэшь добавлять-убирать старший байт 0x34 - ст. байт команды retlw
const data_vector arr_spl1[] =
{ { 0.000000e+00, 0.000000e+00, 0.000000e+00 }, // 0
{ 6.426667e-02, 2.860000e-01, 1.261705e+02 }, // 1
{ 8.890000e-02, 4.940000e-01, 6.205834e+01 }, // 2
{ 1.085333e-01, 6.910000e-01, 4.779862e+01 }, // 3
{ 1.350333e-01, 9.950000e-01, 1.131253e+02 }, // 4
{ 1.976000e-01, 1.985000e+00, 7.496787e+01 }, // 5
{ 4.098000e-01, 7.050000e+00, 0.000000e+00 }, // 6
{ 0.000000e+00, -1.000000e+00, 0.000000e+00 } // 7 последняя точка, значение == -1 - для определения размера массива
};
const data_vector arr_spl2[] =
{ { 0.000000e+00, 0.000000e+00, 0.000000e+00 }, // 0
{ 4.800000e-03, 9.460000e+01, -1.502583e+06 }, // 1
{ 1.620000e-02, 2.370000e+02, 4.720234e+05 }, // 2
{ 3.553333e-02, 5.060000e+02, -1.732172e+05 }, // 3
{ 6.846667e-02, 9.310000e+02, 8.889393e+04 }, // 4
{ 1.089667e-01, 1.501000e+03, -8.287386e+03 }, // 5
{ 1.721000e-01, 2.420000e+03, 1.602982e+04 }, // 6
{ 5.298000e-01, 8.400000e+03, 0.000000e+00 } // 7
};
const data_vector arr_spl3[] =
{ { 0.000000e+00, 0.000000e+00, +0.000000e+00 }, // 0
{ 3.811500e-01, 3.970000e+00, +4.675371e+01 }, // 1
{ 5.833750e-01, 7.980000e+00, +9.550824e+00 }, // 2
{ 6.498000e-01, 9.550000e+00, +1.242192e+02 }, // 3
{ 7.421250e-01, 1.229000e+01, -4.139158e+01 }, // 4
{ 7.991250e-01, 1.401000e+01, +6.805395e+01 }, // 5
{ 8.583500e-01, 1.593000e+01, +0.000000e+00 }, // 6
{ 0.000000e+00, -1.00000e+00, 0.000000e+00 } // 7 // последняя точка, значение == -1 - для определения размера массива
};
const data_vector arr_spl4[] =
{ { 0.000, 0.000, 0. }, // 0
{ 0.100, 355., 0. }, // 1
{ 0.200, 710., 0. }, // 2
{ 0.500, 1775., 0. }, // 3
{ 0.600, 2130., 0. }, // 4
{ 0.700, 2485., 0. }, // 5
{ 0.900, 3195., 0. }, // 6
{ 1.000, 3550., 0. } // 7
};
const data_vector arr_spl5[] =
{ { 0.000, 0.000, 0. }, // 0
{ 0.100, 2.080, 0. }, // 1
{ 0.200, 4.160, 0. }, // 2
{ 0.500, 10.400, 0. }, // 3
{ 0.600, 12.480, 0. }, // 4
{ 0.700, 14.560, 0. }, // 5
{ 0.900, 18.720, 0. }, // 6
{ 1.000, 20.800, 0. } // 7
};
data_vector const *const arr_adr[] = { arr_spl1, arr_spl2, arr_spl3, arr_spl4, arr_spl5 };
/* --- spline() ------------------------ **
* Проверку на выход index за границы массива не делаем из экономии места
* ------------------------------------- */
double spline( char index, double point_x )
{
char a;
double d, e, h, f, p;
data_vector const *arr;
arr = arr_adr[index];
for ( a = 0; a < MAX_POINT; a++ ) // поиск последнего элемента в массиве
{ if ( arr[a].y < 0. )
break;
}
if ( a < 2 ) // пустой массив
return( point_x );
......................................
......................................
......................................
</c>
Функции перезаписи массива констант при калибровке
<c>
/* --- wr_spline() --------------------- **
* т.к. ОЗУ у ПИКа, можно сказать, нету, из последовательного
* порта получаем частями.
* index - какой из const data_vector arr_spl[] сейчас пишем
* point - какой из data_vector в нем.
* получили один data_vector и запишем во флэш
* DataBuf - глобальный массив, в котором находятся принятые данные
* ------------------------------------- */
void wr_spline( char index, char point )
{
unsigned short addr = (unsigned short)arr_adr[index] + point * sizeof( data_vector );
char a;
for ( a = 0; a < sizeof( data_vector ); a++ )
fl_write( addr++, 0x3400 | DataBuf[a] );
}
/* --- rd_spline() --------------------- **
* выдать сплайны в последовательный порт
* ------------------------------------- */
void rd_spline( char index )
{
unsigned short addr = (unsigned short)arr_adr[index];
char summa, cnt = MAX_POINT * sizeof( data_vector );
..................................
..................................
for ( summa = 0; cnt; cnt-- ) // передача массива
summa += wbyte( fl_read( addr++ ));
wbyte( summa ); // передача контрольной суммы
}
/* --- fl_write() ---------------------- **
*
* ------------------------------------- */
void fl_write( unsigned short addr, unsigned short value )
{
EEADR = addr & 0xff;
EEADRH = addr >> 8;
EEDATA = value & 0xff;
EEDATH = value >> 8;
EEPGD = 1;
WREN = 1;
if ( GIE )
CARRY = 1;
GIE = 0;
EECON2 = 0x55;
EECON2 = 0xaa;
WR = 1;
asm( "nop" );
asm( "nop" );
if ( CARRY )
ei();
WREN = 0;
}
/* --- fl_read() ----------------------- **
* Модифицирован для чтения только младшего байта
* ------------------------------------- */
unsigned char fl_read( unsigned short addr )
{
EEADR = addr & 0xff;
EEADRH = addr >> 8;
WREN = 0;
EEPGD = 1;
RD = 1;
asm( "nop" );
asm( "nop" );
return( EEDATA );
}
</c>
Слишком длинно написал, может не все по делу, лень разбираться, проект старый....