0 / 0 / 0
Регистрация: 24.07.2017
Сообщений: 6
|
||||||
1 | ||||||
AVR работа с указателями24.07.2017, 22:30. Показов 3657. Ответов 16
Метки нет (Все метки)
Помогите разобраться с кодом.
Нужно считать строку из порта и отправить ее обратно. Отправить строку в порт - все ок. Работает. Проблема с чтением. Решил в функцию передавать указатель. Объявляю указатель, строку*, присваиваю указатель адрес строки, передаю указатель функции. Читаю строку. Присваиваю ее значение по адресу из указателя. Для проверки вывожу в порт (выводится, все Ок.). Вывожу в порт строку* - выводит мусор. Помогите понять где я напортачил. Код:
0
|
24.07.2017, 22:30 | |
Ответы с готовыми решениями:
16
Странная работа Keil с указателями Работа с указателями Работа с указателями Работа с указателями |
1976 / 1275 / 130
Регистрация: 04.01.2010
Сообщений: 4,607
|
|
24.07.2017, 23:04 | 2 |
1) Дикая путаница с указателями и массивами указателей... Ну да ладно - если это еще и работает, то это просто чудо). Компилятор наверняка матерится на чем свет стоит - но это же не важно, если компилируется, верно?
2) Проблема кроется в настройках компилятора (и в самом компиляторе). В функцию вы передаете указатель на строку-константу, когда как функция работает исключительно с переменными (то есть RAM). В случае с AVR это разные вещи. Из FLASH данные читаются совсем не так, как из RAM. ЗЫ: вот за что я люблю CodeVision, так это за то, что в нем заранее можно сказать компилеру, куда ему класть переменную или константу - в RAM, FLASH или EEPROM. и компилер сам все сожрет (там внутри еще и с указателями путаница) и заработает сходу. ТС, читайте сообщения компилятора внимательнее...
1
|
210 / 163 / 36
Регистрация: 15.11.2012
Сообщений: 788
|
|
26.07.2017, 22:46 | 3 |
Сообщение было отмечено kurakste как решение
Решение
У вас каша в голове про строки и указатели - это нормально -), для начала.
В процедуре main: строка *pstr[255] организует вам 255 указателей, а не указатель на строку в 255 символов. pstr не инициализирован (указывает куда-то, вообще говоря на NULL). Напишите так: char str[255]; // это ваша строка char *pstr; // это указатель, но его надо инициализировать pstr=str; // вот теперь он указывает куда надо. Вот только не ясно, почему нельзя в параметре функции SerialReadString указать просто str (видимо, компилятор говорит об ошибке -)). Теперь о функции. Напишите заголовок так: void SerialReadString (char *ppstr) Таким образом, вы передаете адрес строки, в которую вам надо поместить принятую строку. Уберите char str[255] - он не нужен, ведь вы будете заполнять строку, адрес которой дали при вызове. Вместо str[numOfDataR++]=tmpCh; напишите *(ppstr+numOfDataR++)=tmpCh; *ppstr=str; - не нужна. не забудьте, что любая строка должна заканчиваться нулем - в конце процедуры напишите *(ppstr+numOfDataR)=0; Иначе сначала будет вывод полезный, а дальше - то, что идет дальше по памяти, пока там все-таки не встретится 0. На компе можно и мегабайт мусора так получить вместо (точнее, в дополнение) десятка полезных байт -).
1
|
0 / 0 / 0
Регистрация: 24.07.2017
Сообщений: 6
|
|
27.07.2017, 22:00 [ТС] | 4 |
Большое спасибо!
Помогло. Но статью про указатели прочел еще раз :-) Есть еще вопрос по этому коду. Как я себе понимал эти строки: SerialSendStringLn("Hi, it's a test of new serial library. Is it looks Ok?"); SerialSendString("input>>"); Должны выводиться один раз при старте программы. Но они выводятся при каждом подключении к порту. Как это работает?
0
|
210 / 163 / 36
Регистрация: 15.11.2012
Сообщений: 788
|
|
27.07.2017, 22:41 | 5 |
Должны выводится один раз. Вывод здесь можно сделать только один - контроллер перезапускается. Причины - вопрос отдельный, может быть много вариантов. Первый - при подключении к порту вы подаете питание, при отключении - убираете. Второй - сброс контроллера при подключении (наводки, емкости параллельно питанию контроллера в устройстве, которое вы подключаете).
Теоретически есть еще один вариант. Попробуйте вместо if (numOfDataR==255) написать if (numOfDataR==253). Это может изменить ситуацию. Я с mega328 не работал, но на довольно старых еще контроллерах at90s8515 (это тоже ядро AVR, позже он стал называться mega8515), сталкивался с тем, что они сбрасывались даже от касания платы пинцетом. В последующем была замена на mega16, с которым (на той же фактически плате - там только несколько ног изменено) подобных проблем не было. Однако осадочек остался -)).
1
|
1976 / 1275 / 130
Регистрация: 04.01.2010
Сообщений: 4,607
|
|
28.07.2017, 00:00 | 6 |
одним из отличий at90 и меги стало наличие подтяжки ресета. В принципе, очень много вопросов было у меня из-за этого.
Особенно, когда "на коленке". ТС, какой у Вас чип? Я еле нашел, откуда вам подсказывают насчет "меги328", но имя сторонней библы мне лично ни о чем не говорит. Учитывая ваши действия с памятью, вполне вероятно, вы можете выпадать банально в проблемы со стеком, например. Ничего еще не сделав, вы "легко" выделяете 1кб памяти, что в случае с имбеддед - "это просто праздник какой-то". 1КБ, это роскошь, которой обзавидуются многие разработчики программ для МК . Хотя, я тоже склоняюсь к описанной ув. alexey6689 выше возможной проблеме/
1
|
210 / 163 / 36
Регистрация: 15.11.2012
Сообщений: 788
|
|
28.07.2017, 00:16 | 7 |
Ну, думаю и есть mega328.
Памяти там 2 КБ, а выделяется 255 байт. Жирненько, но для сброса мало. Тем более что написано, что сброс происходит в момент подключения внешнего устройства. Очевидно, при уже подключенном устройстве все работает. Подтяжка дела не решала - у меня всегда был и резистор на питание, и кондюк. Переход на mega8515 ничего не изменил. Коренным образом дело поменялось после перехода на mega16.
1
|
0 / 0 / 0
Регистрация: 24.07.2017
Сообщений: 6
|
||||||
28.07.2017, 21:51 [ТС] | 8 | |||||
Это действительно atmega328p на плате ардуино уно. Взял поиграть и что-то меня увлекло.
Я посмотрел сейчас осциллографом питание - вроде нет никаких изменений при подключении к порту. Посоветуйте алгоритм как понять в чем глюк. Условия следующие: Плата ардуино запитана от USB. Тот который штатно стоит на плате. Подключаюсь к ней через программу Terminal v1,9b К плате ничего не подключено. Мог я что-то напортачить при инициализации usarta? код:
Я так понимаю, что чего-то не понимаю. Я думал что есть у меня 2к памят и это размер переменных + констант которые которые я могу использовать. Прочитав сообщение, задумался о том, что стек тоже лежит в этой памяти. Я вроде стек не использую, но наверное вызов функций с++ сопровождается работой со стеком. А сколько он под него выделил и как расходует не ясно. Потом переменные в функциях живут только в функциях, но может так случится, что при запуске функции не останется место под ее переменные. По идеи компилятор должен был зарезервировать место под это заранее. С другой стороны бестоковый расход памяти. Интересно как он себя ведет? Я в правильную сторону думаю? Или что-то еще упустил?
0
|
210 / 163 / 36
Регистрация: 15.11.2012
Сообщений: 788
|
|
29.07.2017, 03:02 | 10 |
Сообщение было отмечено kurakste как решение
Решение
Да, стек тоже в памяти. Я не знаю, какой у вас компилятор, я работаю в IAR, там размер стека задается в файле .xcl линковщика. Если на стек мало места - возможны странности. Но в моей практике это всегда приводило к зависанию, не к перезапуску.
Вот насчет констант это правда. И на мой взгляд это какой-то косяк. Я задаю константную строку, и она занимает место в оперативной памяти. Приходилось использовать для таких строк атрибут flash, однако работа с ней при этом возможна только специальными функциями, которые умеют из памяти программ брать данные (например, sprintf_P вместо sprintf) - последствия использования гарвардской архитектуры. Если вас напрягает постоянное выделение памяти под переменные в функции, задавайте их с ключевым словом static. Тогда в отчете компилятора (точнее, линковщика) вы сможете узнать сколько именно байт требует ваша программа и данные. Добавлено через 2 минуты А проверку я бы сделал так: в начале программы зажигайте светодиодик какой-нибудь (там они наверняка есть), а через секунду скажем гасите его. Программу для работы с RS при этом можно (и даже нужно) убрать - ведь задача понять это она виновата или электрика. Далее подключайте разъемы, постучите по плате чем-нибудь металлическим (касаясь токоведущих частей, только замыкать их не надо -). Если контроллер сбрасывается, светодиодик будет мигать. Добавлено через 7 минут Как бы вы не задали режим RS, он просто либо будет работать, либо не будет. К сбросу это приводить не должно в любом случае. Однако если линия RxD контроллера не притянута к плюсу, то при отключении вашего разъема контроллер может начать непрерывный прием байта 0 (там будет вылезать ошибка отсутствия стоп-бита, но неизвестно как ведут себя ваши программы-обработчики, да и из самого даташита не очень ясно, будет ли USORT выдавать это байт как принятый несмотря на ошибку). Правда, при корректных обработчиках это тоже к сбросу не приведет. Добавлено через 1 минуту А у вас есть принципиальная схема вашей ардуины, а так же устройства, которое вы втыкаете? Посмотреть бы. Добавлено через 1 минуту Так... Подождите, что вы понимаете под словами "подключаюсь и отключаюсь"? Что вы подключаете и отключаете?
1
|
0 / 0 / 0
Регистрация: 24.07.2017
Сообщений: 6
|
|
29.07.2017, 08:13 [ТС] | 11 |
Похоже не ясно выразился. Ардуина постоянно подключена через USB разъем. Я ее питаю и прошиваю пока через него.
Под подключать я имел ввиду нажатия кнопки коннект в терминальной программе (пробовал в разных). Добавлено через 1 минуту компилятор- atmel studio. Скачал с их сайта.
0
|
210 / 163 / 36
Регистрация: 15.11.2012
Сообщений: 788
|
|
29.07.2017, 19:13 | 12 |
Тогда что-то странное действительно.
Покажите текущий вариант вашей программы?
0
|
0 / 0 / 0
Регистрация: 24.07.2017
Сообщений: 6
|
||||||
29.07.2017, 21:10 [ТС] | 14 | |||||
Вот и я не пойму как это работает. Код я переписал, но эффект тот же:
0
|
210 / 163 / 36
Регистрация: 15.11.2012
Сообщений: 788
|
|
29.07.2017, 21:59 | 15 |
Что-то вас бросает из одной крайности в другую. Долго пытался понять, что вообще делает эта программа и почему она вообще должна выводить что-то кроме Hello, world!
Также я не знаю что будет, если выходить из контроллерной процедуры main. Никогда так не делал. Выполнение начнется сначала?
0
|
0 / 0 / 0
Регистрация: 24.07.2017
Сообщений: 6
|
||||||
29.07.2017, 23:34 [ТС] | 16 | |||||
Я дописал включение выключение светодиода внутри этого кода.
Программа работает как должна - один раз отрабатывает и все. А вот терминальные программы выводят сообщения при каждом подключении. Получается система? то что выдал контролер записала в какой-то буфер и теперь каждый раз выдает эту строчку. Странно. Теперь переписал код:
Добавлено через 1 час 27 минут Я был не прав. При подключении терминала к ардуине она перезагружается. Погуглил - нашел ответ: Именно USB-serial контроллер Arduino перезагружает МК каждый раз, когда терминальная программа (в т.ч. Serial monitor, встроенный в ПО Arduino IDE) устанавливает соединение. Реализовано это следующим образом: у USB-serial контроллера вывод DTR (Data Terminal Ready) связан с выводом RESET. Если программа, работающая с виртуальным последовательным портом, использует DTR, то при установке соединения МК перезагружается.
0
|
210 / 163 / 36
Регистрация: 15.11.2012
Сообщений: 788
|
|
30.07.2017, 05:19 | 17 |
Да уж... Впрочем, просмотр принципиальной схемы решил бы этот вопрос, думаю, существенно быстрее.
0
|
30.07.2017, 05:19 | |
30.07.2017, 05:19 | |
Помогаю со студенческими работами здесь
17
Работа с указателями работа с указателями Работа с указателями Работа с указателями Работа с указателями Работа с указателями работа с указателями Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |