Реклама на сайте English version  DatasheetsDatasheets

KAZUS.RU - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Электронные книги
FAQ по электронике

  Datasheets
Поиск SMD
Он-лайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Избранные схемы
FAQ по электронике
  Программы
Каталог сайтов
Производители электроники
  Форумы по электронике
Помощь проекту


 
Опции темы
Непрочитано 17.05.2016, 03:18  
cogen
Прописка
 
Регистрация: 25.04.2010
Сообщений: 24
Сказал спасибо: 9
Сказали Спасибо 17 раз(а) в 17 сообщении(ях)
cogen на пути к лучшему
По умолчанию Re: Пишем свое API

Сообщение от Easyrider83 Посмотреть сообщение
Надо преобразовать тип. Но ума не приложу, как это оформить.
Вроде так
I2C_SeqRead = (unsigned char (*)(unsigned char, unsigned char, unsigned char * , unsigned char))I2C__Read_Page;
Реклама:
cogen вне форума  
Непрочитано 17.05.2016, 09:31  
Easyrider83
Гуру портала
 
Аватар для Easyrider83
 
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,835
Сказал спасибо: 919
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
Easyrider83 на пути к лучшему
По умолчанию Re: Пишем свое API

Сообщение от omercury Посмотреть сообщение
Смотрю я на этот птичий язык и приходит в голову такая странная мысль - I2C_Result возвращала статус IIC, а BME280 этого не делает. Полагаю, надо обернуть BME аналогичным первому случаю образом, пусть хотя бы отвечает, что транзакция прошла успешно.
Дело в том, что мы имеем дело с разными слоями драйвера. Датчик может использовать так же и SPI интерфейс. В свою очередь I2C зависит от железа и является драйвером интерфейса.
Сообщение от Ar-Gen-Tum Посмотреть сообщение
В первом случае определена функция, возвращающая результат.
А во втором случае имеется структура, содержащая поле данных
и два указателя на методы. Самих методов структура не содержит.
При создании экземпляра структуры, полям методов надо присвоить указатели на соответствующие функции.
Значит, надо написать собственную функцию, которая будет вызывать первую функцию,
результат типа enum приводить к типу unsigned char, записывать результат в память
и возвращать указатель на него.
И уже эту функцию присваивать полю метода в экземпляре структуры.
Тогда они должны совместиться.
Да, это вполне рациональный выход - черед промежуточную функцию. Пусть драйвер будет иметь возможность возвращать код ошибки без использования enum. Идея хорошая.
Сообщение от cogen Посмотреть сообщение
Вроде так
I2C_SeqRead = (unsigned char (*)(unsigned char, unsigned char, unsigned char * , unsigned char))I2C__Read_Page;
Спасибо, попробую дома. Но выглядит ужасно, конечно.
Easyrider83 вне форума  
Непрочитано 17.05.2016, 09:48  
Ar-Gen-Tum
Почётный гражданин KAZUS.RU
 
Регистрация: 19.10.2010
Сообщений: 1,752
Сказал спасибо: 158
Сказали Спасибо 640 раз(а) в 364 сообщении(ях)
Ar-Gen-Tum на пути к лучшему
По умолчанию Re: Пишем свое API

Сообщение от cogen Посмотреть сообщение
Вроде так
I2C_SeqRead = (unsigned char (*)(unsigned char, unsigned char, unsigned char * , unsigned char))I2C__Read_Page;
В этой конструкции производится явное преобразование типа числа к типу указателя на число.
Теоретически компилятор может это "проглотить", но работать это может не правильно.
Ведь число, возвращаемое функцией I2C__Read_Page, будет интерпретироваться, как указатель на ячейку памяти.
Явные приведения разумны либо между разными представлениями чисел,
либо между указателями, например приведение указателя к типу void* .
Указатель типа void* может указывать на любые типы данных.
Ar-Gen-Tum вне форума  
Непрочитано 17.05.2016, 10:43  
cogen
Прописка
 
Регистрация: 25.04.2010
Сообщений: 24
Сказал спасибо: 9
Сказали Спасибо 17 раз(а) в 17 сообщении(ях)
cogen на пути к лучшему
По умолчанию Re: Пишем свое API

Гм, по-моему в этой конструкции производится преобразование указателя на функцию к типу указателя на функцию. Явное преобразование компилятор запрашивает из-за несовместимых типов возвращаемого значения, он хочет убедиться что ты действительно нацеливаешь ружье себе в ногу. В старых стандартах enum - целочисленный тип (int), компилятор может его разместить и в байте, если диапазон перечисления поместится. Если не поместится, скажем там есть значение WEAREDOOMED=0xFF00, то код проверки результата не сможет отличить такое значение от ALL_OK=0x00. А если возврат не через регистр а через стек то с такими явными преобразованиями стек потечет и привет.
cogen вне форума  
Непрочитано 17.05.2016, 11:19  
cogen
Прописка
 
Регистрация: 25.04.2010
Сообщений: 24
Сказал спасибо: 9
Сказали Спасибо 17 раз(а) в 17 сообщении(ях)
cogen на пути к лучшему
По умолчанию Re: Пишем свое API

Сообщение от Easyrider83 Посмотреть сообщение
Но выглядит ужасно, конечно.
Исходный код такой, надо периодически рефакторить. Если контроллер большой, то лучше пусть код читается чем пару байт/тактов наэкономить. Можно вот так оформить
Код:
typedef enum {
    ALL_OK = 0x01,
    WEAREDOOMED=0xff01
} Bus_Result;

typedef struct{
    unsigned char I2c_Address;
    unsigned char Mem_Address;
    unsigned char * pBuffer;
    unsigned char pBufferSize;
    Bus_Result result;
} SBus_Transaction;

void I2C__Read_Page     (SBus_Transaction *t)
{
    t-›result=ALL_OK;
    return;
}

typedef struct
{
  SBus_Transaction transaction;
  void (* SeqRead) (SBus_Transaction *);
  void (* SeqWrite)(SBus_Transaction *);
}BME280_InitStructTypeDef;

#include ‹iostream›
using namespace std;

int main()
{
    BME280_InitStructTypeDef BME280;
    BME280.SeqRead = I2C__Read_Page;
 
    BME280.SeqRead(&BME280.transaction);
    if (ALL_OK==BME280.transaction.result) cout‹‹"OK"‹‹endl;
    else cout‹‹"FAIL"‹‹endl;
    BME280.SeqRead(&BME280.transaction);
    if (WEAREDOOMED!=BME280.transaction.result) cout‹‹"OK"‹‹endl;
    else cout‹‹"FAIL"‹‹endl;
    return 0;
}

Последний раз редактировалось cogen; 17.05.2016 в 11:31.
cogen вне форума  
Сказали "Спасибо" cogen
Easyrider83 (17.05.2016)
Непрочитано 17.05.2016, 11:41  
Easyrider83
Гуру портала
 
Аватар для Easyrider83
 
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,835
Сказал спасибо: 919
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
Easyrider83 на пути к лучшему
По умолчанию Re: Пишем свое API

Там по науке надо еще сделать указатель на структуру с параметрами. Для других интерфейсов параметры будут другие и их количество тоже изменится. Поэтому все еще хитрее будет выглядеть. Но да, стиль вырабатывается правильный.
Easyrider83 вне форума  
Непрочитано 17.05.2016, 12:45  
cogen
Прописка
 
Регистрация: 25.04.2010
Сообщений: 24
Сказал спасибо: 9
Сказали Спасибо 17 раз(а) в 17 сообщении(ях)
cogen на пути к лучшему
По умолчанию Re: Пишем свое API

Абстракция хороша в меру, сколько этих интерфейсов всего? Лишний указатель может снизить читаемость и сьест 2-4байта, плюс при доступе лишние такты. Всё зависит от числа параметров и контроллера, можно все в кучу свалить и использовать только необходимые, однотипные поименовать поабстрактнее, чтобы для разных интерфейсов их использование выглядело логично, разнотипные параметры можно в union обернуть. Буфер и его размер, объем принятых данных, результат транзакции - вещи универсальные. Если переименовать Mem_Address в Target, то такой параметр и в других протоколах логичен.
cogen вне форума  
Непрочитано 17.05.2016, 22:12  
Easyrider83
Гуру портала
 
Аватар для Easyrider83
 
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,835
Сказал спасибо: 919
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
Easyrider83 на пути к лучшему
По умолчанию Re: Пишем свое API

Все заработало через проставку:
Код:
/* Functions without using enum type */

unsigned char I2C_Write_Page    (unsigned char I2c_Address, 
                                 unsigned char Mem_Address, 
                                 unsigned char * pBuffer, 
                                 unsigned char pBufferSize)
{
  return (unsigned char)I2C__Write_Page(I2c_Address, Mem_Address, 
                                        pBuffer, pBufferSize);
}

unsigned char I2C_Read_Page    (unsigned char I2c_Address, 
                                unsigned char Mem_Address, 
                                unsigned char * pBuffer, 
                                unsigned char pBufferSize)
{
  return (unsigned char)I2C__Read_Page(I2c_Address, Mem_Address, 
                                        pBuffer, pBufferSize);
}
Код:
  /* BME280 INIT */
  BME280_InitStruct.I2C_Address = 0xEC;
  BME280_InitStruct.I2C_SeqRead =  I2C_Read_Page;
  BME280_InitStruct.I2C_SeqWrite = I2C_Write_Page;
  BME280_Error = BME280_Init(&BME280_InitStruct);
В общем, оставлю так. Мне нравится.
Easyrider83 вне форума  
Непрочитано 17.05.2016, 22:51  
cogen
Прописка
 
Регистрация: 25.04.2010
Сообщений: 24
Сказал спасибо: 9
Сказали Спасибо 17 раз(а) в 17 сообщении(ях)
cogen на пути к лучшему
По умолчанию Re: Пишем свое API

Ну и зачем стек лишним вызовом пачкать, такты тратить и мотать спагетти в исходниках? Не сработал каст чтоли? Или тут курсы индийских программистов?
Если уж морочиться с обертками, то сделать как я в примере показал, хоть задел на будущее будет. И не только читаемости ради. Как я представляю, весь список параметров при вызове функции обычно передается через стек - получается ноль-один PUSH против трех-четырех в старом коде. Если обмен по шине интенсивный, то можно сэкономить и стек, и время, и энергию.
cogen вне форума  
Непрочитано 17.05.2016, 23:00  
Easyrider83
Гуру портала
 
Аватар для Easyrider83
 
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,835
Сказал спасибо: 919
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
Easyrider83 на пути к лучшему
По умолчанию Re: Пишем свое API

Да просто не надо выпендриваться с enum там, где это не нужно. На будущее вывод сделан. Будем писать проще.
Так тоже работает:
Код:
  /* BME280 INIT */
  BME280_InitStruct.I2C_Address = 0xEC;
  BME280_InitStruct.I2C_SeqRead =  (unsigned char (*)(unsigned char, unsigned char, unsigned char * , unsigned char))I2C__Read_Page;
  BME280_InitStruct.I2C_SeqWrite = (unsigned char (*)(unsigned char, unsigned char, unsigned char * , unsigned char))I2C__Write_Page;
  BME280_Error = BME280_Init(&BME280_InitStruct);

Последний раз редактировалось Easyrider83; 17.05.2016 в 23:07.
Easyrider83 вне форума  
 

Закладки
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
свое USB устройство ESWANT Микроконтроллеры, АЦП, память и т.д 2 08.09.2009 14:58


Часовой пояс GMT +4, время: 07:29.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot