Програмирование pic на СИ.

Поклонники продукции Microchip Technology Inc тусуются тут.
Аватара пользователя
Zhuk72
Сверлит текстолит когтями
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку
Контактная информация:

Re: Програмирование pic на СИ.

Сообщение Zhuk72 »

Siarzhuk писал(а):pos это не переменная, и даже не тип (в С) - а именно что НеизвестнАЯ ИдентификАтыръ. :)
И как тогда мне ее, структуру, объявить, если struct pos {unsigned char x, y;}; объявлено неправильно?
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
Аватара пользователя
КРАМ
Друг Кота
Сообщения: 25184
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Re: Програмирование pic на СИ.

Сообщение КРАМ »

Siarzhuk писал(а):при оптимизации битовыми полями сегмента данных - страдает сегмент кода (читай производительность), за счёт большего количества операций по доступу к полям. Мало того - в зависимости от позиции битового поля в структуре - размер операций тоже может быть разным. Т.е. если с каким-то полем чаще работаем - можно также сэкономить байтики двигая поле в более выгодную позицию. :)
Все это зависит от архитектуры контроллера и его системы команд.
Поскольку речь идет о Микрочипе, то битовые элементы структур как раз очень хорошо ложатся на битовые команды. И код получается компактным и быстрым. Правда все зависит от компилятора и уровня оптимизации. При доступе к биту может и маску применить, а может и битовую операцию.
Категоричные заявления о вредности нестандартных типов из-за непереносимости кода не выдерживают никакой критики, потому что различия между платформами столь велики, что переносимыми будут лишь самые общие участки кода, что лишь запутывает программиста и не дает никаких преимуществ и экономии времени.
Аватара пользователя
Zhuk72
Сверлит текстолит когтями
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку
Контактная информация:

Re: Програмирование pic на СИ.

Сообщение Zhuk72 »

Zhuk72 писал(а):
Siarzhuk писал(а):pos это не переменная, и даже не тип (в С) - а именно что НеизвестнАЯ ИдентификАтыръ. :)
И как тогда мне ее, структуру, объявить, если struct pos {unsigned char x, y;}; объявлено неправильно?
Вот у КиР написано

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

struct point {
                  int x;
                  int у;
                  } ;
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Програмирование pic на СИ.

Сообщение ARV »

Zhuk72 писал(а):И как тогда мне ее, структуру, объявить, если struct pos {unsigned char x, y;}; объявлено неправильно?
лично я в подобных "подозрительных" случаях всегда объявляю пользовательский тип - ни разу сбоев не было!

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

typedef struct{
   unsigned char x, y;
} point_t;

pint_t pos;
Добавлено after 1 minute 49 seconds:
КРАМ писал(а):Категоричные заявления о вредности нестандартных типов из-за непереносимости кода не выдерживают никакой критики
категорические утверждения о невыдерживнии критики не выдерживают никакой критики :)))
потому что если есть стандарт, то надо максимально соблюдать его требования все время, пока не попал в безвыходную ситуацию. а уж в безвыходной ситуации все средства хороши.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

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

Re: Програмирование pic на СИ.

Сообщение Siarzhuk »

ARV писал(а):это на самом деле так? не 1 байт?
Третьего дня самолично в RX-GCC наткнулся. :-) Причём директивы упаковки не спасли. Не PIC, конечно - но иметь ввиду вероятность такого сюрприза не помешает, кмк.
Siarzhuk писал(а):скорее всего он задействует для этой цели аппаратные фичи кристалла. про PIC не скажу, а в MCS51 есть особые области ОЗУ с побитовой адресацией
Обнаружил это в PIC16F630 с XC8 когда и сам заталкивал в него побольше функционала на фоне исчерпания .data. XC8, правда, был Free версии - а в этом режиме он имеет привычку оптимизировать с прохладцей, саботажем и лёгким вредительством - и если в PRO версии с глобальными bit по другому работает - ну тогда я не прав. :)
Последний раз редактировалось Siarzhuk Пт ноя 18, 2016 13:38:48, всего редактировалось 1 раз.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Аватара пользователя
КРАМ
Друг Кота
Сообщения: 25184
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Re: Програмирование pic на СИ.

