Выполнение кода всегда переходит в оператор else

#c #microcontroller #pic #microchip #mikroc

#c #микроконтроллер #рис #микросхема #mikroc

Вопрос:

В моем исходном коде происходят некоторые очень странные вещи. Следующая функция работает хорошо, и она выводит «y», когда пароль правильный, и выводит «n», когда он неверный. Но если я добавлю некоторые функции UART1_Write и Delay в оператор else, появится ошибка, и даже если пароль «zxc» (правильный), он ВСЕГДА вводит оператор else. Я использую mikroC PRO для PIC версии 6.0.0, роботизированная система состоит из PIC18F452 и подключенного к нему модуля Bluetooth RN-42. Я тестирую на ноутбуке с Bluetooth и TeraTerm.

Для получения дополнительной информации: http://instagram.com/p/pLnU9eDL8z /#

Здесь это хорошо работающая процедура:

 void authenticate() {
     char *input = "";
     char *password = "zxc";
     unsigned char ready = 0;

     while (connected amp;amp; !ready) {
           if (UART1_Data_Ready()) {
              UART1_Read_Text(input, "|", 17);
              strcat(input, "");

              if (strcmp(input, password) == 0) {
                 UART1_Write('y');
                 ready = 1;
              } else {
                 UART1_Write('n');
                 ready = 1;
              }
           }
     }
}
  

Эта версия процедуры ВСЕГДА выполняется в инструкции ELSE части strcmp(ввод, пароль) == 0:

 void authenticate() {
     char *input = "";
     char *password = "zxc";
     unsigned char ready = 0;

     while (connected amp;amp; !ready) {
           if (UART1_Data_Ready()) {
              UART1_Read_Text(input, "|", 17);
              strcat(input, "");

              if (strcmp(input, password) == 0) {
                 UART1_Write('y');
                 ready = 1;
              } else {
                 UART1_Write('n');
                 Delay_ms(100);
                 UART1_Write('$');
                 Delay_ms(100);
                 UART1_Write('$');
                 Delay_ms(100);
                 UART1_Write('$');
                 Delay_ms(100);
                 UART1_Write('K');
                 Delay_ms(100);
                 UART1_Write(',');
                 Delay_ms(100);
                 UART1_Write('-');
                 Delay_ms(100);
                 UART1_Write('-');
                 Delay_ms(100);
                 UART1_Write('-');
                 Delay_ms(100);
                 UART1_Write('n');
                 ready = 1;
              }
           }
     }
}
  

Важно отправить все эти символы добавления, чтобы перевести RN-42 в командный режим и отключить пользователя, если пароль неверный.
Пожалуйста, помогите мне решить проблему. Любые идеи приветствуются!

Комментарии:

1. Избавиться от при объявлении пароля? «zxc» вместо «zxc 0»?

2. UART1_Read_Text(input, "|", 17); Выделяет ли память для input ? Если нет, это может быть источником проблемы.

3. Да, то, что ранее говорили оба комментатора, и strcat(input, ""); ничего не делает, если ввод еще не завершен с нулевым завершением, strcat не будет этого делать и strcmp может не сработать из-за этого.

4. Вот описание процедуры UART1_Read_Text(): Считывает символы, полученные через UART, до тех пор, пока не будет обнаружена последовательность разделителей. Последовательность чтения сохраняется в выводе параметра; последовательность разделителей сохраняется в разделителе параметров. Это блокирующий вызов: ожидается последовательность разделителей, в противном случае процедура завершается (если разделитель не найден). Параметры: Вывод: полученный текстовый разделитель: последовательность символов, которая определяет конец принятой строки Попытки: определяет количество полученных символов, в которых ожидается последовательность разделителей.

5. Что касается утверждения @RSahu, кажется char input[18] = ""; , что было бы лучше, чем char *input = "" . Первый выделяет достаточно памяти для 17 символов и null, в то время как второй выделяет только null .

Ответ №1:

Как указывали другие в разделе комментариев, основная проблема вашего кода заключается в том, что вы пытаетесь сохранить данные UART в памяти, которая вам не принадлежит.

Когда вы объявляете char *input = ""; , вы фактически не выделили никакого пространства, кроме одного байта, который хранит « . Затем, когда вы используете UART1_Read_Text() , вы сообщаете этой функции, что у вас может быть до 17 символов, которые будут прочитаны до нахождения разделителя — все они должны храниться в месте, на которое указывает input .

Описание этой библиотечной функции можно найти здесь . Кроме того, на основе описания библиотеки похоже UART1_Read_Text() , что он уже добавляет нулевое завершение к данным UART. Я основываю это предположение на описании UARTx_Write_Text и примере, которые они предоставляют на своем веб-сайте. Однако я бы рекомендовал вам убедиться, что это действительно так.

Кроме того, ваша инициализация password является избыточной и char *password = "zxc" должна быть изменена на char *password = "zxc" . Когда вы объявляете строковый литерал с использованием двойных кавычек, он автоматически завершается нулевым значением. Этот отрывок взят из «C в двух словах»:

Строковый литерал состоит из последовательности символов (и / или escape-последовательностей), заключенных в двойные кавычки… Строковый литерал представляет собой статический массив символов char, который содержит коды символов, за которыми следует строковый ограничитель, нулевой символ … Пустая строка «» занимает ровно один байт в памяти, который содержит завершающий нулевой символ.

Основываясь на вышесказанном, я бы сделал это немного более похоже на это:

 #define MAX_NUM_UART_RX_CHARACTERS    17
void authenticate() 
{
    char input[MAX_NUM_UART_RX_CHARACTERS   1];
    char *password = "zxc";
    unsigned char ready = 0;

    while (connected amp;amp; !ready) 
    {
        if (UART1_Data_Ready()) 
        {
            UART1_Read_Text(input, "|", MAX_NUM_UART_RX_CHARACTERS);

            if (strcmp(input, password) == 0) 
            {
                UART1_Write('y');
                ready = 1;
            } 
            else 
            {
                UART1_Write('n');
                ready = 1;
            }
        }
    }
}