Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей... |
17.05.2018, 01:35
|
|
Почётный гражданин KAZUS.RU
Регистрация: 15.11.2010
Сообщений: 2,379
Сказал спасибо: 338
Сказали Спасибо 328 раз(а) в 253 сообщении(ях)
|
Указатели, чтоб их!
Есть такой говнокод
Код:
|
uint8_t SPI_ReadByte(uint8_t data)
{
//... Отправляем байт
SPI_WriteByte(data);
//... Принятый байт возвращаем
return reg_SPI;
}
//... Отправить и получить несколько байт по SPI. Принятые данные начинаются с data
void SPI_ReadArray(uint8_t num, uint8_t *data)
{
while(num--)
{
*data++ = SPI_ReadByte(*data);
}
} |
Вызываю функцию так
Код:
|
//... Функция приема данных. Функция возвращает длину сообщения,
// ... rx_data указывает на начало сообщения
uint8_t nRF_Receive(uint8_t *rx_data)
{
uint8_t length;
nRF_SELECT();
SPI_WriteByte(nRF_R_RX_PL_WID); // Запрашиваем длину сообщения
length = SPI_ReadByte(nRF_NOP); // Читаем длину сообщения
SPI_ReadArray(length, rx_data); // Читаем сообщение
nRF_DESELECT();
return length;
} |
И получаю предупреждение
Цитата:
|
операция над «данными» может быть неопределенной
|
от компилятора на строчку
Код:
|
*data++ = SPI_ReadByte(*data); |
А если вызвать так
Код:
|
//... Функция приема данных. Функция возвращает длину сообщения, rx_data указывает на начало сообщения
uint8_t nRF_Receive(uint8_t *rx_data)
{
uint8_t length;
nRF_SELECT();
SPI_WriteByte(nRF_R_RX_PL_WID); // Запрашиваем длину сообщения
length = SPI_ReadByte(nRF_NOP); // Читаем длину сообщения
uint8_t Buf[length];
SPI_ReadArray(length, Buf); // Читаем сообщение
nRF_DESELECT();
rx_data = Buf;
return length;
} |
то всё нормуль.
Что-то с ходу не понимаю, что не нравится компилятору? Или я болван, или спать пора =)
|
|
|
|
17.05.2018, 08:03
|
|
Прописка
Регистрация: 21.04.2018
Сообщений: 174
Сказал спасибо: 1
Сказали Спасибо 66 раз(а) в 53 сообщении(ях)
|
Re: Указатели, чтоб их!
Эмм... Чето вы написали какую-то дичь. Утро вечера мудреннее. Проспитесь и попробуйте снова
|
|
|
|
17.05.2018, 08:47
|
|
Гуру портала
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,835
Сказал спасибо: 919
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
|
Re: Указатели, чтоб их!
Код:
|
*data++ = SPI_ReadByte(*data); |
Вы сначала инкрименируете указатель, а потом пишите в него данные, полученные из функции. А надо наоборот:
Код:
|
*data = SPI_ReadByte(*data++); |
У себя я не определяю функции интерфейсов в явном виде. Это заставляет жестко привязаться к железу и с другим железом использование библиотеки становится затруднительно. Поэтому интерфейсы определяю в отдельных функциях:
Код:
|
uint8_t (*Write)(uint8_t reg, uint8_t * buf, uint8_t size);
uint8_t (*Read) (uint8_t reg, uint8_t * buf, uint8_t size); |
Для интерфейсов типа SPI, I2C и им подобных эти функции имеют один и тот же вид. Таким образом, мультиинтерфейсные чипы типа MFRC631 можно подключать как душе угодно без изменения файлов библиотек.
Функции можно определить локально внутри библиотеки или привязать через структуру. Как вам удобнее.
Последний раз редактировалось Easyrider83; 17.05.2018 в 09:00.
|
|
|
|
17.05.2018, 09:30
|
|
Почётный гражданин KAZUS.RU
Регистрация: 27.01.2005
Адрес: Россия, КЧР, Нижний Архыз
Сообщений: 3,637
Сказал спасибо: 117
Сказали Спасибо 814 раз(а) в 591 сообщении(ях)
|
Re: Указатели, чтоб их!
Чтобы такой жути не было, я бы функцию переделал так (возвращает 0, если все ОК):
Код:
|
uint8_t SPI_ReadByte(uint8_t *data)
{
//... Отправляем байт
if(!SPI_WriteByte(*data)) return 1; // ошибка записи - возврат 1
//... Принятый байт возвращаем
*data = reg_SPI;
return 0;
} |
Потому как операции вида *X++ = f(X) не определены: может сначала инкрементироваться указатель, а может, как оно и ожидалось, сначала выполниться функция.
__________________
Союз Советских Социалистических Округов Северной Америки
|
|
|
|
17.05.2018, 09:32
|
|
Почётный гражданин KAZUS.RU
Регистрация: 27.01.2005
Адрес: Россия, КЧР, Нижний Архыз
Сообщений: 3,637
Сказал спасибо: 117
Сказали Спасибо 814 раз(а) в 591 сообщении(ях)
|
Re: Указатели, чтоб их!
Сообщение от Easyrider83
|
Поэтому интерфейсы определяю в отдельных функциях
|
А если одновременно работают CAN, USART, USB, SPI и I2C?
__________________
Союз Советских Социалистических Округов Северной Америки
|
|
|
|
17.05.2018, 10:07
|
|
Гуру портала
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,835
Сказал спасибо: 919
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
|
Re: Указатели, чтоб их!
Сообщение от eddy
|
А если одновременно работают CAN, USART, USB, SPI и I2C?
|
Наступает эйфория
|
|
|
|
17.05.2018, 10:34
|
|
Почётный гражданин KAZUS.RU
Регистрация: 15.11.2010
Сообщений: 2,379
Сказал спасибо: 338
Сказали Спасибо 328 раз(а) в 253 сообщении(ях)
|
Re: Указатели, чтоб их!
Сообщение от eddy
|
Потому как операции вида *X++ = f(X) не определены: может сначала инкрементироваться указатель, а может, как оно и ожидалось, сначала выполниться функция.
|
Это от компилятора зависит или от погоды на Марсе?
Цитата:
|
У себя я не определяю функции интерфейсов в явном виде. Это заставляет жестко привязаться к железу и с другим железом использование библиотеки становится затруднительно. Поэтому интерфейсы определяю в отдельных функциях
|
Видимо это удобно программисту, но неизбежно влечет затраты памяти.
|
|
|
|
17.05.2018, 10:35
|
|
Гуру портала
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,835
Сказал спасибо: 919
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
|
Re: Указатели, чтоб их!
Затраты памяти - это лепить printf туда, где он не нужен. А два указателя - это мелочи.
|
|
|
|
17.05.2018, 10:40
|
|
Почётный гражданин KAZUS.RU
Регистрация: 12.02.2013
Сообщений: 1,038
Сказал спасибо: 43
Сказали Спасибо 273 раз(а) в 214 сообщении(ях)
|
Re: Указатели, чтоб их!
Сообщение от Easyrider83
|
*data++ = SPI_ReadByte(*data);
Вы сначала инкрименируете указатель
|
ИМНО здесь инкремент и запись не в указатель, а в переменную по этому указателю (есть операция разыменования *)
|
|
|
|
17.05.2018, 12:30
|
|
Вид на жительство
Регистрация: 27.11.2007
Сообщений: 429
Сказал спасибо: 19
Сказали Спасибо 39 раз(а) в 30 сообщении(ях)
|
Re: Указатели, чтоб их!
Компилятор должен ругаться в обоих случаях.
*data++ - постинкриментирование прочитанных данных (переменной по указателю), а не указателя. Что не есть правильно.
Код:
|
*data = SPI_ReadByte(*data);
data++; |
Так правильнее будет.
|
|
|
Сказали "Спасибо" sat_art
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 03:12.
|
|