Сообщение КРАМ »

Аlex писал(а):Ещё, плюс объединений переменных в структуры - обработка в функциях. Можно передавать указатель, как аргумент, вместо кучи переменных.
Правда это удобство приводит к достаточно громоздкому скомпилированному коду в КАЖДОЙ функции, куда передается указатель на структуру. Потому как до конкретного элемента структуры нужно еще добраться.
ARV писал(а):
КРАМ писал(а):Категоричные заявления о вредности нестандартных типов из-за непереносимости кода не выдерживают никакой критики
категорические утверждения о невыдерживнии критики не выдерживают никакой критики :)))
потому что если есть стандарт, то надо максимально соблюдать его требования все время, пока не попал в безвыходную ситуацию. а уж в безвыходной ситуации все средства хороши.
Есть стандарт языка, но нет стандарта для создаваемого кода. Все средства хороши В ЛЮБОЙ ситуации.
Более того, если программист не применяет эти самые "все средства" всегда, то в "безвыходной ситуации" он оказывается достаточно беспомощным и полученный код действительно не выдержит никакой критики...
Аватара пользователя
Zhuk72
Сверлит текстолит когтями
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку
Контактная информация:

Re: Програмирование pic на СИ.

Сообщение Zhuk72 »

ARV писал(а):лично я в подобных "подозрительных" случаях всегда объявляю пользовательский тип - ни разу сбоев не было!
Спасибо, получилось!
ARV писал(а):про PIC не скажу, а в MCS51 есть особые области ОЗУ с побитовой адресацией, и соответствующие однобитовые команды ассемблера. так что и тут речь скорее всего об этом - линкер отдыхает.
Именно в ПИКовом проекте объявлял биты, а потом в отладчике наблюдал, как они все оказывались в одном регистре в области общей памяти.
Каждый имеет право на свое личное ошибочное мнение.

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

Re: Програмирование pic на СИ.

Сообщение Siarzhuk »

Zhuk72 писал(а):И как тогда мне ее, структуру, объявить, если struct pos {unsigned char x, y;}; объявлено неправильно?
Объявлен тип, но не объявлена переменная этого типа. :)

С битовыми полями ещё и на проверке индексов можно экономить:

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

#define BIT_SIZE 4
char ringBuffer[1 << SIZE];
struct {
  char headIndex : BIT_SIZE;
  char tailIndex : BIT_SIZE;
};
Добавлено after 1 minute 37 seconds:
Zhuk72 писал(а):а потом в отладчике наблюдал, как они все оказывались в одном регистре в области общей памяти.
В map-файл если ешё не заглядывали - тоже, кмк, будет интересно глянуть.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Аватара пользователя
Zhuk72
Сверлит текстолит когтями
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку
Контактная информация:

Re: Програмирование pic на СИ.

Сообщение Zhuk72 »

Всем спасибо за очень познавательную дискуссию :)
Удаляюсь для воплощения.
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
Аватара пользователя
Zhuk72
Сверлит текстолит когтями
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку
Контактная информация:

Re: Програмирование pic на СИ.

Сообщение Zhuk72 »

В итоге решил делать так:

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

typedef struct {unsigned work: 1;
                unsigned btn_start: 1;
                unsigned flash: 1;
                unsigned b3: 1;
                unsigned b4: 1;
                unsigned b5: 1;
                unsigned b6: 1;
                unsigned b7: 1;} bits;
bits flag;
Поскольку использовать в подобных конструкциях более, чем 1 бит, только ухудшит конечный код (в асме добавятся маски и сдвиги, как я предполагаю), указанное выше - это просто удобство помнить только одну переменную с именем flag, в которую по необходимости можно добавлять и другие подобные флаги.
Каждый имеет право на свое личное ошибочное мнение.

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

Re: Програмирование pic на СИ.

Сообщение Siarzhuk »

