Отговори на тема  [ 14 мнения ] 
Въпрос за MikroC? 
Автор Съобщение
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Сря Мар 08, 2006 2:12 pm
Мнения: 2017
Местоположение: Котел
Мнение Въпрос за MikroC?
Това си е наистина и само за академията :D
С-то ми е мътно и така и не можах да разбра как се работи с bit field :( Искам да си дефинирам битове - примерно Lamp1 = Portc.0; Lamp2 = PortC.1, Lamp3 = Portc.2, и съответно променлива с флагове към тях - примерно Lamp1_Flag = Flags.0... Гледам като индианец, пробвам и нещо не става... Иначе за сега си махам с достъп до битовете като ползвам Portc.F0..., ама си е неприятно, забравям кой за какво беше.
Пробвах някои работи с този компилатор, ADC, USART всичко си работи както искам но ми се опъна като реших да пробвам прекъсване от TMR1. Писах - не иска. Викам чакай да пробвам с примерите, компилирам, пускам примера и - ядец - след при пускането на примера светодиодите на порта се включват след 2-3 сек. и си остават така :( Това го пробвам на 16F688 на 20Мхц. Къде греша че блокирах???
Код:
unsigned short cnt;
unsigned char tb;

void interrupt() {
  cnt++ ;
  PIR1.TMR1IF = 0;            // clear TMR1IF
}//~

void main() {
// TMR1H = 0;
// TMR1L = 0;
  TRISC = 0;
  T1CON = 1;
  PIR1.TMR1IF = 0;            // clear TMR1IF
  PIE1  =   1;                // enable interrupts
  PORTC = 0;
  cnt =   0;                  // initialize cnt
  INTCON = 0xC0;

  do {
    if (cnt == 152) {         // if cnt is 152, then toggle portb leds and
      PORTC  = ~PORTC;        //   reset cnt
      cnt = 0;
    }
  } while (1);
}//~!


Пон Мар 12, 2007 4:27 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Окт 31, 2004 9:19 pm
Мнения: 4464
Местоположение: Stara Zagora
Мнение 
Код:
typedef union
{
char   ch;
struct
{
char bit0:1;
char bit1:1;
char bit2:1;
char bit3:1;
char bit4:1;
char bit5:1;
char bit6:1;
char bit7:1;
};
}BITU;


Един от удобните начини в C да работиш с битовете на някоя променлива е тя да е част от union.
В горния пример при дефинирането на променлива така
BITU MyVariable;
Заема 1 баит.Ако искаш достъп до цялата променлива:
Код:
MyVariable.ch = 0;

или
Код:
if (  MyVariable.ch == 0x20 )
{
------------------------
}

ако искаш достъп до някои бит аналогично с MyVariable.bit0
Код:
MyVariable.bit0 = 0;
if ( MyVariable.bit0 )
{
----------------------
}

другия начин е да работиш с маски. Компилатора ги компилира като битови операции после.
Код:
PORTC |= 0x01;        //ти сетва нулевия бит на порта в единица
PORTC &= ~(0x01);  // ти нулира нулевия баит на порта. ~ e инверсия на всичките битове. //  ~(0x01) = 0xFE

По същия начин става и достъпа
Код:
if ( PORTC & 0x01 )
{
//Изпълнява се ако нулевия бит е единица
--------------------
}
if ( PORTC & 0x81 )
{
//Изпълнява се ако нулевия,7 мия бит или 2та са единица
--------------------
}


Пон Мар 12, 2007 4:46 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Сря Мар 08, 2006 2:12 pm
Мнения: 2017
Местоположение: Котел
Мнение 
Благодаря Николай, светна ми донякъде, това с маските си го ползвам, просто искам да сложа "човешки" имена на пиновете и битовете че много се бъркам иначе... Значи с именуване на битовете в променлива се оправих -
Код:
typedef struct {
  Lamp1:0;
  Lamp2:1;
  Lamp3:2;
  } BitField1;
.
.
BitField1 Flags;
.
.
Flags.Lamp1 = 1;
Flags.Lamp2 = 1;

Работи си ОК, обаче как да си именувам пиновете на портовете. Четох в разните упътвания към компилатора, дават следния пример който обаче не работи :o
Код:
struct Port{
Led_1:0;
Led_2:1;
} PortA;

Компилатора веднага изпищява - PortA identifier redifined!, предполагам и си е така, как да го излъжа??? С указател???
А за прекъсването от Таймер1 някой да има идея???


Пон Мар 12, 2007 5:25 pm
Профил
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Пет Фев 17, 2006 9:17 am
Мнения: 765
Местоположение: Стара Загора
Мнение 
Когато искаш човешки имена пишеш

Код:
#define LAMP1 PortA.bit0


Оттам нататък компилатора като види LAMP1 автоматично си го замества с PortA.bit0. За таймера не мога да кажа. Виж из асемблера какво точно се случва, не ми е много ясно компилатора какво прави с флаговете.


Пон Мар 12, 2007 5:56 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Сря Мар 08, 2006 2:12 pm
Мнения: 2017
Местоположение: Котел
Мнение 
#define LAMP1 PortA.bit0 - това го пробвах първо - с този компилатор не става, дава Invalid expression :(
Прекъсването си работи нормално с 877А, с 688 не мога да разбера защо не вдява, сега препрочитам пдф-то, нещо съм изтървал но с други компилатори и същия чип не съм имал проблеми с прекъсването от таймер1.


Пон Мар 12, 2007 6:02 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Сря Мар 08, 2006 2:12 pm
Мнения: 2017
Местоположение: Котел
Мнение 
Еб.... мама му! След дълго четене и мислене :D смених това:
Код:
  do {
    if (cnt == 152) {         // if cnt is 152, then toggle portb leds and
      PORTC  = ~PORTC;        //   reset cnt
      cnt = 0;
    }
  } while (1);

с това
Код:
  do {
    if (cnt == 70) {PORTC  = 0xff; }
    if (cnt==140) {
      PORTC=0;
      cnt = 0;
      }
  } while (1);

и всичо си е на мястото т.е. работи както се очаква /ако мигането може да се нарече работа.../
Защо става така??? Имаше писано в форума нещо за буфера на портовете но не мога да се сетя. Това което се получава с ~ е че вдига порта в 1-ци а не го установява при последващо изпълнение в 0-ли. И това е само за 688, при 877а си работи???


Пон Мар 12, 2007 6:21 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Сря Мар 08, 2006 2:12 pm
Мнения: 2017
Местоположение: Котел
Мнение 
Странно се държи тази комбинация - MikroC + 16F688 :( За да имам нормално установяване на порт С трябва да го пиша наведнъж, ако пипам отделните битове става каша.Защо е така и къде бъркам...?
Код:
     if (Sec==5) {
        PORTA.F2 = 0;
        PORTC = PORTC & 0b11111000;

        }
     if (Sec==10) {
         Sec = 0;
         PortA.F2 = 1;
         Help = Flags & 0b00000111;
         PORTC = PORTC | Help;

         }

Ей това в прекъсването на таймер1 /0.1с/ си работи но защото пиша портс наведнъж, ако установявам един по един отделните битове всичките ми се вдигат в 1 и си остават така...


Вто Мар 13, 2007 10:30 am
Профил
Ранг: Напреднал
Ранг: Напреднал
Аватар

Регистриран на: Пет Окт 21, 2005 8:45 am
Мнения: 499
Мнение 
Не е от компилатора. При ниските серии е така. От 18 нагоре си имат LAT регистри. Нищо не ти пречи да си направиш PORTB_map, т.е. образ на порта в паметта и да извършваш битови операции с него, а после да го изкарваш на порта като цял байт. workaround, но какво да правиш! Другия начин е да минеш на истински процесор - 18 или дори 24.

_________________
Простотията е Божи дар, но човек не бива да парадира с подаръците си!


Вто Мар 13, 2007 12:43 pm
Профил ICQ
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Чет Ное 25, 2004 3:42 pm
Мнения: 913
Мнение 
evc няма да е така
На асм се вдигат свалят пинове с битови операции без проблем.
А и не само на асм.


Вто Мар 13, 2007 2:55 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Окт 31, 2004 9:19 pm
Мнения: 4464
Местоположение: Stara Zagora
Мнение 
В Hi-Tech и IAR нямам спомен да е имало проблем с операции от типа.
PORTC |= 0x01;


Вто Мар 13, 2007 3:13 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Окт 07, 2004 1:22 pm
Мнения: 1949
Местоположение: София
Мнение 
Какво ще стане ако напишеш следното:
Код:
#define LED1 PORTB.F0
..
..
void main(void){
TRISB = 0;
while(1){
LED = 1;
delay_ms(100);
LED = 0;
delay_ms(100);
}
}


Вто Мар 13, 2007 3:22 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Окт 31, 2004 9:19 pm
Мнения: 4464
Местоположение: Stara Zagora
Мнение 
Погледнах си код от времената когато се рових с PIC16.
Един откъс от мокрочипската документация която обяснява случая
Цитат:
5.3.1 BI-DIRECTIONAL I/O PORTS
Any instruction which writes, operates internally as a
read followed by a write operation. The BCF and BSF
instructions, for example, read the register into the
CPU, execute the bit operation and write the result back
to the register. Caution must be used when these
instructions are applied to a port with both inputs and
outputs defined. For example, a BSF operation on bit5
of PORTB will cause all eight bits of PORTB to be read
into the CPU. Then the BSF operation takes place on
bit5 and PORTB is written to the output latches. If
another bit of PORTB is used as a bi-directional I/O pin
(i.e., bit0) and it is defined as an input at this time, the
input signal present on the pin itself would be read into
the CPU and rewritten to the data latch of this particular
pin, overwriting the previous content. As long as the pin
stays in the input mode, no problem occurs. However,
if bit0 is switched into output mode later on, the content
of the data latch is unknown.
Reading the port register, reads the values of the port
pins. Writing to the port register writes the value to the
port latch. When using read-modify-write instructions
(i.e., BCF, BSF, etc.) on a port, the value of the port pins
is read, the desired operation is done to this value, and
this value is then written to the port latch.
A pin actively outputting a Low or High should not be
driven from external devices at the same time in order
to change the level on this pin (“wired-or”, “wired-and”).
The resulting high output current may damage the chip.


Вто Мар 13, 2007 3:29 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Сря Мар 08, 2006 2:12 pm
Мнения: 2017
Местоположение: Котел
Мнение 
@evc - не е от 16-та серия - на 877а си работи перфектно, не зная защо;
@rumen - от компилатора ще да е, въпреки че гледах асм-то и не разбрах нищо, с друг компилатор и 688 няма проблеми с битовите операции с порта :o
@Predator_MF - този компилатор това #define LED1 PORTB.F0 не го приема /мнооого кофти/, по точно приема декларацията но LED = 1 го отхвърля.
Текста на Никола обяснява донякъде проблема....
Дано съм помогнал на някой с това главоблъскане, исках да направя сравнение /по-точно да пробвам MikroC-то/ в сравнение с Proton-a a и да мина на С компилатор, на първо време по-елементарен като за мене :D Явно няма да е MikroC след този номер, IAR-a ми е много тежък и следователно по-далечна перспектива... Останаха CCS и HiTech, мисля да се спра на CCS-то, сега си качих CCS C Compiler 4.012d, но като гледам ревизиите му... пак някоя глуха акула може да ми се падне!!!
А - ето и резултатите от сравнението - устройството работи по един и същи начин с двата компилатора
MikroC - used Rom - 1176(28%), Used Ram - 56 (27%)
Proton+ - used Rom - 809(20%), Used Ram - 35 (14%)

По големия код на MikroC-то вероятно е защото използвам вградените ф-ии за работа с RS-a, а програмата на Proton-a по скоро си е асемблерска, тук там имам If-Then-Else и работа с ADC-то, а RS-a си е на LowLevel...


Вто Мар 13, 2007 4:12 pm
Профил
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Пет Фев 17, 2006 9:17 am
Мнения: 765
Местоположение: Стара Загора
Мнение 
Ми не, навремето загубих малко време да разгледам МикроС. Вградените му функции са кадърно написани, причината е че компилатора е олигофреничен. Например, когато сравнява 2 числа ги зарежда в стека, вика функция, която ги изважда и също през стека връща резултата. То ако разгледаш асемблерския код се вижда какви олигофренщини върши . :evil:
CCS се държи в по-голяма степен разумно, за останалите нямам наблюдения. Който е ползвал, да казва.


Вто Мар 13, 2007 4:44 pm
Профил ICQ
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 14 мнения ] 

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 4 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни