|
Виж темите без отговор | Виж активните теми
Дата и час: Вто Юли 28, 2026 1:18 am
Работа с битове в C30 за PIC24
| Автор |
Съобщение |
|
dan
Ранг: Форумен бог
Регистриран на: Вто Май 29, 2007 2:23 pm Мнения: 3714 Местоположение: Високо в планината
|
 Работа с битове в C30 за PIC24
Здравейте,
как се задава битова променлива в C30?
_________________ Хайде де!
|
| Вто Сеп 21, 2010 4:26 pm |
|
 |
|
fan
Ранг: Почетен член
Регистриран на: Съб Окт 13, 2007 12:12 pm Мнения: 712
|
|
| Вто Сеп 21, 2010 4:44 pm |
|
 |
|
¶
Ранг: Форумен бог
Регистриран на: Пет Фев 25, 2005 1:58 pm Мнения: 4585 Местоположение: US
|
С обединения ( union ), няма го като вградена променлива.
_________________ Ето аз дишам, работя, живея и програми пиша тъй както умея, с проца под вежди се гледаме строго и боря се с него доколкото мога....
|
| Сря Сеп 22, 2010 4:47 am |
|
 |
|
Цецо
Ранг: Форумен бог
Регистриран на: Пон Сеп 27, 2004 9:22 am Мнения: 15501 Местоположение: София
|
А ако си мързелив или правиш портабъл код, може и така:
typedef enum {
FALSE = 0,
TRUE;
}BOOL;
Естествено това не е оптимално точно за Пик архитектурата. Но пък ще работи на всички процесори ако ти се наложи да прехвърляш кода след това.
Неудобството на битовите полета е че трябва да се съобразяваш къде и как си ги дефинирал - локални/глобални, стек, хип, как ще ги изкомбинираш и така нататък. Въобще битовите полета са правени за структурирани данни и са много неудобни когато ти трябват малко на брой отделени по смисъла си на използване битове из целия сорс. Например да си направиш локално флагче за една функцийка. Там използването на цяла дума (8,16 или 32 битова) в стека/регистър е някак си по разбираемо. Е губиш 7,15 или 31 бита на вятъра, ама.
Проблема при пиковете е, че имат еднотактови инструкции за работа с битове много удобни и бързи...ама ако пишеш на асемблер. Ама в ANSI C няма подходяща имплементация за целта. Просто стандарта е писан за процесори с друга архитектура.
_________________ "Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.
|
| Сря Сеп 22, 2010 12:40 pm |
|
 |
|
¶
Ранг: Форумен бог
Регистриран на: Пет Фев 25, 2005 1:58 pm Мнения: 4585 Местоположение: US
|
Понякога C30 компилатора се усеща и манипулациите на битовите полета ги прави с BTG, BSF & BCF.
_________________ Ето аз дишам, работя, живея и програми пиша тъй както умея, с проца под вежди се гледаме строго и боря се с него доколкото мога....
|
| Сря Сеп 22, 2010 1:48 pm |
|
 |
|
dan
Ранг: Форумен бог
Регистриран на: Вто Май 29, 2007 2:23 pm Мнения: 3714 Местоположение: Високо в планината
|
1.Има ли значение дали ще го направя със struct или с union, щом вътре има само един "елемент"?
2.Ако го направя както е показано на руския сайт, т.е. така :
компилатора как ще подреди променливите в паметта-ще използва ли един адрес за 16 бита?
_________________ Хайде де!
|
| Сря Сеп 22, 2010 2:07 pm |
|
 |
|
Цецо
Ранг: Форумен бог
Регистриран на: Пон Сеп 27, 2004 9:22 am Мнения: 15501 Местоположение: София
|
Така е. Ама може ли да направи битово поле локално за функция (в стека или в регистър)? А да предаде битче от битово поле като параметър на функция? Нямам голям опит с тоя компилатор, ама се съмнявам да може такива чудесии. Аз затова на пикове битови полета използвам само когато се нуждая от върховни времена за реакция - например в прекъсване. Или съм закъсал тотално за Рам. И ги правя глобални. Удобни са например за някакви глобални флагове, дето трябва да се виждат от разни места. Ама става доста "мръсен" кода. И не е особенно портабъл.
Ми пусни го и виж асемблерския листинг. Откъде да знаем, зависи сигурно и от опциите с които е извикан, къде точно си вмъкнал тия редове в сорса.... 
_________________ "Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.
|
| Сря Сеп 22, 2010 2:09 pm |
|
 |
|
Gogo
Ранг: Форумен бог
Регистриран на: Чет Фев 24, 2005 11:41 pm Мнения: 1049 Местоположение: Pz
|
|
| Сря Сеп 22, 2010 3:19 pm |
|
 |
|
head_up
Ранг: Форумен бог
Регистриран на: Нед Юни 01, 2008 9:54 pm Мнения: 1503 Местоположение: Пловдив
|
я се загледайте какво прави отдолу асемблера и ще разберете, че тая операция си хаби доста редове asm код. не съм го правил точно със структури/обединения, а с промяна на бит от специалните регистри и като видях какво се случва ми се изправи косата - от тогава цялата желана стойност за рег-а се хвърля в него със съответното &=/ |=, никакви побитови операции в тоя стил, че ... жална майка като почне да не стига флаша!
|
| Сря Сеп 22, 2010 3:36 pm |
|
 |
|
¶
Ранг: Форумен бог
Регистриран на: Пет Фев 25, 2005 1:58 pm Мнения: 4585 Местоположение: US
|
Ако се използва класическия метод за предаването на параметрите на функция през стека на едното битче винаги ще се направи typecast до широчината на стека. Няма как да вкараш в стека 1 бит, понеже стека е 8, 16 и т.н. битов.
Затова битовите полета обикновено се предават чрез указатели като параметри на функция. Вътре във функцията си правиш локална променлива от тип битовото поле и си манипулираш бита който ти трябва. Тогава вече компилатора си използва наличните инструкции за манипулации на бит.
Ето един пример:
 |  |  |  | Код: typedef struct { union { struct { uint8 fRun:1; uint8 fExpire:1; }; struct { uint8 m_flags; }; }/*flags*/; uint16 ui_Timer16; } MyTimer;
56: void StartTimer(MyTimer *pTimer,uint16 timeout) { 24F2 FA0004 lnk #0x4 24F4 780F00 mov.w 0x0000,[0x001c] 24F6 980711 mov.w 0x0002,[0x001c+2] 57: pTimer->ui_Timer16 = timeout; 24F8 78001E mov.w [0x001c],0x0000 24FA 90009E mov.w [0x001c+2],0x0002 24FC 980011 mov.w 0x0002,[0x0000+2] 58: pTimer->fRun = 1; 24FE 78009E mov.w [0x001c],0x0002 2500 780011 mov.w [0x0002],0x0000 2502 A00000 bset 0x0000,#0 2504 780880 mov.w 0x0000,[0x0002] 59: pTimer->fExpire = 0; 2506 78009E mov.w [0x001c],0x0002 2508 780011 mov.w [0x0002],0x0000 250A A11000 bclr 0x0000,#1 250C 780880 mov.w 0x0000,[0x0002] 60: } 250E FA8000 ulnk 2510 060000 return
|  |  |  |  |
Понеже не използвам локална променлива ами директно манипулирам битовото поле чрез указател, то ясно се вижда, че компилатора първо извлича в регистър стойността на битовото поле от паметта, след това използва blcr/bset за да присвои нова стойност, после обратно копира регистъра в паметта. Дори обаче да бях използвал локална променлива, компилатора отново ще използва същия брой инструкции, защото bclr/bset инструкциите могат да работят само с директна адресация, т.е. предварително те трябва да знаят адреса в паметта. Ако професора позволяваше индиректна адресация с битовите инструкции компилатора нямаше да се замисли да ги използва. PIC30/33/24 компилаторите са GCC компилатори и са много добре оптимизирани, поне досега не съм намерил парче код, който бих го направил кой знае колко по-бърз, ако започна да го оптимизирам на ръка. Ако обаче вътре във функцията дефинирам моето битово поле като static, тогава компилатора използва директната адресация на bclr/bset и си манипулира директно битовете:  |  |  |  | Код: void StartTimer(MyTimer *pTimer,uint16 timeout) { 24F2 FA0004 lnk #0x4 24F4 780F00 mov.w 0x0000,[0x001c] 24F6 980711 mov.w 0x0002,[0x001c+2] 57: static MyTimer mt; 58: /*pTimer->ui_Timer16 = timeout; 59: pTimer->fRun = 1; 60: pTimer->fExpire = 0; */ 61: mt = *pTimer; 24F8 78001E mov.w [0x001c],0x0000 24FA BE0010 mov.d [0x0000],0x0000 24FC 8853C0 mov.w 0x0000,0x0a78 24FE 8853D1 mov.w 0x0002,0x0a7a 62: mt.ui_Timer16 = timeout; 2500 90001E mov.w [0x001c+2],0x0000 2502 8853D0 mov.w 0x0000,0x0a7a 63: mt.fRun = 1; 2504 A80A78 bset.b 0x0a78,#0 64: mt.fExpire = 1; 2506 A82A78 bset.b 0x0a78,#1 65: *pTimer = mt; 2508 78001E mov.w [0x001c],0x0000 250A 8053C2 mov.w 0x0a78,0x0004 250C 8053D3 mov.w 0x0a7a,0x0006 250E BE8802 mov.d 0x0004,[0x0000] 66: } 2510 FA8000 ulnk 2512 060000 return
|  |  |  |  |
По принцип идеята на bclr/bset/btg инструкциите е за манипулиране на служебните регистри плюс глобално дефинираните променливи ( които са статични ).
_________________ Ето аз дишам, работя, живея и програми пиша тъй както умея, с проца под вежди се гледаме строго и боря се с него доколкото мога....
|
| Сря Сеп 22, 2010 7:11 pm |
|
 |
|
Цецо
Ранг: Форумен бог
Регистриран на: Пон Сеп 27, 2004 9:22 am Мнения: 15501 Местоположение: София
|
Аха де и аз това казвам.  За нормални флагчета, какъвто му беше въпроса на чиляка, по-лесно и разбираемо е да и маа на ниво дума, а не бит.
_________________ "Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.
|
| Чет Сеп 23, 2010 10:31 am |
|
 |
|
dan
Ранг: Форумен бог
Регистриран на: Вто Май 29, 2007 2:23 pm Мнения: 3714 Местоположение: Високо в планината
|
Направих го със структура и typedef.
Изникна обаче следващия проблем:когато искам да използвам тази пременлива в друг файл от този проект, нещо не става.
Направих така:
В друг .c файл съм направил това:
излиза ми следната грешка:
и за мястото, където се обръщам към бита:
Странното е, че всичко работеше, докато нещата ми бяха в един файл. Щом пробвах да ги разделя в два файла- работата се оплеска.
_________________ Хайде де!
|
| Чет Сеп 23, 2010 11:47 pm |
|
 |
|
head_up
Ранг: Форумен бог
Регистриран на: Нед Юни 01, 2008 9:54 pm Мнения: 1503 Местоположение: Пловдив
|
първо: не вижда къде си указал какво е bitvar, за това мяка - трябва да му инклиднеш .h файла където си разписал typedef на bitvar. обаче се чудя защо я правиш тая акробатика като можеш да ползваш това (виж приложението). не помня дали съм го копал отделно или е дошло с C30-ката, ама съм го ползвал за една 24-ка (сефте ги ползвах, както и C за PIC).
|
| Пет Сеп 24, 2010 9:57 am |
|
 |
|
Цецо
Ранг: Форумен бог
Регистриран на: Пон Сеп 27, 2004 9:22 am Мнения: 15501 Местоположение: София
|
Начи не става ясно как втория .c фаил (този в който имаш extern) вижда дефиницията на новия тип "bitvar".
Ако в второто си includ-нал първото, ще имаш проблем, щото два пъти дефинираш едно и също (bitvar error_m_B). Ако не си го includ-нал (което вероятно не си направил), пак имаш проблем щото във второто ползваш типа (bitvar) без да си го дефинирал преди това.
Обикновенно практиката е в един съвсем отделен фаил да се сложат всички typdef които ползваш насам натам. Точно по начина по който ти показа head_up преди мен. После този фаил си го инклудваш където ползваш тези типове и си ок. Обърни внимание обаче на редовете:
#ifndef Generic_Type_Defs_h
#define __Generic_Type_Defs_h
#endif //__GENERIC_TYPE_DEFS_H_
Те са ти задължителни!
_________________ "Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.
|
| Пет Сеп 24, 2010 10:04 am |
|
 |
|
dan
Ранг: Форумен бог
Регистриран на: Вто Май 29, 2007 2:23 pm Мнения: 3714 Местоположение: Високо в планината
|
 Ново 20
Направих един общ .h файл с всички променливи, но като го инклудна на няколко места дава грешката "multiple definition of...".
После преместих променливите в друг файл var.c, а в vars.h ги зададох като extern. Въпреки това проблема с "multiple definition of..." си остава.
Ако пък махна дефиницията на променливите от хедъра (т.е. вместо extern int а=10 напиша extern int a), излиза съобщениято за грешка "undefined reference to..."
What could i do? (Както пее Махалия Джаксън  )
_________________ Хайде де!
|
| Пет Сеп 24, 2010 12:07 pm |
|
|
Кой е на линия |
Потребители разглеждащи този форум: 0 регистрирани и 3 госта |
|
Вие не можете да пускате нови теми Вие не можете да отговаряте на теми Вие не можете да променяте собственото си мнение Вие не можете да изтривате собствените си мнения Вие не можете да прикачвате файл
|
|