Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
urry
Сверлит текстолит когтями
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение urry »

мужики такая проблема, программирую PIC18F452, пишу на Си в МСС18, и вот проблема не могу создать массив объёмом, больше 227 ячеек. а нужно 512. причём у пика памяти 1,5 килобайта. в чём проблема то ?

Проблема в нежелании смотреть документацию.
Смотрим файл линкера

Код: Выделить всё

ACCESSBANK NAME=accessram  START=0x0            END=0x7F
DATABANK   NAME=gpr0       START=0x80           END=0xFF
DATABANK   NAME=gpr1       START=0x100          END=0x1FF
DATABANK   NAME=gpr2       START=0x200          END=0x2FF
DATABANK   NAME=gpr3       START=0x300          END=0x3FF
DATABANK   NAME=gpr4       START=0x400          END=0x4FF
DATABANK   NAME=gpr5       START=0x500          END=0x5FF
ACCESSBANK NAME=accesssfr  START=0xF80          END=0xFFF          PROTECTED

SECTION    NAME=CONFIG     ROM=config

STACK SIZE=0x100 RAM=gpr5

Размер страницы 256 байт.
Подключаем линкер к себе в проект и объединяем 2 страницы

Код: Выделить всё

DATABANK   NAME=MY_RAM       START=0x300          END=0x4FF PROTECTED
SECTION    NAME=MY_RAM RAM=MY_RAM


gpr3 gpr4 естественно, вычеркнуть
в программе обращаемся как-то так

Код: Выделить всё

#pragma udata MY_RAM=0x300
unsigned char array[512];
Последний раз редактировалось Аlex Пн авг 13, 2012 17:53:21, всего редактировалось 1 раз.
Причина: -
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение Аlex »

Юра не выдержал. :)) А я хотел, что бы человек сам допёр :write:
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: Вопросы по С/С++ (СИ)

Сообщение shads »

Вопросик есть.....
Стал использовать #include <avr/eeprom.h> для работы с внутренней энергонезависимой памятью, вроде все работает, но постоянно выкидывает предупреждения. Что не так?

Например хочу стереть EEPROM, делаю так:

Код: Выделить всё

      for (unsigned char i=0; i<64; i++)      //цикл стирания
         eeprom_write_byte(i, 0);
Вроде бы все работает, но почему то при компиляции пишет:
"warning: passing argument 1 of '_eewr_byte_tnl3a' makes pointer from integer without a cast"
Что сие значит..... ато глаза режут предупреждения постоянные.....
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение vitalik_1984 »

Видимо эта функция ждет указатель на область памяти, а вы в нее число суете.
Компилятор принимает это число как адрес в памяти, о чем вас и предупреждает.
Нужно преобразовать число в указатель вроде это так делается:
eeprom_write_byte((char*)i, 0)
проверить пока негде, к сожалению.
В поисках истины человек развивается.
Аватара пользователя
БАТАРЕЙКУС
Потрогал лапой паяльник
Сообщения: 346
Зарегистрирован: Сб фев 07, 2009 19:21:25

Re: Вопросы по С/С++ (СИ)

Сообщение БАТАРЕЙКУС »

urry писал(а):
Проблема в нежелании смотреть документацию.


urry писал(а):
Юра не выдержал. А я хотел, что бы человек сам допёр


спасибо за помощь. всё получилось. яж откуда мог знать что линкер файл нужно подключать дополнительно к проекту, и там есчё чтото менять. в том, что что-то надо поменять я сразу догадался, но не мог разобраться где это надо менять. и где оно лежит.
сделал так.

Код: Выделить всё

ACCESSBANK NAME=accessram  START=0x0               END=0x7F
DATABANK   NAME=gpr0       START=0x80              END=0xFF
DATABANK   NAME=buffer_section    START=0x100          END=0x2FF
DATABANK   NAME=gpr3       START=0x300             END=0x3FF
DATABANK   NAME=gpr4       START=0x400             END=0x4FF


Код: Выделить всё

#pragma udata buffer_section
volatile char buffer[512];
#pragma udata
Мечтатель - не тот, кто сидит на диване и думает о несбыточном, а тот, кто всеми силами стремится воплотить несбыточное в реальность.
Tolmi
Говорящий с текстолитом
Сообщения: 1658
Зарегистрирован: Вс дек 11, 2011 05:25:04
Откуда: Киев, Украина
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение Tolmi »

vitalik_1984 писал(а):Нужно преобразовать число в указатель вроде это так делается:
eeprom_write_byte((char*)i, 0)

Или написать

Код: Выделить всё

for (unsigned char *i=0; i<64; i++)

тогда и eeprom_write_byte(i, 0) прокатит.
In theory, theory and practice are the same. In practice, they're not.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение Аlex »

яж откуда мог знать что линкер файл нужно подключать дополнительно к проекту
Дак яж Вам написал:
если только для одного проекта, то добавить его в папку с проектом и подключить к проекту
Или это было по Олбански ? :))

что что-то надо поменять я сразу догадался, но не мог разобраться где это надо менять.
И где и что править я Вам тоже писал:
Нужно править файл линкера
и ссылку дал и страницу назвал - осталось только :hunger: . Или это было тоже по Олбански ? :)

Это обычное нехотение работать с документацией, неумение пользоваться поиском и желание получить всё на блюдечке с голубой каёмочкой., без всяческих лишних телодвижений...
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: Вопросы по С/С++ (СИ)

Сообщение shads »

vitalik_1984
Tolmi
Спасибо. Действительно надо указатели использовать..... Поправил так, и усе красиво стало.....

Код: Выделить всё

      unsigned char eeprom_data[64] EEMEM;       //массив данных в EEPROM

      for (unsigned char i=0; i<64; i++)      //цикл стирания
         eeprom_write_byte(&eeprom_data[i], 0);
ut1wpr
Вымогатель припоя
Сообщения: 581
Зарегистрирован: Ср янв 05, 2011 10:03:18

Re: Вопросы по С/С++ (СИ)

Сообщение ut1wpr »

shads писал(а):Спасибо. Действительно надо указатели использовать..... Поправил так, и усе красиво стало.....

Код: Выделить всё

      unsigned char eeprom_data[64] EEMEM;       //массив данных в EEPROM

      for (unsigned char i=0; i<64; i++)      //цикл стирания
         eeprom_write_byte(&eeprom_data[i], 0);

Попробуйте так. Я в IAR-e так пишу...

Код: Выделить всё

u8  e_data[] EEMEM;
u8 *p = (u8)e_data;

for( u8 i = 0; i < 64; i++ )  *p++ = 0x00;

В вашем случае, наверное надо:

Код: Выделить всё

for( u8 i = 0; i < 64; i++ )  eeprom_write_byte(p++,0);

Запись в Си с истинным указателем, но когда глянете на дизасм, увидите, что разницы почти никакой.
IAR сам различает классы памяти и нет необходимости в явном вызове функции eeprom_write_byte(). Просто применяется оператор присваивания.
Компилятор сам разбирается, как в какой класс писать. За что и люблю умничку. Но помнить о разнице в классах программисту надо всегда! :)
С уважением,
Виктор.
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение vitalik_1984 »

ut1wpr писал(а):Запись в Си с истинным указателем, но когда глянете на дизасм, увидите, что разницы почти никакой.
IAR сам различает классы памяти и нет необходимости в явном вызове функции eeprom_write_byte(). Просто применяется оператор присваивания.

То же самое можно сказать про CVAVR-в нем обычный оператор присваивания.
В поисках истины человек развивается.
Аватара пользователя
urry
Сверлит текстолит когтями
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение urry »

БАТАРЕЙКУС , минус 1 к внимательности, свою память лучше защитить от компилятора.

Код: Выделить всё

DATABANK   NAME=buffer_section    START=0x100          END=0x2FF PROTECTED

в качестве лирического отступления -
в Вашем случае лучше пользовать 24 серию. 18 серию я использую тогда, когда нужен юсб и малоногость - например, пик18ф14к50 пик18ф2550 - а для "общего назначения" - только 24.
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: Вопросы по С/С++ (СИ)

Сообщение shads »

Дошкрябал таки задачу - написал декодер радиоканала на С (всем спасибо за помощ в освоении ентого чуда) .
Вот что получилось http://asis-kbr.ru/forum/viewtopic.php?f=9&t=122

Текст в гифе
receiver433_c.gif
(61.29 КБ) 388 скачиваний

Текст обычно
Спойлер

Код: Выделить всё

//#######################################################################################################################
//#######################################################################################################################
// включаемые файлы
#define F_CPU 9600000
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
//eeprom_read_byte(), eeprom_write_byte(), eeprom_read_word(), eeprom_write_word()

//дефайны
#define BtnPort PINB                     /*порт подключения кнопки*/
#define BtnPin (1<<1)                     /*пин подключения кнопки*/
#define ReceivePort PINB                  /*порт подключения выхода приемника 433*/
#define ReceivePin (1<<3)                  /*пин подключения выхода приемника 433*/
#define LedPort PORTB                     /*порт подключения светодиода*/
#define LedPin (1<<2)                     /*пин подключения светодиода*/
#define RelayPort PORTB                     /*порт подключения реле*/
#define RelayPin (1<<4)                     /*пин подключения реле*/

//прототипы функций   
void Receive (void);                     //ф-ция обработки данных радиоканала в прерывании с частотой 20000Гц
void Int100Hz (void);                     //обработка медленных функций с частотой 100Гц

//глобальные переменные
unsigned long ReceiveData;                  //4 байта для чтения кода с радиоканала
unsigned char RelayOnCoun=0;               //счетчик времени включения реле
unsigned char LedCoun;                     //счетчик для мигания светика с частотой 1Гц

#define EEDataLen 60                     /*длина буфера данных в EEPROM*/
unsigned char EEData[EEDataLen] EEMEM;         //массив данных в EEPROM
unsigned char EEPnt EEMEM;                   //указатель на байт массива в EEPROM (0-59)   

//#######################################################################################################################
//#######################################################################################################################
//Главная функция
int main (void)
{
   DDRB =    (LedPin|RelayPin);               //включение линий порта на вывод
   PORTB = BtnPin;                        //включит подтяжку на кнопке

   TCCR0A = 0x02;                        //режим таймера - CTC (0x02 сброс при совпадении), выводы контроллера не исп-ся
   TCCR0B = 0x02;                        //инициализация режима предделителя таймера (0x02 деление на 8)
   TIMSK0 = 0x04;                         //инициализация таймера\счетчика по совпадению с OCR0A
   OCR0A = 59;                           //настройка регистра сравнения 59 (f прерывания =20khz)

   _delay_ms(200);
   if   (!(BtnPort & BtnPin))               //если кнопка нажата при старте - стереть EEPROM
   {
      for (unsigned char i=0; i<EEDataLen; i++)//цикл стирания данных EEPROM
         eeprom_write_byte(&EEData [i], 0);
         eeprom_write_byte(&EEPnt, 0);      //сброс указателя
     
      for (unsigned char i=0; i<30; i++)
      {                              //индикация стирания (частое мигание в течение 3 сек)
         LedPort |= LedPin;               //мигаем с периодом 100мс
         _delay_ms(50);
         LedPort &= ~LedPin;
         _delay_ms(50);
      }
   }

   sei ();                              //разрешаем глобально прерывания
   while(1)                           //бесконечный цикл
   {
   }
}

//#######################################################################################################################
//#######################################################################################################################
//обработка прерывания (частота вызова 20 кГц)
ISR (TIM0_COMPA_vect)
{
   Receive ();                           //функция обработки данных линии радиоканала

   static unsigned char Div100=0;            //счетчик, для деления частоты прохода с 20000 Гц до 100 Гц
   if (++ Div100 >= 200)
   {                                   
      Div100 =0;                 
      Int100Hz ();                     //функции с частотой вызова 100Гц
   }
}

//----------
//часть функций с частотой вызова 100Гц

void Int100Hz (void)
{
   sei ();                              //разрешить прерывания в медленной части (для выполнения прерываний с частотой 10000 Гц)

   if (BtnPort & BtnPin)
   {                                 //если кнопка отпущена - мигать в режиме StBy
      if (++ LedCoun >= 100)
         LedCoun=0;
      if (LedCoun >= 50)
         LedPort &= (~LedPin);
      else
         LedPort |= LedPin;
   }
   else                              //если кнопка нажата - погасить (ожидаем сигнала с брелка, для занесения в память)
      LedPort &= (~LedPin);


   if (RelayOnCoun)                     //обработка включения реле
   {
      RelayOnCoun --;
      RelayPort |= RelayPin;               //включить реле
   }
   else
      RelayPort &= ~RelayPin;               //выключить реле
}   

//----------
//ф-ция приема данных радиоканала
void Receive (void)
{
   static unsigned char
   Step=0,                              //переменная шагов алгоритма
   BitHiPartCoun=0,                      //счетчик времени приема высокой части полу бита
   BitLoPartCoun=0,                      //счетчик времени приема низкой части полу бита
   BitCounter=0;                         //счетчик принятых бит

   //Step==0 инициализация приема серии
   if (Step==0)
      BitCounter=0;

   //Step==1 начало основного цикла приема бита
   if (Step<2)
   {
      BitHiPartCoun=0;   
      BitLoPartCoun=0;
   }

   //Step==2 обработка высокого уровня полубита
   if (Step<3)                           
   {
      if (ReceivePort & ReceivePin)                   
      {                             
         Step=2;
         if (BitHiPartCoun < 50)            //Подсчитываем длительность высокого уровня сигнала в линии
            BitHiPartCoun ++;
         return;
      }
   }

   //Step==3 обработка низкого уровня полубита
   if (ReceivePort & ReceivePin)                     
   {
      //завершено чтение бита, анализ временных параметров
      Step=0;
      unsigned char temp = (BitLoPartCoun + BitHiPartCoun);
      if ((temp < 8)||(temp >= 15))
         return;                           //временные параметры бита не соответствуют, инициализация

      Step=1;
      ReceiveData <<= 1UL;                  //сдвиг буфера и запись в младший разряд принятого бита
      if (BitLoPartCoun < BitHiPartCoun)
         ReceiveData |=1;

      if (BitCounter < 24)                  //считаем скока бит приняли
         BitCounter ++;
      return;
   }
   else
   {   
      Step =3;                                 
      if (++ BitLoPartCoun < 50)            //если длительность низкого уровня сигнала в линии больше 50мс - значит серия принята
         return;
      Step=0;                           
      if (BitCounter<24)                  //Если принято менее 24 бит - ошибка, начать прием заново
         return;         
      ReceiveData &= 0x00ffffff;            //очистить лишние старшие 8 бит

      //идентификация принятых данных
      unsigned char EEPntTmp = eeprom_read_byte(&EEPnt);
      if (!(BtnPort & BtnPin))           
      {                              //кнопка нажата - запомнить принятый код
         if (EEPntTmp >= EEDataLen)
            return;                     //память заполнена, выход
         eeprom_write_byte (&EEPnt,(EEPntTmp +3));
         eeprom_write_byte (&EEData[EEPntTmp +0], (unsigned char) (ReceiveData >> 0));
         eeprom_write_byte (&EEData[EEPntTmp +1], (unsigned char) (ReceiveData >> 8));
         eeprom_write_byte (&EEData[EEPntTmp +2], (unsigned char) (ReceiveData >> 16UL));
         LedPort |= LedPin;               //индикация выполненного программирования (включ LED на 2 сек)
         _delay_ms(2000);
         return;
      }
      else
      {                              //кнопка не нажата - проверить на соответствие кодам в памяти
         while (EEPntTmp >= 3)            //есть ли данные для сравнения
         {
            EEPntTmp -= 3;
            if ((eeprom_read_byte (&EEData[EEPntTmp +0]) == (unsigned char) (ReceiveData >>0))
            &&(eeprom_read_byte (&EEData[EEPntTmp +1]) == (unsigned char) (ReceiveData >> 8))
            &&(eeprom_read_byte (&EEData[EEPntTmp +2]) == (unsigned char) (ReceiveData >> 16UL)))
            {
               RelayOnCoun=50;            //включить реле на 500мс.
               return;
            }
         }
      }
   }
}

//#######################################################################################################################
//#######################################################################################################################
Последний раз редактировалось shads Вс авг 19, 2012 20:31:42, всего редактировалось 3 раза.
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение vitalik_1984 »

Зачем было в картинку переводить?Чтобы мы посмотрели как у вас редактор синтаксис подсвечивает? :)))

Совет: чтобы сделать подсветку синтаксиса языка Си в форуме можно использовать сочетание тэгов

Код: Выделить всё


[code=php][/code]
В поисках истины человек развивается.
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: Вопросы по С/С++ (СИ)

Сообщение shads »

Попробовал, при этом, текст программы магическим образом кудато испаряется.....
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение vitalik_1984 »

Странно

Спойлер

Код: Выделить всё


 Код
:
//#######################################################################################################################
//#######################################################################################################################
// включаемые файлы
#define F_CPU 9600000
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
//eeprom_read_byte(), eeprom_write_byte(), eeprom_read_word(), eeprom_write_word()

//дефайны
#define BtnPort PINB                     /*порт подключения кнопки*/
#define BtnPin (1<<1)                     /*пин подключения кнопки*/
#define ReceivePort PINB   

 //прототипы функций   
void Receive (void);                     //ф-ция обработки данных радиоканала в прерывании с частотой 20000Гц
void Int100Hz (void);                     //обработка медленных функций с частотой 100Гц

//глобальные переменные
unsigned long ReceiveData;                  //4 байта для чтения кода с радиоканала
unsigned char RelayOnCoun=0;               //счетчик времени включения реле 
unsigned char LedCoun;                     //счетчик для мигания светика с частотой 1Гц 
 

всегда теперь этим пользуюсь, если не забываю
В поисках истины человек развивается.
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: Вопросы по С/С++ (СИ)

Сообщение shads »

Буксую с указателями…..

Объявляю строку:
char TxtDflt [] = {"dflt"};

Есть функция печати сообщения, в которую хочу передать строку:
void DspMessageShow (char TxtDflt[]);

и есть функция печати символов, в которую передаю символ и позицию:
void DspSimbShow (unsigned char simbol, unsigned char position)

С последней ф-цией все нормально, символы печатает. Но как в нее по очереди передать символы из ф-ции печати сообщения, хелпмииииии…..
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение Аlex »

Код: Выделить всё

void DspMessageShow (char *TxtDflt){
  while(*TxtDflt){
    DspSimbShow (*TxtDflt, mPos);
    TxtDflt++;
  }
}
Как то так...
ut1wpr
Вымогатель припоя
Сообщения: 581
Зарегистрирован: Ср янв 05, 2011 10:03:18

Re: Вопросы по С/С++ (СИ)

Сообщение ut1wpr »

Или для ленивых:

Код: Выделить всё

void DspMessageShow ( char *TxtDflt ){
    while( char ch = *TxtDflt )   DspSimbShow ( ch, mPos );
}
По записи вроде бы и короче, на одно обращение по указателю меньше. Но введение переменной сводит на нет всю экономию... :)
Да и чревата такая форма записи.... Не все компиляторы и не всех платформах одинаково с ней разберутся.
С уважением,
Виктор.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение Аlex »

Или для ленивых:
Не нахожу инкремента указателя. Цикл будет вечным :roll:
Тогда уж так:

Код: Выделить всё

void DspMessageShow (char *pStr){
   while(*pStr)    DspSimbShow (*pStr++, mPos);
}
Аватара пользователя
FreshMan
Друг Кота
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Re: Вопросы по С/С++ (СИ)

Сообщение FreshMan »

что значит сия команда ?

Код: Выделить всё

sfrb TWBR=0;
Tell Me The Truth
Ответить

Вернуться в «Разные вопросы по МК»