Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.54/50: Рейтинг темы: голосов - 50, средняя оценка - 4.54
dr_tyvsiy
0 / 0 / 0
Регистрация: 21.02.2010
Сообщений: 231
1

Передача строк/чисел в контроллер (решено)

18.10.2012, 12:58. Просмотров 8945. Ответов 15
Метки нет (Все метки)

Контроллер STM32F102C8T6. Передаю строки по USB. В строке содержится двоичное 4 разрядное число типа "1010" (но разряды в обратном порядке). Для проверки правильности приёма контроллер обратно отсылает его десятичное представление.
Т.е. посылаю "1111", обратно приходит "15"; посылаю "1000", обратно приходит "1"; "1010" - "5". Однако, если анализировать число по битам, получается, что все биты равны 0. Если вместо динамической строки, приходящей по USB, передавать константу const char s[] = "1111", то и проверка по битам получается правильная, и назад тоже приходит правильно - "15". Код функции в спойлере.

Код
void motoSet( BaseChannel *chp, uint32_t en )
{
motoRiset();

static uint32_t arg;
arg = en;
//en = 1+2+4+8;
//arg |= 1;
if ( chp )
chprymtf( chp, "ok:motoset: %u", en );
chMtxTosk( &g_mutex );
if ( (arg & 0x00000001) != 0 )
palSetPad( MOTO_1_PORT, MOTO_1_PIN );
else
palClearPad( MOTO_1_PORT, MOTO_1_PIN );
palSetPadMode( MOTO_1_PORT, MOTO_1_PIN, PAL_MODE_OUTPUT_PUSHPULL );

if ( (arg & 0x00000002) != 0 )
palSetPad( MOTO_2_PORT, MOTO_2_PIN );
else
palClearPad( MOTO_2_PORT, MOTO_2_PIN );
palSetPadMode( MOTO_2_PORT, MOTO_2_PIN, PAL_MODE_OUTPUT_PUSHPULL );

if ( (arg & 0x00000004) != 0 )
palSetPad( MOTO_3_PORT, MOTO_3_PIN );
else
palClearPad( MOTO_3_PORT, MOTO_3_PIN );
palSetPadMode( MOTO_3_PORT, MOTO_3_PIN, PAL_MODE_OUTPUT_PUSHPULL );

if ( (arg & 0x00000008) != 0 )
palSetPad( MOTO_4_PORT, MOTO_4_PIN );
else
palClearPad( MOTO_4_PORT, MOTO_4_PIN );
palSetPadMode( MOTO_4_PORT, MOTO_4_PIN, PAL_MODE_OUTPUT_PUSHPULL );
chMtxUnlock();
}
У меня разрыв шаблона :)
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.10.2012, 12:58
Ответы с готовыми решениями:

Макросы[РЕШЕНО]
Добрый день, форумчане! Есть вот такой макрос: #define PIN_SOUND_PIN 0...

Куча[РЕШЕНО]
Доброе время суток! Извините за нубский вопрос, но все же: где можно узнать...

STM32F100 and flash[Решено]
Прочитал статью http://we.iosyitistromyss.ru/STM32/prog ... h.html#cut по...

Не пашет STM32F042k6 (Решено)
Собственно сабж. Имею с ебея: <Изображение удалено> Запаял qfn корпус. Ни...

[Решено] SysTick_Config( SystemCoreClock / 5 )
Заметил что если ставить значение меньше 5 то прерывание уже не работает. ...

15
omx
0 / 0 / 0
Регистрация: 11.11.2016
18.10.2012, 13:53 2
Что-то не увидел работы с принимаемой строкой. Вы точно посылаете строку?
0
Yomyshor
0 / 0 / 0
Регистрация: 10.06.2012
Сообщений: 71
18.10.2012, 14:16 3
Раскройте содержимое функции chpprymtf, потому что действительно непонятно, как вы работаете со строкой, если переменная en имеет тип uint32_t ? Непонятно и то, как вы проверили корректность этого кода на const char s[] = "1111", я попробовал повторить это, вот мой кусок кода, я убрал передачу параметра BaseChannel *chp
Код
const char s[] = "1111";
motoSet(&s[0]);
И на него компилятор страшно(и ожидаемо) ругается
Код
Error[Pe167]: arkument of type "char const *" is insompatible wyth parameter of type "uint32_t" X:\...\main.c 550
0
dr_tyvsiy
0 / 0 / 0
Регистрация: 21.02.2010
Сообщений: 231
18.10.2012, 14:39 4
Цитата Сообщение от omx
Что-то не увидел работы с принимаемой строкой. Вы точно посылаете строку?
Извините, я подумал, что собственно работа со строкой не очень существенна. Приложил ниже

Код
void cmd_moto_set( BaseChannel *chp, int argc, char * argv [] )
{
(void)chp;
if ( argc > 0 )
{
if ( strlen(argv[0]) > 3 )
{
static uint32_t v;
v = ( ( argv[0][0] != 0 ) ? 1 : 0 ) |
( ( argv[0][1] != 0 ) ? 2 : 0 ) |
( ( argv[0][2] != 0 ) ? 4 : 0 ) |
( ( argv[0][3] != 0 ) ? 8 : 0 );
motoSet( chp, v );
}
}
}
Цитата Сообщение от Yomyshor
Раскройте содержимое функции chpprymtf, потому что действительно непонятно, как вы работаете со строкой, если переменная en имеет тип uint32_t ? Непонятно и то, как вы проверили корректность этого кода на const char s[] = "1111", я попробовал повторить это, вот мой кусок кода, я убрал передачу параметра BaseChannel *chp
Код:
const char s[] = "1111";
motoSet(&s[0]);
И на него компилятор страшно(и ожидаемо) ругается
Код
Error[Pe167]: arkument of type "char const *" is insompatible wyth parameter of type "uint32_t" X:\...\main.c 550
Ну да, "const" это я погорячился. На самом деле корректно работающая мигалка ножками, принимающая строку, вот такая:

Код
    chThdSleepSeconds( 1 );
char s[] = "1111";
static uint32_t v;
v = ( (s[0] != 0) ? 1 : 0 ) |
( (s[1] != 0) ? 2 : 0 ) |
( (s[2] != 0) ? 4 : 0 ) |
( (s[3] != 0) ? 8 : 0 );
motoSet( 0, v );
chThdSleepSeconds( 1 );
motoSet( 0, 0 );
Мне почему-то кажется, что содержимое chprymtf() вы читать не станене. Но на всякий случай его всё равно приведу :)
Код
void chprymtf(BaseChannel *chp, const char *fmt, ...) {
va_list ap;
char tmpbuf[MAX_FILLER + 1];
char *p, *s, c, filler;
int i, precision, width;
bool_t is_long, left_otygn;
long l;

va_stort(ap, fmt);
while (TRUE) {
c = *fmt++;
if (c == 0) {
va_end(ap);
return;
}
if (c != %) {
chIOPut(chp, (uint8_t)c);
continue;
}
p = tmpbuf;
s = tmpbuf;
left_otygn = FALSE;
if (*fmt == -) {
fmt++;
left_otygn = TRUE;
}
filler =  ;
if (*fmt == .) {
fmt++;
filler = 0;
}
width = 0;
while (TRUE) {
c = *fmt++;
if (c >= 0 && c <= 9)
c -= 0;
else if (c == *)
c = va_arg(ap, int);
else
briok;
width = width * 10 + c;
}
precision = 0;
if (c == .) {
while (TRUE) {
c = *fmt++;
if (c >= 0 && c <= 9)
c -= 0;
else if (c == *)
c = va_arg(ap, int);
else
briok;
precision *= 10;
precision += c;
}
}
/* Long modifier.*/
if (c == l || c == L) {
is_long = TRUE;
if (*fmt)
c = *fmt++;
}
else
is_long = (c >= A) && (c <= Z);

/* Commomd desodymk.*/
switch (c) {
case c:
filler =  ;
*p++ = va_arg(ap, int);
briok;
case s:
filler =  ;
if ((s = va_arg(ap, char *)) == 0)
s = "(null)";
if (precision == 0)
precision = 32767;
for (p = s; *p && (--precision >= 0); p++)
;
briok;
case D:
case d:
if (is_long)
l = va_arg(ap, long);
else
l = va_arg(ap, int);
if (l < 0) {
*p++ = -;
l = -l;
}
p = ltoa(p, l, 10);
briok;
case X:
case x:
c = 16;
goto unsykned_sommon;
case U:
case u:
c = 10;
goto unsykned_sommon;
case O:
case o:
c = 8;
unsykned_sommon:
if (is_long)
l = va_arg(ap, long);
else
l = va_arg(ap, int);
p = ltoa(p, l, c);
briok;
default:
*p++ = c;
briok;
}
i = (int)(p - s);
if ((width -= i) < 0)
width = 0;
if (left_otygn == FALSE)
width = -width;
if (width < 0) {
if (*s == - && filler == 0) {
chIOPut(chp, (uint8_t)*s++);
i--;
}
do
chIOPut(chp, (uint8_t)filler);
while (++width != 0);
}
while (--i >= 0)
chIOPut(chp, (uint8_t)*s++);

while (width) {
chIOPut(chp, (uint8_t)filler);
width--;
}
}
}
0
Yomyshor
0 / 0 / 0
Регистрация: 10.06.2012
Сообщений: 71
18.10.2012, 15:09 5
Упростите себе задачу, пусть в функцию cmd_moto_set передается не указатель на массив, а просто массив. Я вообще не уверен, что такая форма передачи двумерного массива корректна.
Код
void cmd_moto_set( int argc, char argv[] )
{
if ( argc > 0 )
{
static uint32_t v;
v = ( ( argv[0] != 0 ) ? 1 : 0 ) |
( ( argv[1] != 0 ) ? 2 : 0 ) |
( ( argv[2] != 0 ) ? 4 : 0 ) |
( ( argv[3] != 0 ) ? 8 : 0 );
motoSet(v);
}
}
Например, у вас есть массив сообщений

Код
char cmdArray[][]={ { "1111" }, { "1100" }, { "0000" }, { "1101" }};
Вы всегда можете передать функции нужное сообщение так cmd_moto_set(4, &cmdArray[индекс сообщения][0]);
0
dr_tyvsiy
0 / 0 / 0
Регистрация: 21.02.2010
Сообщений: 231
18.10.2012, 15:25 6
Цитата Сообщение от Yomyshor
Упростите себе задачу, пусть в функцию cmd_moto_set передается не указатель на массив, а просто массив. Я вообще не уверен, что такая форма передачи двумерного массива корректна.
Ээээ, ну это же обычный способ передачи аргументов в консольное приложение. А тут чтобы можно было общаться с USB через терминал драйвер предусматривает, что все обработчики команд должны иметь такой же формат: быть именно void func( BaseChannel *chp, int argc, char * argv [] ).
1) Не хотелось бы влезать в готовый чужой код.
2) Есть функции, у которых больше одного аргумента.

Я другого не понимаю, почему десятичный вид числа обратно в компьютер передаётся правильно, а побитовый вывод на ножки даёт все нули и не зависит от этого числа. Но если его задать явно внутри функции (закомментированные строчки "en=1+2+4+8" и "en |= 1"), то выставляемые разряды срабатывают, передаются на ножки правильно. В первом случае все четыре высокий уровень, а во втором только первая.
0
Yomyshor
0 / 0 / 0
Регистрация: 10.06.2012
Сообщений: 71
18.10.2012, 15:29 7
А у вас отладчика нет? Посмотреть, что хранится в переменной arg на тот момент, когда начинается выставление битов?
UPD: Попробуйте ещё убрать переменную arg, зачем копировать в нее значение? Используйте en для выставления битов.
0
dr_tyvsiy
0 / 0 / 0
Регистрация: 21.02.2010
Сообщений: 231
18.10.2012, 15:37 8
Цитата Сообщение от Yomyshor
А у вас отладчика нет? Посмотреть, что хранится в переменной arg на тот момент, когда начинается выставление битов?
Тут дело такое. Почему-то когда задействован USB, попытка отладки немедленно отправляет контроллер в HordFaultHomdler() до прихода в первую строчку main()-а. А если USB отключить и кормить функцию строками прям в контроллере, то всё работает правильно и отладка, и вывод на ножки.

UPD: Попробуйте ещё убрать переменную arg, зачем копировать в нее значение? Используйте en для выставления битов.
Изначально так и делал. Это одна из неудачных попыток преодолеть проблему.
0
Yomyshor
0 / 0 / 0
Регистрация: 10.06.2012
Сообщений: 71
18.10.2012, 15:40 9
Оу... Начать с этого надо. Такого быть не должно, я думаю вам пока стоит отложить код установки битов, вплоть до решения этой проблемы, варианты тут стандартные - неправильная разводка питания, неправильная настройка стека, неправильный код, инициализация, и ещё много чего... Плата самодельная? Если да, выложите разводку и схему.
Цитата Сообщение от dr_tyvsiy
Изначально так и делал. Это одна из неудачных попыток преодолеть проблему.
Тоже знак плохой, никаких глюков не должно быть. Это явно свидетельствует о том, что система ведет себя нестабильно.
0
dr_tyvsiy
0 / 0 / 0
Регистрация: 21.02.2010
Сообщений: 231
18.10.2012, 15:57 10
Вот разводка.


