Jump to content

    
Sign in to follow this  
IF_P

Длина имени указателя IAR AVR

Recommended Posts

Вот подпрограмма, которая формирует AT-команду.

void Form_AT (void)
{
  uchar i;
  char preamb[4] = "AT+";
  char *P_IN;
  char BAUD_HC_12[8][7] = {"1200", "2400", "4800", "9600", "19200", "38400",
                           "57600", "115200"};



//  P_OUT_BUF = BUF_HC;
    P_OUT_BUF_HC = BUF_HC;




    for(i = 0; i < 15; i++) BUF_HC[i] = 0x00;
    strcat (BUF_HC, preamb);

    switch (command)
    {
      case 3:                
        strcat (BUF_HC, "B");
        strcat (BUF_HC, BAUD_HC_12[baud_HC]);
        count_buf_HC = strlen (BUF_HC);
      break;

      case 4:                 
        strcat (BUF_HC, "C"); 
        Bin_To_ASCII(channel_HC);                        
        P_IN = Rab.symv6.symv3;                          


//      P_OUT_BUF += 4;                                
        P_OUT_BUF_HC += 4;                               


//      for(i = 0; i < 3; i++) *P_OUT_BUF++    = *P_IN++; 
        for(i = 0; i < 3; i++) *P_OUT_BUF_HC++ = *P_IN++;


        count_buf_HC = strlen (BUF_HC);
      break;
    }
}

В хидерном файле есть описание указателя

char    BUF_HC[15];
//char    *P_OUT_BUF;

char    *P_OUT_BUF_HC;

 

все нормально работает, если имя указателя P_OUT_BUF.

Если меняю имя указателя на P_OUT_BUF_HC, то в цикле for ничего не происходит (не записывает в буфер и длина остается = 4) . В чем может быть причина?

Share this post


Link to post
Share on other sites
6 часов назад, IF_P сказал:

В чем может быть причина?

В стиле программирования. Ты по что так AVR-ку мучаешь?

 

Для поиска проблемы попроси компилятор сделать ассемблерный листинг и смотри что там происходит.

 

Насчёт "мучать AVR-ку". Сравни использование RAM (особенно стека) в твоём и в этом коде.  Да и FLASH в итоге меньше потребуется, так как не нужен код для формирования строк и "гоняния" их по RAM.

#include <stdint.h>
#include "pgmspace.h"

__flash const char at_br[8][11] = {"AT+B1200", "AT+B2400", "AT+B4800", "AT+B9600", "AT+B19200", "AT+B38400", "AT+B57600", "AT+B115200"};

char buf_hc[15];

void AT_BR(char *dst, uint8_t br)
{
  strcpy_P(dst,at_br[br]);
}

int main()
{
  uint8_t command = 3;
  uint8_t br = 4;
  
  switch(command)
  {
    case 3:
      AT_BR(buf_hc,br);
      break;
    case 4:
      // ....
      break;
  }
  
  for(;;);
}

И длину строки не надо по сто раз считать и хранить. Зачем тратить на это время и место? Она же нультерминированная, там где её выводишь пользуйся этим.

 

И зачем PU_OUT_BUF глобальная? Как можно локальней надо делать переменные. Так и ошибок меньше будет, и компилятору проще оптимизировать. Сделай ты её локальной, она просто в регистрах прокрутится и умрёт там же не заняв SRAM вообще.

Share this post


Link to post
Share on other sites
11 hours ago, VladislavS said:

В стиле программирования.

И зачем PU_OUT_BUF глобальная? Как можно локальней надо делать переменные. Так и ошибок меньше будет, и компилятору проще оптимизировать. Сделай ты её локальной, она просто в регистрах прокрутится и умрёт там же не заняв SRAM вообще.

Ну во-первых, у каждого свой стиль программирования.

Во-вторых , тут только часть кода. Поэтому вам не видно весь алгоритм.

Скорости тут  описаны как локальные для отладки. Но в будущем я их перенесу во флэш, т.к. они буду использоваться еще в другом месте. А там мне "AT+" ни к чему.

В-третьих, для этой команды можна так использовать флэш. А как быть с командой "AT+Cxxx", где ххх вводится с пульта от 0 до 127. Не буду же я прописывать все варианты во флэш. Вот поэтому и остановился на таком варианте.

Ну и наконец, указатель PU_OUT_BUF нужен именно глобальный, т.к. массив BUF_HC в этой п/п будет выдаваться в UART:

    UCSRB &=~ ( 1 << RXCIE );
    UCSRB |=    ( 1 << TXCIE );

    P_OUT_BUF_HC = BUF_HC;   

    UDR = *P_OUT_BUF_HC;
    P_OUT_BUF_HC++;

