Форум Микро-Чип
Поиск и заказ электронных компонентов
 

Вернуться   Форум Микро-Чип > Вопросы начинающих

Вопросы начинающих Прежде чем задать вопрос, стоит воспользоваться поиском

Ответ
 
Опции темы Опции просмотра
Старый 10.05.2017, 18:30   #1
Theyler
Junior Member
 
Регистрация: 07.05.2017
Сообщений: 17
Вес репутации: 135/3
Theyler will become famous soon enoughTheyler will become famous soon enough
По умолчанию Одновременная обработка трёх входов 12F629

Дано:
Inp.-> Outp.
GP5 -> GP0 //A
GP4 -> GP1 //B
GP3 -> GP2 //C

Условие:
При подаче на один из Input постоянного сигнала (лог1), на соотв. Output на 2 сек. появляется лог1.
При пропадании сигнала на входе (и даже если ранее 2-х сек), сигнал на соотв. выходе выключается.
Снова подали и держим сигнал на входе - снова на выходе на 2 сек есть лог1, затем снимается.

Нюанс в том, что на входы GP5, 4 и 3 сигналы могут подаваться независимо и даже одновременно. И алгоритм должен так же независимо отрабатывать каждый из трёх каналов.
Так как я начинающий, возник вопрос в выборе самого принципа обработки.

Как я понял, таймер можно контролировать по прерыванию или по состоянию флага переполнения, внутри рабочего цикла.

Грамотно ли - крутить все три входа в цикле и каждому потом включать свой таймер(в таймере)?
Возможно, более грамотным решением было бы использование прерываний, но я в них не могу разобраться уже около недели.

То, что я набросал, мне не нравится, написано через одно место, не оптимизировано.
Надеюсь, можно ещё хуже.

Прошу подсказать, как грамотнее реализовать данную задачку. Если можно, наглядно, кусками кода. Я обучаюсь быстро.

Код:
..
cblock	0x20
	_255
	A_timer
	B_timer
	C_timer
endc
..
	movlw	b'00111000'
	movwf	TRISIO
..
Loop
	btfsс	GPIO, 5
	call	A_
	btfss	GPIO, 5
	call	Charge_A
	
	btfsс	GPIO, 4
	call	B_
	btfss	GPIO, 4
	call	Charge_B
	
	btfsc	GPIO, 3
	call	C_
	btfss	GPIO, 3
	call	Charge_C
	goto	Loop

A_
	movfw	0x00
;	bcf	STATUS, Z
	xorwf	A_timer, 0
	btfss	STATUS, Z	; если таймер по нулям (уже отработал),
	return		; выходим
	bsf	GPIO, 0	; ON
	call	Delay_255	; Нужно разобраться с временными интервалами обоих циклов
	decfsz	A_timer, 1	; и сколько помещать в A_timer, чтобы общий цикл составил 2-3сек.
	return
	bcf	GPIO, 0	; OFF
return

B_
	nop			; аналогично A_
return

C_
	nop			; аналогично A_
return

Delay_255
;	movfw	0x00
	incfsz	_255, f
	goto	$-1
return

Charge_A
	movfw	0xFF
	movwf	A_Timer
	bcf	GPIO, 0	; OFF (если сигнал снят до завершения работы таймера)
return

Charge_B
	movfw	0xFF
	movwf	B_Timer
	bcf	GPIO, 1
return

Charge_C
	movfw	0xFF
	movwf	C_Timer
	bcf	GPIO, 2
return

end

Последний раз редактировалось Theyler; 10.05.2017 в 18:36.
Theyler вне форума   Ответить с цитированием
Старый 10.05.2017, 18:54   #2
Greg
Super Moderator
 
Регистрация: 25.02.2007
Адрес: Moscow, ODBS
Сообщений: 6,652
Вес репутации: 5137/157
Greg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond repute
По умолчанию Re: Одновременная обработка трёх входов 12F629

Цитата:
Сообщение от Theyler Посмотреть сообщение
Дано:
Inp.-> Outp.
GP5 -> GP0 //A
GP4 -> GP1 //B
GP3 -> GP2 //C

Грамотно ли - крутить все три входа в цикле и каждому потом включать свой таймер(в таймере)?
Возможно, более грамотным решением было бы использование прерываний, но я в них не могу разобраться уже около недели.
да, так делать в цикле - вполне грамотно

только надо научиться анализировать все входы одновременно - считывать значение порта и сравнивать его с предыдущим (сохраненным) значением, потом текущее сохранять как предыдущее.
если значение битов различаются - было изменение.
"Различение" надо анализировать операцией XOR.
Greg вне форума   Ответить с цитированием
Старый 10.05.2017, 19:43   #3
DmitrijVDN
Senior Member
 
Регистрация: 09.04.2010
Сообщений: 733
Вес репутации: 1308/48
DmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud of
По умолчанию Re: Одновременная обработка трёх входов 12F629

Цитата:
Сообщение от Theyler Посмотреть сообщение
Грамотно ли - крутить все три входа в цикле и каждому потом включать свой таймер(в таймере)?
Возможно, более грамотным решением было бы использование прерываний, но я в них не могу разобраться уже около недели.
Прошу подсказать, как грамотнее реализовать данную задачку. Если можно, наглядно, кусками кода. Я обучаюсь быстро.
в вашем случае скорее нет чем, да

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

эта задача решается элементарной последовательной машиной состояний, те вечный цикл: опрос входов -> обработка -> вывод данных , на Си недавно выкладывал с объяснениями на соседнем ресурсе
DmitrijVDN вне форума   Ответить с цитированием
Старый 10.05.2017, 20:15   #4
Theyler
Junior Member
 
Регистрация: 07.05.2017
Сообщений: 17
Вес репутации: 135/3
Theyler will become famous soon enoughTheyler will become famous soon enough
По умолчанию Re: Одновременная обработка трёх входов 12F629

Спасибо за подсказку насчёт анализа всего GPIO целиком.

По-сути, задача не требует особой точности.
Вполне достаточно реакции на изменение уровней на входах в интрервале 0,1 сек, а также удержание выхода в течение 2-2,5 сек.
То есть, задержки в 200мкс на одну команду принципиально не влияют на результат и точность внутреннего тактового генератора также вполне приемлема.

Раз метод опроса состояния портов в цикле не считается моветоном, постараюсь собрать всё до кучи и погонять в Протезе.
Затем реализую в железе.

И после этого обязательно буду доводить исходник до идеального вида, воплощая все Ваши подсказки, советы и рекомендации по поводу использования прерываний.

С удовольствием обязательно научусь культуре программирования микроконтроллеров.
Особенно буду рад примерам на ассемблере.
Theyler вне форума   Ответить с цитированием
Старый 10.05.2017, 20:52   #5
DmitrijVDN
Senior Member
 
Регистрация: 09.04.2010
Сообщений: 733
Вес репутации: 1308/48
DmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud of
По умолчанию Re: Одновременная обработка трёх входов 12F629

начните с этого http://www.pic24.ru/doku.php/osa/art...asm_formatting
DmitrijVDN вне форума   Ответить с цитированием
Старый 11.05.2017, 23:02   #6
Guaho
Senior Member
 
Аватар для Guaho
 
Регистрация: 28.06.2013
Возраст: 45
Сообщений: 658
Вес репутации: 1432/37
Guaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud of
По умолчанию Re: Одновременная обработка трёх входов 12F629

Тут можно действовать по-разному. В Вашем случае задача состоит в реакции на воздействия на заданное время, а раз нужно считать время, то удобнее всего задействовать прерывания. Входы можно опрашивать и в основном цикле программы (ОЦП), и в прерываниях. В последнем случае там же и формируется код состояния входов. Это удобно тем, что в ОЦП Вы сосредотачиваетесь на решении основных задач, а код состояния входов формируется как бы "сам собой"; в ОЦП вы его просто читаете при необходимости, не задумываясь о том, как там он формируется. Ну и время легко можно считать в прерываниях.
Контролировать таймер по его состоянию (по флагу переполнения) можно, но удобнее использовать прерывания от этого таймера. Ничего сложного тут нет. Для работы с прерываниями в младшем/среднем подсемействе PIC, где нет системы приоритетов, нужно:
1) Выбрать таймер, который будет служить источником прерываний. Это делается исходя из частоты командных циклов (Fosc/4), требуемой частоты прерываний и прочих особенностей (например, один из потенциально возможных для использования таймеров может быть занят на другие нужды - скажем, TMR2 используется в работе модуля ШИМ).
2) Настроить таймер (выбрать источник тактирования, настроить прескалер).
3) Написать обработчик прерывания, который должен располагаться с адреса 0004h. Внутри обработчка обязательно должен быть код входа в прерывание и выхода из него (сохранение и восстановление контекста; образец такого кода даётся в даташите), а также команда сброса флага возникновения прерывания от таймера, ну и конечно, сам авторский код опроса входов и прочих действий.
Есть ещё один вариант - прерывание по изменению состояния входов GPIO. Здесь, кроме сброса флага прерывания по изменению состояния входов, в обработчике прерывания нужно ещё прочитать порт, входы которого изменились (GPIO), но это и так будет делаться, т.к. нам нужно определить состояние битов порта. Но в Вашем случае, раз требуется отсчёт времени, лучше использовать прерывания от таймера.
Учтите, что если вы опрашиваете клавиатуру, тумблер или даже герконовый контакт, Вы столкнётесь с явлением дребезга контактов. В таких случаях необходимо программное подавление дребезга контактов. Заключается оно в том, что если обнаруживается изменение состояния входов, Вы запоминаете новое значение, затем выдерживаете паузу (обычно 20 мс), после чего вновь опрашиваете те же входы и сверяете текущее значение с тем, что недавно запомнили. Если совпало, значит, изменение можно считать достоверным, и далее формировать код состояния входов. Если нет - изменение было неустойчивым, и нужно его проигнорировать. Разумеется, задержка не должна быть "тупой", затормаживающей все остальные процессы, - она должна быть построена на базе счётчиков и пользовательских флагов. Например, если обнаружено изменение состояния входов, Вы инициализируете счётчик анти-дребезговой задержки. После входа в прерывание у Вас в коде должна стоять проверка: счётчик анти-дребезга равен нулю? Если да, значит, задержка в данный момент не выполняется, и можно смело опрашивать состояние входов. А если счётчик не равен нулю, значит, задержка выполняется, и потому опрос состояния входов - запрещён, и всё, что делается - это декремент данного счётчика. И вот в момент, когда этот счётчик "перещёлкнется" из 1 в 0, вот тогда-то Вы должны вновь прочитать состояние входов, сравнить с тем, что было, и так далее, как было описано выше.
С отсчётом времени в прерываниях тоже нет ничего сложного, навешиваете нужное количество софтовых счётчиков, причём некоторые "базовые" могут работать каскадно: например, если в вашем устройстве время между прерываниями от таймера будет мало (скажем, 512 мкс), а Вам нужно отсчитывать единицы секунд, то Вы можете сделать один счётчик, который будет считать примерно до 1 мс, другой счётчик будет считать до 100 мс (0,1 с), а третий уже сможет считать до 25,5 с (255 * 0,1 = 25,5 с). Это базовые счётчики времени; от них вы можете "щёлкать" счётчиками времени каждого из 3-х каналов Вашей системы.
И напоследок, немного замечаний по коду.
1) Вам нет нужды использовать код "btfss STATUS, Z", правильнее будет использовать инструкции "bz" или "bnz".
2) Инструкцию "return" (возврат из подпрограммы) лучше ставить одну на подпрограмму. Да, это заманчиво, т.к. код с несколькими "return" получается компактнее, но в нём легче запутаться и сложнее отследить ошибку. Говоря проще - желательно, чтобы точка возврата из подпрограммы была одна. Просто делаете goto на эту точку из тех мест подпрограммы, где это нужно.
Guaho вне форума   Ответить с цитированием
Старый 11.05.2017, 23:07   #7
Theyler
Junior Member
 