Zhuk72 писал(а):Поскольку использовать в подобных конструкциях более, чем 1 бит, только ухудшит конечный код (в асме добавятся маски и сдвиги, как я предполагаю)
На всякое категоричное утверждение найдётся аргу́́мент. :) Если .data уже закончился, а .text ещё полупустой - разменять таким образом RОМ на RAM будет вполне себе выходом.
[pedantic mode on]
Если не затруднит - гляньте sizeof(bits) пожалуйста и нам сообщите для общего развития. И да - unsigned это unsigned int, и, припоминаю, явное указание вместо int восьмибитного типа в конкретном случае оптимизации под PIC16F630 сэкономило мне в своё время, таки парочку байтов. Стоит тоже проверить, кмк. :)
[pedantic mode off]
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Аватара пользователя
Zhuk72
Сверлит текстолит когтями
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку
Контактная информация:

Re: Програмирование pic на СИ.

Сообщение Zhuk72 »

Siarzhuk писал(а): [pedantic mode on]
1. Если не затруднит - гляньте sizeof(bits) пожалуйста и нам сообщите для общего развития.

2. И да - unsigned это unsigned int, и, припоминаю, явное указание вместо int восьмибитного типа в конкретном случае оптимизации под PIC16F630 сэкономило мне в своё время, таки парочку байтов. Стоит тоже проверить, кмк. :)
[pedantic mode off]
1. Я не волшебник, я только учусь (с) :))
Вы только намекните где это можно увидеть, а я сразу же...

2. Вот тут я в сомнениях. Что-то написать там нужно, но что именно, чтоб они все упаковались в один байт - я не знаю. Пока времени не было уточнить.
Каждый имеет право на свое личное ошибочное мнение.

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

Re: Програмирование pic на СИ.

Сообщение Siarzhuk »

Zhuk72 писал(а):2. Вот тут я в сомнениях. Что-то написать там нужно, но что именно, чтоб они все упаковались в один байт - я не знаю. Пока времени не было уточнить.
Битовые поля по-честному укладываются на соответствующие биты - вопрос лишь в том, сколько займёт структура. Можно глянуть в отладчике. Можно прикинуть по map-файлу. Вот например ваши флаги в моём файле:

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

_ep_data_out                       bssBANK2     0131
_flag                              bssBANK0     006A                     <--------- flag (в банке 0)
_hid_rpt01                         stringtext   1500
_i2cProtocol                       dataCOMMON   007B
_idle_rate                         bssBANK2     0143
_inBuffer                          dataCOMMON   0079
_inPipes                           bssBANK2     013D
_main                              cinit        104B
_notifyChunks                      bssBANK0     006B                     <--------- следуюший за flag-ом в банке 0
_outBuffer                         dataBANK0    006E
Т.е. очевидно, что всё уместилось в байт. Добавляем девятое поле:

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

_ep_data_out                       bssBANK2     0131
 _flag                              bssBANK2     0133                     <---------
 _hid_rpt01                         stringtext   1500
 _i2cProtocol                       dataCOMMON   007B
 _idle_rate                         bssBANK2     0144
 _inBuffer                          dataCOMMON   0079
 _inPipes                           bssBANK2     013E
 _main                              cinit        1048
 _notifyChunks                      bssBANK0     006A
 _outBuffer                         dataBANK0    006E
 _outPipes                          bssBANK2     0120
 _pBDTEntryEP0OutCurrent            bssBANK1     00EA
 _pBDTEntryEP0OutNext               bssBANK1     00EB
 _pBDTEntryIn                       bssBANK2     0135                     <--------- 134-го в bssBANK2 нету
 _pBDTEntryOut                      bssBANK2     0137
Ага, два байта. И во вторую банку переместилось из нулевой - в которой очевидно место закончилось.

А упаковка относится к структурам, поскольку компилятор порой раскладывает их поля по выровненным (aligned) адресам, для ускорения работы с ними. В итоге размер такой структуры будет больше нежели сумма размеров её элементов. Если вам извне придёт пакет данных без подобных "прорех" - разобрать его простым наложением структуры на указатель будет несколько затруднительно. Поэтому при объявлении нужно явно указывать:

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

typedef struct __attribute__ ((packed)) _USB_DEVICE_DESCRIPTOR
{
    uint8_t bLength;               // Length of this descriptor.
[...]
Ну и за компанию про глобальные bit переменные. Добавим горсть малую в тестовый кот с вашим битовым полем:

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

bit bit1;
bit bit2;
bit bit3;
bit bit4;

MAIN_RETURN main(void)
{
	SYSTEM_Initialize(SYSTEM_STATE_USB_START);

	flag.b3 = 1;
	bit1 = 0;
	bit2 = 1;
	bit3 = flag.b7;
	bit4 = 0;

	if (flag.b6 == 1 && bit1 == bit3 || bit1 != bit2 || bit2 == bit4)
		USBDeviceInit();
И в мап-файле:

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

__size_ofi1_LED_On                 (abs)        0000
_active_protocol                   bssBANK2     0147
_bit1                              bitbssCOMMON 03D0                     <--------- следим
_bit2                              bitnvCOMMON  03C8                     <--------- за
_bit3                              bitnvCOMMON  03C9                     <--------- адреса-
_bit4                              bitbssCOMMON 03D1                     <--------- ми
_configDescriptor1                 stringtext   149C
_controlTransferState              bssBANK1     00E8
[...]
                Name                               Link     Load   Length Selector   Space Scale
[...]
                bssBANK0                             66       66        6       50       1
                dataCOMMON                           7B       7B        1       70       1
                bssCOMMON                            76       76        3       70       1
                bitbssCOMMON                        3D0       7A        2       70       1     8                     <--------- размер 2!
                bitnvCOMMON                         3C8       79        2       70       1     8                     <--------- тоже самое.
                stringtext                         1400     1400       DB       28       0
[...]
Т.е. оно их даже в один байт не упаковало. Вероятно справедливо рассудив, что "места у этого поца покамест ещё хватает". Что самое забавное в режимах PRO Speed и PRO без Speed - картина не меняется. :-)

PS: Других переменных типа bit кроме здесь показанных в программе нету если что.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Аватара пользователя
Zhuk72
Сверлит текстолит когтями
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку
Контактная информация:

Re: Програмирование pic на СИ.

Сообщение Zhuk72 »

Вот мое объявление переменных на данный момент:

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

typedef struct {unsigned work: 1;
                unsigned btn_start: 1;
                unsigned flash: 1;
                unsigned b3: 1;
                unsigned b4: 1;
                unsigned b5: 1;
                unsigned b6: 1;
                unsigned b7: 1;} bits;
bits flag;
unsigned char flash_cnt, flash_pause;
А это в мар-файле:

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

_flag                    bssBANK0     0026
_flash_cnt               bssBANK0     0027
_flash_pause             bssBANK0     0028
Стало быть за границы одного байта ничего не вылезло :)
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
Пока_без_кота
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Re: Програмирование pic на СИ.

Сообщение Пока_без_кота »

Доброго времени суток. Взялся попробовать С. Ну так, самую малость, просто чтобы понять что я теряю, колупаясь в асме. Хочу значит установить предделитель Таймера0. Пишу:

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

OPTION = 1<<0;
Гляжу в дизассемблер, вижу результат:

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

01A    3001     MOVLW 0x1
01B    1683     BSF 0x3, 0x5
01C    0081     MOVWF 0x1
В принципе устраивает (хотя я ручками покороче умею).
Помню, что на асме можно удобно по именам битов устанавливать/сбрасывать. На всякий случай лезу в заголовочный файл на используемый МК, и нахожу там заветные строчки

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

/*	OPTION bits	*/
volatile	bit	RBPU	@ (unsigned)&OPTION*8+7;
volatile	bit	INTEDG	@ (unsigned)&OPTION*8+6;
volatile	bit	T0CS	@ (unsigned)&OPTION*8+5;
volatile	bit	T0SE	@ (unsigned)&OPTION*8+4;
volatile	bit	PSA	@ (unsigned)&OPTION*8+3;
volatile	bit	PS2	@ (unsigned)&OPTION*8+2;
volatile	bit	PS1	@ (unsigned)&OPTION*8+1;
volatile	bit	PS0	@ (unsigned)&OPTION*8+0;
Отлично, заменяю код на:

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

