Jump to content

    

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

Вот подпрограмма, которая формирует 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
10 hours ago, VladislavS said:

Ты по что так AVR-ку мучаешь?

 

А что  б не расслаблялась. Пусть свои деньги отрабатывает

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
2 hours ago, VladislavS said:

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

 

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

Share this post


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

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

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

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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now