Регистрация: 07.05.2017
Сообщений: 17
Вес репутации: 135/3
Theyler will become famous soon enoughTheyler will become famous soon enough
По умолчанию Re: Одновременная обработка трёх входов 12F629

Огромное спасибо.
Рабочий пример (исходник) работы с прерываниями у меня есть.
Попробую использовать применительно к моей задаче.
Главное - я теперь понимаю направление в своих действиях.
Theyler вне форума   Ответить с цитированием
Старый 12.05.2017, 08:06   #8
lisergin
Senior Member
 
Регистрация: 01.03.2007
Сообщений: 133
Вес репутации: 263/43
lisergin is a jewel in the roughlisergin is a jewel in the roughlisergin is a jewel in the rough
По умолчанию Re: Одновременная обработка трёх входов 12F629

Цитата:
Вам нет нужды использовать код "btfss STATUS, Z", правильнее будет использовать инструкции "bz" или "bnz".
В мелких пиках таких инструкций не водится. Можно юзать MPLABовские макросы SKPZ SKPNZ.
lisergin вне форума   Ответить с цитированием
Старый 12.05.2017, 08:40   #9
Zikon
Junior Member
 
Регистрация: 04.07.2012
Сообщений: 20
Вес репутации: 139/21
Zikon will become famous soon enoughZikon will become famous soon enough
По умолчанию Re: Одновременная обработка трёх входов 12F629

Цитата:
Сообщение от lisergin Посмотреть сообщение
В мелких пиках таких инструкций не водится. Можно юзать MPLABовские макросы SKPZ SKPNZ.
ЕСТЬ! такие псевдоинструкции

BZ,BNZ,BC,BNC,CLRZ,SETZ,SKPZ,SKPNZ ......

в документации на ASM есть полный список.

И странные комментарии.

The following pseudo-instructions are applicable
to both the 12-bit and 14-bit instruction word devices.
These pseudo-instructions are alternative mnemonics
for standard PIC1X instructions or are macros
that generate one or more PIC1X instructions.
Use of these pseudo-instructions is not recommended
for new designs
. These are documented mainly
for historical purposes.
Zikon вне форума   Ответить с цитированием
Старый 12.05.2017, 18:00   #10
Guaho
Senior Member
 
Аватар для Guaho
 
Регистрация: 28.06.2013
Возраст: 45
Сообщений: 658
Вес репутации: 1432/37
Guaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud of
По умолчанию Re: Одновременная обработка трёх входов 12F629

Цитата:
Сообщение от lisergin Посмотреть сообщение
В мелких пиках таких инструкций не водится...
В 629-м, о котором шла речь в ветке, - точно водятся. Проверено практикой
Guaho вне форума   Ответить с цитированием
Старый 12.05.2017, 19:29   #11
Theyler
Junior Member
 
Регистрация: 07.05.2017
Сообщений: 17
Вес репутации: 135/3
Theyler will become famous soon enoughTheyler will become famous soon enough
По умолчанию Re: Одновременная обработка трёх входов 12F629

В конструкции A_ (аналогично в B_ и C_)
Код:
	list	r=dec, x=on, p=12f629
#include <p12f629.inc>
	__CONFIG _CPD_OFF&_CP_OFF & _BODEN_ON & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
	ERRORLEVEL	2				;Вывод только ошибок

#define	BANK0	bcf	STATUS,	RP0
#define	BANK1	bsf	STATUS,	RP0

cblock	0x20
	_255
	A_timer
	B_timer
	C_timer
endc

	org		0x00
	goto	START

START
	BANK0
	clrf	GPIO
	movlw	b'111'
	movwf	CMCON
	BANK1
	call	0x3FF
	movwf	OSCCAL
;1nput	>	0utput
;GP5	>	GP0	A
;GP4	>	GP1	B
;GP3	>	GP2	C
	movlw	b'00111000'
	movwf	TRISIO

Loop
	btfsc	GPIO, 5
	call	A_
	btfss	GPIO, 5
	call	Charge_A

	btfsc	GPIO, 4
	call	B_
	btfss	GPIO, 4
	call	Charge_B

	btfsc	GPIO, 3
	call	C_
	btfss	GPIO, 3
	call	Charge_C
	goto	Loop

