Jump to content

    

Salamander

Участник*
  • Content Count

    568
  • Joined

  • Last visited

Everything posted by Salamander


  1. СТранная проблема... Использую DWT для микросекундных задержек и прочих шалостей. Инициализирую вот так uint32_t DWT_Delay_Init(void) { /* Disable TRC */ CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk; // ~0x01000000; /* Enable TRC */ CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // 0x01000000; DWT->LAR = 0xC5ACCE55; /* Disable clock cycle counter */ DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk; //~0x00000001; /* Enable clock cycle counter */ DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; //0x00000001; /* Reset the clock cycle counter value */ DWT->CYCCNT = 0; /* 3 NO OPERATION instructions */ __ASM volatile ("NOP"); __ASM volatile ("NOP"); __ASM volatile ("NOP"); /* Check if clock cycle counter has started */ if(DWT->CYCCNT) { return 0; /*clock cycle counter started*/ } else { return 1; /*clock cycle counter not started*/ } } Когда устройство под отладчиком - все работает. Стоит отсоединиться или просто стартовать без отладчика - в тех местах где программа ждет определенного значения счетчика, она зависает. Такое ощущение, что счетчик не считает. В чем может быть проблема? У меня проц STM32H743, на других процах такого не было. Точнее было на F746, но там это вылечилось добавлением в код DWT->LAR = 0xC5ACCE55; Тут же не прокатило. Что скажете?
  2. Сделал как в статье по ссылке char *strdup(const char *src) { size_t len = strlen(src) + 1; char *s = malloc(len); if (s == NULL) return NULL; return (char *)memcpy(s, src, len); } Схавал компилятор это. Дальше применяю: char months[] = "JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC"; char** tokens; tokens = str_split(months, ','); if (tokens) { int i; for (i = 0; *(tokens + i); i++) { printf("month=[%s]\n", *(tokens + i)); free(*(tokens + i)); } printf("\n"); free(tokens); } смотрю опосля в отладчике переменную tokens. В ней только один элемент - нулевой, он правильный. Хотя в цикле if (result) { size_t idx = 0; char* token = strtok(a_str, delim); while (token) { assert(idx < count); *(result + idx++) = strdup(token); token = strtok(0, delim); // ставлю брейкпоинт, token всегда правильный } assert(idx == count - 1); *(result + idx) = 0; } ставлю брейкоинт - token всегда правильный. Где косяк? Блин... не умею просто пользоваться отладчиком. Все нормально, все разбивается по разделителю, все читается.
  3. Эээ... Ммм... Если нетрудно, можно поподробнее, для тупых?
  4. Хм.. Вы указали на функцию, которая вызывается в той функции, что я привёл. Что скажете?
  5. Друзья еще вопрос. Нашел готовую функцию разбиения строки на подстроки по разделителю #include "stdio.h" #include "stdlib.h" #include "string.h" #include <assert.h> char** str_split(char* a_str, const char a_delim) { char** result = 0; size_t count = 0; char* tmp = a_str; char* last_comma = 0; char delim[2]; delim[0] = a_delim; delim[1] = 0; /* Count how many elements will be extracted. */ while (*tmp) { if (a_delim == *tmp) { count++; last_comma = tmp; } tmp++; } /* Add space for trailing token. */ count += last_comma < (a_str + strlen(a_str) - 1); /* Add space for terminating null string so caller knows where the list of returned strings ends. */ count++; result = malloc(sizeof(char*) * count); if (result) { size_t idx = 0; char* token = strtok(a_str, delim); while (token) { assert(idx < count); *(result + idx++) = strdup(token); token = strtok(0, delim); } assert(idx == count - 1); *(result + idx) = 0; } return result; } Проект с этой функцией компилируется, то есть никаких неизвестных функций в коде нет. Но вот при линковке получаю "Error: L6218E: Undefined symbol strdup (referred from main.o)." Блин... почему так? Стандартные же библиотеки, include прописаны, чего еще не хватает? у меня KEIL, если что. в string.h прототип strdup не описан. Я понимаю, что код писался под навороченные компиляторы и библиотеки к ним, а в KEIL они урезанные что ли.... но чем заменить эту функцию тогда?
  6. Решил костылем. Просто понял, что проблема действительно не имеет чисто математического решения. Заполнял экран, сверху вниз, а опосля включал скроллинг.
  7. Действительно, обнуляется. Ваш код (я уменьшил число строк до 15 для удобства) for(int i = 0; i<100; i++) { int j = i + str_buffer_write_position; if( j > 14) j -= 15; printf(&TERMINAL_TEXT[j][0]); } работает отлично. Если понаблюдать отладчиком то имеем полноценный кольцевой буфер. Но.... блин, вроде задача простая, а я что-то мозг весь сломал. Проблемы начинаются при чтении этого буфера. Хочу чтобы выглядело так - получили первую строку - она вывелась первой, получили вторую строку - на экране ниже первой появилась вторая, ну как при печати. А когда экран заполнен (15 строк) начинается скроллинг. По факту имеем следующее - получаем нулевую строку - она появляется в последней строке экрана, получаем следующую строку - нулевая перескакивает выше, внизу появляется новая. Если непонятно - я хочу, чтобы выглядело как при печати текста, а выглядит как финальные титры фильма. Почему так получается? Смотрите, получена первая строка, str_buffer_write_position=1. Начинаем выводить, заполняем первую строку дисплея. i=0, тогда j = i + str_buffer_write_position дает нам "1". И программа читает строку не из нулевого элемента массива, а из первого, а там пусто. И так дальше. И лишь когда мы выводим последнюю строку, у нас срабатывает if( j > 14) j -= 15; и мы получаем "указатель" на нулевой элемент массива. Логичная попытка сделать j = i + str_buffer_write_position -1 (уменьшили на единицу) - это работает только на первой строке. Как только появляется следующая строка, str_buffer_write_position увеличивается до 2 и тогда уже нужно отнимать 2. По сути - до того как экран заполнится полностью, j = i + str_buffer_write_position нужно заменить на j=i. И тогда работает. Но после заполнения экрана скроллинга нет по понятным причинам. Я конечно могу сделать проверку, поставить некий флажок после заполнения экрана, по срабатыванию которого меняется алгоритм, но мне это кажется "костылем". Хочется сделать изящно.... И не дает покоя мысль, что где-то ошибка, которую можно без костыля решить. ЧТо думаете?
  8. А зачем тут то остаток получать? Str_buffer_write_position на данном этапе гарантированно будет обнуляться после ста, за счёт предшествующего кода.
  9. Я понял в чем ваша идея. Я, по глупости, переписывался содержимое всего массива. Нулевой элемент затирал первыпэм, первый затирал вторым... последний - новым. И так 100 раз. Вы же предлагаете затирать новым элементом самый старый элемент. А чтобы не переписывать все остальные, просто сдвигать фокус чтения и нумероватт элементы от этого самого фокуса. То есть, скажем, получили мы 103 строку, она запишется в третий элемент массива. А чтобы вывести список строк, нам нужно читать с четвёртого по сотый, а дельше нулевой, первый и второй. И так далее. Я правильно понял?
  10. Идея не совсем понятна. Точнее понятна задцэумка - делать скроллинг не строк по 256 байт, а только указателей на них. Но дальше что? Сам исходный буфер тоже надо обновлять... А.. Погодите, кажется понял. Исходгэный буфер сделать кольцевым, а массивом указателей по нему как бы скользить. Чтобы последний элемент массива указателей всегда указывал на только что обновлённый элемент исходного буфера? Ещё есть сопутствующие вопрос. Скажите а что происходит, если при возникновении прерывания по приёму UART, оно успевает обработаться аппаратно, но не успевает программно? У меня пока что код скроллинг а находится в обработчике прерывания. Знаю, это не рационально, но скорость позволяла, между входящими посылка и времени достаточно. Но иногда бывает, что приходит две посылки подряд. Чтение из регистров UART я успеваю сделать, строку тоже успеваю, а вот когда идёт скроллинг - приходит следующая посылка. Выносить скроллинг за пределы обработчик прерывания? Хм... В принципе, с описанным вами вариантом кольцевого буфера это несложно.
  11. В общем я сделал вот так: #define RX_BUFFER_SIZE 256 uint8_t rx_buffer[RX_BUFFER_SIZE]; char TERMINAL_TEXT[100][256]; for(uint8_t i=0;i<255;i++) TERMINAL_TEXT[str_buffer_write_position][i]=rx_buffer[i]; Работает. Дальше мне понадобился скроллинг. То есть, есть 100 строк, появляется 101-я, я в цикле переписываю содержимое строки n+1 в строку n, и лишь потом пишу 101ю строку в ячейку №100. Сделал переписывание грубо, топорно, чтобы хотя бы посмотреть на текст на экране for(uint8_t i=0;i<100;i++) { for(uint8_t j=0;j<256;j++) TERMINAL_TEXT[i][j]=TERMINAL_TEXT[i+1][j] } Вопрос такой - сопряжен ли такой способ копирования с существенным замедлением быстродействия? Есть более быстрые способы?
  12. Господа, ситуация такая. Есть массив из 100 строк char* strings_buffer[10]={"1","2","3","4","5","6","7","8","9","10"}; Есть массив из обычных байт, в который принимаются данные по UART uint8_t rx_buffer[RX_BUFFER_SIZE] = {0,}; Когда ловится символ конца строки, то все содержимое rx_buffer с нулевого символа до того, где был пойман конец строки, должно копироваться в массив строк, точнее в один из его элементов под номером str_buffer_write_position. Я не стал заморачиваться с классическим кольцевым буфером, так как длина принимаемых строк гарантированно не превышает RX_BUFFER_SIZE, после захвата последовательности r\n индекс записи просто переносится на нулевой элемент rx_buffer for (uint8_t i=0;i<rx_write_buffer_position;i++) *strings_buffer[str_buffer_write_position]++=rx_buffer[i]; не работает, вылетает в хард (контроллер STM32) Что я делаю не так?
  13. Поковырялся - заработала вторая микросхема, но все равно какая-то лажа. Пишет нормально. А вот при чтении данные одной микросхемы смещены относительно данных другой. На один байт. Иными словами, DummyCycles в норме должен быть 8. Тогда нормально читается первая микросхема. Если поставить 6, то вторая микросхема начинает выдавать данные несмещенные, но при этом смещение возникает в первой микросхеме.....
  14. Друзья, вчитайтесь в описание ситуации: Контроллер STM32H743, на контроллере установлена QSPI W25Q128 - работает как одна микросхема, так и в режиме DualFlash. Меняю память на MT25QL128. Микросхемы разные, но я настроил параметры так, чтобы они были универсальны - то есть, без изменений в коде меняешь W25Q на MT25Q - все работает. Но почему-то это прокатывает только для режима одной микросхемы. В режиме DualFlash работает только W25Q, если меняю на MT25Q - вторая микросхема работать отказывается, выдает 0x88. Думал, что неисправна микросхема - менял местами первую и вторую, как выяснилось - сбоит не конкретная микросхема, а конкретное место, то есть Flash_ID 2. Грешил на проблемы в контроллере или плате - повторюсь, стоит снять обе микросхемы Mt25Q и поставить w25q - все работает. В чем может быть проблема?
  15. Вычислять размер зума не умеет. Собственно так и сделал. 2 часа ковыряний, 2 чашки кофе и все работает, не без косяков пока, но принципиально задача с зумом решена. Теперь у меня как в том ролике
  16. Ахахах, уписаться можно)))) Сделал я как вы сказали - с численными значениями координат все нормально. Они меняются как надо. А смена направления вращения - это ИЛЛЮЗИЯ! Камера при переходе через горизонт почему-то переворачивается на 180 градусов вокруг оси, соответствующей направлению взгляда. И кубик, который только что "падал" от нас, начинает на нас "заваливаться". Да.... с этой то проблемой я разобрался, теперь нужно лезть в библиотеку и искать где там настройки поворота камеры.
  17. А вот и нет. Входной параметр у меня в норме. Смотрю его отладчиком Вот окончательный вариант dsp3D_setCameraPosition(10*arm_sin_f32(zenital)*arm_cos_f32(azimuthal), 10*arm_cos_f32(zenital), -10*arm_sin_f32(zenital)*arm_sin_f32(azimuthal)); // Перемещаем камеру (при этом сама камера всегда смотрит в точку 0,0,0) dsp3D_setLightPosition(10*arm_sin_f32(zenital)*arm_cos_f32(azimuthal), 10*arm_cos_f32(zenital), -10*arm_sin_f32(zenital)*arm_sin_f32(azimuthal)); // Перемещаем камеру (при этом сама камера всегда смотрит в точку 0,0,0) Смена направления у меня происходит как раз, когда значение zenital переходит через ноль. Блин.... так все правильно - Z у меня рассчитывается по формуле sin*sin, при отрицательном угле зенита оба синуса отрицательные, в произведении это дает плюс. Я понял.... надо в зависимости от полярности зенитного угла менять полярность Z
  18. Помогите мне разобраться с детекцией ZOOM in и ZOOM out. Вот даташитик https://www.newhavendisplay.com/appnotes/datasheets/touchpanel/FT5x16_registers.pdf Как засекать этот самый зум понятно - читаю GEST_ID по адресу 0x01, микросхема распознает оба направления зума. Возникает вопрос - как определить дельту, то есть насколько мы прозуммировали. И вот тут первый вопрос - я правильно понял, что микросхема это вычислять не умеет? Если нет, то ткните носом. Если не умеет, тогда как это сделать ручками? Вот предположим, прочли мы в регистре, что имеет место быть ZOOM in, прочли текущие координаты двух точек касания. А как понять, насколько проскользили пальцы, до момента детекции? Чтобы было с чем сравнивать и рассчитывать масштаб зума..... Есть у микры такой параметр - порог детекции ZOOM - он равен 50, то есть зум детектируется если пальцы скользят более чем на 50 точек по направлению друг к другу (или наоборот). Проскользили еще на 50 - еще одно событие зума. Но меня такой зум, с разрешением в 50 точек не устраивает. Одно дело порог распознавания 50, и совсем другое - разрешающая способность. У кого есть опыт? Ах, да, забыл. Странным кажется то, что если самому в непрерывном режиме мониторить координаты двух точек касания, то не составляет труда самому поймать событие ZOOM. Спрашивается - зачем тогда эта функция присутствует в микросхеме на аппаратном уровне? Так может все таки как-то можно величину зума вытащить из микросхемы?
  19. Вы уверены, что в этом случае будут какие-то проблемы помимо неправильного положения объекта перед камерой? Точнее в ошибке поворота, составляющей 90 градусов? Смотрите, я отклоняю камеру в зените на некий угол - отклоняю бесконечно, и неважно, что у меня идет после 360 - 361 или 1 - камера должна идти по кругу. У меня же почему то движение только в пределах полупериода, в следующем полупериоде направление движения меняется. Она самая http://900igr.net/up/datas/183262/021.jpg
  20. Сделал, работает. Не совсем так как думалось изначально - если камеру поднять высоко, то она по азимуту описывает воронку - но так даже лучше. Но все равно с зенитом фигня - не хочет камера подныривать по горизонтальную плоскость. То есть угол в -1 градус воспринимается как угол в 1 градус и так далее. Угол в 181 градус воспинимается как угол в 179 градусов
  21. Ага.... разница в том, что в моей библиотеке ось Z смотрит на экран, а в формуле - вверх. Переставил оси - вроде заработало почти как надо. Только вот зенит почему-то работает только в пределах 0-180 градусов.... пытаешься заглянуть под объект, при пересечении 0 или 180 градусов начинается вращение в обратную сторону. Это как побороть? dsp3D_setCameraPosition(10*arm_sin_f32(zenital)*arm_sin_f32(azimuthal), 10*arm_cos_f32(zenital), 10*arm_sin_f32(zenital)*arm_cos_f32(azimuthal)); Вот такая на данный момент формула
  22. Плоскость XY смотрит на меня Из нее же на меня направлена ось Z. В этом случае отличие способа отсчета должно сказаться лишь на том, куда будет смотреть камера при угле, скажем, 0 градусов - на "фасад" или на "крышу". Но на вращение то это не должно влиять. Вот видео поведения куба. Посмотрите как меняется его вращение при изменении азимута, вначале он наклоняется вокруг горизонтальной оси, а потом почему-то вращается вокруг вертикальной. https://cloud.mail.ru/public/whtu/BXQvRUxSV
  23. Добрый день, друзья. Есть у меня 3D библиотека, настроил я ее, нарисовал кубик. Теперь хочу его покрутить (при помощи сенсорного экрана). Вначале я крутил сам кубик, но не получил желаемого результата - стоит его горизонтальным движением пальца повернуть вокруг вертикальной оси, вместе с ним поворачивается и горизонтальная (что естественно), а когда после этого начинаешь водить пальцем вверх-вниз, он не заваливается взад-вперед относительно наблюдателя, а крутится вокруг изменившей свое пространственное положение горизонтальной оси (что, опять-таки, естественно). Я решил поступить по другому - вращать не объект, а перемещать камеру вокруг кубика. То есть точка прицела камеры всегда в координатах 0,0,0, а сама камера гуляет по поверхности сферы радиусом 10. Иными словами - ведешь по экрану вверх-вниз - меняется зенитный угол, ведешь вправо-влево - меняется азимут. Высчитываю по вот такой формуле В коде это выглядит так: azimuthal+=(float32_t)d_evt.getDeltaX()/495; // Преобразуем горизонтальный пробег пальца по экрану в приращение азимута zenital+=(float32_t)d_evt.getDeltaY()/445; // Преобразуем вертикальные пробег пальца по экрану в приращение зенитного угла dsp3D_setCameraPosition(10*arm_sin_f32(zenital)*arm_cos_f32(azimuthal), 10*arm_sin_f32(zenital)*arm_sin_f32(azimuthal), 10*arm_cos_f32(zenital)); // Перемещаем камеру (при этом сама камера всегда смотрит в точку 0,0,0) Вращение камеры почему-то неадекватное. Даже трудно описать в чем, но чем дальше поворачивается кубик, тем неадекватнее его реакция на движение. проверял отладкой преобразование пробега пальца по экрану в параметры azimuthal и zenital - оно адекватное. Саму камеру перемещал вверх-вниз, вправо-влево - тоже адекватно. Но она при этом движется во фронтальное плоскости перед объектом, что не соответствует желаемому. А желаемое - двигаться в пределах сферы, окружающей объект. В упор не вижу ошибки, в чем она может быть? взглянем, к примеру на формулу расчета Z - из нее вытекает, что Z зависит только от зенитного угла, но ведь это не так! Если камера, не меняя зенита, будет "водить хоровод" вокруг объекта, Z ведь должен меняться...
  24. Зачитано до дыр. У меня есть проект, сгенерированный кубом, на HAL. С этим проектом при миграции с W25Q на MT25Q нужно просто перепаять микросхему и, кажется, поменять DUMMY_CYCLES. Алогритм, то есть шаблон, работает с несколько другим кодом. Мне кажется, что проблема в самой библиотеке, а не в тактике работы с микросхемой. Короче, в новом кейле версии 5.33, есть DFP версии 2.7.0. А там наконец-то появились и алоритмы под H747 и исходники. Копну там.