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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
Siarzhuk
Потрогал лапой паяльник
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

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

Сообщение Siarzhuk »

WiseLord писал(а):Но ведь это на 8-битном AVR происходило, вот в чём прикол.

Компилятору виднее. Так, глядя на результат инверсии, sizeof(int) небось 2 рапортует.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Триод
Нашел транзистор. Понюхал.
Сообщения: 160
Зарегистрирован: Сб дек 08, 2012 16:40:40

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

Сообщение Триод »

Задал вопрос здесь, но всё же вопрос ближе к данному топику.

В общем, не могу понять почему членам структуры не присваиваются значения?
Код убрал под спойлер

Спойлер

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

#include "stm32f2xx_hal.h"

CAN_HandleTypeDef hcan1;
static void MX_CAN1_Init(void);

int main(void)
{

  while (1)
  {
 
//Смотрю значения до присваивания и вывожу в UART. Результат следующий: по идее, там - мусор)
  hcan1.pTxMsg->DLC = 0xF5;
  hcan1.pTxMsg->Data[0] = 0xE1;
  hcan1.pTxMsg->Data[1] = 0x01;
  hcan1.pTxMsg->Data[2] = 0x00;
  hcan1.pTxMsg->Data[3] = 0x08;
  hcan1.pTxMsg->Data[4] = 0x1B;           
  hcan1.pTxMsg->Data[5] = 0x19;           
  hcan1.pTxMsg->Data[6] = 0x00;           
  hcan1.pTxMsg->Data[7] = 0x08;
 
//Присваиваю значения членам структуры pTxMsg

  hcan1.pTxMsg->DLC = 0x08;
  hcan1.pTxMsg->Data[0] = 0x00;
  hcan1.pTxMsg->Data[1] = 0x01;
  hcan1.pTxMsg->Data[2] = 0x02;
  hcan1.pTxMsg->Data[3] = 0x03;
  hcan1.pTxMsg->Data[4] = 0x04;           
  hcan1.pTxMsg->Data[5] = 0x05;           
  hcan1.pTxMsg->Data[6] = 0x06;           
  hcan1.pTxMsg->Data[7] = 0x07; 
 
//Смотрю значения членов структуры после присваивания и вывожу в UART. Результат -  тот же самый мусор

  hcan1.pTxMsg->DLC = 0xF5;
  hcan1.pTxMsg->Data[0] = 0xE1;
  hcan1.pTxMsg->Data[1] = 0x01;
  hcan1.pTxMsg->Data[2] = 0x00;
  hcan1.pTxMsg->Data[3] = 0x08;
  hcan1.pTxMsg->Data[4] = 0x1B;           
  hcan1.pTxMsg->Data[5] = 0x19;           
  hcan1.pTxMsg->Data[6] = 0x00;           
  hcan1.pTxMsg->Data[7] = 0x08;
 
 
  }


}


/* CAN1 init function */
void MX_CAN1_Init(void)
{

  hcan1.Instance = CAN1;
  hcan1.Init.Prescaler = 5;
  hcan1.Init.Mode = CAN_MODE_NORMAL;
  hcan1.Init.SJW = CAN_SJW_1TQ;
  hcan1.Init.BS1 = CAN_BS1_6TQ;
  hcan1.Init.BS2 = CAN_BS2_5TQ;
  hcan1.Init.TTCM = DISABLE;
  hcan1.Init.ABOM = DISABLE;
  hcan1.Init.AWUM = DISABLE;
  hcan1.Init.NART = DISABLE;
  hcan1.Init.RFLM = DISABLE;
  hcan1.Init.TXFP = DISABLE;
  HAL_CAN_Init(&hcan1);

}


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

* @file    stm32f2xx_hal_can.h
 typedef struct
{
  CAN_TypeDef                 *Instance;  /*!< Register base address          */

  CAN_InitTypeDef             Init;       /*!< CAN required parameters        */

  CanTxMsgTypeDef*            pTxMsg;     /*!< Pointer to transmit structure  */

  CanRxMsgTypeDef*            pRxMsg;     /*!< Pointer to reception structure */

  __IO HAL_CAN_StateTypeDef   State;      /*!< CAN communication state        */

  HAL_LockTypeDef             Lock;       /*!< CAN locking object             */

  __IO uint32_t               ErrorCode;  /*!< CAN Error code                 */

}CAN_HandleTypeDef;

typedef struct
{
  uint32_t Prescaler;  /*!< Specifies the length of a time quantum.
                            This parameter must be a number between Min_Data = 1 and Max_Data = 1024 */

  uint32_t Mode;       /*!< Specifies the CAN operating mode.
                            This parameter can be a value of @ref CAN_operating_mode */

  uint32_t SJW;        /*!< Specifies the maximum number of time quanta
                            the CAN hardware is allowed to lengthen or
                            shorten a bit to perform resynchronization.
                            This parameter can be a value of @ref CAN_synchronisation_jump_width */

  uint32_t BS1;        /*!< Specifies the number of time quanta in Bit Segment 1.
                            This parameter can be a value of @ref CAN_time_quantum_in_bit_segment_1 */

  uint32_t BS2;        /*!< Specifies the number of time quanta in Bit Segment 2.
                            This parameter can be a value of @ref CAN_time_quantum_in_bit_segment_2 */

  uint32_t TTCM;       /*!< Enable or disable the time triggered communication mode.
                            This parameter can be set to ENABLE or DISABLE. */

  uint32_t ABOM;       /*!< Enable or disable the automatic bus-off management.
                            This parameter can be set to ENABLE or DISABLE */

  uint32_t AWUM;       /*!< Enable or disable the automatic wake-up mode.
                            This parameter can be set to ENABLE or DISABLE */

  uint32_t NART;       /*!< Enable or disable the non-automatic retransmission mode.
                            This parameter can be set to ENABLE or DISABLE */

  uint32_t RFLM;       /*!< Enable or disable the receive FIFO Locked mode.
                            This parameter can be set to ENABLE or DISABLE */

  uint32_t TXFP;       /*!< Enable or disable the transmit FIFO priority.
                            This parameter can be set to ENABLE or DISABLE */
}CAN_InitTypeDef;

typedef struct
{
  uint32_t StdId;    /*!< Specifies the standard identifier.
                          This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF */

  uint32_t ExtId;    /*!< Specifies the extended identifier.
                          This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF */

  uint32_t IDE;      /*!< Specifies the type of identifier for the message that will be transmitted.
                          This parameter can be a value of @ref CAN_Identifier_Type */

  uint32_t RTR;      /*!< Specifies the type of frame for the message that will be transmitted.
                          This parameter can be a value of @ref CAN_remote_transmission_request */

  uint32_t DLC;      /*!< Specifies the length of the frame that will be transmitted.
                          This parameter must be a number between Min_Data = 0 and Max_Data = 8 */

  uint8_t Data[8];   /*!< Contains the data to be transmitted.
                          This parameter must be a number between Min_Data = 0 and Max_Data = 0xFF */

}CanTxMsgTypeDef
Триод
Нашел транзистор. Понюхал.
Сообщения: 160
Зарегистрирован: Сб дек 08, 2012 16:40:40

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

Сообщение Триод »

Свой вопрос снимаю
Аватара пользователя
uldemir
Друг Кота
Сообщения: 7359
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

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

Сообщение uldemir »

У меня тоже есть снова вопрос. Пишу в Keil-е. Есть функция для посылки данных через i2c описанная так:

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

t_i2c_status i2c_wr_reg(unsigned char address, unsigned char reg_addr, char * data, unsigned char length);

Так вот, если я хочу в data передать длинную инициализационную последовательность. последовательность не меняется и потому в ОЗУ держать нет смысла. Значит объявляю константой:

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

const char init_sequence[] = {
        // Init sequence for 128x64 OLED module
    SSD1306_DISPLAYOFF,
....
    SSD1306_DISPLAYON //--turn on oled panel
}
В результате получаю ошибку:

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

main.c(178): error:  #167: argument of type "const char *" is incompatible with parameter of type "char *"
        i2c_wr_reg(SD1306_I2C_ADDRESS, 0x00, init_sequence, sizeof(init_sequence));
main.c: 0 warnings, 1 error

Потом, почему-то, не позволет объявление этого массива сделать непосредственно рядом с вызовом этой функции (хотя IAR на это не возражал). Самое интересное, если бы инициализационные коды были бы печатные, то конструкция

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

i2c_wr_reg(SSD1306_I2C_ADDRESS0x00"start_sequence"sizeof(init_sequence)); 
пороходит, несмотря на то, что ему в данном случае передаётся константная строка.

Вопрос собственно и состоит, как эту инициализационную последовательность изящно засунуть в память программ не куроча функцию.
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

А если в аргументах функции передавать не прямо init_sequence, а с приведением типа: (char *)init_sequence?
Аватара пользователя
uldemir
Друг Кота
Сообщения: 7359
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

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

Сообщение uldemir »

Да, спасибо, этот вариант прокатил.

Ах! вот если бы еще была возможность передавать эти последовательности неименованными...
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
Аватара пользователя
Siarzhuk
Потрогал лапой паяльник
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

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

Сообщение Siarzhuk »

uldemir писал(а):Потом, почему-то, не позволет объявление этого массива сделать непосредственно рядом с вызовом этой функции (хотя IAR на это не возражал).

А что говорит? Попробуйте static - это выпихнет локальную переменную в глобальную область, сохранив её видимость локальной.

uldemir писал(а):Самое интересное, если бы инициализационные коды были бы печатные, то конструкция

В строковый литерал можно запихать всё что угодно: "\x00\xFFHalli\xCCHallo!\x1F", ещё можно каждый код задефайнить как строчку
#define AGA "\xFF"
#define OGO "\x00"
#define UGU "\xCC"

i2c_wr_reg( ..., AGA OGO UGU AGA, ...);

компилятор её склеит в один литерал и подставит при оформлении вызова.

uldemir писал(а):пороходит, несмотря на то, что ему в данном случае передаётся константная строка.

константная строка и массив константных символов - судя по всему для него [компилятора] различные типы. Гораздо интереснее, что он не ругается на снятие const при такой передаче - ведь внутри функции это обычный указатель - в который функция может нагадить.

uldemir писал(а):Вопрос собственно и состоит, как эту инициализационную последовательность изящно засунуть в память программ не куроча функцию.

Вопрос в том, что семантика функции предполагает модификацию передаваемого буффера - мол, не огорожен указатель const-ом - не говорите что вас не предупреждали. ;) У прожжёного дизайнера библиотек в определении отдаваемого на передачу буфера обязательно const будет.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Аватара пользователя
uldemir
Друг Кота
Сообщения: 7359
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

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

Сообщение uldemir »

Siarzhuk писал(а):А что говорит?

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

main.c(211): error:  #268: declaration may not appear after executable statement in block
        char start_col[] = {SSD1306_COLUMNADDR, 0, SSD1306_LCDWIDTH-1, SSD1306_PAGEADDR, 0, 7};
main.c: 0 warnings, 1 error
т.е. совершенно это неприемлет. Хотя, помнится, в IARе такое делал. Сейчас не могу найти тот кусок, потому как я его переписал иначе (без таблиц).
Siarzhuk писал(а):В строковый литерал можно запихать всё что угодно: "\x00\xFFHalli\xCCHallo!\x1F",
Способ интересный, но тогда снова придётся делать два комплекта дефайнов - для констант и для строк. Ладно, попробую обойтись.
Siarzhuk писал(а):У прожжёного дизайнера библиотек в определении отдаваемого на передачу буфера обязательно const будет.
О! это хорошо решает проблему. Спасибо. жаль только, не могу найти хорошую библиотеку для мастера I2C для stm32f0. Приходится дёргать огрызки из разных источников.
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

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

Сообщение pokk »

Добрый день, подскажите при модульном программировании в каких случаях подключение других модуль производить в .h файле а в каких в .c файле. Раньше об этом не задумывался и постоянно подключал все в .h но недавно начали вылазить ошибки типа циклическое включение заголовков, так как тогда не было времени сильно разбираться некоторые заголовки перемести в .с файл и все заработало. А вот теперь при формировании новых библиотек задумался где что подключать.
Аватара пользователя
uldemir
Друг Кота
Сообщения: 7359
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

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

Сообщение uldemir »

Чтобы не было циклического включения и повторного переопределения ставят в .h файлах "экран"

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

#ifndef _DRIVER_H_
#define _DRIVER_H_
....сам х-файл
#endif
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
Аватара пользователя
menzoda
Вымогатель припоя
Сообщения: 535
Зарегистрирован: Вт авг 28, 2012 22:21:33

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

Сообщение menzoda »

Включать нужно туда, где это используется. Нужны типы int32_t в foo.h, включи stdint.h в foo.h. Если они нужны в foo.c, то включи stdint.h в foo.c. Нужны в обоих файлах (обычно так и бывает) включи в оба файла, и не важно, что в foo.c они будут опосредовано включены через foo.h. Лучше явно указать зависимости, а не надеяться, что кто-то где-то уже включил. Если при этом возникают ошибки - это проблема архитектуры, пересмотри зависимости между модулями.
Аватара пользователя
Siarzhuk
Потрогал лапой паяльник
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

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

Сообщение Siarzhuk »

uldemir писал(а):declaration may not appear after executable statement in block [....] т.е. совершенно это неприемлет. Хотя, помнится, в IARе такое делал.

Сюшная классика - все переменные до́лжно определять в начале блока. Многие компиляторы не так строги - и дозволяют разбрасывать объявления где заблагорассудится. Впрочем обойти тоже можно - огородившись "фиктивным" блоком:

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

  int i = 0;
[...]
  i = 9;

  {  // <- огораживаемся, огораживаемся
     int u = 5; // и никто больше не ругается на это объявление
     send (u);
  }  // ну вот и всё - окончен блок, беру шинель иду домой ...



uldemir писал(а):Способ интересный, но тогда снова придётся делать два комплекта дефайнов - для констант и для строк.

У препроцессора есть возможность т.н. stringify с помощью одинарного # префикса - превращать число в строку. Вот если задавать коды в восьмеричных константах - по идее должно сработать:

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

#define S(_code) "\0" _S(_code)
#define _S(_code) #_code
#define OGO 000 // decimal 0
#define AGA 050 // decimal 40

const char* ppd = S(OGO) S(AGA); // const char* ppd = "\0" "000" "\0" "050";


С десятичными константами одинокий бэкслеш нам всю красоту замысла рушит, и я, увы, пока не сообразил как его объехать. :(
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

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

Сообщение Reflector »

Apparatchik писал(а):
ARV писал(а):Есче интересно знать, битовые поля применяются когда оперативной памяти мало или просто для удобства. На сколько это выгоднее конструкции типа var |= 1 << 4;

Для ARM gcc генерит одинаковый код при чтении, но разный при записи. Например, для

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

RCC_CFGR->HPRE = presc;

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

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

RCC->CFGR = RCC->CFGR & ~RCC_CFGR_HPRE | (presc << 4);

получим BIC + OR, а если сдвигая 8 битное значение нельзя получить нужную маску, то добавится еще LDR.

ARV писал(а):на сколько я в курсе, подобным образом вся периферия ARM описана в соответствующих хедерах, и вся работа с нею ведется подобным образом

Увы, подобным образом описаны только несколько регистров в CMSIS...
CB1
Прорезались зубы
Сообщения: 232
Зарегистрирован: Чт янв 01, 2015 13:44:12

Программирование C++

Сообщение CB1 »

Привет всем! Для чего нужен суффикс типа вещественной переменной? Читаю книгу - там объявление используется с суффиксом, в других статьях используется без него. Компилятор компилирует два варианта написания.
В чем разница между объявлениями переменной с суффиксом и без:
float a=7.56F;
и
float a=7,56;
Все гениальное - просто
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

В первом случае константа 7.56F - типа float, во втором константа 7.56 - типа double. Переменные же в обоих случаях float, и к ним эти суффиксы никак не относятся.

Будь компилятор поглупее и с отключенной оптимизацией, можно было бы предположить, что во втором случае он бы сгенерировал более сложный машинный код с приведением типов.
Аватара пользователя
Siarzhuk
Потрогал лапой паяльник
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

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

Сообщение Siarzhuk »

WiseLord писал(а):во втором случае он бы сгенерировал более сложный машинный код с приведением типов.
Хм, по ошущениям львиная доля применений f-суффикса - затыкать предупреждения компилятора на "возможную потерю точности" при приведении double литерала к типу float. Т.е. компилятор в сомнениях - или мы явно хотим использовать double константу, но почему-то втискиваем её во float, или просто неряшливо пишем код [без f-суффиксов] и тоже заслуживаем "фе" с его стороны. Но, с другой стороны, если преобразование 7.5 <-> 7.5f происходит без потери точности - отчего-бы и не соптимизировать.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
CB1
Прорезались зубы
Сообщения: 232
Зарегистрирован: Чт янв 01, 2015 13:44:12

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

Сообщение CB1 »

Возможно ли в switch case использовать не отдельные числа, а промежутки чисел?
Например:
switch(a)
{
case 1: код; break;
case 2: код; break;
case 3: код; break;
...............
}
Можно ли на место числа 1, 2 или 3 вставить промежутки 1-2, 3-5 и т.д. ?
Все гениальное - просто
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

Да, такое возможно (как минимум, GCC поддерживает):

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

switch(f){
case 0 ... 5 : break;
case 6 ... 155: break;
default:
   break;
}
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
CB1
Прорезались зубы
Сообщения: 232
Зарегистрирован: Чт янв 01, 2015 13:44:12

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

Сообщение CB1 »

Спасибо ARV ! Компилятор AtmelStudio с восторгом принял Ваш вариант кода. Я когда то видел такой вариант записи, пробовал писать, но забыл про пробелы - а писал так, например 1...3 . По этому компилятор и ругался.
Все гениальное - просто
Аватара пользователя
Hand-Maker
Поставщик валерьянки для Кота
Сообщения: 2142
Зарегистрирован: Чт дек 12, 2013 11:18:14
Откуда: Украина, Черновцы

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

Сообщение Hand-Maker »

Котаны, прошу помощи.
Си начал колупать недавно, опыта мало.
Мне надо объявить поле битов, но так, чтобы оно было видно во всех файлах *.с
Просто с переменной проблем не возникло, в main.c декларировал переменную, в main.h указал, что она extern -- и все поехало. А вот со структурой не получается.
Предыдущий программисть для однобитных флажков использовал целые байты. Теперь это боком вылазит, хочу эти флажки в поле затолкать.
Посоветуйте, плз!
Ответить

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