A_
	movfw	0x00
	xorwf	A_timer, 0
	bz		No_A		; если таймер по нулям (уже отработал),
	bsf		GPIO, 0		; ON
	call	Delay_255	; Нужно разобраться с временными интервалами обоих циклов
	decfsz	A_timer, 1	; и сколько помещать в A_timer, чтобы общий цикл составил 2 сек.
	return
	bcf		GPIO, 0		; OFF
No_A
return

B_
	movfw	0x00
	xorwf	B_timer, 0
	bz		No_B
	bsf		GPIO, 0
	call	Delay_255
	decfsz	B_timer, 1
	return
	bcf		GPIO, 0
No_B
return

C_
	movfw	0x00
	xorwf	C_timer, 0
	bz		No_C
	bsf		GPIO, 0
	call	Delay_255
	decfsz	C_timer, 1
	return
	bcf		GPIO, 0		; OFF
No_C
return

Delay_255
;	movfw	0x00
	incfsz	_255, f
	goto	$-1
return

Charge_A
	movfw	0xFF
	movwf	A_timer
	bcf		GPIO, 0		; OFF (если снят сигнал до завершения работы таймера)
return

Charge_B
	movfw	0xFF
	movwf	B_timer
	bcf		GPIO, 1
return

Charge_C
	movfw	0xFF
	movwf	C_timer
	bcf		GPIO, 2
return
end
Скомпилировалось без ошибок:
Цитата:
----------------------------------------------------------------------
Debug build of project `L:\!ALL\PIC\12F629\TRM_PIC\trm_pic.disposable_mcp ' started.
Preprocessor symbol `__DEBUG' is defined.
Fri May 12 19:26:41 2017
----------------------------------------------------------------------
Clean: Deleting intermediary and output files.
Clean: Deleted file "L:\!ALL\PIC\12F629\TRM_PIC\trm_pic.mcs".
Clean: Done.
Executing: "C:\Program Files\Microchip\MPASM Suite\MPASMWIN.exe" /q /p12F629 "trm_pic.asm" /l"trm_pic.lst" /e"trm_pic.err" /d__DEBUG=1
Executing: "C:\Program Files\Microchip\MPASM Suite\mplink.exe" /p12F629 "trm_pic.o" /u_DEBUG /z__MPLAB_BUILD=1 /z__MPLAB_DEBUG=1 /o"trm_pic.cof" /M"trm_pic.map" /W /x
MPLINK 4.30.01, Linker
Copyright (c) 2009 Microchip Technology Inc.
Errors : 0

Loaded L:\!ALL\PIC\12F629\TRM_PIC\trm_pic.cof.
----------------------------------------------------------------------
Debug build of project `L:\!ALL\PIC\12F629\TRM_PIC\trm_pic.disposable_mcp ' succeeded.
Preprocessor symbol `__DEBUG' is defined.
Fri May 12 19:26:46 2017
----------------------------------------------------------------------
BUILD SUCCEEDED
Я правильно применил инструкцию (Для меня они роднее. Напоминают старые добрые jz и jnz)?

Но где-то накосячил.
В Протеусе не работает, на макетке тоже.

Последний раз редактировалось Theyler; 12.05.2017 в 19:47.
Theyler вне форума   Ответить с цитированием
Старый 13.05.2017, 08:14   #12
lisergin
Senior Member
 
Регистрация: 01.03.2007
Сообщений: 133
Вес репутации: 263/43
lisergin is a jewel in the roughlisergin is a jewel in the roughlisergin is a jewel in the rough
По умолчанию Re: Одновременная обработка трёх входов 12F629

Юзается GP3 и в конфиге _MCLRE_ON. Так задумано?
lisergin вне форума   Ответить с цитированием
Старый 13.05.2017, 08:20   #13
lisergin
Senior Member
 
Регистрация: 01.03.2007
Сообщений: 133
Вес репутации: 263/43
lisergin is a jewel in the roughlisergin is a jewel in the roughlisergin is a jewel in the rough
По умолчанию Re: Одновременная обработка трёх входов 12F629

Цитата:
movfw 0x00
Косвенная адресация?
lisergin вне форума   Ответить с цитированием
Старый 13.05.2017, 08:21   #14
Theyler
Junior Member
 
Регистрация: 07.05.2017
Сообщений: 17
Вес репутации: 135/3
Theyler will become famous soon enoughTheyler will become famous soon enough
По умолчанию Re: Одновременная обработка трёх входов 12F629

Ой. Шапку брал с проги под чтение DS1990A.
Я - криворукий рукожоп.
Сейчас перепроверю всё.

Можно консультацию? Какой бы конфиг был для этой задачи самый оптимальный? То есть, что можно явно не задавать (то есть, оно либо включено по умолчанию, либо не играет рояли для данного алгоритма), а что задавать нужно обязательно?

Ксорил с нулём для проверки нуля же.
Ранее такое работало:
Код:
movfw	EE_family_code
xorwf	DS_family_code,0
btfss	STATUS,Z
goto	Next
Да и вообще, любая ругань в мой адрес приветствуется. Мне полезно.

Последний раз редактировалось Theyler; 13.05.2017 в 08:31.
Theyler вне форума   Ответить с цитированием
Старый 13.05.2017, 09:28   #15
lisergin
Senior Member
 
Регистрация: 01.03.2007
Сообщений: 133
Вес репутации: 263/43
lisergin is a jewel in the roughlisergin is a jewel in the roughlisergin is a jewel in the rough
По умолчанию Re: Одновременная обработка трёх входов 12F629

Так а что в конфиге: смотрим описание опций, задаём себе вопрос "это надо?" и ставим соответственно. Каждый бит.
"Эта задача" подразумевает схему подключения пинов, может надо с регистром WPU чего-то наделать. Хотя это, как правило, видно протеусом.
Ошибки невнимательности в ассемблере -- та ещё мерзость. Часто встречалась путаница между movf, movwf и movlw. Обратите внимание, если вместо movf писать movfw, то каши становится ещё больше: movfw и movlw очень слабо различаются глазом в тексте. Просто рекомендация из практики.
lisergin вне форума   Ответить с цитированием
Старый 13.05.2017, 13:48   #16
Guaho
Senior Member
 
Аватар для Guaho
 
Регистрация: 28.06.2013
Возраст: 45
Сообщений: 658
Вес репутации: 1432/37
Guaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud of
По умолчанию Re: Одновременная обработка трёх входов 12F629

На вкус и цвет товарища нет, но я бы тоже предостерёг автора темы от использования некоторых псевдо-инструкций, и именно по упомянутой причине - похожести на другие инструкции. По-моему, при использовании movfw читаемость кода ухудшается, а вероятность ошибки возрастает. Я бы Вам рекомендовал:
1) Отказаться от movfw;
2) Отказаться от использования "0" и "1" во втором операнде команды.
То есть рекомендую использовать:
movf EE_family_code,f вместо movfw EE_family_code
xorwf DS_family_code,w вместо xorwf DS_family_code,0
С этими ноликами и единичками можно запутаться, а так - всё понятно, w или f.
Ну и опять-таки, "btfss STATUS,Z" - это лишнее, удобнее использовать bz / bnz.
Таким образом, приведённый в посте выше код мог бы выглядеть так:
Код:
movf      EE_family_code,w
xorwf     DS_family_code,w
bnz       Next
Теперь по конфигу (имеется в виду не глобальный конфиг, а Special Function Registers, SFR). С точки зрения оптимальности кода можно использовать значения по умолчанию, НО с точки зрения оптимальности разработки - это плохой подход (на мой взгляд). Имеется в виду, что когда Вы будете делать другой проект на этом же камне, Вам придётся приложить больше усилий по созданию конфига, т.е. глубже курить даташит, да и вероятность пропустить что-нибудь важное будет выше. Если Вы укажете явно все значения для всех SFR, у Вас получится шаблон, который легко будет использовать в других проектах. Вообще, к этому вопросу надо подойти очень тщательно, не торопясь. Если полениться и сделать абы-как, тогда и результат может оказаться непредсказуемым. Поэтому моя рекомендация - явно указать содержимое для всех SFR регистров, задающих режимы работы.
Да, и чтобы не захламлять код, заключите конфиг в подпрограмму. Тогда у Вас будет всего одна команда, после которой пойдёт главный код.
Guaho вне форума   Ответить с цитированием
Старый 13.05.2017, 14:31   #17
Theyler
Junior Member
 
Регистрация: 07.05.2017
Сообщений: 17
Вес репутации: 135/3
Theyler will become famous soon enoughTheyler will become famous soon enough
По умолчанию Re: Одновременная обработка трёх входов 12F629

Отлично. Именно такого рода наставления я и хотел услышать. Ибо, как начнёшь, как привыкнешь сначала, так и потом пойдёт. А мне хочется писать грамотно. Именно поэтому мне рекомендации профессионалов и важны, особенно сейчас.

Концепции уловил, код подправил, вылавливаю монтажные и программные баги.
Обязательно покажу, что получилось. Наверняка Вы увидите что-то ещё для критики.

***

Хотелось небольшую подсказку, как лучше включить цикл в цикле для двухсекундной единицы на выходе.
Понимаю, что опрашивать вход нужно часто, в большом (длинном) временном кольце этих двух секунд, а "быстрый" цикл ставить перед опросом.

Прогой Pic_delay_1_8 сгенерился аж тройной цикл:
Код:
; Задержка 2 000 000 машинных циклов
; Длительность задержки 2 секунд
; Частота задающего генератора 4 МГц
            movlw       .93
            movwf       Reg_1
            movlw       .38
            movwf       Reg_2
            movlw       .11
            movwf       Reg_3
            decfsz      Reg_1,F
            goto        $-1
            decfsz      Reg_2,F
            goto        $-3
            decfsz      Reg_3,F
            goto        $-5
            nop
            nop
Где в него лучше воткнуться проверкой? То есть, как его вплести в код?

И ещё: как лучше одну подпрограмму использовать для нескольких аналогичных вызовов? Я понимаю, что нужно в какую-то переменную типа temp передавать текущее значение таймера, а потом там его подставлять в начале работы циклов, чтобы продолжались с того круга, на котором закончили, а потом эту переменную считывать.

Или же лучше всё же объявить три таких одинаковых цикла для каждого входа и не парить себе мозги с сохранением/восстановлением значений переменных?
Места в ОЗУ под код пока вроде хватает. (=
Theyler вне форума   Ответить с цитированием
Старый 13.05.2017, 17:15   #18
Guaho
Senior Member
 
Аватар для Guaho
 
Регистрация: 28.06.2013
Возраст: 45
Сообщений: 658
Вес репутации: 1432/37
Guaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud ofGuaho has much to be proud of
По умолчанию Re: Одновременная обработка трёх входов 12F629

Ой, как замудро, это перебор! И задержки, и таймер ещё... У меня мозги чуть не закрутились в спираль)))
Вы пытаетесь идти по сложному пути. Не хотите преодолеть маленький бордюрчик, и вместо этого лезете на 2-х-метровую стену, думая, что так будет проще, чем через бордюрчик.
Делать такого рода замедляющие циклы, забирающие на себя всё процессорное время - не лучший вариант... Для начинающих он допустим, это я понимаю, но Вы сами видите, как в простой, казалось бы, задаче использование замедляющего цикла приводит к серьёзной головоломке. Да, её наверно можно решить, но зачем лезть через высоченную стену, если возможен путь намного проще?
В Вашей задаче есть несколько каналов, которые должны работать независимо друг от друга. Если хотя бы один из них уйдёт вот в такую "глухую" задержку, что тогда делать? Опрашивать состояние других каналов внутри замедляющего цикла, выходить оттуда, запоминая состояние счётчиков, потом возвращаться, восстанавливая значение счётчиков? Это дикость какая-то, особенно если учесть, что Ваши проверки нарушат структуру замедляющего цикла (добавят лишние машинные циклы), и надо будет ещё там подгонять время. Как-то жёстко получается, запутаетесь. И главное - очень некрасивое решение выйдет. Изящно-извращённое, может быть, но не красивое.
Вам нужно преодолеть психологический барьер боязни прерываний (если таковой имеется) и сделать всё проще. Прерывания дадут Вам возможность независимого отсчёта любых временнЫх интервалов. Код станет до предела простым, изящным, и главное - понятным! Иначе через какие-нибудь полгода Вы сами просто не сможете понять логику работы этого ужаса с жёсткими циклами и произвольными выходами и возвратами в них.
Так что я бы советовал Вам не торопиться в первую очередь. Спокойно написать код для запуска работы прерываний от таймера, в качестве которого можно взять TMR0. Делаете следующие шаги:
1) Облагораживаете начало Вашего кода, например, вот таким образом:
Код:
;*********************************************************************************************************************
;
;    Супер-система управления не скажу чем.
;
;    Процессор - PIC12F629, тактирование от внутреннего источника, 4 МГц.
;
;*********************************************************************************************************************

    LIST p=12F629, r=dec
    #include <p12F629.inc>    ;подключаем файл констант и символов для заданного контроллера.
    errorlevel -302        ;убираем напоминания о том, что для регистров, находящихся не в 0-м банке памяти,
                ;надо не забыть правильно выставить биты выбора банка.
    
    ;Глобальная конфигурация: .... (описываете словами, что включено, а что - нет, это для себя)
    __CONFIG _FOSC_HS & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BOREN_OFF    & _CPD_OFF & _WRT_OFF & _DEBUG_OFF & _LVP_OFF

;==== Переменные, константы и обозначения ============================================================================

;Тут - описание переменных, констант и т.п.

;====== СТАРТ ПРОГРАММЫ ==============================================================================================

    org    0    
    bcf    INTCON,GIE        ;Все прерывания запрещаются глобально.
    goto    begin    

;------ Обработчик прерываний ----------------------------------------------------------------------------------------

    org    4        
    call    prer   ;Вызываем обработчик прерываний.

;------ Инициализация ------------------------------------------------------------------------------------------------

begin:    call    init_sys    ;Системная инициализация: настройка периферии, прерываний, портов и т.п.
    call    init_vars    ;Инициализация переменных при старте программы.

;====== ОЦП ==========================================================================================================
;Основной цикл программы. Тут располагаете свой основной код.
            bsf INTCON,GIE   ;Разрешаете прерывания.
;..... ну и далее пошёл Ваш код.
2) В подпрограмме init_sys (системная инициализация) прописываете режим работы TMR0 и включаете прерывания от него. Что-то примерно в таком духе:
Код:
    BANKSEL INTCON
    movlw    b'01100000'    ;разрешение прерываний от периферийных модулей,
    movwf    INTCON        ;запрет всех остальных и глобальный запрет всех прерываний.
    BANKSEL OPTION_REG
    movlw    b'10000101'    ;выключаем подтягивающие резисторы (за ненадобностью);
    movwf    OPTION_REG    ;предделитель подключаем к TMR0 и устанавливаем его коэффициент деления 1:64.
;Таким образом, время одного командного цикла при частоте 4 мГц равно 1 мкс, 
;а с предделителем 1:64 таймер будет наращиваться через каждые 1*64 = 64 мкс, 
;а переполняться - через каждые 64 * 256 = 16384 мкс = 16 мс (округляем для простоты расчётов).
3) Пишете процедуру обработки прерываний (подпрограмма prer):
Код:
prer:
..... - сохранение контекста при входе в прерывание, см. в даташите.
А далее пошёл Ваш обработчик:
    bcf    INTCON,T0IF    ;Сбрасываем флаг возникновения прерывания от TMR0.
.... - тут Вы модифицируете свои счётчики, которые будут отсчитывать задержки. 
ВАЖНО: в подпрограмме init_vars (инициализация переменных после подачи питания
 на устройство) Вы должны прописать начальные значения для этих счётчиков.
..... - сохранение контекста при вЫходе из прерывания, см. в даташите.
    retfie
И вот только после этого Вы получаете замечательный механизм, который как бы сам по себе будет считать Вам задержки, причём независимо для любого числа каналов (хоть 3, хоть 33 - без разницы), и не при этом без всяких жёстких зацикливаний с забиранием всего процессорного времени на себя. Для приведённого мною примера время между таймерными прерываниями = 16 мс, а нам нужны более длительные задержки. Смотрим: 16,384 мс * 122 = 2000 мс = 2 с (примерно, с округлением). Вывод: достаточно одного счётчика для подсчёта нужного времени. НО у Вас должно быть три счётчика, по числу каналов. Удобнее считать назад, от начальной величины к нулю.

В основном цикле программы Вы делаете примерно следующее:
- опрашиваете вход канала 1. Если нет запускающего события, переходите к опросу следующего канала, и далее по кругу.
- при обнаружении запускающего события:
1) управляете нужным выходным пином порта;
2) инициализируете счётчик времени для данного канала;
3) переходите к обработке следующего канала, и так далее.

В прерывании для каждого "канального" счётчика:
- проверяете: счётчик равен нулю? Если да, значит, счёт данного канала не запущен.
- если счётчик не обнулён, декрементируете его. Если он после декремента не обнулился - переходите к обработке остальных счётчиков и далее на выход из прерывания. А вот если обнулился - тогда изменяете состояние выходного пина, соответствующего данному каналу.
Система получается на самом деле достаточно простая, код - довольно компактный. И главное - ничто ничему не мешает, и не надо ломать голову и погрязать в замедляющих циклах. А они засасывают всякого туда входящего, проверено
Guaho вне форума   Ответить с цитированием
Старый 13.05.2017, 17:39   #19
DmitrijVDN
Senior Member
 
Регистрация: 09.04.2010
Сообщений: 733
Вес репутации: 1308/48
DmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud ofDmitrijVDN has much to be proud of
По умолчанию Re: Одновременная обработка трёх входов 12F629

Цитата:
Сообщение от Theyler Посмотреть сообщение
хочется писать грамотно. Прогой Pic_delay_1_8 сгенерился аж тройной цикл:
Где в него лучше воткнуться проверкой? То есть, как его вплести в код?
никак, посмотрели на програмку и забыли о ней совсем,от слова навсегда!
DmitrijVDN вне форума   Ответить с цитированием
Старый 13.05.2017, 17:43   #20
Theyler
Junior Member
 
Регистрация: 07.05.2017
Сообщений: 17
Вес репутации: 135/3
Theyler will become famous soon enoughTheyler will become famous soon enough
По умолчанию Re: Одновременная обработка трёх входов 12F629

Именно этого я и хотел.
Уже раньше понял, что нужно плотно садиться на прерывания и не городить колхоз с циклами.

Ваша консультация - именно тот толчок к действию, то руководство, которого мне не хватало для первого шага к прерываниям.

На текущий момент всё работает, но застрял именно на подборе временных задержек (как Вы и говорили). 255 циклов по 255 получается около 0,3 сек. Добавление третьего вложенного цикла даёт геометрическую прогрессию в задержке. Хоть нопами забивай вместо цикла..

Сейчас буду переделывать под прерывания.
Код:
	list	p=12f629
#include <p12f629.inc>
	__CONFIG _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON

	cblock	0x20
	Short_A
	Short_B
	Short_C
	Timer_A
	Timer_B
	Timer_C
	endc
	
	org		0x00
	goto	START
	
START
	bsf		STATUS, 5	;RP0	; bank1
	call	3FFh
	movwf	OSCCAL
	movlw	b'00111000'
	movwf	TRISIO
	bcf		OPTION_REG,	7	; enable drag resistors
	movlw	b'00111000'		; GP5 и GP4 {GP3 внешний}
	movwf	WPU				; on
	bcf		STATUS, 5	;RP0	; bank0
	clrf	GPIO		; clear all ports
	movlw	.7
	movwf	CMCON		; Comparator OFF
Loop
	btfss	GPIO, 5
	call	A_			;bsf		GPIO, 0
	btfsc	GPIO, 5
	call	Charge_A	;bcf		GPIO, 0

	btfss	GPIO, 4
	call	B_			;bsf		GPIO, 1
	btfsc	GPIO, 4
	call	Charge_B	;bcf		GPIO, 1

	btfss	GPIO, 3
	call	C_			;bsf		GPIO, 2
	btfsc	GPIO, 3
	call	Charge_C	;bcf		GPIO, 2
	goto	Loop
A_
	movlw	.0
	xorwf	Timer_A, w
	bz		No_A		; если таймер по нулям (уже отработал),
	bsf		GPIO, 0		; ON
	call	Delay_2sec	; Нужно разобраться с временными интервалами обоих циклов
	decfsz	Timer_A, f	; и сколько помещать в A_timer, чтобы общий цикл составил 2 сек.
	goto	No_A
	bcf		GPIO, 0		; OFF
No_A
	return
B_
	movlw	.0
	xorwf	Timer_B, w
	bz		No_B
	bsf		GPIO, 1
	call	Delay_2sec
	decfsz	Timer_B, 1
	goto	No_B
	bcf		GPIO, 1
No_B
	return
C_
	movlw	.0
	xorwf	Timer_C, w
	bz		No_C
	bsf		GPIO, 2
	call	Delay_2sec
	decfsz	Timer_C, 1
	goto	No_C
	bcf		GPIO, 2
No_C
	return
Delay_2sec
;	decfsz	_5, f
;	goto	$-1
	decfsz	Short_A, f
	goto	$-1
	nop
	nop
	return
Charge_A
;	movlw	.0
;	movwf	_5
	movlw	.255
	movwf	Short_A
	movlw	.255
	movwf	Timer_A
	bcf		GPIO, 0		; OFF (если снят сигнал до завершения работы таймера)
	return
Charge_B
	movlw	.255
	movwf	Timer_B
	bcf		GPIO, 1
	return
Charge_C
	movlw	.255
	movwf	Timer_C
	bcf		GPIO, 2
	return
	org		2100h
	de		0xD5, 0xD3, 0xC9
	END
Theyler вне форума   Ответить с цитированием
Старый 13.05.2017, 18:39   #21
DimaS
Senior Member
 
Регистрация: 05.04.2008
Адрес: Israel
Возраст: 44
Сообщений: 1,403
Вес репутации: 2061/70
DimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond repute
По умолчанию Re: Одновременная обработка трёх входов 12F629

Код:
 
org    4
call    prer   ;Вызываем обработчик прерываний.
Много лет я уже не писал на асме для пиков, но тут точно call а не goto ?
DimaS вне форума   Ответить с цитированием
Старый 13.05.2017, 18:57   #22
Greg
Super Moderator
 
Регистрация: 25.02.2007
Адрес: Moscow, ODBS
Сообщений: 6,652
Вес репутации: 5137/157
Greg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond repute
По умолчанию Re: Одновременная обработка трёх входов 12F629

Цитата:
Сообщение от DimaS Посмотреть сообщение
Код:
 
org    4
call    prer   ;Вызываем обработчик прерываний.
Много лет я уже не писал на асме для пиков, но тут точно call а не goto ?
самый идиотизм, что здесь не нужен ни goto, ни call - а просто писать код прерывания. но очень редко такое вижу...
Greg вне форума   Ответить с цитированием
Старый 13.05.2017, 19:12   #23
DimaS
Senior Member
 
Регистрация: 05.04.2008
Адрес: Israel
Возраст: 44
Сообщений: 1,403
Вес репутации: 2061/70
DimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond reputeDimaS has a reputation beyond repute
По умолчанию Re: Одновременная обработка трёх входов 12F629

Цитата:
Сообщение от Greg Посмотреть сообщение
самый идиотизм, что здесь не нужен ни goto, ни call - а просто писать код прерывания. но очень редко такое вижу...
конечно, но иногда его выносят куда-то в другое место, тогда и надо goto, но почему тут написано call ?
Оно, разумеется, можно и call, только тогда после него дожно быть retfie
DimaS вне форума   Ответить с цитированием
Старый 13.05.2017, 19:21   #24
Theyler
Junior Member
 
Регистрация: 07.05.2017
Сообщений: 17
Вес репутации: 135/3
Theyler will become famous soon enoughTheyler will become famous soon enough
По умолчанию Re: Одновременная обработка трёх входов 12F629

У меня есть рабочий код двух прог.
Там в одной есть
Код:
org		0x00
	goto	START
	org		0x04
	goto	INTERRUPT
...
INTERRUPT
	;разобраться: какого %@$ без этого не работает?!
	incfsz	temp0,f
	goto	$-1

;*** далее обработка чего там надо
; и в конце:
ExitDSReset					;Возвращаемся из подпрограммы обработки прерываний
	BANK1					;Выбираем банк 1
	bsf		DSTRIS			;Настраиваем канал на вход (чтобы регистрировать прерывание по изменению уровня)
	BANK0
;	btfsc	INTCON,GPIF		;Проверяем: подпрограмма DSReset была вызвана программно или через обработку прерывания
;	goto$+2					;если через обработку прерывания (, то пропускаем команду)
;	goto$+3					;если DSReset была вызвана программно (,то пропускаем две команды)
	movf	GPIO,f
	bcf		INTCON,GPIF		;Сбрасываем флаг прерывания по изменению уровня сигнала на GPIO
retfie
А в другом рабочем коде
просто
Код:
	ORG		0x00
	goto	START
И в самой проге работа с прерываниями:
Код:
Delay
delay_0
	bcf		INTCON,2
loop_0
	btfss	INTCON,2
	goto	loop_0
	decfsz	count,1
	goto	delay_0
return
pause
	movlw	0x05
	movwf	count
pause_1
	bcf		INTCON,2
p_loop
	btfss	INTCON,2
	goto	p_loop
	decfsz	count, 1
	goto	pause_1
return
Tone
	bcf		INTCON, 2		;clear timer interupt flag
	movfw	Freq			;700Hz=0xf5 0xF4=640Hz 0xFA=1000Hz
	movwf	TMR0
	bsf		GPIO, 4
high_
	btfss	INTCON, 2		;timer 0 overflow interup flag
	goto	high_			;delay loop
	bcf		INTCON, 2		;clear timer interupt flag
	movfw	Freq			;0xf9
	movwf	TMR0
	bcf		GPIO, 4
low_
	btfss	INTCON, 2		;timer 0 overflow interup flag
	goto	low_			;delay loop
	decfsz	count,1
	goto	Tone
return
Вот пока разбираюсь и осмысливаю.
Theyler вне форума   Ответить с цитированием
Старый 13.05.2017, 19:33   #25
Greg
Super Moderator
 
Регистрация: 25.02.2007
Адрес: Moscow, ODBS
Сообщений: 6,652
Вес репутации: 5137/157
Greg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond repute
По умолчанию Re: Одновременная обработка трёх входов 12F629

Цитата:
Сообщение от DimaS Посмотреть сообщение
конечно, но иногда его выносят куда-то в другое место, тогда и надо goto, но почему тут написано call ?
Оно, разумеется, можно и call, только тогда после него дожно быть retfie
зачем в младших пиках (с одним вектором) куда-то его выносить. в худших традициях пикоманства...
Greg вне форума   Ответить с цитированием
Ответ


Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 
Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход


Часовой пояс GMT +3, время: 11:40.


Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd. Перевод: zCarot