А далее по прерыванию с использованием данного указателя.

 

А что касается первого поста, то сейчас все работает. По шагам все менял и заработало. Причину пока не установил.

Edited by IF_P

Share this post


Link to post
Share on other sites
1 час назад, IF_P сказал:

А далее по прерыванию с использованием данного указателя.

Используется в прерывании, а volatile не наблюдается. 

Впрочем, мне всё равно - отрабатывайте свои деньги :)

Share this post


Link to post
Share on other sites
15 minutes ago, VladislavS said:

Этому есть хоть какое-то разумное объяснение?

Программа простая и не ограничивает меня ни по коду, ни по времени исполнения.

Share this post


Link to post
Share on other sites
23 минуты назад, IF_P сказал:

Программа простая и не ограничивает меня ни по коду, ни по времени исполнения

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

Share this post


Link to post
Share on other sites
20 minutes ago, Сергей Борщ said:

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

Может я чего-то не понимаю. Чем я создаю себе трудности? Зачем везде сунуть оптимизацию? Объясните, пожалуйста, зачем в моём случае нужна оптимизация.

Share this post


Link to post
Share on other sites
1 час назад, IF_P сказал:

Программа простая и не ограничивает меня ни по коду, ни по времени исполнения.

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

 

PS: Вам дают советы, Вы - спорите с ними. Совершенно не понимая и не пытаясь понять смысла советов. Зачем тогда задавали вопрос?

По стилю (а скорее - его отсутствию) я согласен с VladislavS.

 

27 минут назад, IF_P сказал:

Объясните, пожалуйста, зачем в моём случае нужна оптимизация.

Оптимизация всегда полезна. Вне зависимости от простоты программы. Она позволяет выявить многие скрытые ошибки. Если у вас без оптимизации работает, а с ней - нет, значит - код кривой и надо искать баги.

 

5 часов назад, IF_P сказал:

По шагам все менял и заработало. Причину пока не установил.

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

Share this post


Link to post
Share on other sites
1 hour ago, jcxz said:

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

 

PS: Вам дают советы, Вы - спорите с ними. Совершенно не понимая и не пытаясь понять смысла советов. Зачем тогда задавали вопрос?

По стилю (а скорее - его отсутствию) я согласен с VladislavS.

Я как раз пытаюсь понять. Что касается volatile, я спорить не буду, возможно Вы правы.

А вот по стилю хотел бы кое-что уточнить.

VladislavS предложил;

1. AT-команды хранить во флэш. Для некоторых команд это подойдёт, тут я согласен. А вот для AT+Cxxx (где х= 0 - 127) все равно придется использовать формирование строки в п/п.

2. Не вычислять длину строки буфера, а воспользоваться нуль-терминированием. Но в программе обработки прерываний UART мне нужно будет передавать не только строки, но и 16-ные данные из другого буфера. В таком случае проще иметь длину буфера данных. Это займет немного машинного времени, но упростится программа обработки прерываний.

Возможно, я в чем-то ошибаюсь. Буду рад выслушать Ваш комментарий.

 

P.S.

Вот только что посмотрел, что длину строки можно вычислять один раз перед выдачей  в UART.

Edited by IF_P

Share this post


Link to post
Share on other sites
6 hours ago, IF_P said:

А зачем volatile? Я не использую здесь оптимизацию.

Правильно. Вместо вас, её использует компилятор. Настоятельно присоединяюсь к советам выше, и рекомендую вам прочитать, что такое volatile.

Share this post


Link to post
Share on other sites
12 часов назад, IF_P сказал:

т.к. они буду использоваться еще в другом месте. А там мне "AT+" ни к чему

Адрес строки без "AT+B" будет at_br[br]+4 . Это не потребует ни одного дополнительного байта кода, так как для доступа к такой подстроке будет просто использоваться другая константа начального адреса.

// С AT+B
        LDI     R30, LOW(at_br)
        LDI     R31, HIGH(at_br)
          
// Без AT+B
       LDI     R30, LOW((at_br + 4))
       LDI     R31, HIGH((at_br + 4))

Дарю.

Share this post


Link to post
Share on other sites

А вообще, мой посыл по стилю был в том, что переменные надо как можно локальней делать.  Та же глобальная P_OUT_BUF зачем используется в функции там где можно было обойтись локальной переменной? Да ещё потом оказывается, что она в каком-то прерывании используется. Ужас! Вот смотри, в С++17 даже ввели вот такую возможность

if(int i=0; x<y) { ... } else { ... }

И это сделано отнюдь не для того чтобы экономить строки в коде.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this