|
Виж темите без отговор | Виж активните теми
Дата и час: Вто Юли 28, 2026 9:29 am
Проблем със страниците на PIC16F877
| Автор |
Съобщение |
|
E1
Ранг: Почетен член
Регистриран на: Нед Юли 22, 2007 8:57 pm Мнения: 607 Местоположение: Белград
|
 Проблем със страниците на 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. Може ли да дадете някоя примерна част от сорс?
Поздрав!
|
| Пет Фев 08, 2008 10:59 pm |
|
 |
|
ji4ka
Ранг: Форумен бог
Регистриран на: Чет Фев 01, 2007 4:04 am Мнения: 1539
|
 Re: Проблем със страниците на PIC16F877
А това по-долу я познай откъде съм го копнал?
Асемблера те предупреждава да си провериш адресацията. А тя се прави преди 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:35 pm |
|
 |
|
¶
Ранг: Форумен бог
Регистриран на: Пет Фев 25, 2005 1:58 pm Мнения: 4585 Местоположение: US
|
Подреди си подпрограмите по страници, като гледай в една страница да се намират подпрограми, които се викат една друга, за да спестяваш по 2 инструкции на извикване на подпрограма. Главната програма с векторите на прекъсване разположи в нулевата страница. Направи си макрос, с които да викаш нужната ти подпрограма. Примерно, макроса може да бъде с 1 параметър - името на подпрограмата:
Това мисля, че ще е достатъчно.
При връщане от подпрограма от друга страница:
Ако използваш WREG за предаване на параметри на подпрограмата, трябва да промениш mcall . Вътре с #if проверяваш HIGH(Name_Of_The_Subroutine) в коя страница се намира Name_Of_The_Subroutine, след което правиш директно bsf, bcf на PCLATH<4:3>
_________________ Ето аз дишам, работя, живея и програми пиша тъй както умея, с проца под вежди се гледаме строго и боря се с него доколкото мога....
|
| Пет Фев 08, 2008 11:55 pm |
|
 |
|
E1
Ранг: Почетен член
Регистриран на: Нед Юли 22, 2007 8:57 pm Мнения: 607 Местоположение: Белград
|
ji4ka, малко преди да вляза пак на форума и го намерих и аз. Но в началото тръгнах по съкратената процедура: Имам проблем с паметта и търсих в обясненията за паметта. А информацията се намира в обяснението за PCLATH, което е отделено.
Сега прехвърлям цялата програма. На всичкото отгоре, за да ми е по-пригледно, бях направил 6 отделни блока с по 160 GOTO команди и резултатът е няколко стотин предупреждения!
Докато бяха 50-ина условия, нямаше проблем, но като разширих програмата и...
|
| Съб Фев 09, 2008 1:38 am |
|
 |
|
E1
Ранг: Почетен член
Регистриран на: Нед Юли 22, 2007 8:57 pm Мнения: 607 Местоположение: Белград
|
Промених програмата. Сега предупрежденията са около 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!
|
| Съб Фев 09, 2008 4:13 pm |
|
 |
|
MYXATA
Ранг: Форумен бог
Регистриран на: Пон Юни 05, 2006 1:48 pm Мнения: 4906 Местоположение: където небето среща земята, ракията е Jameson, а бирата Guinness
|
да избягаш от хилядо реда асемблерски код.... за малко промени
единствения изход е да преминеш плавно или рязко към писане на С
по принцип избягвам да се меся в коментирането на грешки и проблеми с микроконтролерите от майкрочип. просто не са ми познати....
но все пак за да не се жалиш че си се изкърил от писане само за преметането на един масив от един регистър към друг,
....най-добре ползвай програмният език С
вече има много свободни или "освободени"(  10x to Nikola) компилатори / работни среди.
поне аз ползвам асемблера само в случай на оптимизация - когато времето или мястото е критично. иначе го смятам за най-висша форма на мазохизъм и на загуба на време...
Величината Time to Market  на каквото ида е изделие ни притиска да излезнем от дълбините на асемблера 
_________________ ... ако трети ден не ти се работи... това означава, че е сряда !
|
| Съб Фев 09, 2008 5:02 pm |
|
 |
|
E1
Ранг: Почетен член
Регистриран на: Нед Юли 22, 2007 8:57 pm Мнения: 607 Местоположение: Белград
|
Това е ясно. Но програмата е вече почти готова и не искам да я оставям точно сега. Още повече, че работи, макар и с част от предвидения капацитет. Дори на моменти ми минава през ума да се пробвам да я препиша на Микропаскал. Ама защо да го правя, ако може да се намери решение за тези проблеми. Аз имам чувството, че не работя оптимално в момента и затова търся съвет. Иначе, когато написах(преди няколко месеца) във форума какво възнамерявам да правя, доста хора ми намекнаха, че е самоубийство. Още повече, че тогава дори не знаех КАК да го направя!
|
| Съб Фев 09, 2008 5:16 pm |
|
 |
|
VANK
Ранг: Ориентиран
Регистриран на: Чет Май 12, 2005 11:10 am Мнения: 211
|
Това не те ли устройва, 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
|
| Съб Фев 09, 2008 5:17 pm |
|
 |
|
E1
Ранг: Почетен член
Регистриран на: Нед Юли 22, 2007 8:57 pm Мнения: 607 Местоположение: Белград
|
Да, това работи, разбира се. Работи и макросът, който ми дал ¶. Но няма да ми се налага да обикалям страниците, ако оптимизирам масивите.
Няма ли вариант за въвеждане на указател, така че да се съедини с етикета, подобно на това: 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 надолу.
|
| Съб Фев 09, 2008 6:56 pm |
|
 |
|
ji4ka
Ранг: Форумен бог
Регистриран на: Чет Фев 01, 2007 4:04 am Мнения: 1539
|
Това при пиковете се прави с т.нар. "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 ,явно вече не си за Асемблер. Както ти казаха по-нагоре помисли за С. Асемблера е много трудоемък за обработка на масиви, не че няма да стане.
|
| Съб Фев 09, 2008 10:57 pm |
|
 |
|
E1
Ранг: Почетен член
Регистриран на: Нед Юли 22, 2007 8:57 pm Мнения: 607 Местоположение: Белград
|
Проблемът е, че трябва да организирам таблица от променливи, а не от константи. Имам в програмата си такава таблица(от променливи), но тя се състои от голям брой goto, което искам да променя. Как мога да направя да се чете всеки втори ред от таблицата?
Например на това:
Table addwf PCL,1
nop
A1 movf ROW1,w
return
A2 movf ROW2,w
return
A3 movf ROW3,w
return
Иначе тази таблица се състои в оригинал от поредица goto, пренасочващи към етикетите А1, А2... Какво може да се направи, за да се чете таблицата през ред?
|
| Нед Фев 10, 2008 3:42 am |
|
 |
|
plameniv
Ранг: Форумен бог
Регистриран на: Нед Окт 10, 2004 9:55 am Мнения: 1718
|
 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... Какво може да се направи, за да се чете таблицата през ред? |  |  |  |  |
А пробвал ли си да го направиш това ровене в таблицата с индексен регистър, тогава няма да имаш този проблем със страниците , чрез индексния регистър имаш достъп до таблицата от всяка страница !!!
_________________ Избийте баламите и тарикатите сами ще умрат!
Няма невъзможни работи - има много трудни работи!
----------------------------------------------------------------------------------
"Я в Москве с киркой уран найду, при такой повышенной зарплате" !
|
| Нед Фев 10, 2008 8:08 am |
|
 |
|
ji4ka
Ранг: Форумен бог
Регистриран на: Чет Фев 01, 2007 4:04 am Мнения: 1539
|
Така кажи. Ти бъркаш РАМ(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 може да намериш нещо готово.
|
| Нед Фев 10, 2008 2:22 pm |
|
 |
|
E1
Ранг: Почетен член
Регистриран на: Нед Юли 22, 2007 8:57 pm Мнения: 607 Местоположение: Белград
|
Точно обработка на текст е. По принцип всичко става през паралелния порт, по определен протокол, който позволява и обработка на монохромно (засега) видео в реално време. Тази част работи, въпреки всички критики към възможностите на паралелния порт. Работи и текстът, доколкото се задоволя с 80 символа. Но аз искам 160.
А чрез PCLATH не успявам да прехвърля страниците. Нещо важно ми е убягнало, но засега не мога да разбера какво. Правих невероятни опити да изчисля стойността на регистъра преди да извиквам таблицата, но засега не успявам. Резултатът е непредвидимо смущение и изкривяване на изображението(текста).
|
| Нед Фев 10, 2008 8:21 pm |
|
 |
|
Комбинатор
Ранг: Новодошъл
Регистриран на: Чет Авг 30, 2007 2:14 pm Мнения: 118
|
Това го има в PYTHON.
А за другото може би да дефинираш макроси.
Примерно за PAGE1 сетваш 3 бит и исчистваш 4.
Опитай има ли възможност през паралелния да подаваш сигнал за смяна на страниците, при въвеждане на масива.
А когато пика чете масивите трябва да се следи каде се прекъсва масива и преминава в друга страница.
Поне аз така разбрах нещата.
|
| Нед Фев 10, 2008 8:54 pm |
|
|
Кой е на линия |
Потребители разглеждащи този форум: 0 регистрирани и 0 госта |
|
Вие не можете да пускате нови теми Вие не можете да отговаряте на теми Вие не можете да променяте собственото си мнение Вие не можете да изтривате собствените си мнения Вие не можете да прикачвате файл
|
|