#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;
}
}
}
}