Easyelectronics.ru

Электроника для всех
Текущее время: 25 ноя 2017, 01:27

Часовой пояс: UTC + 5 часов



    • 10 шт. 2-слоя 100*100mm 2$. Быстрый заказ: JLCPCB.com
    • JLCPCB - это крупнейшая фабрика PCB прототипов в Китае.
    • Имеющий более 290,000 клиентов и выполняющий более 8,000 заказов в день.
    • LCSC - Крупнейший китайский онлайн магазин радиодеталей.

Начать новую тему Ответить на тему  [ Сообщений: 16 ] 
Автор Сообщение
 Заголовок сообщения: задать байт при компиляции проекта
СообщениеДобавлено: 09 ноя 2017, 18:24 
Только пришел

Зарегистрирован: 06 янв 2015, 19:49
Сообщения: 26
Откуда: Новороссийск
Добрый день. Я понимаю что мой вопрос для многих здесь покажется глупым, но самостоятельно его решить не могу. Google не помог :( .

Пишу свою библиотеку для РСА9685. У него есть регистр настройки модуля к примеру MODE1 размером 1-байт.
биты регистра :
RESTART
EXTCLK
AI
SLEEP
SUB1
SUB2
SUB3
ALLCALL

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

uint8_t MODE1;

#define RESTART =0
#define EXTCLK =1
#define AI =1
#define SLEEP =0
#define SUB1 =1
#define SUB2 =0
#define SUB3 =1
#define ALLCALL =1

Как теперь эти биты засунуть в переменную типа uint8_t MODE1 ? как я понял нужно написать структуру но у меня не получается.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: задать байт при компиляции проекта
СообщениеДобавлено: 09 ноя 2017, 18:41 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 631
Для обозначения позиции бита можно дефайн записать вот так:
#define EXTCLK (1 << 5 )
#define SLEEP (1 << 6 )
где 5 и 6 - позиция бита в байте.
А в переменную MODE1 значения битов записывать вот так:
MODE1 = EXTCLK | SLEEP ;
убрать один бит из переменной можно вот так:
MODE1 &= ~SLEEP;
а снова добавить вот так:
MODE1 |= SLEEP;

А вот так записывать конечно же нельзя:
#define ALLCALL =1
поскольку директива препроцессора define - это по сути текстовая замена.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: задать байт при компиляции проекта
СообщениеДобавлено: 10 ноя 2017, 12:42 
Только пришел

Зарегистрирован: 06 янв 2015, 19:49
Сообщения: 26
Откуда: Новороссийск
Спасибо. Все получилось. Сделал так.
Код:

#define  ON  1
#define  OFF 0

uint8_t AddressMoDE1=0x00;
uint8_t AddressMoDE2=0x01;


#define  RESTART  (ON<<7)     
#define  EXTCLK   (OFF<<6)
#define  AI       (OFF<<5)
#define  SLEEP    (OFF<<4)
#define  SUB1     (OFF<<3)
#define  SUB2     (OFF<<2)
#define  SUB3     (OFF<<1)
#define  ALLCALL  (ON<<0)

uint8_t MODE1 = RESTART | EXTCLK | AI | SLEEP | SUB1 | SUB2| SUB3 | ALLCALL ;

А есть еще какие то варианты (способы) ?
Просто после ассемблера тяжко изучение си идет.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: задать байт при компиляции проекта
СообщениеДобавлено: 10 ноя 2017, 14:53 
Старожил

Зарегистрирован: 10 июн 2011, 23:01
Сообщения: 2747
uint8_t MODE1 = RESTART | ALLCALL;


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: задать байт при компиляции проекта
СообщениеДобавлено: 10 ноя 2017, 15:11 
Только пришел

Зарегистрирован: 06 янв 2015, 19:49
Сообщения: 26
Откуда: Новороссийск
_pv писал(а):
uint8_t MODE1 = RESTART | ALLCALL;

Указать только старший бит и младший, а остальные как в регистр попадут?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: задать байт при компиляции проекта
СообщениеДобавлено: 10 ноя 2017, 15:20 
Старожил
Аватара пользователя

Зарегистрирован: 23 сен 2012, 20:35
Сообщения: 1114
chif.com писал(а):
Указать только старший бит и младший, а остальные как в регистр попадут?

Они там уже есть в виде 0 на соответствующих позициях.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: задать байт при компиляции проекта
СообщениеДобавлено: 10 ноя 2017, 15:58 
Старожил

Зарегистрирован: 19 мар 2013, 19:37
Сообщения: 2255
Откуда: Санкт-Петербург
Только дефайны надо писать, как вам посоветовали, без всяких ON/OFF:
Код:
#define  RESTART  (1<<7)     
#define  EXTCLK   (1<<6)
#define  AI       (1<<5)
#define  SLEEP    (1<<4)
#define  SUB1     (1<<3)
#define  SUB2     (1<<2)
#define  SUB3     (1<<1)
#define  ALLCALL  (1<<0)
...
uint8_t MODE1 = RESTART | ALLCALL;


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: задать байт при компиляции проекта
СообщениеДобавлено: 10 ноя 2017, 18:38 
Только пришел

Зарегистрирован: 06 янв 2015, 19:49
Сообщения: 26
Откуда: Новороссийск
Спасибо.
Просто самоучитель которым я пользуюсь, рекомендует для удобства чтения кода пользоваться заменами. (для читабельности кода).
И принципе библиотеку вчера собрал, немного подергал сервоприводом, вроде все работает. При компиляции менял дефайнами настройки служебных регистров ON/OFF ми. в отладке видно что регистр меняется корректно.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: задать байт при компиляции проекта
СообщениеДобавлено: 11 ноя 2017, 02:02 
Старожил

Зарегистрирован: 11 сен 2012, 11:19
Сообщения: 4331
chif.com,. дайте ссылку на самомучитель.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: задать байт при компиляции проекта
СообщениеДобавлено: 12 ноя 2017, 13:34 
Заглядывает иногда

Зарегистрирован: 08 авг 2013, 09:43
Сообщения: 188
chif.com тут не в ON/OFF дело. Логика подхода чуть другая. Вы прописываете в DEFINE все биты в 1. Тем самым просто определяя позицию бита. А уже в байтовой переменной указываете те, которые действительно нужно выставить в 1, потому что по умолчанию и так 0 везде. Для "выключения", т.е. снятия бита, используется другая битовая операция.
Поэтому нет никаких ON и OFF. Есть заданная в DEFINE позиция бита и есть битовые операции, с помощью которых выполняется установка, сброс и переключение (инверсия) бита.
А при инициализации переменной изначально вы сразу присваиваете ей значение, если раскрыть должно быть понятно:
uint8_t MODE1 = RESTART | ALLCALL = (1<<7) | (1<<0) = 0b10000000 | 0b00000001 = 0b10000001.
Может вот эта статья немножко прояснит: http://easyelectronics.ru/avr-uchebnyj- ... ast-4.html
И вот еще: https://ph0en1x.net/81-howto-work-with- ... oller.html


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: задать байт при компиляции проекта
СообщениеДобавлено: 12 ноя 2017, 14:27 
Только пришел

Зарегистрирован: 06 янв 2015, 19:49
Сообщения: 26
Откуда: Новороссийск
dosikus_2 писал(а):
chif.com,. дайте ссылку на самомучитель.

http://proavr.narod.ru/05.htm
Но в основном у меня несколько книг по программированию на Си для AVR
NStorm писал(а):
chif.com тут не в ON/OFF дело. Логика подхода чуть другая. Вы прописываете в DEFINE все биты в 1. Тем самым просто определяя позицию бита.

Просто я пытаюсь написать универсальную библиотеку для РСА9685 чтоб потом при компиляции разных проектов просто достаточно было включить или отключить нужный бит регистра.

В принципе вчера крутил сервой, а логическим анализатором сидел на шине I2C и смотрел как сыпятся байты. По разному ON\OFF включал и отключал в регистре MODE1 при компиляции проекта, и смотрел терминале логического анализатора все вроде правильно сыпались байты.
В любом случае я рад замечания и спасибо за ссылку
NStorm писал(а):

Почитал, сразу много стало понятней.

А вот мой код
Код:
I2C_HandleTypeDef hi2c1;
uint8_t boof_1[4];
#define  ON  1
#define  OFF 0
#define  BYTE_0(n)                 ((uint8_t)((n) & (uint8_t)0xFF))        /*!< Returns the low byte of the 16-bit value */
#define  BYTE_1(n)                 ((uint8_t)(BYTE_0((n) >> (uint8_t)8)))  /*!< Returns the second byte of the 16-bit value */
#define  ZERO (15<<7)
//=========Определение адресов служебных регистров модуля РСА9685.==========================================================
//*************
uint8_t Add_MODE1       =0x00;
uint8_t Add_MoDE2       =0x01;
uint8_t Add_PRE_SCALE   =0xFE; //Предделитель внутр. генератора
//***************Канал ШИМ №1***************************************
uint8_t LED0_ON_L       =0x06; //Младший полубайт "Высокого" уровня
uint8_t LED0_ON_H       =0x07; //Старший полубайт "Высокого" уровня
uint8_t LED0_OFF_L      =0x08; //Младший полубайт "Низкого"  уровня
uint8_t LED0_OFF_H      =0x09; //Старший полубайт "Низкого"  уровня
//***************Канал ШИМ №2***************************************
uint8_t LED1_ON_L       =0x0A; //Младший полубайт "Высокого" уровня
uint8_t LED1_ON_H       =0x0B; //Старший полубайт "Высокого" уровня
uint8_t LED1_OFF_L      =0x0C; //Младший полубайт "Низкого"  уровня
uint8_t LED1_OFF_H      =0x0D; //Старший полубайт "Низкого"  уровня
//***************Канал ШИМ №3***************************************
uint8_t LED2_ON_L       =0x0E; //Младший полубайт "Высокого" уровня
uint8_t LED2_ON_H       =0x0F; //Старший полубайт "Высокого" уровня
uint8_t LED2_OFF_L      =0x10; //Младший полубайт "Низкого"  уровня
uint8_t LED2_OFF_H      =0x11; //Старший полубайт "Низкого"  уровня
//***************Канал ШИМ №4***************************************
uint8_t LED3_ON_L       =0x12; //Младший полубайт "Высокого" уровня
uint8_t LED3_ON_H       =0x13; //Старший полубайт "Высокого" уровня
uint8_t LED3_OFF_L      =0x14; //Младший полубайт "Низкого"  уровня
uint8_t LED3_OFF_H      =0x15; //Старший полубайт "Низкого"  уровня
//******************************************************************


//===========================================================================================================================
// Здесь задаем адрес и частоту при компиляции
uint8_t AddressPCA9685  =0x40;  // Адресс модуля РСА9685 на шине I2C
uint8_t PRE_SCALE       =120;   // 3-255 (24-1526 Гц) Частота ШИМ выходов Fpwm=25000000\4096(PRE_SCALE+1)
/***************************************************************************************************************************
RESTART : Флаг перезагрузки (чтение\запись)
EXTCLK  : Разрешает работу от внешнего источника тактирования 
AI      : Разрешает авто инкремент при доступе к регистрам по шине I2C многобайтными пакетами     
SLEEP   : Переводит контроллер в режим энергосбережения и отключает внутренний генератор 
SUB1    : Разрешает контроллеру реагировать на дополнительный адрес 1 шины I2C 
SUB2    : Разрешает контроллеру реагировать на дополнительный адрес 2 шины I2C 
SUB3    : Разрешает контроллеру реагировать на дополнительный адрес 3 шины I2C 
ALLCALL : Разрешает контроллеру реагировать на адрес общего вызова шины I2C 
*/
#define  RESTART  (ON<<7)     
#define  EXTCLK   (OFF<<6)
#define  AI       (OFF<<5)
#define  SLEEP    (OFF<<4)
#define  SUB1     (OFF<<3)
#define  SUB2     (OFF<<2)
#define  SUB3     (OFF<<1)
#define  ALLCALL  (ON<<0)
uint8_t MODE1 = RESTART | EXTCLK | AI | SLEEP | SUB1 | SUB2| SUB3 | ALLCALL ;

void Init_PCA9685 (void)
{
            
   boof_1[0]  = Add_MODE1;
   boof_1[1]  = MODE1 ;
   boof_1[1] |= ON<<4; //Включаем SLEEP режим, чтобы настроить предделитель
   HAL_I2C_Master_Transmit(&hi2c1, AddressPCA9685,  boof_1, 2, 100);
   boof_1[0]  = Add_PRE_SCALE;
   boof_1[1]  = PRE_SCALE ;
   HAL_I2C_Master_Transmit(&hi2c1, AddressPCA9685,  boof_1, 2, 100);
   boof_1[0]  = Add_MODE1;
   boof_1[1]  = MODE1 ;
   boof_1[1] &= ~SLEEP; // Отключаем SLEEP после настройки предделителя.
   boof_1[1] |= SLEEP;  // Выставляем обратно SLEEP так как определенно дефаинами при компиляции
   HAL_I2C_Master_Transmit(&hi2c1, AddressPCA9685,  boof_1, 2, 100);
      

}
void LED_0_PWM (uint16_t PWM_ON, uint16_t PWM_OFF )
{
   boof_1[0]  = LED0_ON_L ;
   boof_1[1]  = BYTE_0 (PWM_ON) ;
   HAL_I2C_Master_Transmit(&hi2c1, AddressPCA9685,  boof_1, 2, 100);
   
   boof_1[0]  = LED0_ON_H;
   boof_1[1]  = BYTE_1 (PWM_ON) ;
   
   HAL_I2C_Master_Transmit(&hi2c1, AddressPCA9685,  boof_1, 2, 100);   
 
   boof_1[0]  = LED0_OFF_L;
   boof_1[1]  = BYTE_0 (PWM_OFF) ;
   HAL_I2C_Master_Transmit(&hi2c1, AddressPCA9685,  boof_1, 2, 100);
   
   boof_1[0]  = LED0_OFF_H;
   boof_1[1]  = BYTE_1 (PWM_OFF) ;
   
   HAL_I2C_Master_Transmit(&hi2c1, AddressPCA9685,  boof_1, 2, 100);
   
}   


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: задать байт при компиляции проекта
СообщениеДобавлено: 12 ноя 2017, 14:43 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 631
вообще-то....
Во-первых, в Си общепринято имена переменных записывать маленькими буквами, в отличие от текстовых замен (#define), записываемых большими буквами. Тогда визуально сразу понятно - либо это переменная, занимающая ячейку памяти, либо это текстовая замена на этапе компиляции, которая "для облегчения понимания".
Во-вторых, отсюда же и ошибка - uint8_t LED0_ON_L =0x06 - это переменная, занимающая память. На то, что это - переменная, указывает её тип uint8_t.
Та же самая ошибка и с uint8_t MODE1. Это - переменная, занимающая ячейку памяти. И ей присвоено значение. То есть, физически переменная MODE1 существует в системе (занимает ячейку памяти с конкретным адресом) постоянно, а на стартовых операциях МК ей присваивается значение, которое вы там указали, и оно более не изменяется в коде. Таким образом, переменная физически бесполезно висит в системе.

Далее идет boof_1[1] = MODE1 ; - по сути, это копирование из одной ячейки памяти в другую.
Вместо этого можно было бы записать MODE1 как #define MODE1 (RESTART) | (ALLCALL), и таким образом, предыдущее выражение после дешифровки текстовых замен стало бы вот таким:
boof_1[1] = (RESTART) | (ALLCALL);
или если дешифровать и далее, то получили бы
boof_1[1] = (1<<7) | (1<<0), что является гораздо более экономичным с точки зрения расхода кода и времени.
Скобки - признак хорошего тона для однозначного задания приоритетов арифметических и логических операций. Лучше будет скобки ставить вот тут: #define RESTART (1<<7) и тогда скобки в #define MODE1 RESTART | ALLCALL можно не ставить.


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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: задать байт при компиляции проекта
СообщениеДобавлено: 14 ноя 2017, 21:25 
Только пришел

Зарегистрирован: 06 янв 2015, 19:49
Сообщения: 26
Откуда: Новороссийск
<BusMaster>
Спасибо на указанные ошибки, постараюсь разобрать их по полочкам.
А вот насчет изучения, то тут приходится на ходу по ходу пьесы, так как изготовление и разработка устройств на 50% составляет мой доход.
Сейчас апетиты заказчиков растут а я со своими ПИКами на асме скоро не буду укладываться в задачи. Вот и хочу переходить потихоньку на STM и Си


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: задать байт при компиляции проекта
СообщениеДобавлено: 14 ноя 2017, 21:56 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 631
Когда-то и я тоже писал на ассемблере и тоже для PIC-ов... А на голом ассемблере далеко не уедешь - основной затык - в математике

В случае с сишной библиотекой для подобных микросхем, у которых есть внутренние номера регистров и управляющие биты в них, наиболее целесообразно делать вот так:
Код:
Дефайны для регистров:
/*------- Level 1 Command --------------*/
#define MADCTL         0x36   // Memory Access Conrol
#define VSCRSADD      0x37   // Vertical Scrolling Start Address
#define IDMOFF         0x38   // Idle Mode OFF
#define IDMON         0x39   // Idle Mode ON
#define PIXSET         0x3A   // Pixel Format Set
#define RAMWRCONTIN      0x3C   // Write Memory Continue
... и так далее...

Дефайны для битов каждого регистра:
/*---- Memory Access Control ------------*/
#define MADCTL_MH            (1<<2)   // Horizontal Order
#define MADCTL_BRG            (1<<3)   // RGB/ BGR Order
#define MADCTL_ML            (1<<4)   // Scan Address Order
#define MADCTL_MV            (1<<5)   // Row/Column Exchange
#define MADCTL_MX            (1<<6)   // Column Address Order
#define MADCTL_MY            (1<<7)   // Row Address Order

/*---- Set Pixel Format -----------------*/
#define PIXSET_DBI_0         (1<<0)   // Pixel Format for RGB interface
#define PIXSET_DBI_1         (1<<1)   //
#define PIXSET_DBI_2         (1<<2)   //
#define PIXSET_DPI_0         (1<<4)   // Pixel format for MCU interface
#define PIXSET_DPI_1         (1<<5)   //
#define PIXSET_DPI_2         (1<<6)   //
... и так далее...

Применение в коде:
  /* BGR, Mirr X, Mirr Y */
  ILI9341_SendCommand(MADCTL);
  ILI9341_SendData(MADCTL_BRG | MADCTL_MX | MADCTL_MY);
 
  /* RGB 18 bit */
  ILI9341_SendCommand(PIXSET);
  ILI9341_SendData(PIXSET_DBI_0 | PIXSET_DBI_2);

  /* column address: 0 - 239 */
  ILI9341_SendCommand(CASET);
  ILI9341_SendData(0x00);
  ILI9341_SendData(0x00);
  ILI9341_SendData(0x00);
  ILI9341_SendData(0xEF);



Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: задать байт при компиляции проекта
СообщениеДобавлено: 14 ноя 2017, 22:06 
Старожил

Зарегистрирован: 10 июн 2011, 23:01
Сообщения: 2747
BusMaster писал(а):
и тогда скобки в #define MODE1 RESTART | ALLCALL можно не ставить.

это чтобы потом написать что-нибудь вроде MODE1 & MASK и удивляться почему RESTART зажатым остался?
общие скобки в дефайнах нужны ВСЕГДА.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: задать байт при компиляции проекта
СообщениеДобавлено: 14 ноя 2017, 22:08 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 631
я имел ввиду, что не ставить вот эти скобки: (RESTART) | (ALLCALL)


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 16 ] 

Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


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

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB