Микроконтролери и електроника
http://mcu-bg.com/mcu_site/

Проблем със страниците на PIC16F877
http://mcu-bg.com/mcu_site/viewtopic.php?f=7&t=5441
Страница 1 от 2

Автор:  E1 [ Пет Фев 08, 2008 10:59 pm ]
Заглавие:  Проблем със страниците на PIC16F877

Написах на Асемблер една доста голяма програма, но при транслирането ми се появяват предупреждения, че съм преминал границата на страниците: "Crossing page boundary -- ensure page bits are set".

Доколкото си спомням, превключването ставаше по тази схема:

PCLATH<4> PCLATH<3> GOTO PAGE
---------------------------------------------
0 0 Page 0
0 1 Page 1
1 0 Page 2
1 1 Page 3

Разрових къде ли не, търсих и в този форум, но не можах да намеря нищо конкретно. В datasheet няма много по въпроса. Проблемът е, че от реда, индециран като първо преминаване между страниците, програмата спира с изпълнението, което ми отне доста време за откриване на грешката.

В общи линии ме интересува следното:
1. Има ли начин превключването да става автоматично(без да трябва да го следя)?
2. Ако НЕ, то къде става това превключване-цялата програма като едно цяло ли се третира или трябва да я организирам по страници, които се отнасят като отделни програми?
3. Със забрана за извеждане на грешките, решава ли се и проблемът със самия преход на страниците(имам предвид командите errorlevel -306 и errorlevel -302 )
4. Може ли да дадете някоя примерна част от сорс?

Поздрав!

Автор:  ji4ka [ Пет Фев 08, 2008 11:35 pm ]
Заглавие:  Re: Проблем със страниците на PIC16F877

E1 написа:
....Разрових къде ли не, търсих и в този форум, но не можах да намеря нищо конкретно. В datasheet няма много по въпроса. Проблемът е, че от реда, индециран като първо преминаване между страниците, програмата спира с изпълнението, което ми отне доста време за откриване на грешката.

А това по-долу я познай откъде съм го копнал?
Асемблера те предупреждава да си провериш адресацията. А тя се прави преди goto и call ако сочат към друга страница и (почти) задължително след връщане от return от друга страница. Подпрограмите се "подреждат" в паметта с org.
Автоматиката при асемблера е да внимаваш. Иначе сам си видял какво става - забиваш у стърнището. :)


2.4 Program Memory Paging
All PIC16F87XA devices are capable of addressing a
continuous 8K word block of program memory. The
CALL and GOTO instructions provide only 11 bits of
address to allow branching within any 2K program
memory page. When doing a CALL or GOTO instruction,
the upper 2 bits of the address are provided by
PCLATH<4:3>. When doing a CALL or GOTO instruc-
tion, the user must ensure that the page select bits are
programmed so that the desired program memory
page is addressed. If a return from a CALL instruction
(or interrupt) is executed, the entire 13-bit PC is popped
off the stack. Therefore, manipulation of the
PCLATH<4:3> bits is not required for the RETURN
instructions (which POPs the address from the stack).
Note: The contents of the PCLATH register are
unchanged after a RETURN or RETFIE
instruction is executed. The user must
rewrite the contents of the PCLATH regis-
ter for any subsequent subroutine calls or
GOTO instructions.
Example 2-1 shows the calling of a subroutine in
page 1 of the program memory. This example assumes
that PCLATH is saved and restored by the Interrupt
(if interrupts are used).
Service Routine
EXAMPLE 2-1: CALL OF A SUBROUTINE
IN PAGE 1 FROM PAGE 0
ORG 0x500
BCF PCLATH,4
BSF PCLATH,3 ;Select page 1
;(800h-FFFh)
CALL SUB1_P1 ;Call subroutine in
: ;page 1 (800h-FFFh)
:
ORG 0x900 ;page 1 (800h-FFFh)
SUB1_P1
: ;called subroutine
;page 1 (800h-FFFh)
:
RETURN ;return to
;Call subroutine
;in page 0

Автор:  [ Пет Фев 08, 2008 11:55 pm ]
Заглавие: 

