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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Опытный кот
Аватара пользователя
Сообщения: 848
Зарегистрирован: Ср мар 02, 2011 07:47:39
Откуда: Уфа

Сообщение Psych »

FreshMan писал(а):а допускается ли такое безобразие
Че эт безобразие-то?!! Вполне естественно.

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

*p_brightness=BrightnessOldDigits[2] // имя массива указатель на нуевой элемент

p_brightness[2]=BrightnessOldDigits[4]      //   Одинаково
*(p_brightness+2)=BrightnessOldDigits[4]  //

uint8_t p_brightness[]={......} // можно число не указывать если инициализируете
Реклама
Открыл глаза
Сообщения: 43
Зарегистрирован: Чт июл 04, 2013 15:15:22

Сообщение VLeshka »

Привет всем.

Создаю программу приёма пакета через uart, используя прерывание.
Код:

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

#pragma vector = USCIAB0RX_VECTOR 
__interrupt void USCIAB0RX_VECTOR_PRE (void)
{
    char buf = UCA0RXBUF; //сбрасываем прерывание
    addItem(ch_exp,buf);  //добавляем символ buf к массиву символов ch_exp
    UARTWriteString(ch_exp);
    //далее заводим таймер на 100мс
}
Конец пакета буду определять просто - по разрыву по времени между принятыми символвми более 100мс.

Проблема в процедуре addItem (написал по докам из яндекса):
Код:

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

void addItem(char *&c, char sim)
{
 char *tt; //использую свой метод определения длины строки, это наверно почти бред:)
  tt = c;
  int ii = 0;
  while (*tt) 
  {
    ii++;
    tt++;
  }
  char *t = new char[ii+1]; //но даже если задавать размерность вручную, то тоже виснет
  for (int i=0; i<ii;i++)
     t[i] = c[i];  
  t[ii] = sim;   
  delete[] c;
  c = t;
}
При первом проходе через процедуру, добавляется символ к массиву и возвращается изменённый массив нормально.
При втором проходе, помимо добавления символа добавляется ещё и символ '.'.
При третьем проходе, всё виснет.

Сперва грешил на символ \0 в конце строки, но вроде он ставится автоматом, и не надо заботиться о его добавлении.
В чём проблема?
Реклама
Держит паяльник хвостом
Аватара пользователя
Сообщения: 960
Зарегистрирован: Вс дек 02, 2012 16:58:33
Откуда: от туда

Сообщение GARMIN »

VLeshka писал(а):

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

void addItem(char *&c, char sim)
{
 char *tt; // это бред
  tt = c;
В чём проблема?
Как ты приравниваешь указатель на адрес переменной к указателю на переменную?
Контактная информация:
Открыл глаза
Сообщения: 43
Зарегистрирован: Чт июл 04, 2013 15:15:22

Сообщение VLeshka »

GARMIN писал(а):
VLeshka писал(а):

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

void addItem(char *&c, char sim)
{
 char *tt; // это бред
  tt = c;
В чём проблема?
Как ты приравниваешь указатель на адрес переменной к указателю на переменную?
Спасибо за указание на эту ошибку. Накидал код:

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

void addItem(char &c, char sim) //тут была ошибка
{
 char *tt;
  tt = &c;
  int ii = 0;
  while (*tt) 
  {
    ii++;
    tt++;
  }
  char *t = new char[ii+1];
  for (int i=0; i<ii;i++)
  {
    t[i] = c;  
    c++;
  }
  t[ii] = sim;   
  c = t[0];
}
и вызываем его:

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

addItem(ch_exp[0],'a');
Вроде работает, но так же с "фокусами в конце массива". Доберусь до компа - проверю досконально (прошлой ночью времени было мало).
Реклама
Эиком - электронные компоненты и радиодетали
Держит паяльник хвостом
Аватара пользователя
Сообщения: 960
Зарегистрирован: Вс дек 02, 2012 16:58:33
Откуда: от туда

Сообщение GARMIN »

void addItem(char &c, char sim) //тут была ошибка
{}

и вызываем его:
addItem(ch_exp[0],'a');
Опять двадцать пять:
ch_exp[0] передаётся по значению.
А ты объявляешь его адресом:
char &c
Контактная информация:
Реклама
Открыл глаза
Сообщения: 43
Зарегистрирован: Чт июл 04, 2013 15:15:22

Сообщение VLeshka »

GARMIN писал(а): Опять двадцать пять:
ch_exp[0] передаётся по значению.
А ты объявляешь его адресом:
char &c
спасибо.

Я после очередного сеанса связи с MSP430 понял, что мне надо изучать поставленную мною тему с "Hello world". :)
Итак, в обработчике прерывания uart-порта при приёме, я написал простенький код по добавлению символа к строке, и выводу этой строки обратно в uart [на комп, для наглядного контроля].

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

char *ch_exp="Mod";
int cnt=3;

#pragma vector = USCIAB0RX_VECTOR 
__interrupt void USCIAB0RX_VECTOR_PRE (void)
{
char buf = UCA0RXBUF; //сбрасываем прерывание
    P1OUT ^= (BIT0 + BIT6); //вкл и выкл диоды

    UARTWriteString(ch_exp); //выводит строку в uart; всегда нормально работает
    UARTWriteString("Ура"); //всегда нормально работает
    
    char *t = new char[cnt+1]; //здесь на второй раз зависает
    for (int i=0; i<cnt;i++)
      t[i] = ch_exp[i];  
    t[cnt] = 'a';
    t[cnt+1] = '\0';   
    cnt++; 
    ch_exp = t;
    
	
    UARTWriteString(ch_exp); 
}
При первом проходе через этот код всё нормально. Но не могу понять, почему намертво зависает при втором проходе на строке:

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

char *t = new char[cnt+1];
Указатель t - локальный и не требует такого удаления:

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

//delete(t); //впрочем, вставлял - не помогает
Упёрся уже в тупой угол. В чём ошибаюсь???
Реклама
Держит паяльник хвостом
Аватара пользователя
Сообщения: 960
Зарегистрирован: Вс дек 02, 2012 16:58:33
Откуда: от туда

Сообщение GARMIN »

VLeshka писал(а): При первом проходе через этот код всё нормально. Но не могу понять, почему намертво зависает при втором проходе на строке:

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

char *t = new char[cnt+1];
Указатель t - локальный и не требует такого удаления
Упёрся уже в тупой угол. В чём ошибаюсь???
Каким ерундовым софтом ты пользуешься, если он тебе компилирует этот код без ошибок?
Ну разберись с указателями и массивами наконец. Почитай, чем отличается элемент массива от указателя на этот элемент.
Тебе дважды говорил разобраться. Опять те же грабли.
Жевать не буду. Читай учебник до просветления.
Контактная информация:
Открыл глаза
Сообщения: 43
Зарегистрирован: Чт июл 04, 2013 15:15:22

Сообщение VLeshka »

GARMIN писал(а): Каким ерундовым софтом ты пользуешься, если он тебе компилирует этот код без ошибок?
спасибо за наводку.
GARMIN писал(а): Ну разберись с указателями и массивами наконец. Почитай, чем отличается элемент массива от указателя на этот элемент.
Тебе дважды говорил разобраться. Опять те же грабли.
Жевать не буду. Читай учебник до просветления.
ок. Вопросы закончились.
Держит паяльник хвостом
Аватара пользователя
Сообщения: 906
Зарегистрирован: Ср апр 16, 2008 13:22:54
Откуда: Приднестровье, Тирасполь

Сообщение Goodefine »

GARMIN писал(а): Каким ерундовым софтом ты пользуешься, если он тебе компилирует этот код без ошибок?

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

char *t = new char[cnt+1];
А где в этом коде ошибка? Стандартная операция выделения памяти под массив в куче с инициализацией указателя.
Жевать не буду. Читай учебник до просветления.
Гм.. категоричное заявление :))
спасибо за наводку.
Посмотрите чему равно cnt в момент выделения памяти. Вполне возможно что в этот момент переменная не инициализирована и содержит мусор, соответственно память выделиться не может. Поставьте также ловушку на исключение std::bad_alloc - скорее всего в него программа и влетает.
Указатель t - локальный и не требует такого удаления:

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

//delete(t); //впрочем, вставлял - не помогает
Не знаю диалекта вашего С++, но обычно массив правильно удаляют так

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

 delete[] t;
Т.е. надо освобождать весь массив, а не указатель - и об этом надо сообщать компилятору
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Держит паяльник хвостом
Аватара пользователя
Сообщения: 960
Зарегистрирован: Вс дек 02, 2012 16:58:33
Откуда: от туда