OPTION = 1<<PS0;
получаю в итоге:
Спойлер

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

 19:                	OPTION = 1<<PS0;
   00D    3001     MOVLW 0x1
   00E    008E     MOVWF 0xe
   00F    3000     MOVLW 0
   010    1683     BSF 0x3, 0x5
   011    1801     BTFSC 0x1, 0
   012    3001     MOVLW 0x1
   013    3E01     ADDLW 0x1
   014    1283     BCF 0x3, 0x5
   015    2818     GOTO 0x18
   016    1003     BCF 0x3, 0
   017    0D8E     RLF 0xe, F
   018    3EFF     ADDLW 0xff
   019    1D03     BTFSS 0x3, 0x2
   01A    2816     GOTO 0x16
   01B    080E     MOVF 0xe, W
   01C    1683     BSF 0x3, 0x5
   01D    0081     MOVWF 0x1
Это как понимать ? :shock:
Аватара пользователя
Zhuk72
Сверлит текстолит когтями
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку
Контактная информация:

Re: Програмирование pic на СИ.

Сообщение Zhuk72 »

С чего это так не скажу, а для изменения отдельных бит в регистре всегда пользуюсь маской. Могли бы сделать так:

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

  OPTION |= 1;
или для второго случая

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

  PS0 = 1;
Но первый лучше.
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
Аватара пользователя
КРАМ
Друг Кота
Сообщения: 25184
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Re: Програмирование pic на СИ.

Сообщение КРАМ »

Пока_без_кота писал(а): Это как понимать ? :shock:
А понимать это так, что компилятор при нулевом уровне оптимизации:
1. Сгенерировал ДОСЛОВНЫЙ код. То есть сделал ровно то, что было написано на Си, включая промежуточные действия.
2. Обеспечил атомарность, выполняя п.1
Таким образом, сначала произвел действия с константами справа и лишь потом присвоил результат регистру option_reg.
Как Вам передо мной уже сказали, заставить ДАННЫЙ компилятор выполнить битовую операцию при нулевой оптимизации можно макросом PS0=1.
Пока_без_кота
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Re: Програмирование pic на СИ.

Сообщение Пока_без_кота »

Спасибо за ответы.
spongebob
Грызет канифоль
Сообщения: 289
Зарегистрирован: Пт мар 20, 2009 12:25:47
Откуда: Ivanovo
Контактная информация:

Re: Програмирование pic на СИ.

Сообщение spongebob »

День добрый!

Подскажите как реализовать такую штуку.
Необходимо создавать "некие таймеры". Их число фиксировано и равно, допустим, 8.
Есть один системный таймер T0. Он считает до 255 и объявляет tick. Дальше по этому tick инкрементируется rtc_timer (может быть long, тут дело не в этом).

Сам "некий таймер" представляет из себя структуру следующих параметров:
-активный
-начало
-продолжительность
-функция окончания

По определенному событию (это не важно) - таймер активируется. "активный" выставляется в 1, в начало записывается текущее значение rtc_timer.

Обработчик таймеров постоянно (каждый цикл) проверяет rtc_timer и начало и продолжительность активных таймеров. как только "начало+продолжительность">=rtc_timer - "активный"=0 и выполняется функция.

Вроде алгоритм понятен, а в структурах я чот туплю.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Програмирование pic на СИ.

Сообщение Аlex »

Ну, примерно как то так :

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

typedef struct{
  unsigned          enabled :1;
  unsigned          start :1;          // Тут не понял, что за "начало" такое и зачем оно нужно...
  unsigned long     time;
  void*             call_back_func;  // Тут, скорее всего будет не так, а указатель на созданный ранее тип каллбека. Это уже тонкости
}Timer;
Ответить

Вернуться в «PIC»