Подреди си подпрограмите по страници, като гледай в една страница да се намират подпрограми, които се викат една друга, за да спестяваш по 2 инструкции на извикване на подпрограма. Главната програма с векторите на прекъсване разположи в нулевата страница. Направи си макрос, с които да викаш нужната ти подпрограма. Примерно, макроса може да бъде с 1 параметър - името на подпрограмата:
Код:
mcall MACRO Name_Of_The_Subroutine
         movlw HIGH(Name_Of_The_Subroutine);
         movwf PCLATH;
         call Name_Of_The_Subroutine;
ENDM


Това мисля, че ще е достатъчно.

При връщане от подпрограма от друга страница:

Цитат:
If a return
from a CALL instruction (or interrupt) is executed, the
entire 13-bit PC is pushed onto the stack. Therefore,
manipulation of the PCLATH<4:3> bits are not required
for the return instructions (which POPs the address
from the stack).


Ако използваш WREG за предаване на параметри на подпрограмата, трябва да промениш mcall . Вътре с #if проверяваш HIGH(Name_Of_The_Subroutine) в коя страница се намира Name_Of_The_Subroutine, след което правиш директно bsf, bcf на PCLATH<4:3>

Автор:  E1 [ Съб Фев 09, 2008 1:38 am ]
Заглавие: 

ji4ka, малко преди да вляза пак на форума и го намерих и аз. Но в началото тръгнах по съкратената процедура: Имам проблем с паметта и търсих в обясненията за паметта. А информацията се намира в обяснението за PCLATH, което е отделено.

Сега прехвърлям цялата програма. На всичкото отгоре, за да ми е по-пригледно, бях направил 6 отделни блока с по 160 GOTO команди и резултатът е няколко стотин предупреждения!
Докато бяха 50-ина условия, нямаше проблем, но като разширих програмата и...

Автор:  E1 [ Съб Фев 09, 2008 4:13 pm ]
Заглавие: 

Промених програмата. Сега предупрежденията са около 80, което е доста по-добре, в сравнение с 350-те в началото. Но остава един съществен проблем: На много места GOTO остава по два пъти след някаква проверка. В такъв случай ми се налага да вкарам по още един условен преход, за да имам място за прехвърлянето към страницата, което става на няколко реда:

NEXT_CHARACTER

bcf STATUS,Z
movf WORK_COUNTER,w
xorlw B'00000000'
btfsc STATUS,Z
goto Ver_field
goto FIND_ASCII

И двете goto тук, отиват към друга страница. За второто не е проблем, но за първото трябва да въведа още едно поле, където да направя пренасочването.

Много би ми помогнало, ако измисля начин за най-икономична направа на едномерен масив. Например:

For i=0 to N
BUFFER=A[i]
.....

Това не го знам как става(ако е изобщо възможно с Асемблер) и практически съм принуден да пиша отделно за всеки елемент от масива, като единствено мога да следя дали е запълнен масивът до предварително определената стойност на i, която е в интервала от 0 до 160!

Друго, което може да ми реши проблема е алгоритъм за проверка дали всички елементи на едномерен масив са =0. Този масив е с размер 80 елемента. Сега програмата ми работи, но докато не разширя масивите.

Ще съм благодарен, ако някой даде идея как да се измъкна, без на 4000-те програмни реда да добавя още 1000!

Автор:  MYXATA [ Съб Фев 09, 2008 5:02 pm ]
Заглавие: 

да избягаш от хилядо реда асемблерски код.... за малко промени :?: ](*,)
единствения изход е да преминеш плавно или рязко към писане на С :!:

по принцип избягвам да се меся в коментирането на грешки и проблеми с микроконтролерите от майкрочип. просто не са ми познати....

но все пак за да не се жалиш че си се изкърил от писане само за преметането на един масив от един регистър към друг, [-o<
....най-добре ползвай програмният език С :!:
вече има много свободни или "освободени"( ;) 10x to Nikola) компилатори / работни среди.
поне аз ползвам асемблера само в случай на оптимизация - когато времето или мястото е критично. иначе го смятам за най-висша форма на мазохизъм и на загуба на време...
Величината Time to Market :!: на каквото ида е изделие ни притиска да излезнем от дълбините на асемблера ;)

Автор:  E1 [ Съб Фев 09, 2008 5:16 pm ]
Заглавие: 

Това е ясно. Но програмата е вече почти готова и не искам да я оставям точно сега. Още повече, че работи, макар и с част от предвидения капацитет. Дори на моменти ми минава през ума да се пробвам да я препиша на Микропаскал. Ама защо да го правя, ако може да се намери решение за тези проблеми. Аз имам чувството, че не работя оптимално в момента и затова търся съвет. Иначе, когато написах(преди няколко месеца) във форума какво възнамерявам да правя, доста хора ми намекнаха, че е самоубийство. Още повече, че тогава дори не знаех КАК да го направя!

Автор:  VANK [ Съб Фев 09, 2008 5:17 pm ]
Заглавие: 

Това не те ли устройва, ako примерно преходите са в 2 и 3 страница и в началото на страницата си сложил етикети page2 и page3?

NEXT_CHARACTER

bcf STATUS,Z
movf WORK_COUNTER,w
xorlw B'00000000'
btfsc STATUS,Z
goto TEMP_1
pagesel page3
goto FIND_ASCII
TEMP_1
pagesel page2
goto Ver_field

Автор:  E1 [ Съб Фев 09, 2008 6:56 pm ]
Заглавие: 

Да, това работи, разбира се. Работи и макросът, който ми дал . Но няма да ми се налага да обикалям страниците, ако оптимизирам масивите.
Няма ли вариант за въвеждане на указател, така че да се съедини с етикета, подобно на това: A[i]?

С макроса успях да намаля съобщенията до 10, което вече е нещо. Но имам проблем с goto. Не знам например в следния участък какъв макрос да направя:


;--ASCII ZA "."
V_SP23 bcf STATUS,Z
movf SYM_BUFFER,w
xorlw H'2E'
btfsc STATUS,Z
goto V_SP24
SP25 ; TO4KA
movlw b'00100000'
movwf Current1
movlw b'00100000'
movwf Current2
goto SCROLL_RRL

;--ASCII ZA ","
V_SP24 bcf STATUS,Z
movf SYM_BUFFER,w
xorlw H'2C'
btfsc STATUS,Z
goto V_SP25
SP26 ; ZAPETAJA
movlw b'10100000'
movwf Current1
movlw b'01100000'
movwf Current2
movlw b'00000000'
movwf Current3
goto SCROLL_RRL


Индицира ми предупреждение на goto V_SP24. Точно между тези две секции минава границата на страниците, защото на разположените нагоре не дава предупреждения, а само от goto V_SP24 надолу.

Автор:  ji4ka [ Съб Фев 09, 2008 10:57 pm ]
Заглавие: 

E1 написа:
For i=0 to N
BUFFER=A[i]
.....

Това не го знам как става(ако е изобщо възможно с Асемблер) и практически съм принуден да пиша отделно за всеки елемент от масива, като единствено мога да следя дали е запълнен масивът до предварително определената стойност на i, която е в интервала от 0 до 160!

Това при пиковете се прави с т.нар. "computed goto" чрез промяна на PCL - също е описано в даташита. Там работите са малко по-сложни , трябва да се следят и сегментите (256 адреса). Обаче зависи от фамилията -16,18 и т.н. .......
:!: Обачеее , тоя масив РАМ ли е или е РОМ , че може да стане голяма обърквация.

Така се прави/чете ром-таблица на Пик16. В I се слага индекса,в W се връща резултата. Важно е таблицата да е в един сегмент (0-255, 256-511 и т.н.) защото иначе е по-сложно.

movf I,w
call GetTable
movwf Buffer

GetTable
addwf PCL,f
retlw B1
retlw B2
...
retlw Bi

Но щом си опрял до ASCII ,явно вече не си за Асемблер. Както ти казаха по-нагоре помисли за С. Асемблера е много трудоемък за обработка на масиви, не че няма да стане.

Автор:  E1 [ Нед Фев 10, 2008 3:42 am ]
Заглавие: 

Проблемът е, че трябва да организирам таблица от променливи, а не от константи. Имам в програмата си такава таблица(от променливи), но тя се състои от голям брой goto, което искам да променя. Как мога да направя да се чете всеки втори ред от таблицата?
Например на това:

Table addwf PCL,1
nop
A1 movf ROW1,w
return
A2 movf ROW2,w
return
A3 movf ROW3,w
return

Иначе тази таблица се състои в оригинал от поредица goto, пренасочващи към етикетите А1, А2... Какво може да се направи, за да се чете таблицата през ред?

Автор:  plameniv [ Нед Фев 10, 2008 8:08 am ]
Заглавие:  MMM

E1 написа:
Проблемът е, че трябва да организирам таблица от променливи, а не от константи. Имам в програмата си такава таблица(от променливи), но тя се състои от голям брой goto, което искам да променя. Как мога да направя да се чете всеки втори ред от таблицата?
Например на това:

Table addwf PCL,1
nop
A1 movf ROW1,w
return
A2 movf ROW2,w
return
A3 movf ROW3,w
return

Иначе тази таблица се състои в оригинал от поредица goto, пренасочващи към етикетите А1, А2... Какво може да се направи, за да се чете таблицата през ред?

А пробвал ли си да го направиш това ровене в таблицата с индексен регистър, тогава няма да имаш този проблем със страниците , чрез индексния регистър имаш достъп до таблицата от всяка страница !!!

Автор:  ji4ka [ Нед Фев 10, 2008 2:22 pm ]
Заглавие: 

E1 написа:
Проблемът е, че трябва да организирам таблица от променливи, а не от константи. Имам в програмата си такава таблица(от променливи), но тя се състои от голям брой goto, което искам да променя. Как мога да направя да се чете всеки втори ред от таблицата?


Така кажи. Ти бъркаш РАМ(DataMemory) с ROM(ProgramMemory). Такава таблица се прави в РАМ-а . Тогава чети този раздел:

2.5 Indirect Addressing, INDF and
FSR Registers
The INDF register is not a physical register. Addressing
the INDF register will cause indirect addressing.
Indirect addressing is possible by using the INDF reg-
ister. Any instruction using the INDF register actually
accesses the register pointed to by the File Select Reg-
ister, FSR. Reading the INDF register itself, indirectly
(FSR = 0) will read 00h. Writing to the INDF register
indirectly results in a no operation (although status bits
may be affected). An effective 9-bit address is obtained
by concatenating the 8-bit FSR register and the IRP bit
(Status<7>) as shown in Figure 2-6.

При адресирането в РАМ-а въобще не се ползва goto,call,PCL защото си има хардуерни регистри точно с тази цел. Даже е по-лесно.

movf I,w ;индекса 0..160
addlw First ;First е началния адрес на таблицата в DataMemory.
movwf FSR ;тук се зарежда вече истинския адрес
movf INDF,w ; тук извлича стойността в W
movwf Buffer ; и я слагаш в буфера

Тука в I се намира индекса 0..160 .Организираш го като брояч. Ако искаш през един,просто всеки път го увеличаваш с 2, напр. два пъти incf I,f.
Тука вече е важно таблицата да е в една банка - прочети как става нагласянето на банките с IRP.

Ти да не правиш обработка на текст.? Провери на http://piclist.com/techref/microchip/codeflow.htm може да намериш нещо готово.

Автор:  E1 [ Нед Фев 10, 2008 8:21 pm ]
Заглавие: 

Точно обработка на текст е. По принцип всичко става през паралелния порт, по определен протокол, който позволява и обработка на монохромно (засега) видео в реално време. Тази част работи, въпреки всички критики към възможностите на паралелния порт. Работи и текстът, доколкото се задоволя с 80 символа. Но аз искам 160.

А чрез PCLATH не успявам да прехвърля страниците. Нещо важно ми е убягнало, но засега не мога да разбера какво. Правих невероятни опити да изчисля стойността на регистъра преди да извиквам таблицата, но засега не успявам. Резултатът е непредвидимо смущение и изкривяване на изображението(текста).

Автор:  Комбинатор [ Нед Фев 10, 2008 8:54 pm ]
Заглавие: 

Цитат:
Много би ми помогнало, ако измисля начин за най-икономична направа на едномерен масив. Например:

For i=0 to N
BUFFER=A[i]
.....

Това го има в PYTHON.
А за другото може би да дефинираш макроси.
Примерно за PAGE1 сетваш 3 бит и исчистваш 4.
Опитай има ли възможност през паралелния да подаваш сигнал за смяна на страниците, при въвеждане на масива.
А когато пика чете масивите трябва да се следи каде се прекъсва масива и преминава в друга страница.
Поне аз така разбрах нещата.

Страница 1 от 2 Часовете са според зоната UTC + 2 часа [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/