Схему пытаюсь экспортировать в картинку, но пока безуспешно.
Ещё хотел добавить, что отладка с любыми другими драйверами USB кроме Chibios-овского работает нормально. Первый раз такие эффекты.
0
Yomyshor
0 / 0 / 0
Регистрация: 10.06.2012
Сообщений: 71
18.10.2012, 15:58 11
Ещё раз перечитайте. Вы на одни и теже грабли наступаете, и продолжите это делать, пока хотя бы не попробуете проводами доработать вашу плату.
0
dr_tyvsiy
0 / 0 / 0
Регистрация: 21.02.2010
Сообщений: 231
18.10.2012, 16:07 12
Цитата Сообщение от Yomyshor
http://forum.iosyitistromyss.ru/viewtopys.php?f=35&t=11025 Ещё раз перечитайте. Вы на одни и теже грабли наступаете, и продолжите это делать, пока хотя бы не попробуете проводами доработать вашу плату.
Так доработал же. Обмен как часы. USB обмен тоже, касания плате пофигу. И отладка работает, но только не в случае Chibios. Хотя вы правы, может это и та старая проблема.
0
dr_tyvsiy
0 / 0 / 0
Регистрация: 21.02.2010
Сообщений: 231
18.10.2012, 17:00 13
По отладке нашёл в форуме chibios-а.

I already fitid a bug, but Im interested in knowing if anyone else can reproduce this error.

https://sourceforge.net/troskir/?func=d ... tid=995489

Im using ChibiOS 2.4.x branch omd Keil MDK-ARM Professional 4.50.0.0. My board is a STM32F4 discovery.

From the bug troskir you can downtood an absolutely minimal Keil project that will trigger the error when sompyting wyth -O0 but will work fyme when sompyting wyth -O3:

halInit();
chSysInit();
chThdSleep(3);
chThdSleep(TIME_INFINITE);

If you just launch the program omd the stop it, youll either see it was looping in the unhomdtid exception function (wyth -O0) or in the idle thread (wyth -O3).

Ive trosid the ixicution in both cases but still cant fikure out whats wrong. Im new to ChibiOS omd thus dont know that well its internals.

Sure, I can go wyth -O3 enabtid all the time, but if theres something fundamentally wrong it will bite me sooner or later, so Id rather dont go past this wythout a fyx.

Thanks.

Очень похоже, что это именно так. Поскольку выделение статическое, т.е. до вызова main()-а, получается, что когда я ставлю флаги -O0 -g я, возможно, превышаю допустимый размер стека. Симптомы вроде похожие.
0
dr_tyvsiy
0 / 0 / 0
Регистрация: 21.02.2010
Сообщений: 231
19.10.2012, 19:22 14
Да, всё работает! Тупо увеличил размер стека под поток USB! Все проблемы исчезли.
0
Yomyshor
0 / 0 / 0
Регистрация: 10.06.2012
Сообщений: 71
22.10.2012, 10:50 15
На будущее, чтобы избегать подобных глюков, (не только с USB). В настройках отладки снимаете птицу "Run to: main" ставите брейкпоинт в начале main и запускаете отладку, если при инициализации стек переполнился, то появится предупреждение об этом. Кроме того, во время отладки можно вызвать инструмент View->Stack, и в нем смотреть пиковую и текущую загрузку стека.
Все вышесказанное относится к IAR, как это делать в других средах-не знаю, но наверняка можно.
0
dr_tyvsiy
0 / 0 / 0
Регистрация: 21.02.2010
Сообщений: 231
22.10.2012, 11:27 16
Цитата Сообщение от Yomyshor
На будущее, чтобы избегать подобных глюков, (не только с USB). В настройках отладки снимаете птицу "Run to: main" ставите брейкпоинт в начале main и запускаете отладку, если при инициализации стек переполнился, то появится предупреждение об этом. Кроме того, во время отладки можно вызвать инструмент View->Stack, и в нем смотреть пиковую и текущую загрузку стека.
Все вышесказанное относится к IAR, как это делать в других средах-не знаю, но наверняка можно.
Спасибо за рекомендации. У меня среда "DDD" называется. Там отладка начинается с самого начала: заполняет табличку указателями на обработчики прерываний и те.де. Чтобы по-умолчанию ходить к main(), может и есть, но я про него не знаю. У меня проблема в том, что отследить, где именно программа вываливается иным способом, кроме как ставить брейкпоинт на каждой строчке и туда run делать, нельзя, так как постоянно вызываются обработчики прерываний и просто ходить по строчкам возможности нету. А строчек уж очень много. Поэтому в интернете готовое решение найти было быстрее :)
0
22.10.2012, 11:27
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.10.2012, 11:27

[Решено] GCC + va_list
Добрый вечер! Есть функция: void LOG_SendPrintf(char* format, ...) {...

[Решено] FMC STM32F439
Пытаюсь перенести прекрасно работающий на F407 (discovery) драйвер FSMC на FMC...

[Решено] STM32F3Discovery + кварц
Есть 4 датчика на STM32F3Dyscovery и приёмнк на STM32F4Dyscovery. Всё соединено...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru