Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Электрический кот
Аватара пользователя
Сообщения: 1031
Зарегистрирован: Чт июн 20, 2013 00:00:58
Откуда: москва, м.Сходненская

Сообщение Mishany »

сбрасываются, только в другом таймере, я его вырезал из примера вместе с сбросом (не доглядел при упрощении кода), проблема уже решена, проблема была в плате, не допаял..
Реклама
Прорезались зубы
Аватара пользователя
Сообщения: 202
Зарегистрирован: Пн сен 26, 2011 13:48:25
Откуда: Харьков

Сообщение slavokhire5 »

Здравствуйте, коты:)
пытаюсь освоить кейл и попутно блютуз микросхемку bluenrg.
компилирую пример от производителя - все ок.

когда попытался это дело перетащить в свой проект, кейл начал ругаться на нулевые размеры некоторых массивов:

typedef __packed struct _evt_le_meta_event{
uint8_t subevent;
uint8_t data[0]; // ругается сюда error: #94-D: the size of an array must be greater than zero
} PACKED evt_le_meta_event;

два вопроса к сообществу:
1. зачем вообще нужны нулевые массивы в структуре? как-то "застолбить" место?
2. как успокоить кейл и не поломать библиотечный код?
Осилит дорогу идущий
--------------------------
Пишу на Си за еду
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

Сообщение Siarzhuk »

slavokhire5 писал(а): компилирую пример от производителя - все ок.

когда попытался это дело перетащить в свой проект, кейл начал ругаться на нулевые размеры некоторых массивов:
[...]
2. как успокоить кейл и не поломать библиотечный код?
Если один и тот же компилятор на идентичный код ругается в зависимости от проекта - то попробуйте сравнить настройки проектов из примера и вашего. Вероятно в части включения поддержки разных фич языка есть разница.
slavokhire5 писал(а):typedef __packed struct _evt_le_meta_event{
uint8_t subevent;
uint8_t data[0]; // ругается сюда error: #94-D: the size of an array must be greater than zero
} PACKED evt_le_meta_event;

два вопроса к сообществу:
1. зачем вообще нужны нулевые массивы в структуре? как-то "застолбить" место?
Возможно это структура есть заголовок данных нефиксированного (неизвестного) размера. Программа обращается к элементам массива data в зависимости от типа события subevent - зная что событие номер 1 тащит с собой десять байт - оперируем индексами 0-9, а событие номер 2 содержит сто байт - значит допустимо обращаться до 99-го индекса. Ну а sizeof такой структуры вернёт чистый размер заголовка - без данных.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Прорезались зубы
Аватара пользователя
Сообщения: 202
Зарегистрирован: Пн сен 26, 2011 13:48:25
Откуда: Харьков

Сообщение slavokhire5 »

Здравствуйте коты:)

у меня вопрос по указателям (см. коменты в коде)

Код: Выделить всё

....
typedef __packed struct _evt_cmd_complete{
  uint8_t  ncmd;
  uint16_t opcode;
} PACKED evt_cmd_complete;
.....

int hci_send_req(struct hci_request *r, BOOL async)
{
...
uint8_t *ptr;
evt_cmd_complete *cc;
......
ptr = hciReadPacket->dataBuff + (1 + HCI_EVENT_HDR_SIZE);   // HCI_EVENT_HDR_SIZE == 2
// dataBuff типа uint8_t. в нем лежат значения 0x04, 0x0e, 0x04, 0x01, 0x0c, 0xfc.....
// в результате *ptr = 0x01
......
 cc = (void *) ptr;     // сс->ncmd = 0x01, cc->opcode == 0x00FC, хотя по логике должен быть равен 0x0CFC. что неправильно?
....
}
UPD1:и после выполнения строчки if (cc->opcode != opcode) я падаю в hard fault. если ее закоментить, то все хорошо. я так понимаю, это что-то с адресацией не так?
UPD2:поэкспериментировал с данными в dataBuff. допустим, он содержит значения 0x04, 0x0e, 0x04, 0x01, 0x0c, 0xfc, 0xaa.....
тогда в сс->opcode будет лежать 0xaafc, а в сс->ncmd будет 0x01. если сс->ncmd сделать типа uint16_t, то в сс->ncmd будет 0x0c01. т.е. байты меняет местами и почему-то отбрасывается 0x0c.

вся проблема в том, что я ковыряю примеры bluetooth от stm. перетаскиваю их с stm32l053 на stm32f030. теоретически в библиотеке должно быть все правильно, значит где-то косячу я.
Осилит дорогу идущий
--------------------------
Пишу на Си за еду
Реклама
Эиком - электронные компоненты и радиодетали
Грызет канифоль
Сообщения: 291
Зарегистрирован: Чт ноя 06, 2014 13:09:06

Сообщение viiv »

slavokhire5 писал(а):после выполнения строчки if (cc->opcode != opcode) я падаю в hard fault.
Твой целовой MCU умеет обращаться по невыровненным данным? Конкретно с твоим MCU не разбирался, но не все "умеют" обращаться к невыровненным данным. С этим связаны и другие, описываемые проблемы.
Например, посмотри sizeof () твоей структуры, думаю, будешь удивлен.
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

Сообщение Siarzhuk »

slavokhire5 писал(а): у меня вопрос по указателям (см. коменты в коде)

Код: Выделить всё

....
typedef __packed struct _evt_cmd_complete{
  uint8_t  ncmd;
  uint16_t opcode;
} PACKED evt_cmd_complete;
.....
поэкспериментировал с данными в dataBuff. допустим, он содержит значения 0x04, 0x0e, 0x04, 0x01, 0x0c, 0xfc, 0xaa.....
тогда в сс->opcode будет лежать 0xaafc, а в сс->ncmd будет 0x01. если сс->ncmd сделать типа uint16_t, то в сс->ncmd будет 0x0c01. т.е. байты меняет местами и почему-то отбрасывается 0x0c.
Похоже компилятор проигнорировал просьбу упаковать структуру. Байты меняются местами потому что платформа Little Endian.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Реклама
Первый раз сказал Мяу!
Сообщения: 23
Зарегистрирован: Пт окт 17, 2014 12:42:38

Сообщение yuriy m »

Доброго времени суток. Есть маленькая задачка,только или я дурак или лыжи не едут. Выход -это обычный быстрый шим. На входе есть переменный резистор,установлен в среднее положение на входе шима нет. При вращении резистора от среднего положения вправо или влево у нас должен увеличиваться шим до максимально значения. Считываем 8 бит ацп и загоняем в OCR предварительно отняв 125 едениц ,то мы получаем в каждую сторону 125 шагов,что будет вялятся примерно половина заполнения шим,потом умножаем на 2. Ну и принципе на выходе мы имеем ,если резистор крутить от среднего положения в право ,на выходе будет менятся шим от 0-255. А теперь вопрос ,как сделать чтобы от середины резистора при вращении влево тоже менялся шим от 0 до 255 ? Ну принципе из куска понятно ,что это управление реверсом моторчика одним резистором со средним положением.

Спасибо

if (ReadADC(3)>130) // ход в перед
{
PORTD &=~(1<<1); // выключить одну диагональ моста
_delay_ms(1); // пауза
PORTD|=(1<<2); // включить другую диагональ моста
speed = (ReadADC(3)-125)*2;
OCR2B=speed;
}
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

я так понимаю, просто надо так: speed = abs(ReadADC(3)-125)*2;
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Первый раз сказал Мяу!
Сообщения: 23
Зарегистрирован: Пт окт 17, 2014 12:42:38

Сообщение yuriy m »

ARV писал(а):я так понимаю, просто надо так: speed = abs(ReadADC(3)-125)*2;
Судя по всему нет,это не то. Выше я код написал ,для случая если резистор крутить от середины в право , а как сделать когда крутишь от середины влево ? Я понимаю что надо что то про инвертировать ,
но что-то не догоняю как...
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

то, что я порекомендовал, вы проверили? или просто обдумали?

насколько я понял, сам реверс вы делаете переключением плеч полумоста, а ШИМ просто задает "амплитуду". так вот, в вашем коде добавка функции abs даст ситуацию, когда в среднем положении резистора будет выдаваться 0, а по мере сдвига к краям - положительные значения в пределах примерно от 0 до 250, т.е. амплитуда будет плавно нарастать.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 20117
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Сообщение Gudd-Head »

ARV писал(а):в среднем положении резистора будет выдаваться 0
Причём этот ноль надо будет ловить с точностью в 1/256 :)))
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Первый раз сказал Мяу!
Сообщения: 23
Зарегистрирован: Пт окт 17, 2014 12:42:38

Сообщение yuriy m »

Я правильно понял ,что это как то так ?

if (ReadADC(3)>133) // ход в перед
{
PORTD &=~(1<<1); // выключить одну диагональ моста
_delay_ms(1); // пауза
PORTD|=(1<<2); // включить другую диагональ моста
speed = ((ReadADC(3)-122)*2)+11;
OCR2B=speed;
}
if ((ReadADC(3)>120)&&(ReadADC(3)<133))
{
OCR2B=0;
}
if (ReadADC(3)<120) // ход назад
{
PORTD &=~(1<<2); // выключить одну диагональ моста
_delay_ms(1); // пауза
PORTD|=(1<<1); // включить другую диагональ моста
speed = abs((ReadADC(3)-122)*2)+11;
OCR2B=speed;
}
То что шим будет не с нуля ,принципе не имеет значения...
Или есть более красивое решение ? ПС Сильно не пинайте ,только учу СИ.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

вот так будет понятнее?

Код: Выделить всё

int adc = 2*(ReadADC(3) - 125);
if(adc < 0) { // назад
   PORTD &=~(1<<2); // выключить одну диагональ моста
   _delay_ms(1); // пауза
   PORTD|=(1<<1); // включить другую диагональ моста
} else { // вперед 
   PORTD &=~(1<<1); // выключить одну диагональ моста
   _delay_ms(1); // пауза
   PORTD|=(1<<2); // включить другую диагональ моста
}
OCR2B= abs(adc);
вообще говоря, задержки при переключениях диагоналей - это глупость: приведет к искажению ШИМа. правильный алгоритм должен быть чуток иной:
1. определяем "зону нуля" - значение АЦП, которое соответствует остановленному состоянию
2. измерили АЦП
3. проверили, вошли в зону нуля или нет
4. если в зоне - выключили ШИМ
5. если вне зоны, то надо сравнить знак этого результата АЦП с предыдущим результатом
6. если знаки совпадают, то перейти к п.8
7. если знаки разные, то для положительного значения текущего значения АЦП включить одну диагональ, для отрицательного - другую
8. задать скорость по абсолютному значению АЦП.
9. запомнить знак результата АЦП для следующей итерации
10. повторять в цикле с п.2
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Первый раз сказал Мяу!
Сообщения: 23
Зарегистрирован: Пт окт 17, 2014 12:42:38

Сообщение yuriy m »

Спасибо за наводку. Буду думать...
Первый раз сказал Мяу!
Сообщения: 23
Зарегистрирован: Пт окт 17, 2014 12:42:38

Сообщение yuriy m »

В связи с похоронами родного человека,немного было не до проекта...
Набросал код,пока не проверял,можно ли упростить или как-то более правильнее написать алгоритм ? Допусти имея мертвую зону в диапазоне 120-134 ацп, 0-120 перевести от 0 ,до 255 ?
Так как стиль у меня больше наверное не сишный ,а для промышленных контроллеров. Более 15 лет программирования разных промышленных контроллеров,а там язык отличается...
И еще ругается на ABS компилятор.
Warning 1 implicit declaration of function 'abs' [-Wimplicit-function-declaration]
Может что подключить надо ?

//--------------------------------ручной режим---------------------------------------------------
void manual()
{
PORTC &=~(1<<0); //выключить поворот
PORTD &=~(1<<6); //тоже
PORTD &=~(1<<5); //тоже

if (((ReadADC(3))>122)&&(ReadADC(3)<132)) //среднее положение ручки
{
OCR2B=0; // выключить шим
TCCR2A=0x00; // тоже
PORTD &=~(1<<1); // отключаем мост
PORTD &=~(1<<2); // тоже

}
else
{
int adc = 2*(ReadADC(3) - 135);

if(adc < 0) // назад
{
PORTD &=~(1<<2); // выключить одну диагональ моста
PORTD|=(1<<1); // включить другую диагональ моста
}
else // вперед
{
PORTD &=~(1<<1); // выключить одну диагональ моста
PORTD|=(1<<2); // включить другую диагональ моста
}
OCR2B = abs(adc);
}
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

подключить math.h или определить abs самостоятельно:
#define abs(x) ((x) < 0 ? -(x) : (x))

что касается упрощения алгоритма, то достаточно 1 раз обратиться к чтению АЦП, а не трижды.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Грызет канифоль
Сообщения: 269
Зарегистрирован: Чт мар 11, 2010 17:45:37
Откуда: г.фрязино

Сообщение mastech »

попросили сделать бутафорскую режиссерскую хлопушку та что с бегущими красными циферками)
суть какая когда "рычажок"(кнопка не нажата)) хлопушки поднят в индикаторах хаотично бегают цифры когда рычажок опущен(кнопка нажата) на индикаторе показывается номер дубля и после поднятия опускания дубль прибавляется, но!! пока рычажок опущен то номер дубля показывается на индикаторе.

что получилось у меня: рычажок поднят цифры бегают, закрываю хлопушку подсказывает дубль 1, поднимаю цифры бегают - опускаю дубль 2 и т.д, если держать хлопушку закрытой то дубли сами с интервалом в 1 секунду прибавляются(через задержку), реализовал в двух циклах, первый проверяет нажатие кнопки,если кнопка не нажата циферки бегают, кнопка нажата срабатывает брейк (вываливается из цикла) и переходит во второй цикл тоже проверяет кнопку если нажата то происходит вывод номера дубля с задержкой и пока кнопка нажата естественно дубли сами прибавляются только хлопушку открыть срабатывает брейк и переходит на бегающие цифры . все это безобразие происходит в общем цикле.
вопрос как остановить прибавление дублей пока кнопка нажата не могу сообразить как реализовать этот алгоритм?
контроллер Мега32 , 8 индикаторов.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

сделайте изменение счетчика не во втором цикле, а между двумя циклами
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Грызет канифоль
Сообщения: 269
Зарегистрирован: Чт мар 11, 2010 17:45:37
Откуда: г.фрязино

Сообщение mastech »

ARV писал(а):сделайте изменение счетчика не во втором цикле, а между двумя циклами
с этим разобрался. Спасибо.
теперь вопрос про прерывания, надо выключать с кнопки без фиксации: настроил так

Код: Выделить всё

volatile unsigned char sleepEnabled = 0;

ISR(INT2_vect)
{
   if (sleepEnabled == 0)
   {
      sleepEnabled = 1;
      set_sleep_mode(SLEEP_MODE_PWR_DOWN);
      sei();
    sleep_mode();
   cli();
}
   sleepEnabled = 0;
}
эту настройку взял отсюда http://forum.easyelectronics.ru/viewtop ... w=previous

работает но нестабильно, много повторных нажатий, кнопка подтянута через резистор, внутренний резистор тоже включен.
Нужно ли в теле программы разрешать прерывания( без разрешения работает).
если нужен код целиком то вечером скину.
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 369
Зарегистрирован: Пт фев 01, 2013 21:05:30

Сообщение es131245 »

Как сравнивать массивы указателей разных типов?

Код: Выделить всё

uint8_t * Buf;
...
if(Buf=="String\r"){
Работает, но с предупреждением.

Код: Выделить всё

..\Src\usbd_cdc_if.c(45): warning:  #42-D: operand types are incompatible ("char *" and "uint8_t *")
Ответить

Вернуться в «Разные вопросы по МК»