Сообщение GARMIN »

Пожалуйста, не используйте выделение памяти в векторах прерываний. Пользуйтесь только статическими переменными. Это неправильно. Это занимает много времени и может привести к сбоям системы.
И, после использования, удаляйте переменные. Памяти может не хватить.

И таки да, в предыдущем посте протупил. :oops: Буду внимательнее.
Контактная информация:
Открыл глаза
Сообщения: 43
Зарегистрирован: Чт июл 04, 2013 15:15:22

Сообщение VLeshka »

Волею случая, использую [глобальный] статический массив. Сделал инкремент массива по указателю, но всё равно это делал используя статический массив (создаю статический массив, указываю в конце символ '\0' и ставлю указатель на этот массив) - так что перешёл на статический массив, как и делается в примерах для MSP430 по всему интернету.
Встал на лапы
Сообщения: 85
Зарегистрирован: Пт фев 01, 2013 17:47:26
Откуда: Украина, Луганская область

Сообщение srg320 »

Вопрос по С++.

Есть класс Свойства
Спойлер

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

template<typename Type, 
        typename Owner,
        Type (Owner::*Getter)(),
        void (Owner::*Setter)(Type)> 
class Property
{
protected:
    Owner * m_owner;

public:
    operator Type () const
    {
        return (m_owner->*Getter)();
    }
    
    Type get() const
    {
        return (m_owner->*Getter)();
    }
    
    void operator  =(Type data) 
    {
        (m_owner->*Setter)(data);
    }
 
    Property() :
        m_owner(0)
    {}
    
    Property(Owner * const owner) :
        m_owner(owner)
    {}
};
и пример использования
Спойлер

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

class Rectangle
{
public:
    int X;
    int Y;
    int Width;
    int Height;
    
    Rectangle() :
        X(0),
        Y(0),
        Width(0),
        Height(0)
    {}
};

class Control 
{
private:
    Rectangle bounds;
    int width;
    
    void setBounds(Rectangle value) { bounds = value;}
    Rectangle getBounds() { return bounds; }
    void setWidth(int value) { width = value;}
    int getWidth() { return width; }
    
public:
    Control() :
        Bounds(this),
        Width(this)
    {}
    
    Property<Rectangle, Control, &Control::getBounds, &Control::setBounds> Bounds;
    Property<int, Control, &Control::getWidth, &Control::setWidth> Width;
};

int main()
{
    int x, width;
    
    Control* c = new Control();
    
    width = c->Width;
    
    x = ((Rectangle)c->Bounds).X;    //такой вариант работает
    
    x = c->Bounds.get().X;               //и такой 
    
    Rectangle bounds = c->Bounds;  //и такой 
    x = bounds.X;
    
    x = c->Bounds.X;                      //!!! а такой - нет
    
    return 0;
}
Когда тип Свойства простой, то проблем нет, а когда типом Свойства является класс, то нет доступа к полям класса. Или по другому и нельзя, или я не правильно написал перегрузку оператора приведения типа в классе Property, а может есть другие варианты достичь желаемого результата. Пишу в IARе, но думаю разницы нет какой компилятор.
Хотелось бы писать так

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

x = c->Bounds.X; 
так и красивее и проще читать

а не так

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

x = ((Rectangle)c->Bounds).X;
или так

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

x = c->Bounds.get().X;
Если кто знает, подскажите.
Заранее благодарен.
Держит паяльник хвостом
Сообщения: 963
Зарегистрирован: Чт апр 03, 2014 23:16:55
Откуда: Россия

Сообщение Rtmip »

Здравствуйте всем!
Язык "С" не знаю, но заинтересовала меня вот эта прога, та что во вложении, отсюда.Полное описание и схема тут, на схеме ошибка, перепутаны столбцы клавиатуры,
но это не суть. Как она работает разобрался, вообщем, перегнал ее в формат WinAvr, добавил возможность ввода кода охраны... Переделал
под Atmega8, все хорошо работает, однако есть там недоработка, позволяющая легко подобрать код охранной системы!
Решил ее тоже исправить, однако не получается, уперся в то, что не понимаю, как работает этот кусок:
Спойлер

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

// HOLD WHILE KEYDOWN
scn = 0;
while (scn != 45) {
scn = 0;
PORTD.4 = 0;
delay_ms(1);
scn = scn + (PIND & 15);
PORTD.4 = 1;
PORTD.5 = 0;
delay_ms(1);
scn = scn + (PIND & 15);
PORTD.5 = 1;
PORTD.6 = 0;
delay_ms(1);
scn = scn + (PIND & 15);
PORTD.6 = 1;
}
Целиком он в этом блоке:
Спойлер

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

// **********************************************************************************************
// **** READ KEYPAD AND RETURN ASCII VALUE
// **********************************************************************************************
unsigned char KEYPAD() {
unsigned char key;
unsigned char scn;
key = 0;

// SCAN KEYS IN COLUMN 1
PORTD.4 = 0;
delay_ms(1);
scn = (PIND & 15);
PORTD.4 = 1;
// CONVERT KEY TO ASCII
if (scn == 14) key = '1';
if (scn == 13) key = '4';
if (scn == 11) key = '7';
if (scn == 7) key = '*';

// SCAN KEYS IN COLUMN 2
PORTD.5 = 0;
delay_ms(1);
scn = (PIND & 15);
PORTD.5 = 1;
// CONVERT KEY TO ASCII
if (scn == 14) key = '2';
if (scn == 13) key = '5';
if (scn == 11) key = '8';
if (scn == 7) key = '0';

// SCAN KEYS IN COLUMN 3
PORTD.6 = 0;
delay_ms(1);
scn = (PIND & 15);
PORTD.6 = 1;
// CONVERT KEY TO ASCII
if (scn == 14) key = '3';
if (scn == 13) key = '6';
if (scn == 11) key = '9';
if (scn == 7) key = '#';

// SEND KEY BEEP
if (key != 0){
for (scn = 0; scn < 50; scn++) {
PORTC.0 = 0;
PORTC.1 = 1;
delay_us(200);
PORTC.0 = 1;
PORTC.1 = 0;
delay_us(200);
}
}

// HOLD WHILE KEYDOWN
scn = 0;
while (scn != 45) {
scn = 0;
PORTD.4 = 0;
delay_ms(1);
scn = scn + (PIND & 15);
PORTD.4 = 1;
PORTD.5 = 0;
delay_ms(1);
scn = scn + (PIND & 15);
PORTD.5 = 1;
PORTD.6 = 0;
delay_ms(1);
scn = scn + (PIND & 15);
PORTD.6 = 1;
}

// RETURN KEY VALUE
delay_ms(100);
return(key);
}
Как сканируются клавиатура понимаю, но как тут работает часть блока, ответственная за удержание кнопок не пойму, растолкуйте, пожалуйста! :)
PS: начало обсуждения было здесь
UPD:Кажется понял как работает: пока нажата любая клавиша будет крутиться в этом цикле, если нет нажатой кнопки, то пройдет его один раз и дальше по программе.
Вопрос снят :)
Вложения
WIDE C Source File.c
(8.06 КБ) 237 скачиваний
Открыл глаза
Сообщения: 43
Зарегистрирован: Чт май 24, 2012 09:19:34
Откуда: Ярославль

Сообщение holy_0dmin »

Всех приветствую!
Интересует грамотный и корректный алгоритм взамиодействия МК с GSM/GPS-модулями SIM900/SIM908.
Во всех примерах в интернете либо шлют модулю 1 команду и на этом успокаиваются, либо заливают ему несколько команд с задержкой. Данный метод мне лично кажется неправильным и делать так мне не хочется. Придумал следующий алгоритм:

Создаем переменную Шаг = 0;

В основной процедуре делаем

while(шаг < 250)
{
если (шаг == 0) {Отсылаем модулю "AT";}
Case

Шаг == 0 : дожидаемся и принимаем ответ, если (ответ == "OK") {Шаг = 5; Отсылаем "AT+CREG?";}
Шаг == 5 : дожидаемся и принимаем ответ, если (ответ == "+CREG: 1,1") {Шаг = 10; Отсылаем "AT+CMGF=1";}
Шаг == 10 : дожидаемся и принимаем ответ, если (ответ == "OK") {Шаг = 15; Отсылаем "AT+CSCS="GSM"";}
Шаг == 15 дожидаемся и принимаем ответ, если (ответ == "OK") {Шаг = 20; Отсылаем ... }
...
_delay_ms(3000);
}

Таким образом модулю отправляется команда и ожидается конкретный ответ. Если ответ не тот, который ожидается, команда отправляется ещё раз, и так до получения ожидаемого ответа.

Прошу покритиковать данный алгоритм или предложить алгоритм лучше.
Контактная информация:
Родился
Сообщения: 9
Зарегистрирован: Чт июн 05, 2014 22:09:46

Сообщение Zhevagin »

А если где-то сбой и правильный ответ никак не приходит? у Вас программа зависнет на этом месте? Тогда уж вводите количество попыток, прежде чем программа выйдет из цикла и сообщит о критической ошибке
Открыл глаза
Сообщения: 43
Зарегистрирован: Чт май 24, 2012 09:19:34
Откуда: Ярославль

Сообщение holy_0dmin »

Zhevagin
Хорошее замечание, спасибо. У меня в схеме ещё будет стоять ATTiny13A, управляющий питанием модуля и основного контроллера. Он всё время спит в Power-down, просыпается 1 раз в 8 секунд по Watchdog и в нужный момент включает модуль и контроллер. Я планировал ограничить время сессии 15 минутами, после чего ATTiny13A вырубил бы питание и МК, и SIM. Теперь ещё соединю основной МК и ATTiny13A несколькими ножками напрямую. При подъеме одной ATTiny13A будет перезагружать SIM, а при подъеме второй будет выключать всё до следующего сеанса связи.

Есть ли ещё какие-то замечания?
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 830
Зарегистрирован: Пт ноя 16, 2007 11:21:37

Сообщение Pavel_1978 »

А ты уверен что за 15 секунд у тебя модуль зарегестририруется в сети, поднимит GPRS соединение и законектится с сервером?
У меня В москве при уровне сигнала +QSC 28,9 регистрация в сети происходит за 5-10 сек, установка GPRS от 5 сек. Так что ваш алгоритм бред полный.
Открыл глаза
Сообщения: 43
Зарегистрирован: Чт май 24, 2012 09:19:34
Откуда: Ярославль

Сообщение holy_0dmin »

Pavel_1978 писал(а):А ты уверен что за 15 секунд у тебя модуль зарегестририруется в сети, поднимит GPRS соединение и законектится с сервером?
У меня В москве при уровне сигнала +QSC 28,9 регистрация в сети происходит за 5-10 сек, установка GPRS от 5 сек. Так что ваш алгоритм бред полный.
А мне не нужен GPRS, только звонки и SMS. И при чем здесь 15 секунд? По моему алгоритму раз в 3 секунды у модуля будут спрашивать AT+CREG? до тех пор, пока не получат правильный ответ +CREG: 1,1, и только после этого начнется работа со звонками и СМС.
А как вы работаете с модулями SIM90x?
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 830
Зарегистрирован: Пт ноя 16, 2007 11:21:37

Сообщение Pavel_1978 »

И что произойдет если модуль так и не ответит 1,1 или 1,0 пришлет???
Если работаете смс - включен ли отчет о доставке? Если у оператора затык и смска будет доставлена только завтра? что в это время ваш модуль будет делать? точнее МК который модулем рулит. Опять же пока идет ожидание ответа от модуля по Вашему алгоритму МК должен забить на все остальное - и нафига в такой системе модуль?
Открыл глаза
Сообщения: 43
Зарегистрирован: Чт май 24, 2012 09:19:34
Откуда: Ярославль

Сообщение holy_0dmin »

Pavel_1978 писал(а):И что произойдет если модуль так и не ответит 1,1 или 1,0 пришлет???
Если работаете смс - включен ли отчет о доставке? Если у оператора затык и смска будет доставлена только завтра? что в это время ваш модуль будет делать? точнее МК который модулем рулит. Опять же пока идет ожидание ответа от модуля по Вашему алгоритму МК должен забить на все остальное - и нафига в такой системе модуль?
Ожидание отчета о доставке не требуется. И у МК как раз и нет других задач кроме отправки СМС в нужный момент. Плюс таймаут работы 15 минут, после которого и МК, и модуль будут отключены.
И ещё раз спрошу: как работаете с модулем вы? Или это великий секрет?
Контактная информация:
Ответить

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